1
First pullreq for arm of the 4.1 series, since I'm back from
1
Just my fp16 work, plus some small stuff for the sbsa-ref board;
2
holiday now. This is mostly my M-profile FPU series and Philippe's
2
but my rule of thumb is to send a pullreq once I get over about
3
devices.h cleanup. I have a pile of other patchsets to work through
3
30 patches...
4
in my to-review folder, but 42 patches is definitely quite
5
big enough to send now...
6
4
7
thanks
8
-- PMM
5
-- PMM
9
6
10
The following changes since commit 413a99a92c13ec408dcf2adaa87918dc81e890c8:
7
The following changes since commit 2f4c51c0f384d7888a04b4815861e6d5fd244d75:
11
8
12
Add Nios II semihosting support. (2019-04-29 16:09:51 +0100)
9
Merge remote-tracking branch 'remotes/kraxel/tags/usb-20200831-pull-request' into staging (2020-08-31 19:39:13 +0100)
13
10
14
are available in the Git repository at:
11
are available in the Git repository at:
15
12
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190429
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200901
17
14
18
for you to fetch changes up to 437cc27ddfded3bbab6afd5ac1761e0e195edba7:
15
for you to fetch changes up to 3f462bf0f6ea6382dd1502d4eb1fcd33c8e774f5:
19
16
20
hw/devices: Move SMSC 91C111 declaration into a new header (2019-04-29 17:57:21 +0100)
17
hw/arm/sbsa-ref : Add embedded controller in secure memory (2020-09-01 14:01:34 +0100)
21
18
22
----------------------------------------------------------------
19
----------------------------------------------------------------
23
target-arm queue:
20
target-arm queue:
24
* remove "bag of random stuff" hw/devices.h header
21
* Implement fp16 support for AArch32 VFP and Neon
25
* implement FPU for Cortex-M and enable it for Cortex-M4 and -M33
22
* hw/arm/sbsa-ref: add "reg" property to DT cpu nodes
26
* hw/dma: Compile the bcm2835_dma device as common object
23
* hw/arm/sbsa-ref : Add embedded controller in secure memory
27
* configure: Remove --source-path option
28
* hw/ssi/xilinx_spips: Avoid variable length array
29
* hw/arm/smmuv3: Remove SMMUNotifierNode
30
24
31
----------------------------------------------------------------
25
----------------------------------------------------------------
32
Eric Auger (1):
26
Graeme Gregory (2):
33
hw/arm/smmuv3: Remove SMMUNotifierNode
27
hw/misc/sbsa_ec : Add an embedded controller for sbsa-ref
28
hw/arm/sbsa-ref : Add embedded controller in secure memory
34
29
35
Peter Maydell (28):
30
Leif Lindholm (1):
36
hw/ssi/xilinx_spips: Avoid variable length array
31
hw/arm/sbsa-ref: add "reg" property to DT cpu nodes
37
configure: Remove --source-path option
38
target/arm: Make sure M-profile FPSCR RES0 bits are not settable
39
hw/intc/armv7m_nvic: Allow reading of M-profile MVFR* registers
40
target/arm: Implement dummy versions of M-profile FP-related registers
41
target/arm: Disable most VFP sysregs for M-profile
42
target/arm: Honour M-profile FP enable bits
43
target/arm: Decode FP instructions for M profile
44
target/arm: Clear CONTROL_S.SFPA in SG insn if FPU present
45
target/arm: Handle SFPA and FPCA bits in reads and writes of CONTROL
46
target/arm/helper: don't return early for STKOF faults during stacking
47
target/arm: Handle floating point registers in exception entry
48
target/arm: Implement v7m_update_fpccr()
49
target/arm: Clear CONTROL.SFPA in BXNS and BLXNS
50
target/arm: Clean excReturn bits when tail chaining
51
target/arm: Allow for floating point in callee stack integrity check
52
target/arm: Handle floating point registers in exception return
53
target/arm: Move NS TBFLAG from bit 19 to bit 6
54
target/arm: Overlap VECSTRIDE and XSCALE_CPAR TB flags
55
target/arm: Set FPCCR.S when executing M-profile floating point insns
56
target/arm: Activate M-profile floating point context when FPCCR.ASPEN is set
57
target/arm: New helper function arm_v7m_mmu_idx_all()
58
target/arm: New function armv7m_nvic_set_pending_lazyfp()
59
target/arm: Add lazy-FP-stacking support to v7m_stack_write()
60
target/arm: Implement M-profile lazy FP state preservation
61
target/arm: Implement VLSTM for v7M CPUs with an FPU
62
target/arm: Implement VLLDM for v7M CPUs with an FPU
63
target/arm: Enable FPU for Cortex-M4 and Cortex-M33
64
32
65
Philippe Mathieu-Daudé (13):
33
Peter Maydell (44):
66
hw/dma: Compile the bcm2835_dma device as common object
34
target/arm: Remove local definitions of float constants
67
hw/arm/aspeed: Use TYPE_TMP105/TYPE_PCA9552 instead of hardcoded string
35
target/arm: Use correct ID register check for aa32_fp16_arith
68
hw/arm/nseries: Use TYPE_TMP105 instead of hardcoded string
36
target/arm: Implement VFP fp16 for VFP_BINOP operations
69
hw/display/tc6393xb: Remove unused functions
37
target/arm: Implement VFP fp16 VMLA, VMLS, VNMLS, VNMLA, VNMUL
70
hw/devices: Move TC6393XB declarations into a new header
38
target/arm: Macroify trans functions for VFMA, VFMS, VFNMA, VFNMS
71
hw/devices: Move Blizzard declarations into a new header
39
target/arm: Implement VFP fp16 for fused-multiply-add
72
hw/devices: Move CBus declarations into a new header
40
target/arm: Macroify uses of do_vfp_2op_sp() and do_vfp_2op_dp()
73
hw/devices: Move Gamepad declarations into a new header
41
target/arm: Implement VFP fp16 for VABS, VNEG, VSQRT
74
hw/devices: Move TI touchscreen declarations into a new header
42
target/arm: Implement VFP fp16 for VMOV immediate
75
hw/devices: Move LAN9118 declarations into a new header
43
target/arm: Implement VFP fp16 VCMP
76
hw/net/ne2000-isa: Add guards to the header
44
target/arm: Implement VFP fp16 VLDR and VSTR
77
hw/net/lan9118: Export TYPE_LAN9118 and use it instead of hardcoded string
45
target/arm: Implement VFP fp16 VCVT between float and integer
78
hw/devices: Move SMSC 91C111 declaration into a new header
46
target/arm: Make VFP_CONV_FIX macros take separate float type and float size
47
target/arm: Use macros instead of open-coding fp16 conversion helpers
48
target/arm: Implement VFP fp16 VCVT between float and fixed-point
49
target/arm: Implement VFP vp16 VCVT-with-specified-rounding-mode
50
target/arm: Implement VFP fp16 VSEL
51
target/arm: Implement VFP fp16 VRINT*
52
target/arm: Implement new VFP fp16 insn VINS
53
target/arm: Implement new VFP fp16 insn VMOVX
54
target/arm: Implement VFP fp16 VMOV between gp and halfprec registers
55
target/arm: Implement FP16 for Neon VADD, VSUB, VABD, VMUL
56
target/arm: Implement fp16 for Neon VRECPE, VRSQRTE using gvec
57
target/arm: Implement fp16 for Neon VABS, VNEG of floats
58
target/arm: Implement fp16 for VCEQ, VCGE, VCGT comparisons
59
target/arm: Implement fp16 for VACGE, VACGT
60
target/arm: Implement fp16 for Neon VMAX, VMIN
61
target/arm: Implement fp16 for Neon VMAXNM, VMINNM
62
target/arm: Implement fp16 for Neon VMLA, VMLS operations
63
target/arm: Implement fp16 for Neon VFMA, VMFS
64
target/arm: Implement fp16 for Neon fp compare-vs-0
65
target/arm: Implement fp16 for Neon VRECPS
66
target/arm: Implement fp16 for Neon VRSQRTS
67
target/arm: Implement fp16 for Neon pairwise fp ops
68
target/arm: Implement fp16 for Neon float-integer VCVT
69
target/arm: Convert Neon VCVT fixed-point to gvec
70
target/arm: Implement fp16 for Neon VCVT fixed-point
71
target/arm: Implement fp16 for Neon VCVT with rounding modes
72
target/arm: Implement fp16 for Neon VRINT-with-specified-rounding-mode
73
target/arm: Implement fp16 for Neon VRINTX
74
target/arm/vec_helper: Handle oprsz less than 16 bytes in indexed operations
75
target/arm/vec_helper: Add gvec fp indexed multiply-and-add operations
76
target/arm: Implement fp16 for Neon VMUL, VMLA, VMLS
77
target/arm: Enable FP16 in '-cpu max'
79
78
80
configure | 10 +-
79
target/arm/cpu.h | 7 +-
81
hw/dma/Makefile.objs | 2 +-
80
target/arm/helper.h | 133 ++++++-
82
include/hw/arm/omap.h | 6 +-
81
target/arm/neon-dp.decode | 8 +-
83
include/hw/arm/smmu-common.h | 8 +-
82
target/arm/vfp-uncond.decode | 27 +-
84
include/hw/devices.h | 62 ---
83
target/arm/vfp.decode | 34 +-
85
include/hw/display/blizzard.h | 22 ++
84
hw/arm/sbsa-ref.c | 43 ++-
86
include/hw/display/tc6393xb.h | 24 ++
85
hw/misc/sbsa_ec.c | 98 +++++
87
include/hw/input/gamepad.h | 19 +
86
target/arm/cpu.c | 3 +-
88
include/hw/input/tsc2xxx.h | 36 ++
87
target/arm/cpu64.c | 10 +-
89
include/hw/misc/cbus.h | 32 ++
88
target/arm/helper-a64.c | 11 -
90
include/hw/net/lan9118.h | 21 +
89
target/arm/translate-sve.c | 4 -
91
include/hw/net/ne2000-isa.h | 6 +
90
target/arm/vec_helper.c | 431 ++++++++++++++++++++-
92
include/hw/net/smc91c111.h | 19 +
91
target/arm/vfp_helper.c | 244 +++++-------
93
include/qemu/typedefs.h | 1 -
92
hw/misc/meson.build | 2 +
94
target/arm/cpu.h | 95 ++++-
93
target/arm/translate-neon.c.inc | 755 +++++++++++++------------------------
95
target/arm/helper.h | 5 +
94
target/arm/translate-vfp.c.inc | 810 ++++++++++++++++++++++++++++++++++++----
96
target/arm/translate.h | 3 +
95
16 files changed, 1819 insertions(+), 801 deletions(-)
97
hw/arm/aspeed.c | 13 +-
96
create mode 100644 hw/misc/sbsa_ec.c
98
hw/arm/exynos4_boards.c | 3 +-
99
hw/arm/gumstix.c | 2 +-
100
hw/arm/integratorcp.c | 2 +-
101
hw/arm/kzm.c | 2 +-
102
hw/arm/mainstone.c | 2 +-
103
hw/arm/mps2-tz.c | 3 +-
104
hw/arm/mps2.c | 2 +-
105
hw/arm/nseries.c | 7 +-
106
hw/arm/palm.c | 2 +-
107
hw/arm/realview.c | 3 +-
108
hw/arm/smmu-common.c | 6 +-
109
hw/arm/smmuv3.c | 28 +-
110
hw/arm/stellaris.c | 2 +-
111
hw/arm/tosa.c | 2 +-
112
hw/arm/versatilepb.c | 2 +-
113
hw/arm/vexpress.c | 2 +-
114
hw/display/blizzard.c | 2 +-
115
hw/display/tc6393xb.c | 18 +-
116
hw/input/stellaris_input.c | 2 +-
117
hw/input/tsc2005.c | 2 +-
118
hw/input/tsc210x.c | 4 +-
119
hw/intc/armv7m_nvic.c | 261 +++++++++++++
120
hw/misc/cbus.c | 2 +-
121
hw/net/lan9118.c | 3 +-
122
hw/net/smc91c111.c | 2 +-
123
hw/ssi/xilinx_spips.c | 6 +-
124
target/arm/cpu.c | 20 +
125
target/arm/helper.c | 873 +++++++++++++++++++++++++++++++++++++++---
126
target/arm/machine.c | 16 +
127
target/arm/translate.c | 150 +++++++-
128
target/arm/vfp_helper.c | 8 +
129
MAINTAINERS | 7 +
130
50 files changed, 1595 insertions(+), 235 deletions(-)
131
delete mode 100644 include/hw/devices.h
132
create mode 100644 include/hw/display/blizzard.h
133
create mode 100644 include/hw/display/tc6393xb.h
134
create mode 100644 include/hw/input/gamepad.h
135
create mode 100644 include/hw/input/tsc2xxx.h
136
create mode 100644 include/hw/misc/cbus.h
137
create mode 100644 include/hw/net/lan9118.h
138
create mode 100644 include/hw/net/smc91c111.h
139
97
diff view generated by jsdifflib
1
Move the NS TBFLAG down from bit 19 to bit 6, which has not
1
In several places the target/arm code defines local float constants
2
been used since commit c1e3781090b9d36c60 in 2015, when we
2
for 2, 3 and 1.5, which are also provided by include/fpu/softfloat.h.
3
started passing the entire MMU index in the TB flags rather
3
Remove the unnecessary local duplicate versions.
4
than just a 'privilege level' bit.
5
6
This rearrangement is not strictly necessary, but means that
7
we can put M-profile-only bits next to each other rather
8
than scattered across the flag word.
9
4
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20190416125744.27770-17-peter.maydell@linaro.org
7
Message-id: 20200828183354.27913-2-peter.maydell@linaro.org
13
---
8
---
14
target/arm/cpu.h | 11 ++++++-----
9
target/arm/helper-a64.c | 11 -----------
15
1 file changed, 6 insertions(+), 5 deletions(-)
10
target/arm/translate-sve.c | 4 ----
11
target/arm/vfp_helper.c | 4 ----
12
3 files changed, 19 deletions(-)
16
13
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
16
--- a/target/arm/helper-a64.c
20
+++ b/target/arm/cpu.h
17
+++ b/target/arm/helper-a64.c
21
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
18
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(neon_cgt_f64)(float64 a, float64 b, void *fpstp)
22
FIELD(TBFLAG_A32, THUMB, 0, 1)
19
* versions, these do a fully fused multiply-add or
23
FIELD(TBFLAG_A32, VECLEN, 1, 3)
20
* multiply-add-and-halve.
24
FIELD(TBFLAG_A32, VECSTRIDE, 4, 2)
25
+/*
26
+ * Indicates whether cp register reads and writes by guest code should access
27
+ * the secure or nonsecure bank of banked registers; note that this is not
28
+ * the same thing as the current security state of the processor!
29
+ */
30
+FIELD(TBFLAG_A32, NS, 6, 1)
31
FIELD(TBFLAG_A32, VFPEN, 7, 1)
32
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
33
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
34
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
35
* checks on the other bits at runtime
36
*/
21
*/
37
FIELD(TBFLAG_A32, XSCALE_CPAR, 17, 2)
22
-#define float16_two make_float16(0x4000)
38
-/* Indicates whether cp register reads and writes by guest code should access
23
-#define float16_three make_float16(0x4200)
39
- * the secure or nonsecure bank of banked registers; note that this is not
24
-#define float16_one_point_five make_float16(0x3e00)
40
- * the same thing as the current security state of the processor!
25
-
41
- */
26
-#define float32_two make_float32(0x40000000)
42
-FIELD(TBFLAG_A32, NS, 19, 1)
27
-#define float32_three make_float32(0x40400000)
43
/* For M profile only, Handler (ie not Thread) mode */
28
-#define float32_one_point_five make_float32(0x3fc00000)
44
FIELD(TBFLAG_A32, HANDLER, 21, 1)
29
-
45
/* For M profile only, whether we should generate stack-limit checks */
30
-#define float64_two make_float64(0x4000000000000000ULL)
31
-#define float64_three make_float64(0x4008000000000000ULL)
32
-#define float64_one_point_five make_float64(0x3FF8000000000000ULL)
33
34
uint32_t HELPER(recpsf_f16)(uint32_t a, uint32_t b, void *fpstp)
35
{
36
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate-sve.c
39
+++ b/target/arm/translate-sve.c
40
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME##_zpzi(DisasContext *s, arg_rpri_esz *a) \
41
return true; \
42
}
43
44
-#define float16_two make_float16(0x4000)
45
-#define float32_two make_float32(0x40000000)
46
-#define float64_two make_float64(0x4000000000000000ULL)
47
-
48
DO_FP_IMM(FADD, fadds, half, one)
49
DO_FP_IMM(FSUB, fsubs, half, one)
50
DO_FP_IMM(FMUL, fmuls, half, two)
51
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/vfp_helper.c
54
+++ b/target/arm/vfp_helper.c
55
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
56
return r;
57
}
58
59
-#define float32_two make_float32(0x40000000)
60
-#define float32_three make_float32(0x40400000)
61
-#define float32_one_point_five make_float32(0x3fc00000)
62
-
63
float32 HELPER(recps_f32)(CPUARMState *env, float32 a, float32 b)
64
{
65
float_status *s = &env->vfp.standard_fp_status;
46
--
66
--
47
2.20.1
67
2.20.1
48
68
49
69
diff view generated by jsdifflib
1
The M-profile floating point support has three associated config
1
The aa32_fp16_arith feature check function currently looks at the
2
registers: FPCAR, FPCCR and FPDSCR. It also makes the registers
2
AArch64 ID_AA64PFR0 register. This is (as the comment notes) not
3
CPACR and NSACR have behaviour other than reads-as-zero.
3
correct. The bogus check was put in mostly to allow testing of the
4
Add support for all of these as simple reads-as-written registers.
4
fp16 variants of the VCMLA instructions and it was something of
5
We will hook up actual functionality later.
5
a mistake that we allowed them to exist in master.
6
6
7
The main complexity here is handling the FPCCR register, which
7
Switch the feature check function to testing VMFR1.FPHP, which is
8
has a mix of banked and unbanked bits.
8
what it ought to be.
9
9
10
Note that we don't share storage with the A-profile
10
This will remove emulation of the VCMLA and VCADD insns from
11
cpu->cp15.nsacr and cpu->cp15.cpacr_el1, though the behaviour
11
AArch32 code running on an AArch64 '-cpu max' using system emulation.
12
is quite similar, for two reasons:
12
(They were never enabled for aarch32 linux-user and system-emulation.)
13
* the M profile CPACR is banked between security states
13
Since we weren't advertising their existence via the AArch32 ID
14
* it preserves the invariant that M profile uses no state
14
register, well-behaved guests wouldn't have been using them anyway.
15
inside the cp15 substruct
15
16
Once we have implemented all the AArch32 support for the FP16 extension
17
we will advertise it in the MVFR1 ID register field, which will reenable
18
these insns along with all the others.
16
19
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20190416125744.27770-4-peter.maydell@linaro.org
22
Message-id: 20200828183354.27913-3-peter.maydell@linaro.org
20
---
23
---
21
target/arm/cpu.h | 34 ++++++++++++
24
target/arm/cpu.h | 7 +------
22
hw/intc/armv7m_nvic.c | 125 ++++++++++++++++++++++++++++++++++++++++++
25
1 file changed, 1 insertion(+), 6 deletions(-)
23
target/arm/cpu.c | 5 ++
24
target/arm/machine.c | 16 ++++++
25
4 files changed, 180 insertions(+)
26
26
27
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
28
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/cpu.h
29
--- a/target/arm/cpu.h
30
+++ b/target/arm/cpu.h
30
+++ b/target/arm/cpu.h
31
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
32
uint32_t scr[M_REG_NUM_BANKS];
32
33
uint32_t msplim[M_REG_NUM_BANKS];
33
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
34
uint32_t psplim[M_REG_NUM_BANKS];
34
{
35
+ uint32_t fpcar[M_REG_NUM_BANKS];
35
- /*
36
+ uint32_t fpccr[M_REG_NUM_BANKS];
36
- * This is a placeholder for use by VCMA until the rest of
37
+ uint32_t fpdscr[M_REG_NUM_BANKS];
37
- * the ARMv8.2-FP16 extension is implemented for aa32 mode.
38
+ uint32_t cpacr[M_REG_NUM_BANKS];
38
- * At which point we can properly set and check MVFR1.FPHP.
39
+ uint32_t nsacr;
39
- */
40
} v7m;
40
- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
41
41
+ return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3;
42
/* Information associated with an exception about to be taken:
42
}
43
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CSSELR, LEVEL, 1, 3)
43
44
*/
44
static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id)
45
FIELD(V7M_CSSELR, INDEX, 0, 4)
46
47
+/* v7M FPCCR bits */
48
+FIELD(V7M_FPCCR, LSPACT, 0, 1)
49
+FIELD(V7M_FPCCR, USER, 1, 1)
50
+FIELD(V7M_FPCCR, S, 2, 1)
51
+FIELD(V7M_FPCCR, THREAD, 3, 1)
52
+FIELD(V7M_FPCCR, HFRDY, 4, 1)
53
+FIELD(V7M_FPCCR, MMRDY, 5, 1)
54
+FIELD(V7M_FPCCR, BFRDY, 6, 1)
55
+FIELD(V7M_FPCCR, SFRDY, 7, 1)
56
+FIELD(V7M_FPCCR, MONRDY, 8, 1)
57
+FIELD(V7M_FPCCR, SPLIMVIOL, 9, 1)
58
+FIELD(V7M_FPCCR, UFRDY, 10, 1)
59
+FIELD(V7M_FPCCR, RES0, 11, 15)
60
+FIELD(V7M_FPCCR, TS, 26, 1)
61
+FIELD(V7M_FPCCR, CLRONRETS, 27, 1)
62
+FIELD(V7M_FPCCR, CLRONRET, 28, 1)
63
+FIELD(V7M_FPCCR, LSPENS, 29, 1)
64
+FIELD(V7M_FPCCR, LSPEN, 30, 1)
65
+FIELD(V7M_FPCCR, ASPEN, 31, 1)
66
+/* These bits are banked. Others are non-banked and live in the M_REG_S bank */
67
+#define R_V7M_FPCCR_BANKED_MASK \
68
+ (R_V7M_FPCCR_LSPACT_MASK | \
69
+ R_V7M_FPCCR_USER_MASK | \
70
+ R_V7M_FPCCR_THREAD_MASK | \
71
+ R_V7M_FPCCR_MMRDY_MASK | \
72
+ R_V7M_FPCCR_SPLIMVIOL_MASK | \
73
+ R_V7M_FPCCR_UFRDY_MASK | \
74
+ R_V7M_FPCCR_ASPEN_MASK)
75
+
76
/*
77
* System register ID fields.
78
*/
79
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/hw/intc/armv7m_nvic.c
82
+++ b/hw/intc/armv7m_nvic.c
83
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
84
}
85
case 0xd84: /* CSSELR */
86
return cpu->env.v7m.csselr[attrs.secure];
87
+ case 0xd88: /* CPACR */
88
+ if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
89
+ return 0;
90
+ }
91
+ return cpu->env.v7m.cpacr[attrs.secure];
92
+ case 0xd8c: /* NSACR */
93
+ if (!attrs.secure || !arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
94
+ return 0;
95
+ }
96
+ return cpu->env.v7m.nsacr;
97
/* TODO: Implement debug registers. */
98
case 0xd90: /* MPU_TYPE */
99
/* Unified MPU; if the MPU is not present this value is zero */
100
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
101
return 0;
102
}
103
return cpu->env.v7m.sfar;
104
+ case 0xf34: /* FPCCR */
105
+ if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
106
+ return 0;
107
+ }
108
+ if (attrs.secure) {
109
+ return cpu->env.v7m.fpccr[M_REG_S];
110
+ } else {
111
+ /*
112
+ * NS can read LSPEN, CLRONRET and MONRDY. It can read
113
+ * BFRDY and HFRDY if AIRCR.BFHFNMINS != 0;
114
+ * other non-banked bits RAZ.
115
+ * TODO: MONRDY should RAZ/WI if DEMCR.SDME is set.
116
+ */
117
+ uint32_t value = cpu->env.v7m.fpccr[M_REG_S];
118
+ uint32_t mask = R_V7M_FPCCR_LSPEN_MASK |
119
+ R_V7M_FPCCR_CLRONRET_MASK |
120
+ R_V7M_FPCCR_MONRDY_MASK;
121
+
122
+ if (s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK) {
123
+ mask |= R_V7M_FPCCR_BFRDY_MASK | R_V7M_FPCCR_HFRDY_MASK;
124
+ }
125
+
126
+ value &= mask;
127
+
128
+ value |= cpu->env.v7m.fpccr[M_REG_NS];
129
+ return value;
130
+ }
131
+ case 0xf38: /* FPCAR */
132
+ if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
133
+ return 0;
134
+ }
135
+ return cpu->env.v7m.fpcar[attrs.secure];
136
+ case 0xf3c: /* FPDSCR */
137
+ if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
138
+ return 0;
139
+ }
140
+ return cpu->env.v7m.fpdscr[attrs.secure];
141
case 0xf40: /* MVFR0 */
142
return cpu->isar.mvfr0;
143
case 0xf44: /* MVFR1 */
144
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
145
cpu->env.v7m.csselr[attrs.secure] = value & R_V7M_CSSELR_INDEX_MASK;
146
}
147
break;
148
+ case 0xd88: /* CPACR */
149
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
150
+ /* We implement only the Floating Point extension's CP10/CP11 */
151
+ cpu->env.v7m.cpacr[attrs.secure] = value & (0xf << 20);
152
+ }
153
+ break;
154
+ case 0xd8c: /* NSACR */
155
+ if (attrs.secure && arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
156
+ /* We implement only the Floating Point extension's CP10/CP11 */
157
+ cpu->env.v7m.nsacr = value & (3 << 10);
158
+ }
159
+ break;
160
case 0xd90: /* MPU_TYPE */
161
return; /* RO */
162
case 0xd94: /* MPU_CTRL */
163
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
164
}
165
break;
166
}
167
+ case 0xf34: /* FPCCR */
168
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
169
+ /* Not all bits here are banked. */
170
+ uint32_t fpccr_s;
171
+
172
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
173
+ /* Don't allow setting of bits not present in v7M */
174
+ value &= (R_V7M_FPCCR_LSPACT_MASK |
175
+ R_V7M_FPCCR_USER_MASK |
176
+ R_V7M_FPCCR_THREAD_MASK |
177
+ R_V7M_FPCCR_HFRDY_MASK |
178
+ R_V7M_FPCCR_MMRDY_MASK |
179
+ R_V7M_FPCCR_BFRDY_MASK |
180
+ R_V7M_FPCCR_MONRDY_MASK |
181
+ R_V7M_FPCCR_LSPEN_MASK |
182
+ R_V7M_FPCCR_ASPEN_MASK);
183
+ }
184
+ value &= ~R_V7M_FPCCR_RES0_MASK;
185
+
186
+ if (!attrs.secure) {
187
+ /* Some non-banked bits are configurably writable by NS */
188
+ fpccr_s = cpu->env.v7m.fpccr[M_REG_S];
189
+ if (!(fpccr_s & R_V7M_FPCCR_LSPENS_MASK)) {
190
+ uint32_t lspen = FIELD_EX32(value, V7M_FPCCR, LSPEN);
191
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, LSPEN, lspen);
192
+ }
193
+ if (!(fpccr_s & R_V7M_FPCCR_CLRONRETS_MASK)) {
194
+ uint32_t cor = FIELD_EX32(value, V7M_FPCCR, CLRONRET);
195
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, CLRONRET, cor);
196
+ }
197
+ if ((s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
198
+ uint32_t hfrdy = FIELD_EX32(value, V7M_FPCCR, HFRDY);
199
+ uint32_t bfrdy = FIELD_EX32(value, V7M_FPCCR, BFRDY);
200
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, HFRDY, hfrdy);
201
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, BFRDY, bfrdy);
202
+ }
203
+ /* TODO MONRDY should RAZ/WI if DEMCR.SDME is set */
204
+ {
205
+ uint32_t monrdy = FIELD_EX32(value, V7M_FPCCR, MONRDY);
206
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, MONRDY, monrdy);
207
+ }
208
+
209
+ /*
210
+ * All other non-banked bits are RAZ/WI from NS; write
211
+ * just the banked bits to fpccr[M_REG_NS].
212
+ */
213
+ value &= R_V7M_FPCCR_BANKED_MASK;
214
+ cpu->env.v7m.fpccr[M_REG_NS] = value;
215
+ } else {
216
+ fpccr_s = value;
217
+ }
218
+ cpu->env.v7m.fpccr[M_REG_S] = fpccr_s;
219
+ }
220
+ break;
221
+ case 0xf38: /* FPCAR */
222
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
223
+ value &= ~7;
224
+ cpu->env.v7m.fpcar[attrs.secure] = value;
225
+ }
226
+ break;
227
+ case 0xf3c: /* FPDSCR */
228
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
229
+ value &= 0x07c00000;
230
+ cpu->env.v7m.fpdscr[attrs.secure] = value;
231
+ }
232
+ break;
233
case 0xf50: /* ICIALLU */
234
case 0xf58: /* ICIMVAU */
235
case 0xf5c: /* DCIMVAC */
236
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
237
index XXXXXXX..XXXXXXX 100644
238
--- a/target/arm/cpu.c
239
+++ b/target/arm/cpu.c
240
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
241
env->v7m.ccr[M_REG_S] |= R_V7M_CCR_UNALIGN_TRP_MASK;
242
}
243
244
+ if (arm_feature(env, ARM_FEATURE_VFP)) {
245
+ env->v7m.fpccr[M_REG_NS] = R_V7M_FPCCR_ASPEN_MASK;
246
+ env->v7m.fpccr[M_REG_S] = R_V7M_FPCCR_ASPEN_MASK |
247
+ R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK;
248
+ }
249
/* Unlike A/R profile, M profile defines the reset LR value */
250
env->regs[14] = 0xffffffff;
251
252
diff --git a/target/arm/machine.c b/target/arm/machine.c
253
index XXXXXXX..XXXXXXX 100644
254
--- a/target/arm/machine.c
255
+++ b/target/arm/machine.c
256
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_v8m = {
257
}
258
};
259
260
+static const VMStateDescription vmstate_m_fp = {
261
+ .name = "cpu/m/fp",
262
+ .version_id = 1,
263
+ .minimum_version_id = 1,
264
+ .needed = vfp_needed,
265
+ .fields = (VMStateField[]) {
266
+ VMSTATE_UINT32_ARRAY(env.v7m.fpcar, ARMCPU, M_REG_NUM_BANKS),
267
+ VMSTATE_UINT32_ARRAY(env.v7m.fpccr, ARMCPU, M_REG_NUM_BANKS),
268
+ VMSTATE_UINT32_ARRAY(env.v7m.fpdscr, ARMCPU, M_REG_NUM_BANKS),
269
+ VMSTATE_UINT32_ARRAY(env.v7m.cpacr, ARMCPU, M_REG_NUM_BANKS),
270
+ VMSTATE_UINT32(env.v7m.nsacr, ARMCPU),
271
+ VMSTATE_END_OF_LIST()
272
+ }
273
+};
274
+
275
static const VMStateDescription vmstate_m = {
276
.name = "cpu/m",
277
.version_id = 4,
278
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
279
&vmstate_m_scr,
280
&vmstate_m_other_sp,
281
&vmstate_m_v8m,
282
+ &vmstate_m_fp,
283
NULL
284
}
285
};
286
--
45
--
287
2.20.1
46
2.20.1
288
47
289
48
diff view generated by jsdifflib
New patch
1
1
Implmeent VFP fp16 support for simple binary-operator VFP insns VADD,
2
VSUB, VMUL, VDIV, VMINNM and VMAXNM:
3
4
* make the VFP_BINOP() macro generate float16 helpers as well as
5
float32 and float64
6
* implement a do_vfp_3op_hp() function similar to the existing
7
do_vfp_3op_sp()
8
* add decode for the half-precision insn patterns
9
10
Note that the VFP_BINOP macro use creates a couple of unused helper
11
functions vfp_maxh and vfp_minh, but they're small so it's not worth
12
splitting the BINOP operations into "needs halfprec" and "no
13
halfprec" groups.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20200828183354.27913-4-peter.maydell@linaro.org
18
---
19
target/arm/helper.h | 8 ++++
20
target/arm/vfp-uncond.decode | 3 ++
21
target/arm/vfp.decode | 4 ++
22
target/arm/vfp_helper.c | 5 ++
23
target/arm/translate-vfp.c.inc | 86 ++++++++++++++++++++++++++++++++++
24
5 files changed, 106 insertions(+)
25
26
diff --git a/target/arm/helper.h b/target/arm/helper.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/helper.h
29
+++ b/target/arm/helper.h
30
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(probe_access, TCG_CALL_NO_WG, void, env, tl, i32, i32, i32)
31
DEF_HELPER_1(vfp_get_fpscr, i32, env)
32
DEF_HELPER_2(vfp_set_fpscr, void, env, i32)
33
34
+DEF_HELPER_3(vfp_addh, f16, f16, f16, ptr)
35
DEF_HELPER_3(vfp_adds, f32, f32, f32, ptr)
36
DEF_HELPER_3(vfp_addd, f64, f64, f64, ptr)
37
+DEF_HELPER_3(vfp_subh, f16, f16, f16, ptr)
38
DEF_HELPER_3(vfp_subs, f32, f32, f32, ptr)
39
DEF_HELPER_3(vfp_subd, f64, f64, f64, ptr)
40
+DEF_HELPER_3(vfp_mulh, f16, f16, f16, ptr)
41
DEF_HELPER_3(vfp_muls, f32, f32, f32, ptr)
42
DEF_HELPER_3(vfp_muld, f64, f64, f64, ptr)
43
+DEF_HELPER_3(vfp_divh, f16, f16, f16, ptr)
44
DEF_HELPER_3(vfp_divs, f32, f32, f32, ptr)
45
DEF_HELPER_3(vfp_divd, f64, f64, f64, ptr)
46
+DEF_HELPER_3(vfp_maxh, f16, f16, f16, ptr)
47
DEF_HELPER_3(vfp_maxs, f32, f32, f32, ptr)
48
DEF_HELPER_3(vfp_maxd, f64, f64, f64, ptr)
49
+DEF_HELPER_3(vfp_minh, f16, f16, f16, ptr)
50
DEF_HELPER_3(vfp_mins, f32, f32, f32, ptr)
51
DEF_HELPER_3(vfp_mind, f64, f64, f64, ptr)
52
+DEF_HELPER_3(vfp_maxnumh, f16, f16, f16, ptr)
53
DEF_HELPER_3(vfp_maxnums, f32, f32, f32, ptr)
54
DEF_HELPER_3(vfp_maxnumd, f64, f64, f64, ptr)
55
+DEF_HELPER_3(vfp_minnumh, f16, f16, f16, ptr)
56
DEF_HELPER_3(vfp_minnums, f32, f32, f32, ptr)
57
DEF_HELPER_3(vfp_minnumd, f64, f64, f64, ptr)
58
DEF_HELPER_1(vfp_negs, f32, f32)
59
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/vfp-uncond.decode
62
+++ b/target/arm/vfp-uncond.decode
63
@@ -XXX,XX +XXX,XX @@ VSEL 1111 1110 0. cc:2 .... .... 1010 .0.0 .... \
64
VSEL 1111 1110 0. cc:2 .... .... 1011 .0.0 .... \
65
vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
66
67
+VMAXNM_hp 1111 1110 1.00 .... .... 1001 .0.0 .... @vfp_dnm_s
68
+VMINNM_hp 1111 1110 1.00 .... .... 1001 .1.0 .... @vfp_dnm_s
69
+
70
VMAXNM_sp 1111 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
71
VMINNM_sp 1111 1110 1.00 .... .... 1010 .1.0 .... @vfp_dnm_s
72
73
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
74
index XXXXXXX..XXXXXXX 100644
75
--- a/target/arm/vfp.decode
76
+++ b/target/arm/vfp.decode
77
@@ -XXX,XX +XXX,XX @@ VNMLS_dp ---- 1110 0.01 .... .... 1011 .0.0 .... @vfp_dnm_d
78
VNMLA_sp ---- 1110 0.01 .... .... 1010 .1.0 .... @vfp_dnm_s
79
VNMLA_dp ---- 1110 0.01 .... .... 1011 .1.0 .... @vfp_dnm_d
80
81
+VMUL_hp ---- 1110 0.10 .... .... 1001 .0.0 .... @vfp_dnm_s
82
VMUL_sp ---- 1110 0.10 .... .... 1010 .0.0 .... @vfp_dnm_s
83
VMUL_dp ---- 1110 0.10 .... .... 1011 .0.0 .... @vfp_dnm_d
84
85
VNMUL_sp ---- 1110 0.10 .... .... 1010 .1.0 .... @vfp_dnm_s
86
VNMUL_dp ---- 1110 0.10 .... .... 1011 .1.0 .... @vfp_dnm_d
87
88
+VADD_hp ---- 1110 0.11 .... .... 1001 .0.0 .... @vfp_dnm_s
89
VADD_sp ---- 1110 0.11 .... .... 1010 .0.0 .... @vfp_dnm_s
90
VADD_dp ---- 1110 0.11 .... .... 1011 .0.0 .... @vfp_dnm_d
91
92
+VSUB_hp ---- 1110 0.11 .... .... 1001 .1.0 .... @vfp_dnm_s
93
VSUB_sp ---- 1110 0.11 .... .... 1010 .1.0 .... @vfp_dnm_s
94
VSUB_dp ---- 1110 0.11 .... .... 1011 .1.0 .... @vfp_dnm_d
95
96
+VDIV_hp ---- 1110 1.00 .... .... 1001 .0.0 .... @vfp_dnm_s
97
VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
98
VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
99
100
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/target/arm/vfp_helper.c
103
+++ b/target/arm/vfp_helper.c
104
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val)
105
#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
106
107
#define VFP_BINOP(name) \
108
+dh_ctype_f16 VFP_HELPER(name, h)(dh_ctype_f16 a, dh_ctype_f16 b, void *fpstp) \
109
+{ \
110
+ float_status *fpst = fpstp; \
111
+ return float16_ ## name(a, b, fpst); \
112
+} \
113
float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
114
{ \
115
float_status *fpst = fpstp; \
116
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
117
index XXXXXXX..XXXXXXX 100644
118
--- a/target/arm/translate-vfp.c.inc
119
+++ b/target/arm/translate-vfp.c.inc
120
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn,
121
return true;
122
}
123
124
+static bool do_vfp_3op_hp(DisasContext *s, VFPGen3OpSPFn *fn,
125
+ int vd, int vn, int vm, bool reads_vd)
126
+{
127
+ /*
128
+ * Do a half-precision operation. Functionally this is
129
+ * the same as do_vfp_3op_sp(), except:
130
+ * - it uses the FPST_FPCR_F16
131
+ * - it doesn't need the VFP vector handling (fp16 is a
132
+ * v8 feature, and in v8 VFP vectors don't exist)
133
+ * - it does the aa32_fp16_arith feature test
134
+ */
135
+ TCGv_i32 f0, f1, fd;
136
+ TCGv_ptr fpst;
137
+
138
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
139
+ return false;
140
+ }
141
+
142
+ if (s->vec_len != 0 || s->vec_stride != 0) {
143
+ return false;
144
+ }
145
+
146
+ if (!vfp_access_check(s)) {
147
+ return true;
148
+ }
149
+
150
+ f0 = tcg_temp_new_i32();
151
+ f1 = tcg_temp_new_i32();
152
+ fd = tcg_temp_new_i32();
153
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
154
+
155
+ neon_load_reg32(f0, vn);
156
+ neon_load_reg32(f1, vm);
157
+
158
+ if (reads_vd) {
159
+ neon_load_reg32(fd, vd);
160
+ }
161
+ fn(fd, f0, f1, fpst);
162
+ neon_store_reg32(fd, vd);
163
+
164
+ tcg_temp_free_i32(f0);
165
+ tcg_temp_free_i32(f1);
166
+ tcg_temp_free_i32(fd);
167
+ tcg_temp_free_ptr(fpst);
168
+
169
+ return true;
170
+}
171
+
172
static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
173
int vd, int vn, int vm, bool reads_vd)
174
{
175
@@ -XXX,XX +XXX,XX @@ static bool trans_VNMLA_dp(DisasContext *s, arg_VNMLA_dp *a)
176
return do_vfp_3op_dp(s, gen_VNMLA_dp, a->vd, a->vn, a->vm, true);
177
}
178
179
+static bool trans_VMUL_hp(DisasContext *s, arg_VMUL_sp *a)
180
+{
181
+ return do_vfp_3op_hp(s, gen_helper_vfp_mulh, a->vd, a->vn, a->vm, false);
182
+}
183
+
184
static bool trans_VMUL_sp(DisasContext *s, arg_VMUL_sp *a)
185
{
186
return do_vfp_3op_sp(s, gen_helper_vfp_muls, a->vd, a->vn, a->vm, false);
187
@@ -XXX,XX +XXX,XX @@ static bool trans_VNMUL_dp(DisasContext *s, arg_VNMUL_dp *a)
188
return do_vfp_3op_dp(s, gen_VNMUL_dp, a->vd, a->vn, a->vm, false);
189
}
190
191
+static bool trans_VADD_hp(DisasContext *s, arg_VADD_sp *a)
192
+{
193
+ return do_vfp_3op_hp(s, gen_helper_vfp_addh, a->vd, a->vn, a->vm, false);
194
+}
195
+
196
static bool trans_VADD_sp(DisasContext *s, arg_VADD_sp *a)
197
{
198
return do_vfp_3op_sp(s, gen_helper_vfp_adds, a->vd, a->vn, a->vm, false);
199
@@ -XXX,XX +XXX,XX @@ static bool trans_VADD_dp(DisasContext *s, arg_VADD_dp *a)
200
return do_vfp_3op_dp(s, gen_helper_vfp_addd, a->vd, a->vn, a->vm, false);
201
}
202
203
+static bool trans_VSUB_hp(DisasContext *s, arg_VSUB_sp *a)
204
+{
205
+ return do_vfp_3op_hp(s, gen_helper_vfp_subh, a->vd, a->vn, a->vm, false);
206
+}
207
+
208
static bool trans_VSUB_sp(DisasContext *s, arg_VSUB_sp *a)
209
{
210
return do_vfp_3op_sp(s, gen_helper_vfp_subs, a->vd, a->vn, a->vm, false);
211
@@ -XXX,XX +XXX,XX @@ static bool trans_VSUB_dp(DisasContext *s, arg_VSUB_dp *a)
212
return do_vfp_3op_dp(s, gen_helper_vfp_subd, a->vd, a->vn, a->vm, false);
213
}
214
215
+static bool trans_VDIV_hp(DisasContext *s, arg_VDIV_sp *a)
216
+{
217
+ return do_vfp_3op_hp(s, gen_helper_vfp_divh, a->vd, a->vn, a->vm, false);
218
+}
219
+
220
static bool trans_VDIV_sp(DisasContext *s, arg_VDIV_sp *a)
221
{
222
return do_vfp_3op_sp(s, gen_helper_vfp_divs, a->vd, a->vn, a->vm, false);
223
@@ -XXX,XX +XXX,XX @@ static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_dp *a)
224
return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false);
225
}
226
227
+static bool trans_VMINNM_hp(DisasContext *s, arg_VMINNM_sp *a)
228
+{
229
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
230
+ return false;
231
+ }
232
+ return do_vfp_3op_hp(s, gen_helper_vfp_minnumh,
233
+ a->vd, a->vn, a->vm, false);
234
+}
235
+
236
+static bool trans_VMAXNM_hp(DisasContext *s, arg_VMAXNM_sp *a)
237
+{
238
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
239
+ return false;
240
+ }
241
+ return do_vfp_3op_hp(s, gen_helper_vfp_maxnumh,
242
+ a->vd, a->vn, a->vm, false);
243
+}
244
+
245
static bool trans_VMINNM_sp(DisasContext *s, arg_VMINNM_sp *a)
246
{
247
if (!dc_isar_feature(aa32_vminmaxnm, s)) {
248
--
249
2.20.1
250
251
diff view generated by jsdifflib
New patch
1
1
Implement fp16 versions of the VFP VMLA, VMLS, VNMLS, VNMLA, VNMUL
2
instructions. (These are all the remaining ones which we implement
3
via do_vfp_3op_[hsd]p().)
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200828183354.27913-5-peter.maydell@linaro.org
8
---
9
target/arm/helper.h | 1 +
10
target/arm/vfp.decode | 5 ++
11
target/arm/vfp_helper.c | 5 ++
12
target/arm/translate-vfp.c.inc | 84 ++++++++++++++++++++++++++++++++++
13
4 files changed, 95 insertions(+)
14
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
18
+++ b/target/arm/helper.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_maxnumd, f64, f64, f64, ptr)
20
DEF_HELPER_3(vfp_minnumh, f16, f16, f16, ptr)
21
DEF_HELPER_3(vfp_minnums, f32, f32, f32, ptr)
22
DEF_HELPER_3(vfp_minnumd, f64, f64, f64, ptr)
23
+DEF_HELPER_1(vfp_negh, f16, f16)
24
DEF_HELPER_1(vfp_negs, f32, f32)
25
DEF_HELPER_1(vfp_negd, f64, f64)
26
DEF_HELPER_1(vfp_abss, f32, f32)
27
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/vfp.decode
30
+++ b/target/arm/vfp.decode
31
@@ -XXX,XX +XXX,XX @@ VLDM_VSTM_dp ---- 1101 0.1 l:1 rn:4 .... 1011 imm:8 \
32
vd=%vd_dp p=1 u=0 w=1
33
34
# 3-register VFP data-processing; bits [23,21:20,6] identify the operation.
35
+VMLA_hp ---- 1110 0.00 .... .... 1001 .0.0 .... @vfp_dnm_s
36
VMLA_sp ---- 1110 0.00 .... .... 1010 .0.0 .... @vfp_dnm_s
37
VMLA_dp ---- 1110 0.00 .... .... 1011 .0.0 .... @vfp_dnm_d
38
39
+VMLS_hp ---- 1110 0.00 .... .... 1001 .1.0 .... @vfp_dnm_s
40
VMLS_sp ---- 1110 0.00 .... .... 1010 .1.0 .... @vfp_dnm_s
41
VMLS_dp ---- 1110 0.00 .... .... 1011 .1.0 .... @vfp_dnm_d
42
43
+VNMLS_hp ---- 1110 0.01 .... .... 1001 .0.0 .... @vfp_dnm_s
44
VNMLS_sp ---- 1110 0.01 .... .... 1010 .0.0 .... @vfp_dnm_s
45
VNMLS_dp ---- 1110 0.01 .... .... 1011 .0.0 .... @vfp_dnm_d
46
47
+VNMLA_hp ---- 1110 0.01 .... .... 1001 .1.0 .... @vfp_dnm_s
48
VNMLA_sp ---- 1110 0.01 .... .... 1010 .1.0 .... @vfp_dnm_s
49
VNMLA_dp ---- 1110 0.01 .... .... 1011 .1.0 .... @vfp_dnm_d
50
51
@@ -XXX,XX +XXX,XX @@ VMUL_hp ---- 1110 0.10 .... .... 1001 .0.0 .... @vfp_dnm_s
52
VMUL_sp ---- 1110 0.10 .... .... 1010 .0.0 .... @vfp_dnm_s
53
VMUL_dp ---- 1110 0.10 .... .... 1011 .0.0 .... @vfp_dnm_d
54
55
+VNMUL_hp ---- 1110 0.10 .... .... 1001 .1.0 .... @vfp_dnm_s
56
VNMUL_sp ---- 1110 0.10 .... .... 1010 .1.0 .... @vfp_dnm_s
57
VNMUL_dp ---- 1110 0.10 .... .... 1011 .1.0 .... @vfp_dnm_d
58
59
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/vfp_helper.c
62
+++ b/target/arm/vfp_helper.c
63
@@ -XXX,XX +XXX,XX @@ VFP_BINOP(minnum)
64
VFP_BINOP(maxnum)
65
#undef VFP_BINOP
66
67
+dh_ctype_f16 VFP_HELPER(neg, h)(dh_ctype_f16 a)
68
+{
69
+ return float16_chs(a);
70
+}
71
+
72
float32 VFP_HELPER(neg, s)(float32 a)
73
{
74
return float32_chs(a);
75
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/translate-vfp.c.inc
78
+++ b/target/arm/translate-vfp.c.inc
79
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
80
return true;
81
}
82
83
+static void gen_VMLA_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
84
+{
85
+ /* Note that order of inputs to the add matters for NaNs */
86
+ TCGv_i32 tmp = tcg_temp_new_i32();
87
+
88
+ gen_helper_vfp_mulh(tmp, vn, vm, fpst);
89
+ gen_helper_vfp_addh(vd, vd, tmp, fpst);
90
+ tcg_temp_free_i32(tmp);
91
+}
92
+
93
+static bool trans_VMLA_hp(DisasContext *s, arg_VMLA_sp *a)
94
+{
95
+ return do_vfp_3op_hp(s, gen_VMLA_hp, a->vd, a->vn, a->vm, true);
96
+}
97
+
98
static void gen_VMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
99
{
100
/* Note that order of inputs to the add matters for NaNs */
101
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLA_dp(DisasContext *s, arg_VMLA_dp *a)
102
return do_vfp_3op_dp(s, gen_VMLA_dp, a->vd, a->vn, a->vm, true);
103
}
104
105
+static void gen_VMLS_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
106
+{
107
+ /*
108
+ * VMLS: vd = vd + -(vn * vm)
109
+ * Note that order of inputs to the add matters for NaNs.
110
+ */
111
+ TCGv_i32 tmp = tcg_temp_new_i32();
112
+
113
+ gen_helper_vfp_mulh(tmp, vn, vm, fpst);
114
+ gen_helper_vfp_negh(tmp, tmp);
115
+ gen_helper_vfp_addh(vd, vd, tmp, fpst);
116
+ tcg_temp_free_i32(tmp);
117
+}
118
+
119
+static bool trans_VMLS_hp(DisasContext *s, arg_VMLS_sp *a)
120
+{
121
+ return do_vfp_3op_hp(s, gen_VMLS_hp, a->vd, a->vn, a->vm, true);
122
+}
123
+
124
static void gen_VMLS_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
125
{
126
/*
127
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLS_dp(DisasContext *s, arg_VMLS_dp *a)
128
return do_vfp_3op_dp(s, gen_VMLS_dp, a->vd, a->vn, a->vm, true);
129
}
130
131
+static void gen_VNMLS_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
132
+{
133
+ /*
134
+ * VNMLS: -fd + (fn * fm)
135
+ * Note that it isn't valid to replace (-A + B) with (B - A) or similar
136
+ * plausible looking simplifications because this will give wrong results
137
+ * for NaNs.
138
+ */
139
+ TCGv_i32 tmp = tcg_temp_new_i32();
140
+
141
+ gen_helper_vfp_mulh(tmp, vn, vm, fpst);
142
+ gen_helper_vfp_negh(vd, vd);
143
+ gen_helper_vfp_addh(vd, vd, tmp, fpst);
144
+ tcg_temp_free_i32(tmp);
145
+}
146
+
147
+static bool trans_VNMLS_hp(DisasContext *s, arg_VNMLS_sp *a)
148
+{
149
+ return do_vfp_3op_hp(s, gen_VNMLS_hp, a->vd, a->vn, a->vm, true);
150
+}
151
+
152
static void gen_VNMLS_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
153
{
154
/*
155
@@ -XXX,XX +XXX,XX @@ static bool trans_VNMLS_dp(DisasContext *s, arg_VNMLS_dp *a)
156
return do_vfp_3op_dp(s, gen_VNMLS_dp, a->vd, a->vn, a->vm, true);
157
}
158
159
+static void gen_VNMLA_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
160
+{
161
+ /* VNMLA: -fd + -(fn * fm) */
162
+ TCGv_i32 tmp = tcg_temp_new_i32();
163
+
164
+ gen_helper_vfp_mulh(tmp, vn, vm, fpst);
165
+ gen_helper_vfp_negh(tmp, tmp);
166
+ gen_helper_vfp_negh(vd, vd);
167
+ gen_helper_vfp_addh(vd, vd, tmp, fpst);
168
+ tcg_temp_free_i32(tmp);
169
+}
170
+
171
+static bool trans_VNMLA_hp(DisasContext *s, arg_VNMLA_sp *a)
172
+{
173
+ return do_vfp_3op_hp(s, gen_VNMLA_hp, a->vd, a->vn, a->vm, true);
174
+}
175
+
176
static void gen_VNMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
177
{
178
/* VNMLA: -fd + -(fn * fm) */
179
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_dp(DisasContext *s, arg_VMUL_dp *a)
180
return do_vfp_3op_dp(s, gen_helper_vfp_muld, a->vd, a->vn, a->vm, false);
181
}
182
183
+static void gen_VNMUL_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
184
+{
185
+ /* VNMUL: -(fn * fm) */
186
+ gen_helper_vfp_mulh(vd, vn, vm, fpst);
187
+ gen_helper_vfp_negh(vd, vd);
188
+}
189
+
190
+static bool trans_VNMUL_hp(DisasContext *s, arg_VNMUL_sp *a)
191
+{
192
+ return do_vfp_3op_hp(s, gen_VNMUL_hp, a->vd, a->vn, a->vm, false);
193
+}
194
+
195
static void gen_VNMUL_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
196
{
197
/* VNMUL: -(fn * fm) */
198
--
199
2.20.1
200
201
diff view generated by jsdifflib
New patch
1
Macroify creation of the trans functions for single and double
2
precision VFMA, VFMS, VFNMA, VFNMS. The repetition was OK for
3
two sizes, but we're about to add halfprec and it will get a bit
4
more than seems reasonable.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200828183354.27913-6-peter.maydell@linaro.org
9
---
10
target/arm/translate-vfp.c.inc | 50 +++++++++-------------------------
11
1 file changed, 13 insertions(+), 37 deletions(-)
12
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
18
return true;
19
}
20
21
-static bool trans_VFMA_sp(DisasContext *s, arg_VFMA_sp *a)
22
-{
23
- return do_vfm_sp(s, a, false, false);
24
-}
25
-
26
-static bool trans_VFMS_sp(DisasContext *s, arg_VFMS_sp *a)
27
-{
28
- return do_vfm_sp(s, a, true, false);
29
-}
30
-
31
-static bool trans_VFNMA_sp(DisasContext *s, arg_VFNMA_sp *a)
32
-{
33
- return do_vfm_sp(s, a, false, true);
34
-}
35
-
36
-static bool trans_VFNMS_sp(DisasContext *s, arg_VFNMS_sp *a)
37
-{
38
- return do_vfm_sp(s, a, true, true);
39
-}
40
-
41
static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
42
{
43
/*
44
@@ -XXX,XX +XXX,XX @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
45
return true;
46
}
47
48
-static bool trans_VFMA_dp(DisasContext *s, arg_VFMA_dp *a)
49
-{
50
- return do_vfm_dp(s, a, false, false);
51
-}
52
+#define MAKE_ONE_VFM_TRANS_FN(INSN, PREC, NEGN, NEGD) \
53
+ static bool trans_##INSN##_##PREC(DisasContext *s, \
54
+ arg_##INSN##_##PREC *a) \
55
+ { \
56
+ return do_vfm_##PREC(s, a, NEGN, NEGD); \
57
+ }
58
59
-static bool trans_VFMS_dp(DisasContext *s, arg_VFMS_dp *a)
60
-{
61
- return do_vfm_dp(s, a, true, false);
62
-}
63
+#define MAKE_VFM_TRANS_FNS(PREC) \
64
+ MAKE_ONE_VFM_TRANS_FN(VFMA, PREC, false, false) \
65
+ MAKE_ONE_VFM_TRANS_FN(VFMS, PREC, true, false) \
66
+ MAKE_ONE_VFM_TRANS_FN(VFNMA, PREC, false, true) \
67
+ MAKE_ONE_VFM_TRANS_FN(VFNMS, PREC, true, true)
68
69
-static bool trans_VFNMA_dp(DisasContext *s, arg_VFNMA_dp *a)
70
-{
71
- return do_vfm_dp(s, a, false, true);
72
-}
73
-
74
-static bool trans_VFNMS_dp(DisasContext *s, arg_VFNMS_dp *a)
75
-{
76
- return do_vfm_dp(s, a, true, true);
77
-}
78
+MAKE_VFM_TRANS_FNS(sp)
79
+MAKE_VFM_TRANS_FNS(dp)
80
81
static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
82
{
83
--
84
2.20.1
85
86
diff view generated by jsdifflib
1
Implement the VLSTM instruction for v7M for the FPU present case.
1
Implement VFP fp16 support for fused multiply-add insns
2
VFNMA, VFNMS, VFMA, VFMS.
2
3
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190416125744.27770-25-peter.maydell@linaro.org
6
Message-id: 20200828183354.27913-7-peter.maydell@linaro.org
6
---
7
---
7
target/arm/cpu.h | 2 +
8
target/arm/helper.h | 1 +
8
target/arm/helper.h | 2 +
9
target/arm/vfp.decode | 5 +++
9
target/arm/helper.c | 84 ++++++++++++++++++++++++++++++++++++++++++
10
target/arm/vfp_helper.c | 7 ++++
10
target/arm/translate.c | 15 +++++++-
11
target/arm/translate-vfp.c.inc | 64 ++++++++++++++++++++++++++++++++++
11
4 files changed, 102 insertions(+), 1 deletion(-)
12
4 files changed, 77 insertions(+)
12
13
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
16
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@
18
#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
19
#define EXCP_STKOF 19 /* v8M STKOF UsageFault */
20
#define EXCP_LAZYFP 20 /* v7M fault during lazy FP stacking */
21
+#define EXCP_LSERR 21 /* v8M LSERR SecureFault */
22
+#define EXCP_UNALIGNED 22 /* v7M UNALIGNED UsageFault */
23
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
24
25
#define ARMV7M_EXCP_RESET 1
26
diff --git a/target/arm/helper.h b/target/arm/helper.h
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/helper.h
16
--- a/target/arm/helper.h
29
+++ b/target/arm/helper.h
17
+++ b/target/arm/helper.h
30
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(vfp_fcvt_f64_to_f16, TCG_CALL_NO_RWG, f16, f64, ptr, i32)
31
19
32
DEF_HELPER_1(v7m_preserve_fp_state, void, env)
20
DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
33
21
DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
34
+DEF_HELPER_2(v7m_vlstm, void, env, i32)
22
+DEF_HELPER_4(vfp_muladdh, f16, f16, f16, f16, ptr)
23
24
DEF_HELPER_3(recps_f32, f32, env, f32, f32)
25
DEF_HELPER_3(rsqrts_f32, f32, env, f32, f32)
26
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/vfp.decode
29
+++ b/target/arm/vfp.decode
30
@@ -XXX,XX +XXX,XX @@ VDIV_hp ---- 1110 1.00 .... .... 1001 .0.0 .... @vfp_dnm_s
31
VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
32
VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
33
34
+VFMA_hp ---- 1110 1.10 .... .... 1001 .0. 0 .... @vfp_dnm_s
35
+VFMS_hp ---- 1110 1.10 .... .... 1001 .1. 0 .... @vfp_dnm_s
36
+VFNMA_hp ---- 1110 1.01 .... .... 1001 .0. 0 .... @vfp_dnm_s
37
+VFNMS_hp ---- 1110 1.01 .... .... 1001 .1. 0 .... @vfp_dnm_s
35
+
38
+
36
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
39
VFMA_sp ---- 1110 1.10 .... .... 1010 .0. 0 .... @vfp_dnm_s
37
40
VFMS_sp ---- 1110 1.10 .... .... 1010 .1. 0 .... @vfp_dnm_s
38
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
41
VFNMA_sp ---- 1110 1.01 .... .... 1010 .0. 0 .... @vfp_dnm_s
39
diff --git a/target/arm/helper.c b/target/arm/helper.c
42
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
40
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/helper.c
44
--- a/target/arm/vfp_helper.c
42
+++ b/target/arm/helper.c
45
+++ b/target/arm/vfp_helper.c
43
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_preserve_fp_state)(CPUARMState *env)
46
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(rsqrte_u32)(uint32_t a)
44
g_assert_not_reached();
45
}
47
}
46
48
47
+void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
49
/* VFPv4 fused multiply-accumulate */
50
+dh_ctype_f16 VFP_HELPER(muladd, h)(dh_ctype_f16 a, dh_ctype_f16 b,
51
+ dh_ctype_f16 c, void *fpstp)
48
+{
52
+{
49
+ /* translate.c should never generate calls here in user-only mode */
53
+ float_status *fpst = fpstp;
50
+ g_assert_not_reached();
54
+ return float16_muladd(a, b, c, 0, fpst);
51
+}
55
+}
52
+
56
+
53
uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
57
float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
54
{
58
{
55
/* The TT instructions can be used by unprivileged code, but in
59
float_status *fpst = fpstp;
56
@@ -XXX,XX +XXX,XX @@ static void v7m_update_fpccr(CPUARMState *env, uint32_t frameptr,
60
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
57
}
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/translate-vfp.c.inc
63
+++ b/target/arm/translate-vfp.c.inc
64
@@ -XXX,XX +XXX,XX @@ static bool trans_VMAXNM_dp(DisasContext *s, arg_VMAXNM_dp *a)
65
a->vd, a->vn, a->vm, false);
58
}
66
}
59
67
60
+void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
68
+static bool do_vfm_hp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
61
+{
69
+{
62
+ /* fptr is the value of Rn, the frame pointer we store the FP regs to */
70
+ /*
63
+ bool s = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
71
+ * VFNMA : fd = muladd(-fd, fn, fm)
64
+ bool lspact = env->v7m.fpccr[s] & R_V7M_FPCCR_LSPACT_MASK;
72
+ * VFNMS : fd = muladd(-fd, -fn, fm)
73
+ * VFMA : fd = muladd( fd, fn, fm)
74
+ * VFMS : fd = muladd( fd, -fn, fm)
75
+ *
76
+ * These are fused multiply-add, and must be done as one floating
77
+ * point operation with no rounding between the multiplication and
78
+ * addition steps. NB that doing the negations here as separate
79
+ * steps is correct : an input NaN should come out with its sign
80
+ * bit flipped if it is a negated-input.
81
+ */
82
+ TCGv_ptr fpst;
83
+ TCGv_i32 vn, vm, vd;
65
+
84
+
66
+ assert(env->v7m.secure);
85
+ /*
67
+
86
+ * Present in VFPv4 only, and only with the FP16 extension.
68
+ if (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)) {
87
+ * Note that we can't rely on the SIMDFMAC check alone, because
69
+ return;
88
+ * in a Neon-no-VFP core that ID register field will be non-zero.
89
+ */
90
+ if (!dc_isar_feature(aa32_fp16_arith, s) ||
91
+ !dc_isar_feature(aa32_simdfmac, s) ||
92
+ !dc_isar_feature(aa32_fpsp_v2, s)) {
93
+ return false;
70
+ }
94
+ }
71
+
95
+
72
+ /* Check access to the coprocessor is permitted */
96
+ if (s->vec_len != 0 || s->vec_stride != 0) {
73
+ if (!v7m_cpacr_pass(env, true, arm_current_el(env) != 0)) {
97
+ return false;
74
+ raise_exception_ra(env, EXCP_NOCP, 0, 1, GETPC());
75
+ }
98
+ }
76
+
99
+
77
+ if (lspact) {
100
+ if (!vfp_access_check(s)) {
78
+ /* LSPACT should not be active when there is active FP state */
101
+ return true;
79
+ raise_exception_ra(env, EXCP_LSERR, 0, 1, GETPC());
80
+ }
102
+ }
81
+
103
+
82
+ if (fptr & 7) {
104
+ vn = tcg_temp_new_i32();
83
+ raise_exception_ra(env, EXCP_UNALIGNED, 0, 1, GETPC());
105
+ vm = tcg_temp_new_i32();
106
+ vd = tcg_temp_new_i32();
107
+
108
+ neon_load_reg32(vn, a->vn);
109
+ neon_load_reg32(vm, a->vm);
110
+ if (neg_n) {
111
+ /* VFNMS, VFMS */
112
+ gen_helper_vfp_negh(vn, vn);
84
+ }
113
+ }
114
+ neon_load_reg32(vd, a->vd);
115
+ if (neg_d) {
116
+ /* VFNMA, VFNMS */
117
+ gen_helper_vfp_negh(vd, vd);
118
+ }
119
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
120
+ gen_helper_vfp_muladdh(vd, vn, vm, vd, fpst);
121
+ neon_store_reg32(vd, a->vd);
85
+
122
+
86
+ /*
123
+ tcg_temp_free_ptr(fpst);
87
+ * Note that we do not use v7m_stack_write() here, because the
124
+ tcg_temp_free_i32(vn);
88
+ * accesses should not set the FSR bits for stacking errors if they
125
+ tcg_temp_free_i32(vm);
89
+ * fail. (In pseudocode terms, they are AccType_NORMAL, not AccType_STACK
126
+ tcg_temp_free_i32(vd);
90
+ * or AccType_LAZYFP). Faults in cpu_stl_data() will throw exceptions
91
+ * and longjmp out.
92
+ */
93
+ if (!(env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPEN_MASK)) {
94
+ bool ts = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK;
95
+ int i;
96
+
127
+
97
+ for (i = 0; i < (ts ? 32 : 16); i += 2) {
128
+ return true;
98
+ uint64_t dn = *aa32_vfp_dreg(env, i / 2);
99
+ uint32_t faddr = fptr + 4 * i;
100
+ uint32_t slo = extract64(dn, 0, 32);
101
+ uint32_t shi = extract64(dn, 32, 32);
102
+
103
+ if (i >= 16) {
104
+ faddr += 8; /* skip the slot for the FPSCR */
105
+ }
106
+ cpu_stl_data(env, faddr, slo);
107
+ cpu_stl_data(env, faddr + 4, shi);
108
+ }
109
+ cpu_stl_data(env, fptr + 0x40, vfp_get_fpscr(env));
110
+
111
+ /*
112
+ * If TS is 0 then s0 to s15 and FPSCR are UNKNOWN; we choose to
113
+ * leave them unchanged, matching our choice in v7m_preserve_fp_state.
114
+ */
115
+ if (ts) {
116
+ for (i = 0; i < 32; i += 2) {
117
+ *aa32_vfp_dreg(env, i / 2) = 0;
118
+ }
119
+ vfp_set_fpscr(env, 0);
120
+ }
121
+ } else {
122
+ v7m_update_fpccr(env, fptr, false);
123
+ }
124
+
125
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
126
+}
129
+}
127
+
130
+
128
static bool v7m_push_stack(ARMCPU *cpu)
131
static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
129
{
132
{
130
/* Do the "set up stack frame" part of exception entry,
133
/*
131
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
134
@@ -XXX,XX +XXX,XX @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
132
[EXCP_INVSTATE] = "v7M INVSTATE UsageFault",
135
MAKE_ONE_VFM_TRANS_FN(VFNMA, PREC, false, true) \
133
[EXCP_STKOF] = "v8M STKOF UsageFault",
136
MAKE_ONE_VFM_TRANS_FN(VFNMS, PREC, true, true)
134
[EXCP_LAZYFP] = "v7M exception during lazy FP stacking",
137
135
+ [EXCP_LSERR] = "v8M LSERR UsageFault",
138
+MAKE_VFM_TRANS_FNS(hp)
136
+ [EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
139
MAKE_VFM_TRANS_FNS(sp)
137
};
140
MAKE_VFM_TRANS_FNS(dp)
138
141
139
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
140
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
141
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
142
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_STKOF_MASK;
143
break;
144
+ case EXCP_LSERR:
145
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
146
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
147
+ break;
148
+ case EXCP_UNALIGNED:
149
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
150
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNALIGNED_MASK;
151
+ break;
152
case EXCP_SWI:
153
/* The PC already points to the next instruction. */
154
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC, env->v7m.secure);
155
diff --git a/target/arm/translate.c b/target/arm/translate.c
156
index XXXXXXX..XXXXXXX 100644
157
--- a/target/arm/translate.c
158
+++ b/target/arm/translate.c
159
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
160
if (!s->v8m_secure || (insn & 0x0040f0ff)) {
161
goto illegal_op;
162
}
163
- /* Just NOP since FP support is not implemented */
164
+
165
+ if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
166
+ TCGv_i32 fptr = load_reg(s, rn);
167
+
168
+ if (extract32(insn, 20, 1)) {
169
+ /* VLLDM */
170
+ } else {
171
+ gen_helper_v7m_vlstm(cpu_env, fptr);
172
+ }
173
+ tcg_temp_free_i32(fptr);
174
+
175
+ /* End the TB, because we have updated FP control bits */
176
+ s->base.is_jmp = DISAS_UPDATE;
177
+ }
178
break;
179
}
180
if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
181
--
142
--
182
2.20.1
143
2.20.1
183
144
184
145
diff view generated by jsdifflib
1
Add a new helper function which returns the MMU index to use
1
Macroify the uses of do_vfp_2op_sp() and do_vfp_2op_dp(); this will
2
for v7M, where the caller specifies all of the security
2
make it easier to add the halfprec support.
3
state, privilege level and whether the execution priority
4
is negative, and reimplement the existing
5
arm_v7m_mmu_idx_for_secstate_and_priv() in terms of it.
6
7
We are going to need this for the lazy-FP-stacking code.
8
3
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20190416125744.27770-21-peter.maydell@linaro.org
6
Message-id: 20200828183354.27913-8-peter.maydell@linaro.org
12
---
7
---
13
target/arm/cpu.h | 7 +++++++
8
target/arm/translate-vfp.c.inc | 49 ++++++++++------------------------
14
target/arm/helper.c | 14 +++++++++++---
9
1 file changed, 14 insertions(+), 35 deletions(-)
15
2 files changed, 18 insertions(+), 3 deletions(-)
16
10
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
11
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
18
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
13
--- a/target/arm/translate-vfp.c.inc
20
+++ b/target/arm/cpu.h
14
+++ b/target/arm/translate-vfp.c.inc
21
@@ -XXX,XX +XXX,XX @@ static inline int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
22
}
16
return true;
23
}
17
}
24
18
25
+/*
19
-static bool trans_VMOV_reg_sp(DisasContext *s, arg_VMOV_reg_sp *a)
26
+ * Return the MMU index for a v7M CPU with all relevant information
20
-{
27
+ * manually specified.
21
- return do_vfp_2op_sp(s, tcg_gen_mov_i32, a->vd, a->vm);
28
+ */
22
-}
29
+ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
23
+#define DO_VFP_2OP(INSN, PREC, FN) \
30
+ bool secstate, bool priv, bool negpri);
24
+ static bool trans_##INSN##_##PREC(DisasContext *s, \
31
+
25
+ arg_##INSN##_##PREC *a) \
32
/* Return the MMU index for a v7M CPU in the specified security and
26
+ { \
33
* privilege state.
27
+ return do_vfp_2op_##PREC(s, FN, a->vd, a->vm); \
34
*/
28
+ }
35
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
36
index XXXXXXX..XXXXXXX 100644
30
-static bool trans_VMOV_reg_dp(DisasContext *s, arg_VMOV_reg_dp *a)
37
--- a/target/arm/helper.c
31
-{
38
+++ b/target/arm/helper.c
32
- return do_vfp_2op_dp(s, tcg_gen_mov_i64, a->vd, a->vm);
39
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
33
-}
40
return 0;
34
+DO_VFP_2OP(VMOV_reg, sp, tcg_gen_mov_i32)
35
+DO_VFP_2OP(VMOV_reg, dp, tcg_gen_mov_i64)
36
37
-static bool trans_VABS_sp(DisasContext *s, arg_VABS_sp *a)
38
-{
39
- return do_vfp_2op_sp(s, gen_helper_vfp_abss, a->vd, a->vm);
40
-}
41
+DO_VFP_2OP(VABS, sp, gen_helper_vfp_abss)
42
+DO_VFP_2OP(VABS, dp, gen_helper_vfp_absd)
43
44
-static bool trans_VABS_dp(DisasContext *s, arg_VABS_dp *a)
45
-{
46
- return do_vfp_2op_dp(s, gen_helper_vfp_absd, a->vd, a->vm);
47
-}
48
-
49
-static bool trans_VNEG_sp(DisasContext *s, arg_VNEG_sp *a)
50
-{
51
- return do_vfp_2op_sp(s, gen_helper_vfp_negs, a->vd, a->vm);
52
-}
53
-
54
-static bool trans_VNEG_dp(DisasContext *s, arg_VNEG_dp *a)
55
-{
56
- return do_vfp_2op_dp(s, gen_helper_vfp_negd, a->vd, a->vm);
57
-}
58
+DO_VFP_2OP(VNEG, sp, gen_helper_vfp_negs)
59
+DO_VFP_2OP(VNEG, dp, gen_helper_vfp_negd)
60
61
static void gen_VSQRT_sp(TCGv_i32 vd, TCGv_i32 vm)
62
{
63
gen_helper_vfp_sqrts(vd, vm, cpu_env);
41
}
64
}
42
65
43
-ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
66
-static bool trans_VSQRT_sp(DisasContext *s, arg_VSQRT_sp *a)
44
- bool secstate, bool priv)
67
-{
45
+ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
68
- return do_vfp_2op_sp(s, gen_VSQRT_sp, a->vd, a->vm);
46
+ bool secstate, bool priv, bool negpri)
69
-}
70
-
71
static void gen_VSQRT_dp(TCGv_i64 vd, TCGv_i64 vm)
47
{
72
{
48
ARMMMUIdx mmu_idx = ARM_MMU_IDX_M;
73
gen_helper_vfp_sqrtd(vd, vm, cpu_env);
49
50
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
51
mmu_idx |= ARM_MMU_IDX_M_PRIV;
52
}
53
54
- if (armv7m_nvic_neg_prio_requested(env->nvic, secstate)) {
55
+ if (negpri) {
56
mmu_idx |= ARM_MMU_IDX_M_NEGPRI;
57
}
58
59
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
60
return mmu_idx;
61
}
74
}
62
75
63
+ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
76
-static bool trans_VSQRT_dp(DisasContext *s, arg_VSQRT_dp *a)
64
+ bool secstate, bool priv)
77
-{
65
+{
78
- return do_vfp_2op_dp(s, gen_VSQRT_dp, a->vd, a->vm);
66
+ bool negpri = armv7m_nvic_neg_prio_requested(env->nvic, secstate);
79
-}
67
+
80
+DO_VFP_2OP(VSQRT, sp, gen_VSQRT_sp)
68
+ return arm_v7m_mmu_idx_all(env, secstate, priv, negpri);
81
+DO_VFP_2OP(VSQRT, dp, gen_VSQRT_dp)
69
+}
82
70
+
83
static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a)
71
/* Return the MMU index for a v7M CPU in the specified security state */
72
ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
73
{
84
{
74
--
85
--
75
2.20.1
86
2.20.1
76
87
77
88
diff view generated by jsdifflib
1
The M-profile architecture floating point system supports
1
Implement VFP fp16 for VABS, VNEG and VSQRT. This is all
2
lazy FP state preservation, where FP registers are not
2
the fp16 insns that use the DO_VFP_2OP macro, because there
3
pushed to the stack when an exception occurs but are instead
3
is no fp16 version of VMOV_reg.
4
only saved if and when the first FP instruction in the exception
4
5
handler is executed. Implement this in QEMU, corresponding
5
Notes:
6
to the check of LSPACT in the pseudocode ExecuteFPCheck().
6
* the gen_helper_vfp_negh already exists as we needed to create
7
it for the fp16 multiply-add insns
8
* as usual we need to use the f16 version of the fp_status;
9
this is only relevant for VSQRT
7
10
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20190416125744.27770-24-peter.maydell@linaro.org
13
Message-id: 20200828183354.27913-9-peter.maydell@linaro.org
11
---
14
---
12
target/arm/cpu.h | 3 ++
15
target/arm/helper.h | 2 ++
13
target/arm/helper.h | 2 +
16
target/arm/vfp.decode | 3 +++
14
target/arm/translate.h | 1 +
17
target/arm/vfp_helper.c | 10 +++++++++
15
target/arm/helper.c | 112 +++++++++++++++++++++++++++++++++++++++++
18
target/arm/translate-vfp.c.inc | 40 ++++++++++++++++++++++++++++++++++
16
target/arm/translate.c | 22 ++++++++
19
4 files changed, 55 insertions(+)
17
5 files changed, 140 insertions(+)
18
20
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@
24
#define EXCP_NOCP 17 /* v7M NOCP UsageFault */
25
#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
26
#define EXCP_STKOF 19 /* v8M STKOF UsageFault */
27
+#define EXCP_LAZYFP 20 /* v7M fault during lazy FP stacking */
28
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
29
30
#define ARMV7M_EXCP_RESET 1
31
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
32
FIELD(TBFLAG_A32, VFPEN, 7, 1)
33
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
34
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
35
+/* For M profile only, set if FPCCR.LSPACT is set */
36
+FIELD(TBFLAG_A32, LSPACT, 18, 1)
37
/* For M profile only, set if we must create a new FP context */
38
FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1)
39
/* For M profile only, set if FPCCR.S does not match current security state */
40
diff --git a/target/arm/helper.h b/target/arm/helper.h
21
diff --git a/target/arm/helper.h b/target/arm/helper.h
41
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/helper.h
23
--- a/target/arm/helper.h
43
+++ b/target/arm/helper.h
24
+++ b/target/arm/helper.h
44
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(v7m_blxns, void, env, i32)
25
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_minnumd, f64, f64, f64, ptr)
45
26
DEF_HELPER_1(vfp_negh, f16, f16)
46
DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
27
DEF_HELPER_1(vfp_negs, f32, f32)
47
28
DEF_HELPER_1(vfp_negd, f64, f64)
48
+DEF_HELPER_1(v7m_preserve_fp_state, void, env)
29
+DEF_HELPER_1(vfp_absh, f16, f16)
49
+
30
DEF_HELPER_1(vfp_abss, f32, f32)
50
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
31
DEF_HELPER_1(vfp_absd, f64, f64)
51
32
+DEF_HELPER_2(vfp_sqrth, f16, f16, env)
52
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
33
DEF_HELPER_2(vfp_sqrts, f32, f32, env)
53
diff --git a/target/arm/translate.h b/target/arm/translate.h
34
DEF_HELPER_2(vfp_sqrtd, f64, f64, env)
35
DEF_HELPER_3(vfp_cmps, void, f32, f32, env)
36
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
54
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/translate.h
38
--- a/target/arm/vfp.decode
56
+++ b/target/arm/translate.h
39
+++ b/target/arm/vfp.decode
57
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
40
@@ -XXX,XX +XXX,XX @@ VMOV_imm_dp ---- 1110 1.11 .... .... 1011 0000 .... \
58
bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
41
VMOV_reg_sp ---- 1110 1.11 0000 .... 1010 01.0 .... @vfp_dm_ss
59
bool v8m_fpccr_s_wrong; /* true if v8M FPCCR.S != v8m_secure */
42
VMOV_reg_dp ---- 1110 1.11 0000 .... 1011 01.0 .... @vfp_dm_dd
60
bool v7m_new_fp_ctxt_needed; /* ASPEN set but no active FP context */
43
61
+ bool v7m_lspact; /* FPCCR.LSPACT set */
44
+VABS_hp ---- 1110 1.11 0000 .... 1001 11.0 .... @vfp_dm_ss
62
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
45
VABS_sp ---- 1110 1.11 0000 .... 1010 11.0 .... @vfp_dm_ss
63
* so that top level loop can generate correct syndrome information.
46
VABS_dp ---- 1110 1.11 0000 .... 1011 11.0 .... @vfp_dm_dd
64
*/
47
65
diff --git a/target/arm/helper.c b/target/arm/helper.c
48
+VNEG_hp ---- 1110 1.11 0001 .... 1001 01.0 .... @vfp_dm_ss
49
VNEG_sp ---- 1110 1.11 0001 .... 1010 01.0 .... @vfp_dm_ss
50
VNEG_dp ---- 1110 1.11 0001 .... 1011 01.0 .... @vfp_dm_dd
51
52
+VSQRT_hp ---- 1110 1.11 0001 .... 1001 11.0 .... @vfp_dm_ss
53
VSQRT_sp ---- 1110 1.11 0001 .... 1010 11.0 .... @vfp_dm_ss
54
VSQRT_dp ---- 1110 1.11 0001 .... 1011 11.0 .... @vfp_dm_dd
55
56
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
66
index XXXXXXX..XXXXXXX 100644
57
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/helper.c
58
--- a/target/arm/vfp_helper.c
68
+++ b/target/arm/helper.c
59
+++ b/target/arm/vfp_helper.c
69
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
60
@@ -XXX,XX +XXX,XX @@ float64 VFP_HELPER(neg, d)(float64 a)
70
g_assert_not_reached();
61
return float64_chs(a);
71
}
62
}
72
63
73
+void HELPER(v7m_preserve_fp_state)(CPUARMState *env)
64
+dh_ctype_f16 VFP_HELPER(abs, h)(dh_ctype_f16 a)
74
+{
65
+{
75
+ /* translate.c should never generate calls here in user-only mode */
66
+ return float16_abs(a);
76
+ g_assert_not_reached();
77
+}
67
+}
78
+
68
+
79
uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
69
float32 VFP_HELPER(abs, s)(float32 a)
80
{
70
{
81
/* The TT instructions can be used by unprivileged code, but in
71
return float32_abs(a);
82
@@ -XXX,XX +XXX,XX @@ pend_fault:
72
@@ -XXX,XX +XXX,XX @@ float64 VFP_HELPER(abs, d)(float64 a)
83
return false;
73
return float64_abs(a);
84
}
74
}
85
75
86
+void HELPER(v7m_preserve_fp_state)(CPUARMState *env)
76
+dh_ctype_f16 VFP_HELPER(sqrt, h)(dh_ctype_f16 a, CPUARMState *env)
77
+{
78
+ return float16_sqrt(a, &env->vfp.fp_status_f16);
79
+}
80
+
81
float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
82
{
83
return float32_sqrt(a, &env->vfp.fp_status);
84
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/translate-vfp.c.inc
87
+++ b/target/arm/translate-vfp.c.inc
88
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
89
return true;
90
}
91
92
+static bool do_vfp_2op_hp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
87
+{
93
+{
88
+ /*
94
+ /*
89
+ * Preserve FP state (because LSPACT was set and we are about
95
+ * Do a half-precision operation. Functionally this is
90
+ * to execute an FP instruction). This corresponds to the
96
+ * the same as do_vfp_2op_sp(), except:
91
+ * PreserveFPState() pseudocode.
97
+ * - it doesn't need the VFP vector handling (fp16 is a
92
+ * We may throw an exception if the stacking fails.
98
+ * v8 feature, and in v8 VFP vectors don't exist)
99
+ * - it does the aa32_fp16_arith feature test
93
+ */
100
+ */
94
+ ARMCPU *cpu = arm_env_get_cpu(env);
101
+ TCGv_i32 f0;
95
+ bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
96
+ bool negpri = !(env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_HFRDY_MASK);
97
+ bool is_priv = !(env->v7m.fpccr[is_secure] & R_V7M_FPCCR_USER_MASK);
98
+ bool splimviol = env->v7m.fpccr[is_secure] & R_V7M_FPCCR_SPLIMVIOL_MASK;
99
+ uint32_t fpcar = env->v7m.fpcar[is_secure];
100
+ bool stacked_ok = true;
101
+ bool ts = is_secure && (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK);
102
+ bool take_exception;
103
+
102
+
104
+ /* Take the iothread lock as we are going to touch the NVIC */
103
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
105
+ qemu_mutex_lock_iothread();
104
+ return false;
106
+
107
+ /* Check the background context had access to the FPU */
108
+ if (!v7m_cpacr_pass(env, is_secure, is_priv)) {
109
+ armv7m_nvic_set_pending_lazyfp(env->nvic, ARMV7M_EXCP_USAGE, is_secure);
110
+ env->v7m.cfsr[is_secure] |= R_V7M_CFSR_NOCP_MASK;
111
+ stacked_ok = false;
112
+ } else if (!is_secure && !extract32(env->v7m.nsacr, 10, 1)) {
113
+ armv7m_nvic_set_pending_lazyfp(env->nvic, ARMV7M_EXCP_USAGE, M_REG_S);
114
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
115
+ stacked_ok = false;
116
+ }
105
+ }
117
+
106
+
118
+ if (!splimviol && stacked_ok) {
107
+ if (s->vec_len != 0 || s->vec_stride != 0) {
119
+ /* We only stack if the stack limit wasn't violated */
108
+ return false;
120
+ int i;
121
+ ARMMMUIdx mmu_idx;
122
+
123
+ mmu_idx = arm_v7m_mmu_idx_all(env, is_secure, is_priv, negpri);
124
+ for (i = 0; i < (ts ? 32 : 16); i += 2) {
125
+ uint64_t dn = *aa32_vfp_dreg(env, i / 2);
126
+ uint32_t faddr = fpcar + 4 * i;
127
+ uint32_t slo = extract64(dn, 0, 32);
128
+ uint32_t shi = extract64(dn, 32, 32);
129
+
130
+ if (i >= 16) {
131
+ faddr += 8; /* skip the slot for the FPSCR */
132
+ }
133
+ stacked_ok = stacked_ok &&
134
+ v7m_stack_write(cpu, faddr, slo, mmu_idx, STACK_LAZYFP) &&
135
+ v7m_stack_write(cpu, faddr + 4, shi, mmu_idx, STACK_LAZYFP);
136
+ }
137
+
138
+ stacked_ok = stacked_ok &&
139
+ v7m_stack_write(cpu, fpcar + 0x40,
140
+ vfp_get_fpscr(env), mmu_idx, STACK_LAZYFP);
141
+ }
109
+ }
142
+
110
+
143
+ /*
111
+ if (!vfp_access_check(s)) {
144
+ * We definitely pended an exception, but it's possible that it
112
+ return true;
145
+ * might not be able to be taken now. If its priority permits us
146
+ * to take it now, then we must not update the LSPACT or FP regs,
147
+ * but instead jump out to take the exception immediately.
148
+ * If it's just pending and won't be taken until the current
149
+ * handler exits, then we do update LSPACT and the FP regs.
150
+ */
151
+ take_exception = !stacked_ok &&
152
+ armv7m_nvic_can_take_pending_exception(env->nvic);
153
+
154
+ qemu_mutex_unlock_iothread();
155
+
156
+ if (take_exception) {
157
+ raise_exception_ra(env, EXCP_LAZYFP, 0, 1, GETPC());
158
+ }
113
+ }
159
+
114
+
160
+ env->v7m.fpccr[is_secure] &= ~R_V7M_FPCCR_LSPACT_MASK;
115
+ f0 = tcg_temp_new_i32();
116
+ neon_load_reg32(f0, vm);
117
+ fn(f0, f0);
118
+ neon_store_reg32(f0, vd);
119
+ tcg_temp_free_i32(f0);
161
+
120
+
162
+ if (ts) {
121
+ return true;
163
+ /* Clear s0 to s31 and the FPSCR */
164
+ int i;
165
+
166
+ for (i = 0; i < 32; i += 2) {
167
+ *aa32_vfp_dreg(env, i / 2) = 0;
168
+ }
169
+ vfp_set_fpscr(env, 0);
170
+ }
171
+ /*
172
+ * Otherwise s0 to s15 and FPSCR are UNKNOWN; we choose to leave them
173
+ * unchanged.
174
+ */
175
+}
122
+}
176
+
123
+
177
/* Write to v7M CONTROL.SPSEL bit for the specified security bank.
124
static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
178
* This may change the current stack pointer between Main and Process
125
{
179
* stack pointers if it is done for the CONTROL register for the current
126
uint32_t delta_m = 0;
180
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
127
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
181
[EXCP_NOCP] = "v7M NOCP UsageFault",
128
DO_VFP_2OP(VMOV_reg, sp, tcg_gen_mov_i32)
182
[EXCP_INVSTATE] = "v7M INVSTATE UsageFault",
129
DO_VFP_2OP(VMOV_reg, dp, tcg_gen_mov_i64)
183
[EXCP_STKOF] = "v8M STKOF UsageFault",
130
184
+ [EXCP_LAZYFP] = "v7M exception during lazy FP stacking",
131
+DO_VFP_2OP(VABS, hp, gen_helper_vfp_absh)
185
};
132
DO_VFP_2OP(VABS, sp, gen_helper_vfp_abss)
186
133
DO_VFP_2OP(VABS, dp, gen_helper_vfp_absd)
187
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
134
188
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
135
+DO_VFP_2OP(VNEG, hp, gen_helper_vfp_negh)
189
return;
136
DO_VFP_2OP(VNEG, sp, gen_helper_vfp_negs)
190
}
137
DO_VFP_2OP(VNEG, dp, gen_helper_vfp_negd)
191
break;
138
192
+ case EXCP_LAZYFP:
139
+static void gen_VSQRT_hp(TCGv_i32 vd, TCGv_i32 vm)
193
+ /*
140
+{
194
+ * We already pended the specific exception in the NVIC in the
141
+ gen_helper_vfp_sqrth(vd, vm, cpu_env);
195
+ * v7m_preserve_fp_state() helper function.
142
+}
196
+ */
197
+ break;
198
default:
199
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
200
return; /* Never happens. Keep compiler happy. */
201
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
202
flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
203
}
204
205
+ if (arm_feature(env, ARM_FEATURE_M)) {
206
+ bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
207
+
143
+
208
+ if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
144
static void gen_VSQRT_sp(TCGv_i32 vd, TCGv_i32 vm)
209
+ flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
145
{
210
+ }
146
gen_helper_vfp_sqrts(vd, vm, cpu_env);
211
+ }
147
@@ -XXX,XX +XXX,XX @@ static void gen_VSQRT_dp(TCGv_i64 vd, TCGv_i64 vm)
212
+
148
gen_helper_vfp_sqrtd(vd, vm, cpu_env);
213
*pflags = flags;
214
*cs_base = 0;
215
}
149
}
216
diff --git a/target/arm/translate.c b/target/arm/translate.c
150
217
index XXXXXXX..XXXXXXX 100644
151
+DO_VFP_2OP(VSQRT, hp, gen_VSQRT_hp)
218
--- a/target/arm/translate.c
152
DO_VFP_2OP(VSQRT, sp, gen_VSQRT_sp)
219
+++ b/target/arm/translate.c
153
DO_VFP_2OP(VSQRT, dp, gen_VSQRT_dp)
220
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
221
if (arm_dc_feature(s, ARM_FEATURE_M)) {
222
/* Handle M-profile lazy FP state mechanics */
223
224
+ /* Trigger lazy-state preservation if necessary */
225
+ if (s->v7m_lspact) {
226
+ /*
227
+ * Lazy state saving affects external memory and also the NVIC,
228
+ * so we must mark it as an IO operation for icount.
229
+ */
230
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
231
+ gen_io_start();
232
+ }
233
+ gen_helper_v7m_preserve_fp_state(cpu_env);
234
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
235
+ gen_io_end();
236
+ }
237
+ /*
238
+ * If the preserve_fp_state helper doesn't throw an exception
239
+ * then it will clear LSPACT; we don't need to repeat this for
240
+ * any further FP insns in this TB.
241
+ */
242
+ s->v7m_lspact = false;
243
+ }
244
+
245
/* Update ownership of FP context: set FPCCR.S to match current state */
246
if (s->v8m_fpccr_s_wrong) {
247
TCGv_i32 tmp;
248
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
249
dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
250
dc->v7m_new_fp_ctxt_needed =
251
FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
252
+ dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
253
dc->cp_regs = cpu->cp_regs;
254
dc->features = env->features;
255
154
256
--
155
--
257
2.20.1
156
2.20.1
258
157
259
158
diff view generated by jsdifflib
New patch
1
Implement VFP fp16 support for the VMOV immediate insn.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200828183354.27913-10-peter.maydell@linaro.org
6
---
7
target/arm/vfp.decode | 2 ++
8
target/arm/translate-vfp.c.inc | 22 ++++++++++++++++++++++
9
2 files changed, 24 insertions(+)
10
11
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/vfp.decode
14
+++ b/target/arm/vfp.decode
15
@@ -XXX,XX +XXX,XX @@ VFMS_dp ---- 1110 1.10 .... .... 1011 .1.0 .... @vfp_dnm_d
16
VFNMA_dp ---- 1110 1.01 .... .... 1011 .0.0 .... @vfp_dnm_d
17
VFNMS_dp ---- 1110 1.01 .... .... 1011 .1.0 .... @vfp_dnm_d
18
19
+VMOV_imm_hp ---- 1110 1.11 .... .... 1001 0000 .... \
20
+ vd=%vd_sp imm=%vmov_imm
21
VMOV_imm_sp ---- 1110 1.11 .... .... 1010 0000 .... \
22
vd=%vd_sp imm=%vmov_imm
23
VMOV_imm_dp ---- 1110 1.11 .... .... 1011 0000 .... \
24
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/translate-vfp.c.inc
27
+++ b/target/arm/translate-vfp.c.inc
28
@@ -XXX,XX +XXX,XX @@ MAKE_VFM_TRANS_FNS(hp)
29
MAKE_VFM_TRANS_FNS(sp)
30
MAKE_VFM_TRANS_FNS(dp)
31
32
+static bool trans_VMOV_imm_hp(DisasContext *s, arg_VMOV_imm_sp *a)
33
+{
34
+ TCGv_i32 fd;
35
+
36
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
37
+ return false;
38
+ }
39
+
40
+ if (s->vec_len != 0 || s->vec_stride != 0) {
41
+ return false;
42
+ }
43
+
44
+ if (!vfp_access_check(s)) {
45
+ return true;
46
+ }
47
+
48
+ fd = tcg_const_i32(vfp_expand_imm(MO_16, a->imm));
49
+ neon_store_reg32(fd, a->vd);
50
+ tcg_temp_free_i32(fd);
51
+ return true;
52
+}
53
+
54
static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
55
{
56
uint32_t delta_d = 0;
57
--
58
2.20.1
59
60
diff view generated by jsdifflib
New patch
1
Implement fp16 version of VCMP.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200828183354.27913-11-peter.maydell@linaro.org
6
---
7
target/arm/helper.h | 2 ++
8
target/arm/vfp.decode | 2 ++
9
target/arm/vfp_helper.c | 15 +++++++------
10
target/arm/translate-vfp.c.inc | 39 ++++++++++++++++++++++++++++++++++
11
4 files changed, 51 insertions(+), 7 deletions(-)
12
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
16
+++ b/target/arm/helper.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(vfp_absd, f64, f64)
18
DEF_HELPER_2(vfp_sqrth, f16, f16, env)
19
DEF_HELPER_2(vfp_sqrts, f32, f32, env)
20
DEF_HELPER_2(vfp_sqrtd, f64, f64, env)
21
+DEF_HELPER_3(vfp_cmph, void, f16, f16, env)
22
DEF_HELPER_3(vfp_cmps, void, f32, f32, env)
23
DEF_HELPER_3(vfp_cmpd, void, f64, f64, env)
24
+DEF_HELPER_3(vfp_cmpeh, void, f16, f16, env)
25
DEF_HELPER_3(vfp_cmpes, void, f32, f32, env)
26
DEF_HELPER_3(vfp_cmped, void, f64, f64, env)
27
28
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/vfp.decode
31
+++ b/target/arm/vfp.decode
32
@@ -XXX,XX +XXX,XX @@ VSQRT_hp ---- 1110 1.11 0001 .... 1001 11.0 .... @vfp_dm_ss
33
VSQRT_sp ---- 1110 1.11 0001 .... 1010 11.0 .... @vfp_dm_ss
34
VSQRT_dp ---- 1110 1.11 0001 .... 1011 11.0 .... @vfp_dm_dd
35
36
+VCMP_hp ---- 1110 1.11 010 z:1 .... 1001 e:1 1.0 .... \
37
+ vd=%vd_sp vm=%vm_sp
38
VCMP_sp ---- 1110 1.11 010 z:1 .... 1010 e:1 1.0 .... \
39
vd=%vd_sp vm=%vm_sp
40
VCMP_dp ---- 1110 1.11 010 z:1 .... 1011 e:1 1.0 .... \
41
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/vfp_helper.c
44
+++ b/target/arm/vfp_helper.c
45
@@ -XXX,XX +XXX,XX @@ static void softfloat_to_vfp_compare(CPUARMState *env, FloatRelation cmp)
46
}
47
48
/* XXX: check quiet/signaling case */
49
-#define DO_VFP_cmp(p, type) \
50
-void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
51
+#define DO_VFP_cmp(P, FLOATTYPE, ARGTYPE, FPST) \
52
+void VFP_HELPER(cmp, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \
53
{ \
54
softfloat_to_vfp_compare(env, \
55
- type ## _compare_quiet(a, b, &env->vfp.fp_status)); \
56
+ FLOATTYPE ## _compare_quiet(a, b, &env->vfp.FPST)); \
57
} \
58
-void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
59
+void VFP_HELPER(cmpe, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \
60
{ \
61
softfloat_to_vfp_compare(env, \
62
- type ## _compare(a, b, &env->vfp.fp_status)); \
63
+ FLOATTYPE ## _compare(a, b, &env->vfp.FPST)); \
64
}
65
-DO_VFP_cmp(s, float32)
66
-DO_VFP_cmp(d, float64)
67
+DO_VFP_cmp(h, float16, dh_ctype_f16, fp_status_f16)
68
+DO_VFP_cmp(s, float32, float32, fp_status)
69
+DO_VFP_cmp(d, float64, float64, fp_status)
70
#undef DO_VFP_cmp
71
72
/* Integer to float and float to integer conversions */
73
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
74
index XXXXXXX..XXXXXXX 100644
75
--- a/target/arm/translate-vfp.c.inc
76
+++ b/target/arm/translate-vfp.c.inc
77
@@ -XXX,XX +XXX,XX @@ DO_VFP_2OP(VSQRT, hp, gen_VSQRT_hp)
78
DO_VFP_2OP(VSQRT, sp, gen_VSQRT_sp)
79
DO_VFP_2OP(VSQRT, dp, gen_VSQRT_dp)
80
81
+static bool trans_VCMP_hp(DisasContext *s, arg_VCMP_sp *a)
82
+{
83
+ TCGv_i32 vd, vm;
84
+
85
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
86
+ return false;
87
+ }
88
+
89
+ /* Vm/M bits must be zero for the Z variant */
90
+ if (a->z && a->vm != 0) {
91
+ return false;
92
+ }
93
+
94
+ if (!vfp_access_check(s)) {
95
+ return true;
96
+ }
97
+
98
+ vd = tcg_temp_new_i32();
99
+ vm = tcg_temp_new_i32();
100
+
101
+ neon_load_reg32(vd, a->vd);
102
+ if (a->z) {
103
+ tcg_gen_movi_i32(vm, 0);
104
+ } else {
105
+ neon_load_reg32(vm, a->vm);
106
+ }
107
+
108
+ if (a->e) {
109
+ gen_helper_vfp_cmpeh(vd, vm, cpu_env);
110
+ } else {
111
+ gen_helper_vfp_cmph(vd, vm, cpu_env);
112
+ }
113
+
114
+ tcg_temp_free_i32(vd);
115
+ tcg_temp_free_i32(vm);
116
+
117
+ return true;
118
+}
119
+
120
static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a)
121
{
122
TCGv_i32 vd, vm;
123
--
124
2.20.1
125
126
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
Implement the fp16 versions of the VFP VLDR/VSTR (immediate).
2
2
3
This commit finally deletes "hw/devices.h".
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200828183354.27913-12-peter.maydell@linaro.org
6
---
7
target/arm/vfp.decode | 3 +--
8
target/arm/translate-vfp.c.inc | 35 ++++++++++++++++++++++++++++++++++
9
2 files changed, 36 insertions(+), 2 deletions(-)
4
10
5
Reviewed-by: Markus Armbruster <armbru@redhat.com>
11
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
index XXXXXXX..XXXXXXX 100644
7
Message-id: 20190412165416.7977-13-philmd@redhat.com
13
--- a/target/arm/vfp.decode
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
+++ b/target/arm/vfp.decode
9
---
15
@@ -XXX,XX +XXX,XX @@ VMOV_single ---- 1110 000 l:1 .... rt:4 1010 . 001 0000 vn=%vn_sp
10
include/hw/devices.h | 11 -----------
16
VMOV_64_sp ---- 1100 010 op:1 rt2:4 rt:4 1010 00.1 .... vm=%vm_sp
11
include/hw/net/smc91c111.h | 19 +++++++++++++++++++
17
VMOV_64_dp ---- 1100 010 op:1 rt2:4 rt:4 1011 00.1 .... vm=%vm_dp
12
hw/arm/gumstix.c | 2 +-
18
13
hw/arm/integratorcp.c | 2 +-
19
-# Note that the half-precision variants of VLDR and VSTR are
14
hw/arm/mainstone.c | 2 +-
20
-# not part of this decodetree at all because they have bits [9:8] == 0b01
15
hw/arm/realview.c | 2 +-
21
+VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
16
hw/arm/versatilepb.c | 2 +-
22
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
17
hw/net/smc91c111.c | 2 +-
23
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
18
8 files changed, 25 insertions(+), 17 deletions(-)
24
19
delete mode 100644 include/hw/devices.h
25
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
20
create mode 100644 include/hw/net/smc91c111.h
26
index XXXXXXX..XXXXXXX 100644
21
27
--- a/target/arm/translate-vfp.c.inc
22
diff --git a/include/hw/devices.h b/include/hw/devices.h
28
+++ b/target/arm/translate-vfp.c.inc
23
deleted file mode 100644
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_dp *a)
24
index XXXXXXX..XXXXXXX
30
return true;
25
--- a/include/hw/devices.h
31
}
26
+++ /dev/null
32
27
@@ -XXX,XX +XXX,XX @@
33
+static bool trans_VLDR_VSTR_hp(DisasContext *s, arg_VLDR_VSTR_sp *a)
28
-#ifndef QEMU_DEVICES_H
34
+{
29
-#define QEMU_DEVICES_H
35
+ uint32_t offset;
30
-
36
+ TCGv_i32 addr, tmp;
31
-/* Devices that have nowhere better to go. */
32
-
33
-#include "hw/hw.h"
34
-
35
-/* smc91c111.c */
36
-void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
37
-
38
-#endif
39
diff --git a/include/hw/net/smc91c111.h b/include/hw/net/smc91c111.h
40
new file mode 100644
41
index XXXXXXX..XXXXXXX
42
--- /dev/null
43
+++ b/include/hw/net/smc91c111.h
44
@@ -XXX,XX +XXX,XX @@
45
+/*
46
+ * SMSC 91C111 Ethernet interface emulation
47
+ *
48
+ * Copyright (c) 2005 CodeSourcery, LLC.
49
+ * Written by Paul Brook
50
+ *
51
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
52
+ * See the COPYING file in the top-level directory.
53
+ */
54
+
37
+
55
+#ifndef HW_NET_SMC91C111_H
38
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
56
+#define HW_NET_SMC91C111_H
39
+ return false;
40
+ }
57
+
41
+
58
+#include "hw/irq.h"
42
+ if (!vfp_access_check(s)) {
59
+#include "net/net.h"
43
+ return true;
44
+ }
60
+
45
+
61
+void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
46
+ /* imm8 field is offset/2 for fp16, unlike fp32 and fp64 */
47
+ offset = a->imm << 1;
48
+ if (!a->u) {
49
+ offset = -offset;
50
+ }
62
+
51
+
63
+#endif
52
+ /* For thumb, use of PC is UNPREDICTABLE. */
64
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
53
+ addr = add_reg_for_lit(s, a->rn, offset);
65
index XXXXXXX..XXXXXXX 100644
54
+ tmp = tcg_temp_new_i32();
66
--- a/hw/arm/gumstix.c
55
+ if (a->l) {
67
+++ b/hw/arm/gumstix.c
56
+ gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
68
@@ -XXX,XX +XXX,XX @@
57
+ neon_store_reg32(tmp, a->vd);
69
#include "hw/arm/pxa.h"
58
+ } else {
70
#include "net/net.h"
59
+ neon_load_reg32(tmp, a->vd);
71
#include "hw/block/flash.h"
60
+ gen_aa32_st16(s, tmp, addr, get_mem_index(s));
72
-#include "hw/devices.h"
61
+ }
73
+#include "hw/net/smc91c111.h"
62
+ tcg_temp_free_i32(tmp);
74
#include "hw/boards.h"
63
+ tcg_temp_free_i32(addr);
75
#include "exec/address-spaces.h"
64
+
76
#include "sysemu/qtest.h"
65
+ return true;
77
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
66
+}
78
index XXXXXXX..XXXXXXX 100644
67
+
79
--- a/hw/arm/integratorcp.c
68
static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a)
80
+++ b/hw/arm/integratorcp.c
69
{
81
@@ -XXX,XX +XXX,XX @@
70
uint32_t offset;
82
#include "qemu-common.h"
83
#include "cpu.h"
84
#include "hw/sysbus.h"
85
-#include "hw/devices.h"
86
#include "hw/boards.h"
87
#include "hw/arm/arm.h"
88
#include "hw/misc/arm_integrator_debug.h"
89
+#include "hw/net/smc91c111.h"
90
#include "net/net.h"
91
#include "exec/address-spaces.h"
92
#include "sysemu/sysemu.h"
93
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/hw/arm/mainstone.c
96
+++ b/hw/arm/mainstone.c
97
@@ -XXX,XX +XXX,XX @@
98
#include "hw/arm/pxa.h"
99
#include "hw/arm/arm.h"
100
#include "net/net.h"
101
-#include "hw/devices.h"
102
+#include "hw/net/smc91c111.h"
103
#include "hw/boards.h"
104
#include "hw/block/flash.h"
105
#include "hw/sysbus.h"
106
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/hw/arm/realview.c
109
+++ b/hw/arm/realview.c
110
@@ -XXX,XX +XXX,XX @@
111
#include "hw/sysbus.h"
112
#include "hw/arm/arm.h"
113
#include "hw/arm/primecell.h"
114
-#include "hw/devices.h"
115
#include "hw/net/lan9118.h"
116
+#include "hw/net/smc91c111.h"
117
#include "hw/pci/pci.h"
118
#include "net/net.h"
119
#include "sysemu/sysemu.h"
120
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/arm/versatilepb.c
123
+++ b/hw/arm/versatilepb.c
124
@@ -XXX,XX +XXX,XX @@
125
#include "cpu.h"
126
#include "hw/sysbus.h"
127
#include "hw/arm/arm.h"
128
-#include "hw/devices.h"
129
+#include "hw/net/smc91c111.h"
130
#include "net/net.h"
131
#include "sysemu/sysemu.h"
132
#include "hw/pci/pci.h"
133
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/hw/net/smc91c111.c
136
+++ b/hw/net/smc91c111.c
137
@@ -XXX,XX +XXX,XX @@
138
#include "qemu/osdep.h"
139
#include "hw/sysbus.h"
140
#include "net/net.h"
141
-#include "hw/devices.h"
142
+#include "hw/net/smc91c111.h"
143
#include "qemu/log.h"
144
/* For crc32 */
145
#include <zlib.h>
146
--
71
--
147
2.20.1
72
2.20.1
148
73
149
74
diff view generated by jsdifflib
1
Implement the code which updates the FPCCR register on an
1
Implement the fp16 versions of the VFP VCVT instruction forms which
2
exception entry where we are going to use lazy FP stacking.
2
convert between floating point and integer.
3
We have to defer to the NVIC to determine whether the
4
various exceptions are currently ready or not.
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20190416125744.27770-12-peter.maydell@linaro.org
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-13-peter.maydell@linaro.org
8
---
7
---
9
target/arm/cpu.h | 14 +++++++++
8
target/arm/vfp.decode | 4 +++
10
hw/intc/armv7m_nvic.c | 34 ++++++++++++++++++++++
9
target/arm/translate-vfp.c.inc | 65 ++++++++++++++++++++++++++++++++++
11
target/arm/helper.c | 67 ++++++++++++++++++++++++++++++++++++++++++-
10
2 files changed, 69 insertions(+)
12
3 files changed, 114 insertions(+), 1 deletion(-)
13
11
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
14
--- a/target/arm/vfp.decode
17
+++ b/target/arm/cpu.h
15
+++ b/target/arm/vfp.decode
18
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque);
16
@@ -XXX,XX +XXX,XX @@ VCVT_sp ---- 1110 1.11 0111 .... 1010 11.0 .... @vfp_dm_ds
19
* (Ignoring -1, this is the same as the RETTOBASE value before completion.)
17
VCVT_dp ---- 1110 1.11 0111 .... 1011 11.0 .... @vfp_dm_sd
20
*/
18
21
int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure);
19
# VCVT from integer to floating point: Vm always single; Vd depends on size
22
+/**
20
+VCVT_int_hp ---- 1110 1.11 1000 .... 1001 s:1 1.0 .... \
23
+ * armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
21
+ vd=%vd_sp vm=%vm_sp
24
+ * @opaque: the NVIC
22
VCVT_int_sp ---- 1110 1.11 1000 .... 1010 s:1 1.0 .... \
25
+ * @irq: the exception number to mark pending
23
vd=%vd_sp vm=%vm_sp
26
+ * @secure: false for non-banked exceptions or for the nonsecure
24
VCVT_int_dp ---- 1110 1.11 1000 .... 1011 s:1 1.0 .... \
27
+ * version of a banked exception, true for the secure version of a banked
25
@@ -XXX,XX +XXX,XX @@ VCVT_fix_dp ---- 1110 1.11 1.1. .... 1011 .1.0 .... \
28
+ * exception.
26
vd=%vd_dp imm=%vm_sp opc=%vcvt_fix_op
29
+ *
27
30
+ * Return whether an exception is "ready", i.e. whether the exception is
28
# VCVT float to integer (VCVT and VCVTR): Vd always single; Vd depends on size
31
+ * enabled and is configured at a priority which would allow it to
29
+VCVT_hp_int ---- 1110 1.11 110 s:1 .... 1001 rz:1 1.0 .... \
32
+ * interrupt the current execution priority. This controls whether the
30
+ vd=%vd_sp vm=%vm_sp
33
+ * RDY bit for it in the FPCCR is set.
31
VCVT_sp_int ---- 1110 1.11 110 s:1 .... 1010 rz:1 1.0 .... \
34
+ */
32
vd=%vd_sp vm=%vm_sp
35
+bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure);
33
VCVT_dp_int ---- 1110 1.11 110 s:1 .... 1011 rz:1 1.0 .... \
36
/**
34
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
37
* armv7m_nvic_raw_execution_priority: return the raw execution priority
38
* @opaque: the NVIC
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
36
--- a/target/arm/translate-vfp.c.inc
42
+++ b/hw/intc/armv7m_nvic.c
37
+++ b/target/arm/translate-vfp.c.inc
43
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
44
return ret;
39
return true;
45
}
40
}
46
41
47
+bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
42
+static bool trans_VCVT_int_hp(DisasContext *s, arg_VCVT_int_sp *a)
48
+{
43
+{
49
+ /*
44
+ TCGv_i32 vm;
50
+ * Return whether an exception is "ready", i.e. it is enabled and is
45
+ TCGv_ptr fpst;
51
+ * configured at a priority which would allow it to interrupt the
52
+ * current execution priority.
53
+ *
54
+ * irq and secure have the same semantics as for armv7m_nvic_set_pending():
55
+ * for non-banked exceptions secure is always false; for banked exceptions
56
+ * it indicates which of the exceptions is required.
57
+ */
58
+ NVICState *s = (NVICState *)opaque;
59
+ bool banked = exc_is_banked(irq);
60
+ VecInfo *vec;
61
+ int running = nvic_exec_prio(s);
62
+
46
+
63
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
47
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
64
+ assert(!secure || banked);
48
+ return false;
65
+
66
+ /*
67
+ * HardFault is an odd special case: we always check against -1,
68
+ * even if we're secure and HardFault has priority -3; we never
69
+ * need to check for enabled state.
70
+ */
71
+ if (irq == ARMV7M_EXCP_HARD) {
72
+ return running > -1;
73
+ }
49
+ }
74
+
50
+
75
+ vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
51
+ if (!vfp_access_check(s)) {
52
+ return true;
53
+ }
76
+
54
+
77
+ return vec->enabled &&
55
+ vm = tcg_temp_new_i32();
78
+ exc_group_prio(s, vec->prio, secure) < running;
56
+ neon_load_reg32(vm, a->vm);
57
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
58
+ if (a->s) {
59
+ /* i32 -> f16 */
60
+ gen_helper_vfp_sitoh(vm, vm, fpst);
61
+ } else {
62
+ /* u32 -> f16 */
63
+ gen_helper_vfp_uitoh(vm, vm, fpst);
64
+ }
65
+ neon_store_reg32(vm, a->vd);
66
+ tcg_temp_free_i32(vm);
67
+ tcg_temp_free_ptr(fpst);
68
+ return true;
79
+}
69
+}
80
+
70
+
81
/* callback when external interrupt line is changed */
71
static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a)
82
static void set_irq_level(void *opaque, int n, int level)
83
{
72
{
84
diff --git a/target/arm/helper.c b/target/arm/helper.c
73
TCGv_i32 vm;
85
index XXXXXXX..XXXXXXX 100644
74
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
86
--- a/target/arm/helper.c
75
return true;
87
+++ b/target/arm/helper.c
88
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
89
env->thumb = addr & 1;
90
}
76
}
91
77
92
+static void v7m_update_fpccr(CPUARMState *env, uint32_t frameptr,
78
+static bool trans_VCVT_hp_int(DisasContext *s, arg_VCVT_sp_int *a)
93
+ bool apply_splim)
94
+{
79
+{
95
+ /*
80
+ TCGv_i32 vm;
96
+ * Like the pseudocode UpdateFPCCR: save state in FPCAR and FPCCR
81
+ TCGv_ptr fpst;
97
+ * that we will need later in order to do lazy FP reg stacking.
98
+ */
99
+ bool is_secure = env->v7m.secure;
100
+ void *nvic = env->nvic;
101
+ /*
102
+ * Some bits are unbanked and live always in fpccr[M_REG_S]; some bits
103
+ * are banked and we want to update the bit in the bank for the
104
+ * current security state; and in one case we want to specifically
105
+ * update the NS banked version of a bit even if we are secure.
106
+ */
107
+ uint32_t *fpccr_s = &env->v7m.fpccr[M_REG_S];
108
+ uint32_t *fpccr_ns = &env->v7m.fpccr[M_REG_NS];
109
+ uint32_t *fpccr = &env->v7m.fpccr[is_secure];
110
+ bool hfrdy, bfrdy, mmrdy, ns_ufrdy, s_ufrdy, sfrdy, monrdy;
111
+
82
+
112
+ env->v7m.fpcar[is_secure] = frameptr & ~0x7;
83
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
113
+
84
+ return false;
114
+ if (apply_splim && arm_feature(env, ARM_FEATURE_V8)) {
115
+ bool splimviol;
116
+ uint32_t splim = v7m_sp_limit(env);
117
+ bool ign = armv7m_nvic_neg_prio_requested(nvic, is_secure) &&
118
+ (env->v7m.ccr[is_secure] & R_V7M_CCR_STKOFHFNMIGN_MASK);
119
+
120
+ splimviol = !ign && frameptr < splim;
121
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, SPLIMVIOL, splimviol);
122
+ }
85
+ }
123
+
86
+
124
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, LSPACT, 1);
87
+ if (!vfp_access_check(s)) {
88
+ return true;
89
+ }
125
+
90
+
126
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, S, is_secure);
91
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
92
+ vm = tcg_temp_new_i32();
93
+ neon_load_reg32(vm, a->vm);
127
+
94
+
128
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, USER, arm_current_el(env) == 0);
95
+ if (a->s) {
129
+
96
+ if (a->rz) {
130
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, THREAD,
97
+ gen_helper_vfp_tosizh(vm, vm, fpst);
131
+ !arm_v7m_is_handler_mode(env));
98
+ } else {
132
+
99
+ gen_helper_vfp_tosih(vm, vm, fpst);
133
+ hfrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_HARD, false);
100
+ }
134
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, HFRDY, hfrdy);
101
+ } else {
135
+
102
+ if (a->rz) {
136
+ bfrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_BUS, false);
103
+ gen_helper_vfp_touizh(vm, vm, fpst);
137
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, BFRDY, bfrdy);
104
+ } else {
138
+
105
+ gen_helper_vfp_touih(vm, vm, fpst);
139
+ mmrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_MEM, is_secure);
106
+ }
140
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, MMRDY, mmrdy);
141
+
142
+ ns_ufrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_USAGE, false);
143
+ *fpccr_ns = FIELD_DP32(*fpccr_ns, V7M_FPCCR, UFRDY, ns_ufrdy);
144
+
145
+ monrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_DEBUG, false);
146
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, MONRDY, monrdy);
147
+
148
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
149
+ s_ufrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_USAGE, true);
150
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, UFRDY, s_ufrdy);
151
+
152
+ sfrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_SECURE, false);
153
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, SFRDY, sfrdy);
154
+ }
107
+ }
108
+ neon_store_reg32(vm, a->vd);
109
+ tcg_temp_free_i32(vm);
110
+ tcg_temp_free_ptr(fpst);
111
+ return true;
155
+}
112
+}
156
+
113
+
157
static bool v7m_push_stack(ARMCPU *cpu)
114
static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a)
158
{
115
{
159
/* Do the "set up stack frame" part of exception entry,
116
TCGv_i32 vm;
160
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
161
}
162
} else {
163
/* Lazy stacking enabled, save necessary info to stack later */
164
- /* TODO : equivalent of UpdateFPCCR() pseudocode */
165
+ v7m_update_fpccr(env, frameptr + 0x20, true);
166
}
167
}
168
}
169
--
117
--
170
2.20.1
118
2.20.1
171
119
172
120
diff view generated by jsdifflib
1
Enforce that for M-profile various FPSCR bits which are RES0 there
1
Currently the VFP_CONV_FIX macros take a single fsz argument for the
2
but have defined meanings on A-profile are never settable. This
2
size of the float type, which is used both to select the name of
3
ensures that M-profile code can't enable the A-profile behaviour
3
the functions to call (eg float32_is_any_nan()) and also for the
4
(notably vector length/stride handling) by accident.
4
type to use for the float inputs and outputs (eg float32).
5
6
Separate these into fsz and ftype arguments, so that we can use them
7
for fp16, which uses 'float16' in the function names but is still
8
passing inputs and outputs in a 32-bit sized type.
5
9
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190416125744.27770-2-peter.maydell@linaro.org
12
Message-id: 20200828183354.27913-14-peter.maydell@linaro.org
9
---
13
---
10
target/arm/vfp_helper.c | 8 ++++++++
14
target/arm/vfp_helper.c | 46 ++++++++++++++++++++---------------------
11
1 file changed, 8 insertions(+)
15
1 file changed, 23 insertions(+), 23 deletions(-)
12
16
13
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
17
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/vfp_helper.c
19
--- a/target/arm/vfp_helper.c
16
+++ b/target/arm/vfp_helper.c
20
+++ b/target/arm/vfp_helper.c
17
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
21
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
18
val &= ~FPCR_FZ16;
22
}
19
}
23
20
24
/* VFP3 fixed point conversion. */
21
+ if (arm_feature(env, ARM_FEATURE_M)) {
25
-#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
22
+ /*
26
-float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
23
+ * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
27
+#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
24
+ * and also for the trapped-exception-handling bits IxE.
28
+ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
25
+ */
29
void *fpstp) \
26
+ val &= 0xf7c0009f;
30
{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
27
+ }
31
28
+
32
-#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
29
/*
33
-uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
30
* We don't implement trapped exception handling, so the
34
+#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
31
* trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
35
+uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
36
void *fpst) \
37
{ \
38
if (unlikely(float##fsz##_is_any_nan(x))) { \
39
@@ -XXX,XX +XXX,XX @@ uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
40
return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
41
}
42
43
-#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
44
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
45
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
46
+#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \
47
+VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
48
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
49
float_round_to_zero, _round_to_zero) \
50
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
51
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
52
get_float_rounding_mode(fpst), )
53
54
-#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
55
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
56
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
57
+#define VFP_CONV_FIX_A64(name, p, fsz, ftype, isz, itype) \
58
+VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
59
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
60
get_float_rounding_mode(fpst), )
61
62
-VFP_CONV_FIX(sh, d, 64, 64, int16)
63
-VFP_CONV_FIX(sl, d, 64, 64, int32)
64
-VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
65
-VFP_CONV_FIX(uh, d, 64, 64, uint16)
66
-VFP_CONV_FIX(ul, d, 64, 64, uint32)
67
-VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
68
-VFP_CONV_FIX(sh, s, 32, 32, int16)
69
-VFP_CONV_FIX(sl, s, 32, 32, int32)
70
-VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
71
-VFP_CONV_FIX(uh, s, 32, 32, uint16)
72
-VFP_CONV_FIX(ul, s, 32, 32, uint32)
73
-VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
74
+VFP_CONV_FIX(sh, d, 64, float64, 64, int16)
75
+VFP_CONV_FIX(sl, d, 64, float64, 64, int32)
76
+VFP_CONV_FIX_A64(sq, d, 64, float64, 64, int64)
77
+VFP_CONV_FIX(uh, d, 64, float64, 64, uint16)
78
+VFP_CONV_FIX(ul, d, 64, float64, 64, uint32)
79
+VFP_CONV_FIX_A64(uq, d, 64, float64, 64, uint64)
80
+VFP_CONV_FIX(sh, s, 32, float32, 32, int16)
81
+VFP_CONV_FIX(sl, s, 32, float32, 32, int32)
82
+VFP_CONV_FIX_A64(sq, s, 32, float32, 64, int64)
83
+VFP_CONV_FIX(uh, s, 32, float32, 32, uint16)
84
+VFP_CONV_FIX(ul, s, 32, float32, 32, uint32)
85
+VFP_CONV_FIX_A64(uq, s, 32, float32, 64, uint64)
86
87
#undef VFP_CONV_FIX
88
#undef VFP_CONV_FIX_FLOAT
32
--
89
--
33
2.20.1
90
2.20.1
34
91
35
92
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
Now the VFP_CONV_FIX macros can handle fp16's distinction between the
2
width of the operation and the width of the type used to pass operands,
3
use the macros rather than the open-coded functions.
2
4
3
Reviewed-by: Markus Armbruster <armbru@redhat.com>
5
This creates an extra six helper functions, all of which we are going
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
to need for the AArch32 VFP fp16 instructions.
5
Message-id: 20190412165416.7977-12-philmd@redhat.com
7
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200828183354.27913-15-peter.maydell@linaro.org
7
---
11
---
8
include/hw/net/lan9118.h | 2 ++
12
target/arm/helper.h | 6 +++
9
hw/arm/exynos4_boards.c | 3 ++-
13
target/arm/vfp_helper.c | 86 +++--------------------------------------
10
hw/arm/mps2-tz.c | 3 ++-
14
2 files changed, 12 insertions(+), 80 deletions(-)
11
hw/net/lan9118.c | 1 -
12
4 files changed, 6 insertions(+), 3 deletions(-)
13
15
14
diff --git a/include/hw/net/lan9118.h b/include/hw/net/lan9118.h
16
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/net/lan9118.h
18
--- a/target/arm/helper.h
17
+++ b/include/hw/net/lan9118.h
19
+++ b/target/arm/helper.h
18
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(vfp_tosizh, s32, f16, ptr)
19
#include "hw/irq.h"
21
DEF_HELPER_2(vfp_tosizs, s32, f32, ptr)
20
#include "net/net.h"
22
DEF_HELPER_2(vfp_tosizd, s32, f64, ptr)
21
23
22
+#define TYPE_LAN9118 "lan9118"
24
+DEF_HELPER_3(vfp_toshh_round_to_zero, i32, f16, i32, ptr)
23
+
25
+DEF_HELPER_3(vfp_toslh_round_to_zero, i32, f16, i32, ptr)
24
void lan9118_init(NICInfo *, uint32_t, qemu_irq);
26
+DEF_HELPER_3(vfp_touhh_round_to_zero, i32, f16, i32, ptr)
25
27
+DEF_HELPER_3(vfp_toulh_round_to_zero, i32, f16, i32, ptr)
26
#endif
28
DEF_HELPER_3(vfp_toshs_round_to_zero, i32, f32, i32, ptr)
27
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
29
DEF_HELPER_3(vfp_tosls_round_to_zero, i32, f32, i32, ptr)
30
DEF_HELPER_3(vfp_touhs_round_to_zero, i32, f32, i32, ptr)
31
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_sqtod, f64, i64, i32, ptr)
32
DEF_HELPER_3(vfp_uhtod, f64, i64, i32, ptr)
33
DEF_HELPER_3(vfp_ultod, f64, i64, i32, ptr)
34
DEF_HELPER_3(vfp_uqtod, f64, i64, i32, ptr)
35
+DEF_HELPER_3(vfp_shtoh, f16, i32, i32, ptr)
36
+DEF_HELPER_3(vfp_uhtoh, f16, i32, i32, ptr)
37
DEF_HELPER_3(vfp_sltoh, f16, i32, i32, ptr)
38
DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
39
DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
40
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
28
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/exynos4_boards.c
42
--- a/target/arm/vfp_helper.c
30
+++ b/hw/arm/exynos4_boards.c
43
+++ b/target/arm/vfp_helper.c
31
@@ -XXX,XX +XXX,XX @@
44
@@ -XXX,XX +XXX,XX @@ VFP_CONV_FIX_A64(sq, s, 32, float32, 64, int64)
32
#include "hw/arm/arm.h"
45
VFP_CONV_FIX(uh, s, 32, float32, 32, uint16)
33
#include "exec/address-spaces.h"
46
VFP_CONV_FIX(ul, s, 32, float32, 32, uint32)
34
#include "hw/arm/exynos4210.h"
47
VFP_CONV_FIX_A64(uq, s, 32, float32, 64, uint64)
35
+#include "hw/net/lan9118.h"
48
+VFP_CONV_FIX(sh, h, 16, dh_ctype_f16, 32, int16)
36
#include "hw/boards.h"
49
+VFP_CONV_FIX(sl, h, 16, dh_ctype_f16, 32, int32)
37
50
+VFP_CONV_FIX_A64(sq, h, 16, dh_ctype_f16, 64, int64)
38
#undef DEBUG
51
+VFP_CONV_FIX(uh, h, 16, dh_ctype_f16, 32, uint16)
39
@@ -XXX,XX +XXX,XX @@ static void lan9215_init(uint32_t base, qemu_irq irq)
52
+VFP_CONV_FIX(ul, h, 16, dh_ctype_f16, 32, uint32)
40
/* This should be a 9215 but the 9118 is close enough */
53
+VFP_CONV_FIX_A64(uq, h, 16, dh_ctype_f16, 64, uint64)
41
if (nd_table[0].used) {
54
42
qemu_check_nic_model(&nd_table[0], "lan9118");
55
#undef VFP_CONV_FIX
43
- dev = qdev_create(NULL, "lan9118");
56
#undef VFP_CONV_FIX_FLOAT
44
+ dev = qdev_create(NULL, TYPE_LAN9118);
57
#undef VFP_CONV_FLOAT_FIX_ROUND
45
qdev_set_nic_properties(dev, &nd_table[0]);
58
#undef VFP_CONV_FIX_A64
46
qdev_prop_set_uint32(dev, "mode_16bit", 1);
59
47
qdev_init_nofail(dev);
60
-uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
48
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
61
-{
49
index XXXXXXX..XXXXXXX 100644
62
- return int32_to_float16_scalbn(x, -shift, fpst);
50
--- a/hw/arm/mps2-tz.c
63
-}
51
+++ b/hw/arm/mps2-tz.c
64
-
52
@@ -XXX,XX +XXX,XX @@
65
-uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
53
#include "hw/arm/armsse.h"
66
-{
54
#include "hw/dma/pl080.h"
67
- return uint32_to_float16_scalbn(x, -shift, fpst);
55
#include "hw/ssi/pl022.h"
68
-}
56
+#include "hw/net/lan9118.h"
69
-
57
#include "net/net.h"
70
-uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
58
#include "hw/core/split-irq.h"
71
-{
59
72
- return int64_to_float16_scalbn(x, -shift, fpst);
60
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
73
-}
61
* except that it doesn't support the checksum-offload feature.
74
-
62
*/
75
-uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
63
qemu_check_nic_model(nd, "lan9118");
76
-{
64
- mms->lan9118 = qdev_create(NULL, "lan9118");
77
- return uint64_to_float16_scalbn(x, -shift, fpst);
65
+ mms->lan9118 = qdev_create(NULL, TYPE_LAN9118);
78
-}
66
qdev_set_nic_properties(mms->lan9118, nd);
79
-
67
qdev_init_nofail(mms->lan9118);
80
-uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
68
81
-{
69
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
82
- if (unlikely(float16_is_any_nan(x))) {
70
index XXXXXXX..XXXXXXX 100644
83
- float_raise(float_flag_invalid, fpst);
71
--- a/hw/net/lan9118.c
84
- return 0;
72
+++ b/hw/net/lan9118.c
85
- }
73
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118_packet = {
86
- return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
74
}
87
- shift, fpst);
75
};
88
-}
76
89
-
77
-#define TYPE_LAN9118 "lan9118"
90
-uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
78
#define LAN9118(obj) OBJECT_CHECK(lan9118_state, (obj), TYPE_LAN9118)
91
-{
79
92
- if (unlikely(float16_is_any_nan(x))) {
80
typedef struct {
93
- float_raise(float_flag_invalid, fpst);
94
- return 0;
95
- }
96
- return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
97
- shift, fpst);
98
-}
99
-
100
-uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
101
-{
102
- if (unlikely(float16_is_any_nan(x))) {
103
- float_raise(float_flag_invalid, fpst);
104
- return 0;
105
- }
106
- return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
107
- shift, fpst);
108
-}
109
-
110
-uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
111
-{
112
- if (unlikely(float16_is_any_nan(x))) {
113
- float_raise(float_flag_invalid, fpst);
114
- return 0;
115
- }
116
- return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
117
- shift, fpst);
118
-}
119
-
120
-uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
121
-{
122
- if (unlikely(float16_is_any_nan(x))) {
123
- float_raise(float_flag_invalid, fpst);
124
- return 0;
125
- }
126
- return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
127
- shift, fpst);
128
-}
129
-
130
-uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
131
-{
132
- if (unlikely(float16_is_any_nan(x))) {
133
- float_raise(float_flag_invalid, fpst);
134
- return 0;
135
- }
136
- return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
137
- shift, fpst);
138
-}
139
-
140
/* Set the current fp rounding mode and return the old one.
141
* The argument is a softfloat float_round_ value.
142
*/
81
--
143
--
82
2.20.1
144
2.20.1
83
145
84
146
diff view generated by jsdifflib
1
In the v7M architecture, if an exception is generated in the process
1
Implement the fp16 versions of the VFP VCVT instruction forms which
2
of doing the lazy stacking of FP registers, the handling of
2
convert between floating point and fixed-point.
3
possible escalation to HardFault is treated differently to the normal
4
approach: it works based on the saved information about exception
5
readiness that was stored in the FPCCR when the stack frame was
6
created. Provide a new function armv7m_nvic_set_pending_lazyfp()
7
which pends exceptions during lazy stacking, and implements
8
this logic.
9
10
This corresponds to the pseudocode TakePreserveFPException().
11
3
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20190416125744.27770-22-peter.maydell@linaro.org
6
Message-id: 20200828183354.27913-16-peter.maydell@linaro.org
15
---
7
---
16
target/arm/cpu.h | 12 ++++++
8
target/arm/vfp.decode | 2 ++
17
hw/intc/armv7m_nvic.c | 96 +++++++++++++++++++++++++++++++++++++++++++
9
target/arm/translate-vfp.c.inc | 59 ++++++++++++++++++++++++++++++++++
18
2 files changed, 108 insertions(+)
10
2 files changed, 61 insertions(+)
19
11
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
14
--- a/target/arm/vfp.decode
23
+++ b/target/arm/cpu.h
15
+++ b/target/arm/vfp.decode
24
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure);
16
@@ -XXX,XX +XXX,XX @@ VJCVT ---- 1110 1.11 1001 .... 1011 11.0 .... @vfp_dm_sd
25
* a different exception).
17
# We assemble bits 18 (op), 16 (u) and 7 (sx) into a single opc field
26
*/
18
# for the convenience of the trans_VCVT_fix functions.
27
void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
19
%vcvt_fix_op 18:1 16:1 7:1
28
+/**
20
+VCVT_fix_hp ---- 1110 1.11 1.1. .... 1001 .1.0 .... \
29
+ * armv7m_nvic_set_pending_lazyfp: mark this lazy FP exception as pending
21
+ vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op
30
+ * @opaque: the NVIC
22
VCVT_fix_sp ---- 1110 1.11 1.1. .... 1010 .1.0 .... \
31
+ * @irq: the exception number to mark pending
23
vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op
32
+ * @secure: false for non-banked exceptions or for the nonsecure
24
VCVT_fix_dp ---- 1110 1.11 1.1. .... 1011 .1.0 .... \
33
+ * version of a banked exception, true for the secure version of a banked
25
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
34
+ * exception.
35
+ *
36
+ * Similar to armv7m_nvic_set_pending(), but specifically for exceptions
37
+ * generated in the course of lazy stacking of FP registers.
38
+ */
39
+void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure);
40
/**
41
* armv7m_nvic_get_pending_irq_info: return highest priority pending
42
* exception, and whether it targets Secure state
43
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
44
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/intc/armv7m_nvic.c
27
--- a/target/arm/translate-vfp.c.inc
46
+++ b/hw/intc/armv7m_nvic.c
28
+++ b/target/arm/translate-vfp.c.inc
47
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure)
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
48
do_armv7m_nvic_set_pending(opaque, irq, secure, true);
30
return true;
49
}
31
}
50
32
51
+void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure)
33
+static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
52
+{
34
+{
53
+ /*
35
+ TCGv_i32 vd, shift;
54
+ * Pend an exception during lazy FP stacking. This differs
36
+ TCGv_ptr fpst;
55
+ * from the usual exception pending because the logic for
37
+ int frac_bits;
56
+ * whether we should escalate depends on the saved context
57
+ * in the FPCCR register, not on the current state of the CPU/NVIC.
58
+ */
59
+ NVICState *s = (NVICState *)opaque;
60
+ bool banked = exc_is_banked(irq);
61
+ VecInfo *vec;
62
+ bool targets_secure;
63
+ bool escalate = false;
64
+ /*
65
+ * We will only look at bits in fpccr if this is a banked exception
66
+ * (in which case 'secure' tells us whether it is the S or NS version).
67
+ * All the bits for the non-banked exceptions are in fpccr_s.
68
+ */
69
+ uint32_t fpccr_s = s->cpu->env.v7m.fpccr[M_REG_S];
70
+ uint32_t fpccr = s->cpu->env.v7m.fpccr[secure];
71
+
38
+
72
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
39
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
73
+ assert(!secure || banked);
40
+ return false;
41
+ }
74
+
42
+
75
+ vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
43
+ if (!vfp_access_check(s)) {
44
+ return true;
45
+ }
76
+
46
+
77
+ targets_secure = banked ? secure : exc_targets_secure(s, irq);
47
+ frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm);
78
+
48
+
79
+ switch (irq) {
49
+ vd = tcg_temp_new_i32();
80
+ case ARMV7M_EXCP_DEBUG:
50
+ neon_load_reg32(vd, a->vd);
81
+ if (!(fpccr_s & R_V7M_FPCCR_MONRDY_MASK)) {
51
+
82
+ /* Ignore DebugMonitor exception */
52
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
83
+ return;
53
+ shift = tcg_const_i32(frac_bits);
84
+ }
54
+
55
+ /* Switch on op:U:sx bits */
56
+ switch (a->opc) {
57
+ case 0:
58
+ gen_helper_vfp_shtoh(vd, vd, shift, fpst);
85
+ break;
59
+ break;
86
+ case ARMV7M_EXCP_MEM:
60
+ case 1:
87
+ escalate = !(fpccr & R_V7M_FPCCR_MMRDY_MASK);
61
+ gen_helper_vfp_sltoh(vd, vd, shift, fpst);
88
+ break;
62
+ break;
89
+ case ARMV7M_EXCP_USAGE:
63
+ case 2:
90
+ escalate = !(fpccr & R_V7M_FPCCR_UFRDY_MASK);
64
+ gen_helper_vfp_uhtoh(vd, vd, shift, fpst);
91
+ break;
65
+ break;
92
+ case ARMV7M_EXCP_BUS:
66
+ case 3:
93
+ escalate = !(fpccr_s & R_V7M_FPCCR_BFRDY_MASK);
67
+ gen_helper_vfp_ultoh(vd, vd, shift, fpst);
94
+ break;
68
+ break;
95
+ case ARMV7M_EXCP_SECURE:
69
+ case 4:
96
+ escalate = !(fpccr_s & R_V7M_FPCCR_SFRDY_MASK);
70
+ gen_helper_vfp_toshh_round_to_zero(vd, vd, shift, fpst);
71
+ break;
72
+ case 5:
73
+ gen_helper_vfp_toslh_round_to_zero(vd, vd, shift, fpst);
74
+ break;
75
+ case 6:
76
+ gen_helper_vfp_touhh_round_to_zero(vd, vd, shift, fpst);
77
+ break;
78
+ case 7:
79
+ gen_helper_vfp_toulh_round_to_zero(vd, vd, shift, fpst);
97
+ break;
80
+ break;
98
+ default:
81
+ default:
99
+ g_assert_not_reached();
82
+ g_assert_not_reached();
100
+ }
83
+ }
101
+
84
+
102
+ if (escalate) {
85
+ neon_store_reg32(vd, a->vd);
103
+ /*
86
+ tcg_temp_free_i32(vd);
104
+ * Escalate to HardFault: faults that initially targeted Secure
87
+ tcg_temp_free_i32(shift);
105
+ * continue to do so, even if HF normally targets NonSecure.
88
+ tcg_temp_free_ptr(fpst);
106
+ */
89
+ return true;
107
+ irq = ARMV7M_EXCP_HARD;
108
+ if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY) &&
109
+ (targets_secure ||
110
+ !(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK))) {
111
+ vec = &s->sec_vectors[irq];
112
+ } else {
113
+ vec = &s->vectors[irq];
114
+ }
115
+ }
116
+
117
+ if (!vec->enabled ||
118
+ nvic_exec_prio(s) <= exc_group_prio(s, vec->prio, secure)) {
119
+ if (!(fpccr_s & R_V7M_FPCCR_HFRDY_MASK)) {
120
+ /*
121
+ * We want to escalate to HardFault but the context the
122
+ * FP state belongs to prevents the exception pre-empting.
123
+ */
124
+ cpu_abort(&s->cpu->parent_obj,
125
+ "Lockup: can't escalate to HardFault during "
126
+ "lazy FP register stacking\n");
127
+ }
128
+ }
129
+
130
+ if (escalate) {
131
+ s->cpu->env.v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
132
+ }
133
+ if (!vec->pending) {
134
+ vec->pending = 1;
135
+ /*
136
+ * We do not call nvic_irq_update(), because we know our caller
137
+ * is going to handle causing us to take the exception by
138
+ * raising EXCP_LAZYFP, so raising the IRQ line would be
139
+ * pointless extra work. We just need to recompute the
140
+ * priorities so that armv7m_nvic_can_take_pending_exception()
141
+ * returns the right answer.
142
+ */
143
+ nvic_recompute_state(s);
144
+ }
145
+}
90
+}
146
+
91
+
147
/* Make pending IRQ active. */
92
static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
148
void armv7m_nvic_acknowledge_irq(void *opaque)
149
{
93
{
94
TCGv_i32 vd, shift;
150
--
95
--
151
2.20.1
96
2.20.1
152
97
153
98
diff view generated by jsdifflib
1
We are close to running out of TB flags for AArch32; we could
1
Implement the fp16 versions of the VFP VCVT instruction forms
2
start using the cs_base word, but before we do that we can
2
which convert between floating point and integer with a specified
3
economise on our usage by sharing the same bits for the VFP
3
rounding mode.
4
VECSTRIDE field and the XScale XSCALE_CPAR field. This
5
works because no XScale CPU ever had VFP.
6
4
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190416125744.27770-18-peter.maydell@linaro.org
7
Message-id: 20200828183354.27913-17-peter.maydell@linaro.org
10
---
8
---
11
target/arm/cpu.h | 10 ++++++----
9
target/arm/vfp-uncond.decode | 6 ++++--
12
target/arm/cpu.c | 7 +++++++
10
target/arm/translate-vfp.c.inc | 32 ++++++++++++++++++++++++--------
13
target/arm/helper.c | 6 +++++-
11
2 files changed, 28 insertions(+), 10 deletions(-)
14
target/arm/translate.c | 9 +++++++--
15
4 files changed, 25 insertions(+), 7 deletions(-)
16
12
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
15
--- a/target/arm/vfp-uncond.decode
20
+++ b/target/arm/cpu.h
16
+++ b/target/arm/vfp-uncond.decode
21
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
17
@@ -XXX,XX +XXX,XX @@ VRINT 1111 1110 1.11 10 rm:2 .... 1011 01.0 .... \
22
FIELD(TBFLAG_A32, THUMB, 0, 1)
18
vm=%vm_dp vd=%vd_dp dp=1
23
FIELD(TBFLAG_A32, VECLEN, 1, 3)
19
24
FIELD(TBFLAG_A32, VECSTRIDE, 4, 2)
20
# VCVT float to int with specified rounding mode; Vd is always single-precision
25
+/*
21
+VCVT 1111 1110 1.11 11 rm:2 .... 1001 op:1 1.0 .... \
26
+ * We store the bottom two bits of the CPAR as TB flags and handle
22
+ vm=%vm_sp vd=%vd_sp sz=1
27
+ * checks on the other bits at runtime. This shares the same bits as
23
VCVT 1111 1110 1.11 11 rm:2 .... 1010 op:1 1.0 .... \
28
+ * VECSTRIDE, which is OK as no XScale CPU has VFP.
24
- vm=%vm_sp vd=%vd_sp dp=0
29
+ */
25
+ vm=%vm_sp vd=%vd_sp sz=2
30
+FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
26
VCVT 1111 1110 1.11 11 rm:2 .... 1011 op:1 1.0 .... \
31
/*
27
- vm=%vm_dp vd=%vd_sp dp=1
32
* Indicates whether cp register reads and writes by guest code should access
28
+ vm=%vm_dp vd=%vd_sp sz=3
33
* the secure or nonsecure bank of banked registers; note that this is not
29
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
34
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
35
FIELD(TBFLAG_A32, VFPEN, 7, 1)
36
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
37
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
38
-/* We store the bottom two bits of the CPAR as TB flags and handle
39
- * checks on the other bits at runtime
40
- */
41
-FIELD(TBFLAG_A32, XSCALE_CPAR, 17, 2)
42
/* For M profile only, Handler (ie not Thread) mode */
43
FIELD(TBFLAG_A32, HANDLER, 21, 1)
44
/* For M profile only, whether we should generate stack-limit checks */
45
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
46
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/cpu.c
31
--- a/target/arm/translate-vfp.c.inc
48
+++ b/target/arm/cpu.c
32
+++ b/target/arm/translate-vfp.c.inc
49
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
33
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
50
set_feature(env, ARM_FEATURE_THUMB_DSP);
34
static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
35
{
36
uint32_t rd, rm;
37
- bool dp = a->dp;
38
+ int sz = a->sz;
39
TCGv_ptr fpst;
40
TCGv_i32 tcg_rmode, tcg_shift;
41
int rounding = fp_decode_rm[a->rm];
42
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
43
return false;
51
}
44
}
52
45
53
+ /*
46
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
54
+ * We rely on no XScale CPU having VFP so we can use the same bits in the
47
+ if (sz == 3 && !dc_isar_feature(aa32_fpdp_v2, s)) {
55
+ * TB flags field for VECSTRIDE and XSCALE_CPAR.
48
+ return false;
56
+ */
49
+ }
57
+ assert(!(arm_feature(env, ARM_FEATURE_VFP) &&
58
+ arm_feature(env, ARM_FEATURE_XSCALE)));
59
+
50
+
60
if (arm_feature(env, ARM_FEATURE_V7) &&
51
+ if (sz == 1 && !dc_isar_feature(aa32_fp16_arith, s)) {
61
!arm_feature(env, ARM_FEATURE_M) &&
52
return false;
62
!arm_feature(env, ARM_FEATURE_PMSA)) {
53
}
63
diff --git a/target/arm/helper.c b/target/arm/helper.c
54
64
index XXXXXXX..XXXXXXX 100644
55
/* UNDEF accesses to D16-D31 if they don't exist */
65
--- a/target/arm/helper.c
56
- if (dp && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
66
+++ b/target/arm/helper.c
57
+ if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
67
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
58
return false;
68
|| arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
59
}
69
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
60
61
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
62
return true;
63
}
64
65
- fpst = fpstatus_ptr(FPST_FPCR);
66
+ if (sz == 1) {
67
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
68
+ } else {
69
+ fpst = fpstatus_ptr(FPST_FPCR);
70
+ }
71
72
tcg_shift = tcg_const_i32(0);
73
74
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
75
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
76
77
- if (dp) {
78
+ if (sz == 3) {
79
TCGv_i64 tcg_double, tcg_res;
80
TCGv_i32 tcg_tmp;
81
tcg_double = tcg_temp_new_i64();
82
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
83
tcg_single = tcg_temp_new_i32();
84
tcg_res = tcg_temp_new_i32();
85
neon_load_reg32(tcg_single, rm);
86
- if (is_signed) {
87
- gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
88
+ if (sz == 1) {
89
+ if (is_signed) {
90
+ gen_helper_vfp_toslh(tcg_res, tcg_single, tcg_shift, fpst);
91
+ } else {
92
+ gen_helper_vfp_toulh(tcg_res, tcg_single, tcg_shift, fpst);
93
+ }
94
} else {
95
- gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
96
+ if (is_signed) {
97
+ gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
98
+ } else {
99
+ gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
100
+ }
70
}
101
}
71
- flags = FIELD_DP32(flags, TBFLAG_A32, XSCALE_CPAR, env->cp15.c15_cpar);
102
neon_store_reg32(tcg_res, rd);
72
+ /* Note that XSCALE_CPAR shares bits with VECSTRIDE */
103
tcg_temp_free_i32(tcg_res);
73
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
74
+ flags = FIELD_DP32(flags, TBFLAG_A32,
75
+ XSCALE_CPAR, env->cp15.c15_cpar);
76
+ }
77
}
78
79
flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, arm_to_core_mmu_idx(mmu_idx));
80
diff --git a/target/arm/translate.c b/target/arm/translate.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/translate.c
83
+++ b/target/arm/translate.c
84
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
85
dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
86
dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
87
dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
88
- dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
89
- dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
90
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
91
+ dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
92
+ dc->vec_stride = 0;
93
+ } else {
94
+ dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
95
+ dc->c15_cpar = 0;
96
+ }
97
dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
98
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
99
regime_is_secure(env, dc->mmu_idx);
100
--
104
--
101
2.20.1
105
2.20.1
102
106
103
107
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
Implement the fp16 versions of the VFP VSEL instruction.
2
2
3
Reviewed-by: Markus Armbruster <armbru@redhat.com>
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Message-id: 20190412165416.7977-10-philmd@redhat.com
6
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>
5
Message-id: 20200828183354.27913-18-peter.maydell@linaro.org
7
---
6
---
8
include/hw/devices.h | 3 ---
7
target/arm/vfp-uncond.decode | 6 ++++--
9
include/hw/net/lan9118.h | 19 +++++++++++++++++++
8
target/arm/translate-vfp.c.inc | 16 ++++++++++++----
10
hw/arm/kzm.c | 2 +-
9
2 files changed, 16 insertions(+), 6 deletions(-)
11
hw/arm/mps2.c | 2 +-
12
hw/arm/realview.c | 1 +
13
hw/arm/vexpress.c | 2 +-
14
hw/net/lan9118.c | 2 +-
15
7 files changed, 24 insertions(+), 7 deletions(-)
16
create mode 100644 include/hw/net/lan9118.h
17
10
18
diff --git a/include/hw/devices.h b/include/hw/devices.h
11
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
19
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/devices.h
13
--- a/target/arm/vfp-uncond.decode
21
+++ b/include/hw/devices.h
14
+++ b/target/arm/vfp-uncond.decode
22
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@
23
/* smc91c111.c */
16
@vfp_dnm_s ................................ vm=%vm_sp vn=%vn_sp vd=%vd_sp
24
void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
17
@vfp_dnm_d ................................ vm=%vm_dp vn=%vn_dp vd=%vd_dp
25
18
26
-/* lan9118.c */
19
+VSEL 1111 1110 0. cc:2 .... .... 1001 .0.0 .... \
27
-void lan9118_init(NICInfo *, uint32_t, qemu_irq);
20
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp sz=1
28
-
21
VSEL 1111 1110 0. cc:2 .... .... 1010 .0.0 .... \
29
#endif
22
- vm=%vm_sp vn=%vn_sp vd=%vd_sp dp=0
30
diff --git a/include/hw/net/lan9118.h b/include/hw/net/lan9118.h
23
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp sz=2
31
new file mode 100644
24
VSEL 1111 1110 0. cc:2 .... .... 1011 .0.0 .... \
32
index XXXXXXX..XXXXXXX
25
- vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
33
--- /dev/null
26
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp sz=3
34
+++ b/include/hw/net/lan9118.h
27
35
@@ -XXX,XX +XXX,XX @@
28
VMAXNM_hp 1111 1110 1.00 .... .... 1001 .0.0 .... @vfp_dnm_s
36
+/*
29
VMINNM_hp 1111 1110 1.00 .... .... 1001 .1.0 .... @vfp_dnm_s
37
+ * SMSC LAN9118 Ethernet interface emulation
30
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
38
+ *
31
index XXXXXXX..XXXXXXX 100644
39
+ * Copyright (c) 2009 CodeSourcery, LLC.
32
--- a/target/arm/translate-vfp.c.inc
40
+ * Written by Paul Brook
33
+++ b/target/arm/translate-vfp.c.inc
41
+ *
34
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check(DisasContext *s)
42
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
35
static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
43
+ * See the COPYING file in the top-level directory.
36
{
44
+ */
37
uint32_t rd, rn, rm;
38
- bool dp = a->dp;
39
+ int sz = a->sz;
40
41
if (!dc_isar_feature(aa32_vsel, s)) {
42
return false;
43
}
44
45
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
46
+ if (sz == 3 && !dc_isar_feature(aa32_fpdp_v2, s)) {
47
+ return false;
48
+ }
45
+
49
+
46
+#ifndef HW_NET_LAN9118_H
50
+ if (sz == 1 && !dc_isar_feature(aa32_fp16_arith, s)) {
47
+#define HW_NET_LAN9118_H
51
return false;
48
+
52
}
49
+#include "hw/irq.h"
53
50
+#include "net/net.h"
54
/* UNDEF accesses to D16-D31 if they don't exist */
51
+
55
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
52
+void lan9118_init(NICInfo *, uint32_t, qemu_irq);
56
+ if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) &&
53
+
57
((a->vm | a->vn | a->vd) & 0x10)) {
54
+#endif
58
return false;
55
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
59
}
56
index XXXXXXX..XXXXXXX 100644
60
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
57
--- a/hw/arm/kzm.c
61
return true;
58
+++ b/hw/arm/kzm.c
62
}
59
@@ -XXX,XX +XXX,XX @@
63
60
#include "qemu/error-report.h"
64
- if (dp) {
61
#include "exec/address-spaces.h"
65
+ if (sz == 3) {
62
#include "net/net.h"
66
TCGv_i64 frn, frm, dest;
63
-#include "hw/devices.h"
67
TCGv_i64 tmp, zero, zf, nf, vf;
64
+#include "hw/net/lan9118.h"
68
65
#include "hw/char/serial.h"
69
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
66
#include "sysemu/qtest.h"
70
tcg_temp_free_i32(tmp);
67
71
break;
68
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
72
}
69
index XXXXXXX..XXXXXXX 100644
73
+ /* For fp16 the top half is always zeroes */
70
--- a/hw/arm/mps2.c
74
+ if (sz == 1) {
71
+++ b/hw/arm/mps2.c
75
+ tcg_gen_andi_i32(dest, dest, 0xffff);
72
@@ -XXX,XX +XXX,XX @@
76
+ }
73
#include "hw/timer/cmsdk-apb-timer.h"
77
neon_store_reg32(dest, rd);
74
#include "hw/timer/cmsdk-apb-dualtimer.h"
78
tcg_temp_free_i32(frn);
75
#include "hw/misc/mps2-scc.h"
79
tcg_temp_free_i32(frm);
76
-#include "hw/devices.h"
77
+#include "hw/net/lan9118.h"
78
#include "net/net.h"
79
80
typedef enum MPS2FPGAType {
81
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/hw/arm/realview.c
84
+++ b/hw/arm/realview.c
85
@@ -XXX,XX +XXX,XX @@
86
#include "hw/arm/arm.h"
87
#include "hw/arm/primecell.h"
88
#include "hw/devices.h"
89
+#include "hw/net/lan9118.h"
90
#include "hw/pci/pci.h"
91
#include "net/net.h"
92
#include "sysemu/sysemu.h"
93
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/hw/arm/vexpress.c
96
+++ b/hw/arm/vexpress.c
97
@@ -XXX,XX +XXX,XX @@
98
#include "hw/sysbus.h"
99
#include "hw/arm/arm.h"
100
#include "hw/arm/primecell.h"
101
-#include "hw/devices.h"
102
+#include "hw/net/lan9118.h"
103
#include "hw/i2c/i2c.h"
104
#include "net/net.h"
105
#include "sysemu/sysemu.h"
106
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/hw/net/lan9118.c
109
+++ b/hw/net/lan9118.c
110
@@ -XXX,XX +XXX,XX @@
111
#include "hw/sysbus.h"
112
#include "net/net.h"
113
#include "net/eth.h"
114
-#include "hw/devices.h"
115
+#include "hw/net/lan9118.h"
116
#include "sysemu/sysemu.h"
117
#include "hw/ptimer.h"
118
#include "qemu/log.h"
119
--
80
--
120
2.20.1
81
2.20.1
121
82
122
83
diff view generated by jsdifflib
1
For v8M floating point support, transitions from Secure
1
Implement the fp16 version of the VFP VRINT* insns.
2
to Non-secure state via BLNS and BLXNS must clear the
3
CONTROL.SFPA bit. (This corresponds to the pseudocode
4
BranchToNS() function.)
5
2
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190416125744.27770-13-peter.maydell@linaro.org
5
Message-id: 20200828183354.27913-19-peter.maydell@linaro.org
9
---
6
---
10
target/arm/helper.c | 4 ++++
7
target/arm/helper.h | 2 +
11
1 file changed, 4 insertions(+)
8
target/arm/vfp-uncond.decode | 6 ++-
12
9
target/arm/vfp.decode | 3 ++
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
10
target/arm/vfp_helper.c | 21 ++++++++
14
index XXXXXXX..XXXXXXX 100644
11
target/arm/translate-vfp.c.inc | 98 +++++++++++++++++++++++++++++++---
15
--- a/target/arm/helper.c
12
5 files changed, 122 insertions(+), 8 deletions(-)
16
+++ b/target/arm/helper.c
13
17
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
/* translate.c should have made BXNS UNDEF unless we're secure */
15
index XXXXXXX..XXXXXXX 100644
19
assert(env->v7m.secure);
16
--- a/target/arm/helper.h
20
17
+++ b/target/arm/helper.h
21
+ if (!(dest & 1)) {
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(shr_cc, i32, env, i32, i32)
22
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
19
DEF_HELPER_3(sar_cc, i32, env, i32, i32)
23
+ }
20
DEF_HELPER_3(ror_cc, i32, env, i32, i32)
24
switch_v7m_security_state(env, dest & 1);
21
25
env->thumb = 1;
22
+DEF_HELPER_FLAGS_2(rinth_exact, TCG_CALL_NO_RWG, f16, f16, ptr)
26
env->regs[15] = dest & ~1;
23
DEF_HELPER_FLAGS_2(rints_exact, TCG_CALL_NO_RWG, f32, f32, ptr)
27
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
24
DEF_HELPER_FLAGS_2(rintd_exact, TCG_CALL_NO_RWG, f64, f64, ptr)
28
*/
25
+DEF_HELPER_FLAGS_2(rinth, TCG_CALL_NO_RWG, f16, f16, ptr)
29
write_v7m_exception(env, 1);
26
DEF_HELPER_FLAGS_2(rints, TCG_CALL_NO_RWG, f32, f32, ptr)
30
}
27
DEF_HELPER_FLAGS_2(rintd, TCG_CALL_NO_RWG, f64, f64, ptr)
31
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
28
32
switch_v7m_security_state(env, 0);
29
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
33
env->thumb = 1;
30
index XXXXXXX..XXXXXXX 100644
34
env->regs[15] = dest;
31
--- a/target/arm/vfp-uncond.decode
32
+++ b/target/arm/vfp-uncond.decode
33
@@ -XXX,XX +XXX,XX @@ VMINNM_sp 1111 1110 1.00 .... .... 1010 .1.0 .... @vfp_dnm_s
34
VMAXNM_dp 1111 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
35
VMINNM_dp 1111 1110 1.00 .... .... 1011 .1.0 .... @vfp_dnm_d
36
37
+VRINT 1111 1110 1.11 10 rm:2 .... 1001 01.0 .... \
38
+ vm=%vm_sp vd=%vd_sp sz=1
39
VRINT 1111 1110 1.11 10 rm:2 .... 1010 01.0 .... \
40
- vm=%vm_sp vd=%vd_sp dp=0
41
+ vm=%vm_sp vd=%vd_sp sz=2
42
VRINT 1111 1110 1.11 10 rm:2 .... 1011 01.0 .... \
43
- vm=%vm_dp vd=%vd_dp dp=1
44
+ vm=%vm_dp vd=%vd_dp sz=3
45
46
# VCVT float to int with specified rounding mode; Vd is always single-precision
47
VCVT 1111 1110 1.11 11 rm:2 .... 1001 op:1 1.0 .... \
48
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/vfp.decode
51
+++ b/target/arm/vfp.decode
52
@@ -XXX,XX +XXX,XX @@ VCVT_f16_f32 ---- 1110 1.11 0011 .... 1010 t:1 1.0 .... \
53
VCVT_f16_f64 ---- 1110 1.11 0011 .... 1011 t:1 1.0 .... \
54
vd=%vd_sp vm=%vm_dp
55
56
+VRINTR_hp ---- 1110 1.11 0110 .... 1001 01.0 .... @vfp_dm_ss
57
VRINTR_sp ---- 1110 1.11 0110 .... 1010 01.0 .... @vfp_dm_ss
58
VRINTR_dp ---- 1110 1.11 0110 .... 1011 01.0 .... @vfp_dm_dd
59
60
+VRINTZ_hp ---- 1110 1.11 0110 .... 1001 11.0 .... @vfp_dm_ss
61
VRINTZ_sp ---- 1110 1.11 0110 .... 1010 11.0 .... @vfp_dm_ss
62
VRINTZ_dp ---- 1110 1.11 0110 .... 1011 11.0 .... @vfp_dm_dd
63
64
+VRINTX_hp ---- 1110 1.11 0111 .... 1001 01.0 .... @vfp_dm_ss
65
VRINTX_sp ---- 1110 1.11 0111 .... 1010 01.0 .... @vfp_dm_ss
66
VRINTX_dp ---- 1110 1.11 0111 .... 1011 01.0 .... @vfp_dm_dd
67
68
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/target/arm/vfp_helper.c
71
+++ b/target/arm/vfp_helper.c
72
@@ -XXX,XX +XXX,XX @@ float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
73
}
74
75
/* ARMv8 round to integral */
76
+dh_ctype_f16 HELPER(rinth_exact)(dh_ctype_f16 x, void *fp_status)
77
+{
78
+ return float16_round_to_int(x, fp_status);
79
+}
80
+
81
float32 HELPER(rints_exact)(float32 x, void *fp_status)
82
{
83
return float32_round_to_int(x, fp_status);
84
@@ -XXX,XX +XXX,XX @@ float64 HELPER(rintd_exact)(float64 x, void *fp_status)
85
return float64_round_to_int(x, fp_status);
86
}
87
88
+dh_ctype_f16 HELPER(rinth)(dh_ctype_f16 x, void *fp_status)
89
+{
90
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
91
+ float16 ret;
92
+
93
+ ret = float16_round_to_int(x, fp_status);
94
+
95
+ /* Suppress any inexact exceptions the conversion produced */
96
+ if (!(old_flags & float_flag_inexact)) {
97
+ new_flags = get_float_exception_flags(fp_status);
98
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
99
+ }
100
+
101
+ return ret;
102
+}
103
+
104
float32 HELPER(rints)(float32 x, void *fp_status)
105
{
106
int old_flags = get_float_exception_flags(fp_status), new_flags;
107
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
108
index XXXXXXX..XXXXXXX 100644
109
--- a/target/arm/translate-vfp.c.inc
110
+++ b/target/arm/translate-vfp.c.inc
111
@@ -XXX,XX +XXX,XX @@ static const uint8_t fp_decode_rm[] = {
112
static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
113
{
114
uint32_t rd, rm;
115
- bool dp = a->dp;
116
+ int sz = a->sz;
117
TCGv_ptr fpst;
118
TCGv_i32 tcg_rmode;
119
int rounding = fp_decode_rm[a->rm];
120
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
121
return false;
122
}
123
124
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
125
+ if (sz == 3 && !dc_isar_feature(aa32_fpdp_v2, s)) {
126
+ return false;
127
+ }
128
+
129
+ if (sz == 1 && !dc_isar_feature(aa32_fp16_arith, s)) {
130
return false;
131
}
132
133
/* UNDEF accesses to D16-D31 if they don't exist */
134
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
135
+ if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) &&
136
((a->vm | a->vd) & 0x10)) {
137
return false;
138
}
139
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
140
return true;
141
}
142
143
- fpst = fpstatus_ptr(FPST_FPCR);
144
+ if (sz == 1) {
145
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
146
+ } else {
147
+ fpst = fpstatus_ptr(FPST_FPCR);
148
+ }
149
150
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
151
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
152
153
- if (dp) {
154
+ if (sz == 3) {
155
TCGv_i64 tcg_op;
156
TCGv_i64 tcg_res;
157
tcg_op = tcg_temp_new_i64();
158
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
159
tcg_op = tcg_temp_new_i32();
160
tcg_res = tcg_temp_new_i32();
161
neon_load_reg32(tcg_op, rm);
162
- gen_helper_rints(tcg_res, tcg_op, fpst);
163
+ if (sz == 1) {
164
+ gen_helper_rinth(tcg_res, tcg_op, fpst);
165
+ } else {
166
+ gen_helper_rints(tcg_res, tcg_op, fpst);
167
+ }
168
neon_store_reg32(tcg_res, rd);
169
tcg_temp_free_i32(tcg_op);
170
tcg_temp_free_i32(tcg_res);
171
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
172
return true;
173
}
174
175
+static bool trans_VRINTR_hp(DisasContext *s, arg_VRINTR_sp *a)
176
+{
177
+ TCGv_ptr fpst;
178
+ TCGv_i32 tmp;
179
+
180
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
181
+ return false;
182
+ }
183
+
184
+ if (!vfp_access_check(s)) {
185
+ return true;
186
+ }
187
+
188
+ tmp = tcg_temp_new_i32();
189
+ neon_load_reg32(tmp, a->vm);
190
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
191
+ gen_helper_rinth(tmp, tmp, fpst);
192
+ neon_store_reg32(tmp, a->vd);
193
+ tcg_temp_free_ptr(fpst);
194
+ tcg_temp_free_i32(tmp);
195
+ return true;
196
+}
197
+
198
static bool trans_VRINTR_sp(DisasContext *s, arg_VRINTR_sp *a)
199
{
200
TCGv_ptr fpst;
201
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
202
return true;
203
}
204
205
+static bool trans_VRINTZ_hp(DisasContext *s, arg_VRINTZ_sp *a)
206
+{
207
+ TCGv_ptr fpst;
208
+ TCGv_i32 tmp;
209
+ TCGv_i32 tcg_rmode;
210
+
211
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
212
+ return false;
213
+ }
214
+
215
+ if (!vfp_access_check(s)) {
216
+ return true;
217
+ }
218
+
219
+ tmp = tcg_temp_new_i32();
220
+ neon_load_reg32(tmp, a->vm);
221
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
222
+ tcg_rmode = tcg_const_i32(float_round_to_zero);
223
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
224
+ gen_helper_rinth(tmp, tmp, fpst);
225
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
226
+ neon_store_reg32(tmp, a->vd);
227
+ tcg_temp_free_ptr(fpst);
228
+ tcg_temp_free_i32(tcg_rmode);
229
+ tcg_temp_free_i32(tmp);
230
+ return true;
231
+}
232
+
233
static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a)
234
{
235
TCGv_ptr fpst;
236
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
237
return true;
238
}
239
240
+static bool trans_VRINTX_hp(DisasContext *s, arg_VRINTX_sp *a)
241
+{
242
+ TCGv_ptr fpst;
243
+ TCGv_i32 tmp;
244
+
245
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
246
+ return false;
247
+ }
248
+
249
+ if (!vfp_access_check(s)) {
250
+ return true;
251
+ }
252
+
253
+ tmp = tcg_temp_new_i32();
254
+ neon_load_reg32(tmp, a->vm);
255
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
256
+ gen_helper_rinth_exact(tmp, tmp, fpst);
257
+ neon_store_reg32(tmp, a->vd);
258
+ tcg_temp_free_ptr(fpst);
259
+ tcg_temp_free_i32(tmp);
260
+ return true;
261
+}
262
+
263
static bool trans_VRINTX_sp(DisasContext *s, arg_VRINTX_sp *a)
264
{
265
TCGv_ptr fpst;
35
--
266
--
36
2.20.1
267
2.20.1
37
268
38
269
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
The fp16 extension includes a new instruction VINS, which copies the
2
lower 16 bits of a 32-bit source VFP register into the upper 16 bits
3
of the destination. Implement it.
2
4
3
Reviewed-by: Thomas Huth <thuth@redhat.com>
4
Reviewed-by: Markus Armbruster <armbru@redhat.com>
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Message-id: 20190412165416.7977-11-philmd@redhat.com
7
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>
7
Message-id: 20200828183354.27913-20-peter.maydell@linaro.org
8
---
8
---
9
include/hw/net/ne2000-isa.h | 6 ++++++
9
target/arm/vfp-uncond.decode | 3 +++
10
1 file changed, 6 insertions(+)
10
target/arm/translate-vfp.c.inc | 28 ++++++++++++++++++++++++++++
11
2 files changed, 31 insertions(+)
11
12
12
diff --git a/include/hw/net/ne2000-isa.h b/include/hw/net/ne2000-isa.h
13
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/net/ne2000-isa.h
15
--- a/target/arm/vfp-uncond.decode
15
+++ b/include/hw/net/ne2000-isa.h
16
+++ b/target/arm/vfp-uncond.decode
16
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ VCVT 1111 1110 1.11 11 rm:2 .... 1010 op:1 1.0 .... \
17
* This work is licensed under the terms of the GNU GPL, version 2 or later.
18
vm=%vm_sp vd=%vd_sp sz=2
18
* See the COPYING file in the top-level directory.
19
VCVT 1111 1110 1.11 11 rm:2 .... 1011 op:1 1.0 .... \
19
*/
20
vm=%vm_dp vd=%vd_sp sz=3
20
+
21
+
21
+#ifndef HW_NET_NE2K_ISA_H
22
+VINS 1111 1110 1.11 0000 .... 1010 11 . 0 .... \
22
+#define HW_NET_NE2K_ISA_H
23
+ vd=%vd_sp vm=%vm_sp
23
+
24
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
24
#include "hw/hw.h"
25
index XXXXXXX..XXXXXXX 100644
25
#include "hw/qdev.h"
26
--- a/target/arm/translate-vfp.c.inc
26
#include "hw/isa/isa.h"
27
+++ b/target/arm/translate-vfp.c.inc
27
@@ -XXX,XX +XXX,XX @@ static inline ISADevice *isa_ne2000_init(ISABus *bus, int base, int irq,
28
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
28
}
29
29
return d;
30
return false;
30
}
31
}
31
+
32
+
32
+#endif
33
+static bool trans_VINS(DisasContext *s, arg_VINS *a)
34
+{
35
+ TCGv_i32 rd, rm;
36
+
37
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
38
+ return false;
39
+ }
40
+
41
+ if (s->vec_len != 0 || s->vec_stride != 0) {
42
+ return false;
43
+ }
44
+
45
+ if (!vfp_access_check(s)) {
46
+ return true;
47
+ }
48
+
49
+ /* Insert low half of Vm into high half of Vd */
50
+ rm = tcg_temp_new_i32();
51
+ rd = tcg_temp_new_i32();
52
+ neon_load_reg32(rm, a->vm);
53
+ neon_load_reg32(rd, a->vd);
54
+ tcg_gen_deposit_i32(rd, rd, rm, 16, 16);
55
+ neon_store_reg32(rd, a->vd);
56
+ tcg_temp_free_i32(rm);
57
+ tcg_temp_free_i32(rd);
58
+ return true;
59
+}
33
--
60
--
34
2.20.1
61
2.20.1
35
62
36
63
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
The fp16 extension includes a new instruction VMOVX, which copies the
2
upper 16 bits of a 32-bit source VFP register into the lower 16
3
bits of the destination and zeroes the high half of the destination.
4
Implement it.
2
5
3
Since uWireSlave is only used in this new header, there is no
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
need to expose it via "qemu/typedefs.h".
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200828183354.27913-21-peter.maydell@linaro.org
9
---
10
target/arm/vfp-uncond.decode | 3 +++
11
target/arm/translate-vfp.c.inc | 25 +++++++++++++++++++++++++
12
2 files changed, 28 insertions(+)
5
13
6
Reviewed-by: Markus Armbruster <armbru@redhat.com>
14
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20190412165416.7977-9-philmd@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/arm/omap.h | 6 +-----
12
include/hw/devices.h | 15 ---------------
13
include/hw/input/tsc2xxx.h | 36 ++++++++++++++++++++++++++++++++++++
14
include/qemu/typedefs.h | 1 -
15
hw/arm/nseries.c | 2 +-
16
hw/arm/palm.c | 2 +-
17
hw/input/tsc2005.c | 2 +-
18
hw/input/tsc210x.c | 4 ++--
19
MAINTAINERS | 2 ++
20
9 files changed, 44 insertions(+), 26 deletions(-)
21
create mode 100644 include/hw/input/tsc2xxx.h
22
23
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
24
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/omap.h
16
--- a/target/arm/vfp-uncond.decode
26
+++ b/include/hw/arm/omap.h
17
+++ b/target/arm/vfp-uncond.decode
27
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ VCVT 1111 1110 1.11 11 rm:2 .... 1010 op:1 1.0 .... \
28
#include "exec/memory.h"
19
VCVT 1111 1110 1.11 11 rm:2 .... 1011 op:1 1.0 .... \
29
# define hw_omap_h        "omap.h"
20
vm=%vm_dp vd=%vd_sp sz=3
30
#include "hw/irq.h"
21
31
+#include "hw/input/tsc2xxx.h"
22
+VMOVX 1111 1110 1.11 0000 .... 1010 01 . 0 .... \
32
#include "target/arm/cpu-qom.h"
23
+ vd=%vd_sp vm=%vm_sp
33
#include "qemu/log.h"
24
+
34
25
VINS 1111 1110 1.11 0000 .... 1010 11 . 0 .... \
35
@@ -XXX,XX +XXX,XX @@ qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
26
vd=%vd_sp vm=%vm_sp
36
void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
27
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
37
void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
38
39
-struct uWireSlave {
40
- uint16_t (*receive)(void *opaque);
41
- void (*send)(void *opaque, uint16_t data);
42
- void *opaque;
43
-};
44
struct omap_uwire_s;
45
void omap_uwire_attach(struct omap_uwire_s *s,
46
uWireSlave *slave, int chipselect);
47
diff --git a/include/hw/devices.h b/include/hw/devices.h
48
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
49
--- a/include/hw/devices.h
29
--- a/target/arm/translate-vfp.c.inc
50
+++ b/include/hw/devices.h
30
+++ b/target/arm/translate-vfp.c.inc
51
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@ static bool trans_VINS(DisasContext *s, arg_VINS *a)
52
/* Devices that have nowhere better to go. */
32
tcg_temp_free_i32(rd);
53
33
return true;
54
#include "hw/hw.h"
34
}
55
-#include "ui/console.h"
56
57
/* smc91c111.c */
58
void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
59
@@ -XXX,XX +XXX,XX @@ void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
60
/* lan9118.c */
61
void lan9118_init(NICInfo *, uint32_t, qemu_irq);
62
63
-/* tsc210x.c */
64
-uWireSlave *tsc2102_init(qemu_irq pint);
65
-uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav);
66
-I2SCodec *tsc210x_codec(uWireSlave *chip);
67
-uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len);
68
-void tsc210x_set_transform(uWireSlave *chip,
69
- MouseTransformInfo *info);
70
-void tsc210x_key_event(uWireSlave *chip, int key, int down);
71
-
72
-/* tsc2005.c */
73
-void *tsc2005_init(qemu_irq pintdav);
74
-uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
75
-void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
76
-
77
#endif
78
diff --git a/include/hw/input/tsc2xxx.h b/include/hw/input/tsc2xxx.h
79
new file mode 100644
80
index XXXXXXX..XXXXXXX
81
--- /dev/null
82
+++ b/include/hw/input/tsc2xxx.h
83
@@ -XXX,XX +XXX,XX @@
84
+/*
85
+ * TI touchscreen controller
86
+ *
87
+ * Copyright (c) 2006 Andrzej Zaborowski
88
+ * Copyright (C) 2008 Nokia Corporation
89
+ *
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
91
+ * See the COPYING file in the top-level directory.
92
+ */
93
+
35
+
94
+#ifndef HW_INPUT_TSC2XXX_H
36
+static bool trans_VMOVX(DisasContext *s, arg_VINS *a)
95
+#define HW_INPUT_TSC2XXX_H
37
+{
38
+ TCGv_i32 rm;
96
+
39
+
97
+#include "hw/irq.h"
40
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
98
+#include "ui/console.h"
41
+ return false;
42
+ }
99
+
43
+
100
+typedef struct uWireSlave {
44
+ if (s->vec_len != 0 || s->vec_stride != 0) {
101
+ uint16_t (*receive)(void *opaque);
45
+ return false;
102
+ void (*send)(void *opaque, uint16_t data);
46
+ }
103
+ void *opaque;
104
+} uWireSlave;
105
+
47
+
106
+/* tsc210x.c */
48
+ if (!vfp_access_check(s)) {
107
+uWireSlave *tsc2102_init(qemu_irq pint);
49
+ return true;
108
+uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav);
50
+ }
109
+I2SCodec *tsc210x_codec(uWireSlave *chip);
110
+uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len);
111
+void tsc210x_set_transform(uWireSlave *chip, MouseTransformInfo *info);
112
+void tsc210x_key_event(uWireSlave *chip, int key, int down);
113
+
51
+
114
+/* tsc2005.c */
52
+ /* Set Vd to high half of Vm */
115
+void *tsc2005_init(qemu_irq pintdav);
53
+ rm = tcg_temp_new_i32();
116
+uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
54
+ neon_load_reg32(rm, a->vm);
117
+void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
55
+ tcg_gen_shri_i32(rm, rm, 16);
118
+
56
+ neon_store_reg32(rm, a->vd);
119
+#endif
57
+ tcg_temp_free_i32(rm);
120
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
58
+ return true;
121
index XXXXXXX..XXXXXXX 100644
59
+}
122
--- a/include/qemu/typedefs.h
123
+++ b/include/qemu/typedefs.h
124
@@ -XXX,XX +XXX,XX @@ typedef struct RAMBlock RAMBlock;
125
typedef struct Range Range;
126
typedef struct SHPCDevice SHPCDevice;
127
typedef struct SSIBus SSIBus;
128
-typedef struct uWireSlave uWireSlave;
129
typedef struct VirtIODevice VirtIODevice;
130
typedef struct Visitor Visitor;
131
typedef void SaveStateHandler(QEMUFile *f, void *opaque);
132
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/hw/arm/nseries.c
135
+++ b/hw/arm/nseries.c
136
@@ -XXX,XX +XXX,XX @@
137
#include "ui/console.h"
138
#include "hw/boards.h"
139
#include "hw/i2c/i2c.h"
140
-#include "hw/devices.h"
141
#include "hw/display/blizzard.h"
142
+#include "hw/input/tsc2xxx.h"
143
#include "hw/misc/cbus.h"
144
#include "hw/misc/tmp105.h"
145
#include "hw/block/flash.h"
146
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/arm/palm.c
149
+++ b/hw/arm/palm.c
150
@@ -XXX,XX +XXX,XX @@
151
#include "hw/arm/omap.h"
152
#include "hw/boards.h"
153
#include "hw/arm/arm.h"
154
-#include "hw/devices.h"
155
+#include "hw/input/tsc2xxx.h"
156
#include "hw/loader.h"
157
#include "exec/address-spaces.h"
158
#include "cpu.h"
159
diff --git a/hw/input/tsc2005.c b/hw/input/tsc2005.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/hw/input/tsc2005.c
162
+++ b/hw/input/tsc2005.c
163
@@ -XXX,XX +XXX,XX @@
164
#include "hw/hw.h"
165
#include "qemu/timer.h"
166
#include "ui/console.h"
167
-#include "hw/devices.h"
168
+#include "hw/input/tsc2xxx.h"
169
#include "trace.h"
170
171
#define TSC_CUT_RESOLUTION(value, p)    ((value) >> (16 - (p ? 12 : 10)))
172
diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/hw/input/tsc210x.c
175
+++ b/hw/input/tsc210x.c
176
@@ -XXX,XX +XXX,XX @@
177
#include "audio/audio.h"
178
#include "qemu/timer.h"
179
#include "ui/console.h"
180
-#include "hw/arm/omap.h"    /* For I2SCodec and uWireSlave */
181
-#include "hw/devices.h"
182
+#include "hw/arm/omap.h" /* For I2SCodec */
183
+#include "hw/input/tsc2xxx.h"
184
185
#define TSC_DATA_REGISTERS_PAGE        0x0
186
#define TSC_CONTROL_REGISTERS_PAGE    0x1
187
diff --git a/MAINTAINERS b/MAINTAINERS
188
index XXXXXXX..XXXXXXX 100644
189
--- a/MAINTAINERS
190
+++ b/MAINTAINERS
191
@@ -XXX,XX +XXX,XX @@ F: hw/input/tsc2005.c
192
F: hw/misc/cbus.c
193
F: hw/timer/twl92230.c
194
F: include/hw/display/blizzard.h
195
+F: include/hw/input/tsc2xxx.h
196
F: include/hw/misc/cbus.h
197
198
Palm
199
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
200
S: Odd Fixes
201
F: hw/arm/palm.c
202
F: hw/input/tsc210x.c
203
+F: include/hw/input/tsc2xxx.h
204
205
Raspberry Pi
206
M: Peter Maydell <peter.maydell@linaro.org>
207
--
60
--
208
2.20.1
61
2.20.1
209
62
210
63
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
Implement the VFP fp16 variant of VMOV that transfers a 16-bit
2
value between a general purpose register and a VFP register.
2
3
3
Reviewed-by: Markus Armbruster <armbru@redhat.com>
4
Note that Rt == 15 is UNPREDICTABLE; since this insn is v8 and later
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
only we have no need to replicate the old "updates CPSR.NZCV"
5
Message-id: 20190412165416.7977-8-philmd@redhat.com
6
behaviour that the singleprec version of this insn does.
7
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200828183354.27913-22-peter.maydell@linaro.org
7
---
11
---
8
include/hw/devices.h | 3 ---
12
target/arm/vfp.decode | 1 +
9
include/hw/input/gamepad.h | 19 +++++++++++++++++++
13
target/arm/translate-vfp.c.inc | 34 ++++++++++++++++++++++++++++++++++
10
hw/arm/stellaris.c | 2 +-
14
2 files changed, 35 insertions(+)
11
hw/input/stellaris_input.c | 2 +-
12
MAINTAINERS | 1 +
13
5 files changed, 22 insertions(+), 5 deletions(-)
14
create mode 100644 include/hw/input/gamepad.h
15
15
16
diff --git a/include/hw/devices.h b/include/hw/devices.h
16
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/devices.h
18
--- a/target/arm/vfp.decode
19
+++ b/include/hw/devices.h
19
+++ b/target/arm/vfp.decode
20
@@ -XXX,XX +XXX,XX @@ void *tsc2005_init(qemu_irq pintdav);
20
@@ -XXX,XX +XXX,XX @@ VDUP ---- 1110 1 b:1 q:1 0 .... rt:4 1011 . 0 e:1 1 0000 \
21
uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
21
vn=%vn_dp
22
void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
22
23
23
VMSR_VMRS ---- 1110 111 l:1 reg:4 rt:4 1010 0001 0000
24
-/* stellaris_input.c */
24
+VMOV_half ---- 1110 000 l:1 .... rt:4 1001 . 001 0000 vn=%vn_sp
25
-void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
25
VMOV_single ---- 1110 000 l:1 .... rt:4 1010 . 001 0000 vn=%vn_sp
26
-
26
27
#endif
27
VMOV_64_sp ---- 1100 010 op:1 rt2:4 rt:4 1010 00.1 .... vm=%vm_sp
28
diff --git a/include/hw/input/gamepad.h b/include/hw/input/gamepad.h
28
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
29
new file mode 100644
29
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX
30
--- a/target/arm/translate-vfp.c.inc
31
--- /dev/null
31
+++ b/target/arm/translate-vfp.c.inc
32
+++ b/include/hw/input/gamepad.h
32
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
33
@@ -XXX,XX +XXX,XX @@
33
return true;
34
+/*
34
}
35
+ * Gamepad style buttons connected to IRQ/GPIO lines
35
36
+ *
36
+static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
37
+ * Copyright (c) 2007 CodeSourcery.
37
+{
38
+ * Written by Paul Brook
38
+ TCGv_i32 tmp;
39
+ *
40
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
41
+ * See the COPYING file in the top-level directory.
42
+ */
43
+
39
+
44
+#ifndef HW_INPUT_GAMEPAD_H
40
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
45
+#define HW_INPUT_GAMEPAD_H
41
+ return false;
42
+ }
46
+
43
+
47
+#include "hw/irq.h"
44
+ if (a->rt == 15) {
45
+ /* UNPREDICTABLE; we choose to UNDEF */
46
+ return false;
47
+ }
48
+
48
+
49
+/* stellaris_input.c */
49
+ if (!vfp_access_check(s)) {
50
+void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
50
+ return true;
51
+ }
51
+
52
+
52
+#endif
53
+ if (a->l) {
53
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
54
+ /* VFP to general purpose register */
54
index XXXXXXX..XXXXXXX 100644
55
+ tmp = tcg_temp_new_i32();
55
--- a/hw/arm/stellaris.c
56
+ neon_load_reg32(tmp, a->vn);
56
+++ b/hw/arm/stellaris.c
57
+ tcg_gen_andi_i32(tmp, tmp, 0xffff);
57
@@ -XXX,XX +XXX,XX @@
58
+ store_reg(s, a->rt, tmp);
58
#include "hw/sysbus.h"
59
+ } else {
59
#include "hw/ssi/ssi.h"
60
+ /* general purpose register to VFP */
60
#include "hw/arm/arm.h"
61
+ tmp = load_reg(s, a->rt);
61
-#include "hw/devices.h"
62
+ tcg_gen_andi_i32(tmp, tmp, 0xffff);
62
#include "qemu/timer.h"
63
+ neon_store_reg32(tmp, a->vn);
63
#include "hw/i2c/i2c.h"
64
+ tcg_temp_free_i32(tmp);
64
#include "net/net.h"
65
+ }
65
@@ -XXX,XX +XXX,XX @@
66
+
66
#include "sysemu/sysemu.h"
67
+ return true;
67
#include "hw/arm/armv7m.h"
68
+}
68
#include "hw/char/pl011.h"
69
+
69
+#include "hw/input/gamepad.h"
70
static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a)
70
#include "hw/watchdog/cmsdk-apb-watchdog.h"
71
{
71
#include "hw/misc/unimp.h"
72
TCGv_i32 tmp;
72
#include "cpu.h"
73
diff --git a/hw/input/stellaris_input.c b/hw/input/stellaris_input.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/input/stellaris_input.c
76
+++ b/hw/input/stellaris_input.c
77
@@ -XXX,XX +XXX,XX @@
78
*/
79
#include "qemu/osdep.h"
80
#include "hw/hw.h"
81
-#include "hw/devices.h"
82
+#include "hw/input/gamepad.h"
83
#include "ui/console.h"
84
85
typedef struct {
86
diff --git a/MAINTAINERS b/MAINTAINERS
87
index XXXXXXX..XXXXXXX 100644
88
--- a/MAINTAINERS
89
+++ b/MAINTAINERS
90
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
91
L: qemu-arm@nongnu.org
92
S: Maintained
93
F: hw/*/stellaris*
94
+F: include/hw/input/gamepad.h
95
96
Versatile Express
97
M: Peter Maydell <peter.maydell@linaro.org>
98
--
73
--
99
2.20.1
74
2.20.1
100
75
101
76
diff view generated by jsdifflib
1
Implement the VLLDM instruction for v7M for the FPU present cas.
1
Implement FP16 support for the Neon insns which use the DO_3S_FP_GVEC
2
macro: VADD, VSUB, VABD, VMUL.
3
4
For VABD this requires us to implement a new gvec_fabd_h helper
5
using the machinery we have already for the other helpers.
2
6
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190416125744.27770-26-peter.maydell@linaro.org
9
Message-id: 20200828183354.27913-24-peter.maydell@linaro.org
6
---
10
---
7
target/arm/helper.h | 1 +
11
target/arm/helper.h | 1 +
8
target/arm/helper.c | 54 ++++++++++++++++++++++++++++++++++++++++++
12
target/arm/vec_helper.c | 6 ++++++
9
target/arm/translate.c | 2 +-
13
target/arm/translate-neon.c.inc | 36 +++++++++++++++++----------------
10
3 files changed, 56 insertions(+), 1 deletion(-)
14
3 files changed, 26 insertions(+), 17 deletions(-)
11
15
12
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.h
18
--- a/target/arm/helper.h
15
+++ b/target/arm/helper.h
19
+++ b/target/arm/helper.h
16
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmul_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
17
DEF_HELPER_1(v7m_preserve_fp_state, void, env)
21
DEF_HELPER_FLAGS_5(gvec_fmul_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
18
22
DEF_HELPER_FLAGS_5(gvec_fmul_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
DEF_HELPER_2(v7m_vlstm, void, env, i32)
23
20
+DEF_HELPER_2(v7m_vlldm, void, env, i32)
24
+DEF_HELPER_FLAGS_5(gvec_fabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
25
DEF_HELPER_FLAGS_5(gvec_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
22
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
26
23
27
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
24
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
25
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.c
30
--- a/target/arm/vec_helper.c
27
+++ b/target/arm/helper.c
31
+++ b/target/arm/vec_helper.c
28
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
32
@@ -XXX,XX +XXX,XX @@ static float64 float64_ftsmul(float64 op1, uint64_t op2, float_status *stat)
29
g_assert_not_reached();
33
return result;
30
}
34
}
31
35
32
+void HELPER(v7m_vlldm)(CPUARMState *env, uint32_t fptr)
36
+static float16 float16_abd(float16 op1, float16 op2, float_status *stat)
33
+{
37
+{
34
+ /* translate.c should never generate calls here in user-only mode */
38
+ return float16_abs(float16_sub(op1, op2, stat));
35
+ g_assert_not_reached();
36
+}
39
+}
37
+
40
+
38
uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
41
static float32 float32_abd(float32 op1, float32 op2, float_status *stat)
39
{
42
{
40
/* The TT instructions can be used by unprivileged code, but in
43
return float32_abs(float32_sub(op1, op2, stat));
41
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
44
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_ftsmul_h, float16_ftsmul, float16)
42
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
45
DO_3OP(gvec_ftsmul_s, float32_ftsmul, float32)
46
DO_3OP(gvec_ftsmul_d, float64_ftsmul, float64)
47
48
+DO_3OP(gvec_fabd_h, float16_abd, float16)
49
DO_3OP(gvec_fabd_s, float32_abd, float32)
50
51
#ifdef TARGET_AARCH64
52
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/translate-neon.c.inc
55
+++ b/target/arm/translate-neon.c.inc
56
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn,
57
return true;
43
}
58
}
44
59
45
+void HELPER(v7m_vlldm)(CPUARMState *env, uint32_t fptr)
60
-/*
46
+{
61
- * For all the functions using this macro, size == 1 means fp16,
47
+ /* fptr is the value of Rn, the frame pointer we load the FP regs from */
62
- * which is an architecture extension we don't implement yet.
48
+ assert(env->v7m.secure);
63
- */
49
+
64
-#define DO_3S_FP_GVEC(INSN,FUNC) \
50
+ if (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)) {
65
- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
51
+ return;
66
- uint32_t rn_ofs, uint32_t rm_ofs, \
67
- uint32_t oprsz, uint32_t maxsz) \
68
+#define WRAP_FP_GVEC(WRAPNAME, FPST, FUNC) \
69
+ static void WRAPNAME(unsigned vece, uint32_t rd_ofs, \
70
+ uint32_t rn_ofs, uint32_t rm_ofs, \
71
+ uint32_t oprsz, uint32_t maxsz) \
72
{ \
73
- TCGv_ptr fpst = fpstatus_ptr(FPST_STD); \
74
+ TCGv_ptr fpst = fpstatus_ptr(FPST); \
75
tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpst, \
76
oprsz, maxsz, 0, FUNC); \
77
tcg_temp_free_ptr(fpst); \
78
- } \
52
+ }
79
+ }
53
+
80
+
54
+ /* Check access to the coprocessor is permitted */
81
+#define DO_3S_FP_GVEC(INSN,SFUNC,HFUNC) \
55
+ if (!v7m_cpacr_pass(env, true, arm_current_el(env) != 0)) {
82
+ WRAP_FP_GVEC(gen_##INSN##_fp32_3s, FPST_STD, SFUNC) \
56
+ raise_exception_ra(env, EXCP_NOCP, 0, 1, GETPC());
83
+ WRAP_FP_GVEC(gen_##INSN##_fp16_3s, FPST_STD_F16, HFUNC) \
57
+ }
84
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
58
+
85
{ \
59
+ if (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPACT_MASK) {
86
if (a->size != 0) { \
60
+ /* State in FP is still valid */
87
- /* TODO fp16 support */ \
61
+ env->v7m.fpccr[M_REG_S] &= ~R_V7M_FPCCR_LSPACT_MASK;
88
- return false; \
62
+ } else {
89
+ if (!dc_isar_feature(aa32_fp16_arith, s)) { \
63
+ bool ts = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK;
90
+ return false; \
64
+ int i;
91
+ } \
65
+ uint32_t fpscr;
92
+ return do_3same(s, a, gen_##INSN##_fp16_3s); \
66
+
93
} \
67
+ if (fptr & 7) {
94
- return do_3same(s, a, gen_##INSN##_3s); \
68
+ raise_exception_ra(env, EXCP_UNALIGNED, 0, 1, GETPC());
95
+ return do_3same(s, a, gen_##INSN##_fp32_3s); \
69
+ }
96
}
70
+
97
71
+ for (i = 0; i < (ts ? 32 : 16); i += 2) {
98
72
+ uint32_t slo, shi;
99
-DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s)
73
+ uint64_t dn;
100
-DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s)
74
+ uint32_t faddr = fptr + 4 * i;
101
-DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s)
75
+
102
-DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s)
76
+ if (i >= 16) {
103
+DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s, gen_helper_gvec_fadd_h)
77
+ faddr += 8; /* skip the slot for the FPSCR */
104
+DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s, gen_helper_gvec_fsub_h)
78
+ }
105
+DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s, gen_helper_gvec_fabd_h)
79
+
106
+DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s, gen_helper_gvec_fmul_h)
80
+ slo = cpu_ldl_data(env, faddr);
107
81
+ shi = cpu_ldl_data(env, faddr + 4);
108
/*
82
+
109
* For all the functions using this macro, size == 1 means fp16,
83
+ dn = (uint64_t) shi << 32 | slo;
84
+ *aa32_vfp_dreg(env, i / 2) = dn;
85
+ }
86
+ fpscr = cpu_ldl_data(env, fptr + 0x40);
87
+ vfp_set_fpscr(env, fpscr);
88
+ }
89
+
90
+ env->v7m.control[M_REG_S] |= R_V7M_CONTROL_FPCA_MASK;
91
+}
92
+
93
static bool v7m_push_stack(ARMCPU *cpu)
94
{
95
/* Do the "set up stack frame" part of exception entry,
96
diff --git a/target/arm/translate.c b/target/arm/translate.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate.c
99
+++ b/target/arm/translate.c
100
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
101
TCGv_i32 fptr = load_reg(s, rn);
102
103
if (extract32(insn, 20, 1)) {
104
- /* VLLDM */
105
+ gen_helper_v7m_vlldm(cpu_env, fptr);
106
} else {
107
gen_helper_v7m_vlstm(cpu_env, fptr);
108
}
109
--
110
--
110
2.20.1
111
2.20.1
111
112
112
113
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
We already have gvec helpers for floating point VRECPE and
2
VRQSRTE, so convert the Neon decoder to use them and
3
add the fp16 support.
2
4
3
Add an entries the Blizzard device in MAINTAINERS.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200828183354.27913-25-peter.maydell@linaro.org
8
---
9
target/arm/translate-neon.c.inc | 31 +++++++++++++++++++++++++++++--
10
1 file changed, 29 insertions(+), 2 deletions(-)
4
11
5
Reviewed-by: Thomas Huth <thuth@redhat.com>
12
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
6
Reviewed-by: Markus Armbruster <armbru@redhat.com>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20190412165416.7977-6-philmd@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/devices.h | 7 -------
12
include/hw/display/blizzard.h | 22 ++++++++++++++++++++++
13
hw/arm/nseries.c | 1 +
14
hw/display/blizzard.c | 2 +-
15
MAINTAINERS | 2 ++
16
5 files changed, 26 insertions(+), 8 deletions(-)
17
create mode 100644 include/hw/display/blizzard.h
18
19
diff --git a/include/hw/devices.h b/include/hw/devices.h
20
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/devices.h
14
--- a/target/arm/translate-neon.c.inc
22
+++ b/include/hw/devices.h
15
+++ b/target/arm/translate-neon.c.inc
23
@@ -XXX,XX +XXX,XX @@ void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
16
@@ -XXX,XX +XXX,XX @@ static bool do_2misc_fp(DisasContext *s, arg_2misc *a,
24
/* stellaris_input.c */
17
return do_2misc_fp(s, a, FUNC); \
25
void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
18
}
26
19
27
-/* blizzard.c */
20
-DO_2MISC_FP(VRECPE_F, gen_helper_recpe_f32)
28
-void *s1d13745_init(qemu_irq gpio_int);
21
-DO_2MISC_FP(VRSQRTE_F, gen_helper_rsqrte_f32)
29
-void s1d13745_write(void *opaque, int dc, uint16_t value);
22
DO_2MISC_FP(VCVT_FS, gen_helper_vfp_sitos)
30
-void s1d13745_write_block(void *opaque, int dc,
23
DO_2MISC_FP(VCVT_FU, gen_helper_vfp_uitos)
31
- void *buf, size_t len, int pitch);
24
DO_2MISC_FP(VCVT_SF, gen_helper_vfp_tosizs)
32
-uint16_t s1d13745_read(void *opaque, int dc);
25
DO_2MISC_FP(VCVT_UF, gen_helper_vfp_touizs)
33
-
26
34
/* cbus.c */
27
+#define DO_2MISC_FP_VEC(INSN, HFUNC, SFUNC) \
35
typedef struct {
28
+ static void gen_##INSN(unsigned vece, uint32_t rd_ofs, \
36
qemu_irq clk;
29
+ uint32_t rm_ofs, \
37
diff --git a/include/hw/display/blizzard.h b/include/hw/display/blizzard.h
30
+ uint32_t oprsz, uint32_t maxsz) \
38
new file mode 100644
31
+ { \
39
index XXXXXXX..XXXXXXX
32
+ static gen_helper_gvec_2_ptr * const fns[4] = { \
40
--- /dev/null
33
+ NULL, HFUNC, SFUNC, NULL, \
41
+++ b/include/hw/display/blizzard.h
34
+ }; \
42
@@ -XXX,XX +XXX,XX @@
35
+ TCGv_ptr fpst; \
43
+/*
36
+ fpst = fpstatus_ptr(vece == MO_16 ? FPST_STD_F16 : FPST_STD); \
44
+ * Epson S1D13744/S1D13745 (Blizzard/Hailstorm/Tornado) LCD/TV controller.
37
+ tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, oprsz, maxsz, 0, \
45
+ *
38
+ fns[vece]); \
46
+ * Copyright (C) 2008 Nokia Corporation
39
+ tcg_temp_free_ptr(fpst); \
47
+ * Written by Andrzej Zaborowski
40
+ } \
48
+ *
41
+ static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
49
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
42
+ { \
50
+ * See the COPYING file in the top-level directory.
43
+ if (a->size == MO_16) { \
51
+ */
44
+ if (!dc_isar_feature(aa32_fp16_arith, s)) { \
45
+ return false; \
46
+ } \
47
+ } else if (a->size != MO_32) { \
48
+ return false; \
49
+ } \
50
+ return do_2misc_vec(s, a, gen_##INSN); \
51
+ }
52
+
52
+
53
+#ifndef HW_DISPLAY_BLIZZARD_H
53
+DO_2MISC_FP_VEC(VRECPE_F, gen_helper_gvec_frecpe_h, gen_helper_gvec_frecpe_s)
54
+#define HW_DISPLAY_BLIZZARD_H
54
+DO_2MISC_FP_VEC(VRSQRTE_F, gen_helper_gvec_frsqrte_h, gen_helper_gvec_frsqrte_s)
55
+
55
+
56
+#include "hw/irq.h"
56
static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
57
+
57
{
58
+void *s1d13745_init(qemu_irq gpio_int);
58
if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
59
+void s1d13745_write(void *opaque, int dc, uint16_t value);
60
+void s1d13745_write_block(void *opaque, int dc,
61
+ void *buf, size_t len, int pitch);
62
+uint16_t s1d13745_read(void *opaque, int dc);
63
+
64
+#endif
65
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/arm/nseries.c
68
+++ b/hw/arm/nseries.c
69
@@ -XXX,XX +XXX,XX @@
70
#include "hw/boards.h"
71
#include "hw/i2c/i2c.h"
72
#include "hw/devices.h"
73
+#include "hw/display/blizzard.h"
74
#include "hw/misc/tmp105.h"
75
#include "hw/block/flash.h"
76
#include "hw/hw.h"
77
diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/display/blizzard.c
80
+++ b/hw/display/blizzard.c
81
@@ -XXX,XX +XXX,XX @@
82
#include "qemu/osdep.h"
83
#include "qemu-common.h"
84
#include "ui/console.h"
85
-#include "hw/devices.h"
86
+#include "hw/display/blizzard.h"
87
#include "ui/pixel_ops.h"
88
89
typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int);
90
diff --git a/MAINTAINERS b/MAINTAINERS
91
index XXXXXXX..XXXXXXX 100644
92
--- a/MAINTAINERS
93
+++ b/MAINTAINERS
94
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
95
L: qemu-arm@nongnu.org
96
S: Odd Fixes
97
F: hw/arm/nseries.c
98
+F: hw/display/blizzard.c
99
F: hw/input/lm832x.c
100
F: hw/input/tsc2005.c
101
F: hw/misc/cbus.c
102
F: hw/timer/twl92230.c
103
+F: include/hw/display/blizzard.h
104
105
Palm
106
M: Andrzej Zaborowski <balrogg@gmail.com>
107
--
59
--
108
2.20.1
60
2.20.1
109
61
110
62
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
Rewrite Neon VABS/VNEG of floats to use gvec logical AND and XOR, so
2
that we can implement the fp16 version of the insns.
2
3
3
Reviewed-by: Markus Armbruster <armbru@redhat.com>
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Message-id: 20190412165416.7977-5-philmd@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-26-peter.maydell@linaro.org
7
---
7
---
8
include/hw/devices.h | 6 ------
8
target/arm/translate-neon.c.inc | 34 +++++++++++++++++++++++++++------
9
include/hw/display/tc6393xb.h | 24 ++++++++++++++++++++++++
9
1 file changed, 28 insertions(+), 6 deletions(-)
10
hw/arm/tosa.c | 2 +-
11
hw/display/tc6393xb.c | 2 +-
12
MAINTAINERS | 1 +
13
5 files changed, 27 insertions(+), 8 deletions(-)
14
create mode 100644 include/hw/display/tc6393xb.h
15
10
16
diff --git a/include/hw/devices.h b/include/hw/devices.h
11
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/devices.h
13
--- a/target/arm/translate-neon.c.inc
19
+++ b/include/hw/devices.h
14
+++ b/target/arm/translate-neon.c.inc
20
@@ -XXX,XX +XXX,XX @@ void *tahvo_init(qemu_irq irq, int betty);
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VCNT(DisasContext *s, arg_2misc *a)
21
16
return do_2misc(s, a, gen_helper_neon_cnt_u8);
22
void retu_key_event(void *retu, int state);
17
}
23
18
24
-/* tc6393xb.c */
19
+static void gen_VABS_F(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
25
-typedef struct TC6393xbState TC6393xbState;
20
+ uint32_t oprsz, uint32_t maxsz)
26
-TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
21
+{
27
- uint32_t base, qemu_irq irq);
22
+ tcg_gen_gvec_andi(vece, rd_ofs, rm_ofs,
28
-qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
23
+ vece == MO_16 ? 0x7fff : 0x7fffffff,
29
-
24
+ oprsz, maxsz);
30
#endif
25
+}
31
diff --git a/include/hw/display/tc6393xb.h b/include/hw/display/tc6393xb.h
32
new file mode 100644
33
index XXXXXXX..XXXXXXX
34
--- /dev/null
35
+++ b/include/hw/display/tc6393xb.h
36
@@ -XXX,XX +XXX,XX @@
37
+/*
38
+ * Toshiba TC6393XB I/O Controller.
39
+ * Found in Sharp Zaurus SL-6000 (tosa) or some
40
+ * Toshiba e-Series PDAs.
41
+ *
42
+ * Copyright (c) 2007 Hervé Poussineau
43
+ *
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
45
+ * See the COPYING file in the top-level directory.
46
+ */
47
+
26
+
48
+#ifndef HW_DISPLAY_TC6393XB_H
27
static bool trans_VABS_F(DisasContext *s, arg_2misc *a)
49
+#define HW_DISPLAY_TC6393XB_H
28
{
29
- if (a->size != 2) {
30
+ if (a->size == MO_16) {
31
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
32
+ return false;
33
+ }
34
+ } else if (a->size != MO_32) {
35
return false;
36
}
37
- /* TODO: FP16 : size == 1 */
38
- return do_2misc(s, a, gen_helper_vfp_abss);
39
+ return do_2misc_vec(s, a, gen_VABS_F);
40
+}
50
+
41
+
51
+#include "exec/memory.h"
42
+static void gen_VNEG_F(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
52
+#include "hw/irq.h"
43
+ uint32_t oprsz, uint32_t maxsz)
53
+
44
+{
54
+typedef struct TC6393xbState TC6393xbState;
45
+ tcg_gen_gvec_xori(vece, rd_ofs, rm_ofs,
55
+
46
+ vece == MO_16 ? 0x8000 : 0x80000000,
56
+TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
47
+ oprsz, maxsz);
57
+ uint32_t base, qemu_irq irq);
48
}
58
+qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
49
59
+
50
static bool trans_VNEG_F(DisasContext *s, arg_2misc *a)
60
+#endif
51
{
61
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
52
- if (a->size != 2) {
62
index XXXXXXX..XXXXXXX 100644
53
+ if (a->size == MO_16) {
63
--- a/hw/arm/tosa.c
54
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
64
+++ b/hw/arm/tosa.c
55
+ return false;
65
@@ -XXX,XX +XXX,XX @@
56
+ }
66
#include "hw/hw.h"
57
+ } else if (a->size != MO_32) {
67
#include "hw/arm/pxa.h"
58
return false;
68
#include "hw/arm/arm.h"
59
}
69
-#include "hw/devices.h"
60
- /* TODO: FP16 : size == 1 */
70
#include "hw/arm/sharpsl.h"
61
- return do_2misc(s, a, gen_helper_vfp_negs);
71
#include "hw/pcmcia.h"
62
+ return do_2misc_vec(s, a, gen_VNEG_F);
72
#include "hw/boards.h"
63
}
73
+#include "hw/display/tc6393xb.h"
64
74
#include "hw/i2c/i2c.h"
65
static bool trans_VRECPE(DisasContext *s, arg_2misc *a)
75
#include "hw/ssi/ssi.h"
76
#include "hw/sysbus.h"
77
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/display/tc6393xb.c
80
+++ b/hw/display/tc6393xb.c
81
@@ -XXX,XX +XXX,XX @@
82
#include "qapi/error.h"
83
#include "qemu/host-utils.h"
84
#include "hw/hw.h"
85
-#include "hw/devices.h"
86
+#include "hw/display/tc6393xb.h"
87
#include "hw/block/flash.h"
88
#include "ui/console.h"
89
#include "ui/pixel_ops.h"
90
diff --git a/MAINTAINERS b/MAINTAINERS
91
index XXXXXXX..XXXXXXX 100644
92
--- a/MAINTAINERS
93
+++ b/MAINTAINERS
94
@@ -XXX,XX +XXX,XX @@ F: hw/misc/mst_fpga.c
95
F: hw/misc/max111x.c
96
F: include/hw/arm/pxa.h
97
F: include/hw/arm/sharpsl.h
98
+F: include/hw/display/tc6393xb.h
99
100
SABRELITE / i.MX6
101
M: Peter Maydell <peter.maydell@linaro.org>
102
--
66
--
103
2.20.1
67
2.20.1
104
68
105
69
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
Convert the Neon floating-point vector comparison ops VCEQ,
2
VCGE and VCGT over to using a gvec helper and use this to
3
implement the fp16 case.
2
4
3
Suggested-by: Markus Armbruster <armbru@redhat.com>
5
(We put the float16_ceq() etc functions above the DO_2OP()
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
macro definition because later when we convert the
5
Message-id: 20190412165416.7977-3-philmd@redhat.com
7
compare-against-zero instructions we'll want their
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
definitions to be visible at that point in the source file.)
9
7
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
Message-id: 20200828183354.27913-27-peter.maydell@linaro.org
8
---
13
---
9
hw/arm/nseries.c | 3 ++-
14
target/arm/helper.h | 9 +++++++
10
1 file changed, 2 insertions(+), 1 deletion(-)
15
target/arm/vec_helper.c | 44 +++++++++++++++++++++++++++++++++
16
target/arm/translate-neon.c.inc | 6 ++---
17
3 files changed, 56 insertions(+), 3 deletions(-)
11
18
12
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
19
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/nseries.c
21
--- a/target/arm/helper.h
15
+++ b/hw/arm/nseries.c
22
+++ b/target/arm/helper.h
16
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmul_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
17
#include "hw/boards.h"
24
DEF_HELPER_FLAGS_5(gvec_fabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
18
#include "hw/i2c/i2c.h"
25
DEF_HELPER_FLAGS_5(gvec_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
#include "hw/devices.h"
26
20
+#include "hw/misc/tmp105.h"
27
+DEF_HELPER_FLAGS_5(gvec_fceq_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
#include "hw/block/flash.h"
28
+DEF_HELPER_FLAGS_5(gvec_fceq_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
22
#include "hw/hw.h"
29
+
23
#include "hw/bt.h"
30
+DEF_HELPER_FLAGS_5(gvec_fcge_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
@@ -XXX,XX +XXX,XX @@ static void n8x0_i2c_setup(struct n800_s *s)
31
+DEF_HELPER_FLAGS_5(gvec_fcge_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier);
32
+
26
33
+DEF_HELPER_FLAGS_5(gvec_fcgt_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
/* Attach a TMP105 PM chip (A0 wired to ground) */
34
+DEF_HELPER_FLAGS_5(gvec_fcgt_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
28
- dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
35
+
29
+ dev = i2c_create_slave(i2c, TYPE_TMP105, N8X0_TMP105_ADDR);
36
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
30
qdev_connect_gpio_out(dev, 0, tmp_irq);
37
void, ptr, ptr, ptr, ptr, i32)
38
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
39
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/vec_helper.c
42
+++ b/target/arm/vec_helper.c
43
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
44
clear_tail(d, opr_sz, simd_maxsz(desc));
31
}
45
}
32
46
47
+/*
48
+ * Floating point comparisons producing an integer result (all 1s or all 0s).
49
+ * Note that EQ doesn't signal InvalidOp for QNaNs but GE and GT do.
50
+ * Softfloat routines return 0/1, which we convert to the 0/-1 Neon requires.
51
+ */
52
+static uint16_t float16_ceq(float16 op1, float16 op2, float_status *stat)
53
+{
54
+ return -float16_eq_quiet(op1, op2, stat);
55
+}
56
+
57
+static uint32_t float32_ceq(float32 op1, float32 op2, float_status *stat)
58
+{
59
+ return -float32_eq_quiet(op1, op2, stat);
60
+}
61
+
62
+static uint16_t float16_cge(float16 op1, float16 op2, float_status *stat)
63
+{
64
+ return -float16_le(op2, op1, stat);
65
+}
66
+
67
+static uint32_t float32_cge(float32 op1, float32 op2, float_status *stat)
68
+{
69
+ return -float32_le(op2, op1, stat);
70
+}
71
+
72
+static uint16_t float16_cgt(float16 op1, float16 op2, float_status *stat)
73
+{
74
+ return -float16_lt(op2, op1, stat);
75
+}
76
+
77
+static uint32_t float32_cgt(float32 op1, float32 op2, float_status *stat)
78
+{
79
+ return -float32_lt(op2, op1, stat);
80
+}
81
+
82
#define DO_2OP(NAME, FUNC, TYPE) \
83
void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
84
{ \
85
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_ftsmul_d, float64_ftsmul, float64)
86
DO_3OP(gvec_fabd_h, float16_abd, float16)
87
DO_3OP(gvec_fabd_s, float32_abd, float32)
88
89
+DO_3OP(gvec_fceq_h, float16_ceq, float16)
90
+DO_3OP(gvec_fceq_s, float32_ceq, float32)
91
+
92
+DO_3OP(gvec_fcge_h, float16_cge, float16)
93
+DO_3OP(gvec_fcge_s, float32_cge, float32)
94
+
95
+DO_3OP(gvec_fcgt_h, float16_cgt, float16)
96
+DO_3OP(gvec_fcgt_s, float32_cgt, float32)
97
+
98
#ifdef TARGET_AARCH64
99
100
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
101
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
102
index XXXXXXX..XXXXXXX 100644
103
--- a/target/arm/translate-neon.c.inc
104
+++ b/target/arm/translate-neon.c.inc
105
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s, gen_helper_gvec_fadd_h)
106
DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s, gen_helper_gvec_fsub_h)
107
DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s, gen_helper_gvec_fabd_h)
108
DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s, gen_helper_gvec_fmul_h)
109
+DO_3S_FP_GVEC(VCEQ, gen_helper_gvec_fceq_s, gen_helper_gvec_fceq_h)
110
+DO_3S_FP_GVEC(VCGE, gen_helper_gvec_fcge_s, gen_helper_gvec_fcge_h)
111
+DO_3S_FP_GVEC(VCGT, gen_helper_gvec_fcgt_s, gen_helper_gvec_fcgt_h)
112
113
/*
114
* For all the functions using this macro, size == 1 means fp16,
115
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s, gen_helper_gvec_fmul_h)
116
return do_3same_fp(s, a, FUNC, READS_VD); \
117
}
118
119
-DO_3S_FP(VCEQ, gen_helper_neon_ceq_f32, false)
120
-DO_3S_FP(VCGE, gen_helper_neon_cge_f32, false)
121
-DO_3S_FP(VCGT, gen_helper_neon_cgt_f32, false)
122
DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false)
123
DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false)
124
DO_3S_FP(VMAX, gen_helper_vfp_maxs, false)
33
--
125
--
34
2.20.1
126
2.20.1
35
127
36
128
diff view generated by jsdifflib
1
Like AArch64, M-profile floating point has no FPEXC enable
1
Convert the neon floating-point vector absolute comparison ops
2
bit to gate floating point; so always set the VFPEN TB flag.
2
VACGE and VACGT over to using a gvec hepler and use this to
3
3
implement the fp16 case.
4
M-profile also has CPACR and NSACR similar to A-profile;
5
they behave slightly differently:
6
* the CPACR is banked between Secure and Non-Secure
7
* if the NSACR forces a trap then this is taken to
8
the Secure state, not the Non-Secure state
9
10
Honour the CPACR and NSACR settings. The NSACR handling
11
requires us to borrow the exception.target_el field
12
(usually meaningless for M profile) to distinguish the
13
NOCP UsageFault taken to Secure state from the more
14
usual fault taken to the current security state.
15
4
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20190416125744.27770-6-peter.maydell@linaro.org
7
Message-id: 20200828183354.27913-28-peter.maydell@linaro.org
19
---
8
---
20
target/arm/helper.c | 55 +++++++++++++++++++++++++++++++++++++++---
9
target/arm/helper.h | 6 ++++++
21
target/arm/translate.c | 10 ++++++--
10
target/arm/vec_helper.c | 26 ++++++++++++++++++++++++++
22
2 files changed, 60 insertions(+), 5 deletions(-)
11
target/arm/translate-neon.c.inc | 4 ++--
12
3 files changed, 34 insertions(+), 2 deletions(-)
23
13
24
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
25
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.c
16
--- a/target/arm/helper.h
27
+++ b/target/arm/helper.c
17
+++ b/target/arm/helper.h
28
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fcge_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
29
return target_el;
19
DEF_HELPER_FLAGS_5(gvec_fcgt_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
DEF_HELPER_FLAGS_5(gvec_fcgt_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
22
+DEF_HELPER_FLAGS_5(gvec_facge_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_5(gvec_facge_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
+
25
+DEF_HELPER_FLAGS_5(gvec_facgt_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_5(gvec_facgt_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
+
28
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
29
void, ptr, ptr, ptr, ptr, i32)
30
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
31
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/vec_helper.c
34
+++ b/target/arm/vec_helper.c
35
@@ -XXX,XX +XXX,XX @@ static uint32_t float32_cgt(float32 op1, float32 op2, float_status *stat)
36
return -float32_lt(op2, op1, stat);
30
}
37
}
31
38
32
+/*
39
+static uint16_t float16_acge(float16 op1, float16 op2, float_status *stat)
33
+ * Return true if the v7M CPACR permits access to the FPU for the specified
34
+ * security state and privilege level.
35
+ */
36
+static bool v7m_cpacr_pass(CPUARMState *env, bool is_secure, bool is_priv)
37
+{
40
+{
38
+ switch (extract32(env->v7m.cpacr[is_secure], 20, 2)) {
41
+ return -float16_le(float16_abs(op2), float16_abs(op1), stat);
39
+ case 0:
40
+ case 2: /* UNPREDICTABLE: we treat like 0 */
41
+ return false;
42
+ case 1:
43
+ return is_priv;
44
+ case 3:
45
+ return true;
46
+ default:
47
+ g_assert_not_reached();
48
+ }
49
+}
42
+}
50
+
43
+
51
static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
44
+static uint32_t float32_acge(float32 op1, float32 op2, float_status *stat)
52
ARMMMUIdx mmu_idx, bool ignfault)
45
+{
53
{
46
+ return -float32_le(float32_abs(op2), float32_abs(op1), stat);
54
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
47
+}
55
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNDEFINSTR_MASK;
56
break;
57
case EXCP_NOCP:
58
- armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
59
- env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_NOCP_MASK;
60
+ {
61
+ /*
62
+ * NOCP might be directed to something other than the current
63
+ * security state if this fault is because of NSACR; we indicate
64
+ * the target security state using exception.target_el.
65
+ */
66
+ int target_secstate;
67
+
48
+
68
+ if (env->exception.target_el == 3) {
49
+static uint16_t float16_acgt(float16 op1, float16 op2, float_status *stat)
69
+ target_secstate = M_REG_S;
50
+{
70
+ } else {
51
+ return -float16_lt(float16_abs(op2), float16_abs(op1), stat);
71
+ target_secstate = env->v7m.secure;
52
+}
72
+ }
53
+
73
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, target_secstate);
54
+static uint32_t float32_acgt(float32 op1, float32 op2, float_status *stat)
74
+ env->v7m.cfsr[target_secstate] |= R_V7M_CFSR_NOCP_MASK;
55
+{
75
break;
56
+ return -float32_lt(float32_abs(op2), float32_abs(op1), stat);
76
+ }
57
+}
77
case EXCP_INVSTATE:
58
+
78
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
59
#define DO_2OP(NAME, FUNC, TYPE) \
79
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVSTATE_MASK;
60
void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
80
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
61
{ \
81
return 0;
62
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_fcge_s, float32_cge, float32)
63
DO_3OP(gvec_fcgt_h, float16_cgt, float16)
64
DO_3OP(gvec_fcgt_s, float32_cgt, float32)
65
66
+DO_3OP(gvec_facge_h, float16_acge, float16)
67
+DO_3OP(gvec_facge_s, float32_acge, float32)
68
+
69
+DO_3OP(gvec_facgt_h, float16_acgt, float16)
70
+DO_3OP(gvec_facgt_s, float32_acgt, float32)
71
+
72
#ifdef TARGET_AARCH64
73
74
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
75
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/translate-neon.c.inc
78
+++ b/target/arm/translate-neon.c.inc
79
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s, gen_helper_gvec_fmul_h)
80
DO_3S_FP_GVEC(VCEQ, gen_helper_gvec_fceq_s, gen_helper_gvec_fceq_h)
81
DO_3S_FP_GVEC(VCGE, gen_helper_gvec_fcge_s, gen_helper_gvec_fcge_h)
82
DO_3S_FP_GVEC(VCGT, gen_helper_gvec_fcgt_s, gen_helper_gvec_fcgt_h)
83
+DO_3S_FP_GVEC(VACGE, gen_helper_gvec_facge_s, gen_helper_gvec_facge_h)
84
+DO_3S_FP_GVEC(VACGT, gen_helper_gvec_facgt_s, gen_helper_gvec_facgt_h)
85
86
/*
87
* For all the functions using this macro, size == 1 means fp16,
88
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VCGT, gen_helper_gvec_fcgt_s, gen_helper_gvec_fcgt_h)
89
return do_3same_fp(s, a, FUNC, READS_VD); \
82
}
90
}
83
91
84
+ if (arm_feature(env, ARM_FEATURE_M)) {
92
-DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false)
85
+ /* CPACR can cause a NOCP UsageFault taken to current security state */
93
-DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false)
86
+ if (!v7m_cpacr_pass(env, env->v7m.secure, cur_el != 0)) {
94
DO_3S_FP(VMAX, gen_helper_vfp_maxs, false)
87
+ return 1;
95
DO_3S_FP(VMIN, gen_helper_vfp_mins, false)
88
+ }
89
+
90
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY) && !env->v7m.secure) {
91
+ if (!extract32(env->v7m.nsacr, 10, 1)) {
92
+ /* FP insns cause a NOCP UsageFault taken to Secure */
93
+ return 3;
94
+ }
95
+ }
96
+
97
+ return 0;
98
+ }
99
+
100
/* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
101
* 0, 2 : trap EL0 and EL1/PL1 accesses
102
* 1 : trap only EL0 accesses
103
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
104
flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env));
105
flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
106
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
107
- || arm_el_is_aa64(env, 1)) {
108
+ || arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
109
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
110
}
111
flags = FIELD_DP32(flags, TBFLAG_A32, XSCALE_CPAR, env->cp15.c15_cpar);
112
diff --git a/target/arm/translate.c b/target/arm/translate.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/target/arm/translate.c
115
+++ b/target/arm/translate.c
116
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
117
* for attempts to execute invalid vfp/neon encodings with FP disabled.
118
*/
119
if (s->fp_excp_el) {
120
- gen_exception_insn(s, 4, EXCP_UDEF,
121
- syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
122
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
123
+ gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
124
+ s->fp_excp_el);
125
+ } else {
126
+ gen_exception_insn(s, 4, EXCP_UDEF,
127
+ syn_fp_access_trap(1, 0xe, false),
128
+ s->fp_excp_el);
129
+ }
130
return 0;
131
}
132
96
133
--
97
--
134
2.20.1
98
2.20.1
135
99
136
100
diff view generated by jsdifflib
1
The M-profile CONTROL register has two bits -- SFPA and FPCA --
1
Convert the Neon float-point VMAX and VMIN insns over to using
2
which relate to floating-point support, and should be RES0 otherwise.
2
a gvec helper, and use this to implement the fp16 case.
3
Handle them correctly in the MSR/MRS register access code.
4
Neither is banked between security states, so they are stored
5
in v7m.control[M_REG_S] regardless of current security state.
6
3
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190416125744.27770-9-peter.maydell@linaro.org
6
Message-id: 20200828183354.27913-29-peter.maydell@linaro.org
10
---
7
---
11
target/arm/helper.c | 57 ++++++++++++++++++++++++++++++++++++++-------
8
target/arm/helper.h | 6 ++++++
12
1 file changed, 49 insertions(+), 8 deletions(-)
9
target/arm/vec_helper.c | 6 ++++++
10
target/arm/translate-neon.c.inc | 5 ++---
11
3 files changed, 14 insertions(+), 3 deletions(-)
13
12
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
15
--- a/target/arm/helper.h
17
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper.h
18
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_facge_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
return xpsr_read(env) & mask;
18
DEF_HELPER_FLAGS_5(gvec_facgt_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
break;
19
DEF_HELPER_FLAGS_5(gvec_facgt_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
case 20: /* CONTROL */
20
22
- return env->v7m.control[env->v7m.secure];
21
+DEF_HELPER_FLAGS_5(gvec_fmax_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
23
+ {
22
+DEF_HELPER_FLAGS_5(gvec_fmax_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
+ uint32_t value = env->v7m.control[env->v7m.secure];
23
+
25
+ if (!env->v7m.secure) {
24
+DEF_HELPER_FLAGS_5(gvec_fmin_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
+ /* SFPA is RAZ/WI from NS; FPCA is stored in the M_REG_S bank */
25
+DEF_HELPER_FLAGS_5(gvec_fmin_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
+ value |= env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK;
26
+
28
+ }
27
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
29
+ return value;
28
void, ptr, ptr, ptr, ptr, i32)
30
+ }
29
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
31
case 0x94: /* CONTROL_NS */
30
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
32
/* We have to handle this here because unprivileged Secure code
31
index XXXXXXX..XXXXXXX 100644
33
* can read the NS CONTROL register.
32
--- a/target/arm/vec_helper.c
34
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
33
+++ b/target/arm/vec_helper.c
35
if (!env->v7m.secure) {
34
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_facge_s, float32_acge, float32)
36
return 0;
35
DO_3OP(gvec_facgt_h, float16_acgt, float16)
37
}
36
DO_3OP(gvec_facgt_s, float32_acgt, float32)
38
- return env->v7m.control[M_REG_NS];
37
39
+ return env->v7m.control[M_REG_NS] |
38
+DO_3OP(gvec_fmax_h, float16_max, float16)
40
+ (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK);
39
+DO_3OP(gvec_fmax_s, float32_max, float32)
40
+
41
+DO_3OP(gvec_fmin_h, float16_min, float16)
42
+DO_3OP(gvec_fmin_s, float32_min, float32)
43
+
44
#ifdef TARGET_AARCH64
45
46
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
47
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate-neon.c.inc
50
+++ b/target/arm/translate-neon.c.inc
51
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VCGE, gen_helper_gvec_fcge_s, gen_helper_gvec_fcge_h)
52
DO_3S_FP_GVEC(VCGT, gen_helper_gvec_fcgt_s, gen_helper_gvec_fcgt_h)
53
DO_3S_FP_GVEC(VACGE, gen_helper_gvec_facge_s, gen_helper_gvec_facge_h)
54
DO_3S_FP_GVEC(VACGT, gen_helper_gvec_facgt_s, gen_helper_gvec_facgt_h)
55
+DO_3S_FP_GVEC(VMAX, gen_helper_gvec_fmax_s, gen_helper_gvec_fmax_h)
56
+DO_3S_FP_GVEC(VMIN, gen_helper_gvec_fmin_s, gen_helper_gvec_fmin_h)
57
58
/*
59
* For all the functions using this macro, size == 1 means fp16,
60
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VACGT, gen_helper_gvec_facgt_s, gen_helper_gvec_facgt_h)
61
return do_3same_fp(s, a, FUNC, READS_VD); \
41
}
62
}
42
63
43
if (el == 0) {
64
-DO_3S_FP(VMAX, gen_helper_vfp_maxs, false)
44
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
65
-DO_3S_FP(VMIN, gen_helper_vfp_mins, false)
45
*/
66
-
46
uint32_t mask = extract32(maskreg, 8, 4);
67
static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
47
uint32_t reg = extract32(maskreg, 0, 8);
68
TCGv_ptr fpstatus)
48
+ int cur_el = arm_current_el(env);
69
{
49
50
- if (arm_current_el(env) == 0 && reg > 7) {
51
- /* only xPSR sub-fields may be written by unprivileged */
52
+ if (cur_el == 0 && reg > 7 && reg != 20) {
53
+ /*
54
+ * only xPSR sub-fields and CONTROL.SFPA may be written by
55
+ * unprivileged code
56
+ */
57
return;
58
}
59
60
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
61
env->v7m.control[M_REG_NS] &= ~R_V7M_CONTROL_NPRIV_MASK;
62
env->v7m.control[M_REG_NS] |= val & R_V7M_CONTROL_NPRIV_MASK;
63
}
64
+ /*
65
+ * SFPA is RAZ/WI from NS. FPCA is RO if NSACR.CP10 == 0,
66
+ * RES0 if the FPU is not present, and is stored in the S bank
67
+ */
68
+ if (arm_feature(env, ARM_FEATURE_VFP) &&
69
+ extract32(env->v7m.nsacr, 10, 1)) {
70
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
71
+ env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
72
+ }
73
return;
74
case 0x98: /* SP_NS */
75
{
76
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
77
env->v7m.faultmask[env->v7m.secure] = val & 1;
78
break;
79
case 20: /* CONTROL */
80
- /* Writing to the SPSEL bit only has an effect if we are in
81
+ /*
82
+ * Writing to the SPSEL bit only has an effect if we are in
83
* thread mode; other bits can be updated by any privileged code.
84
* write_v7m_control_spsel() deals with updating the SPSEL bit in
85
* env->v7m.control, so we only need update the others.
86
* For v7M, we must just ignore explicit writes to SPSEL in handler
87
* mode; for v8M the write is permitted but will have no effect.
88
+ * All these bits are writes-ignored from non-privileged code,
89
+ * except for SFPA.
90
*/
91
- if (arm_feature(env, ARM_FEATURE_V8) ||
92
- !arm_v7m_is_handler_mode(env)) {
93
+ if (cur_el > 0 && (arm_feature(env, ARM_FEATURE_V8) ||
94
+ !arm_v7m_is_handler_mode(env))) {
95
write_v7m_control_spsel(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
96
}
97
- if (arm_feature(env, ARM_FEATURE_M_MAIN)) {
98
+ if (cur_el > 0 && arm_feature(env, ARM_FEATURE_M_MAIN)) {
99
env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
100
env->v7m.control[env->v7m.secure] |= val & R_V7M_CONTROL_NPRIV_MASK;
101
}
102
+ if (arm_feature(env, ARM_FEATURE_VFP)) {
103
+ /*
104
+ * SFPA is RAZ/WI from NS or if no FPU.
105
+ * FPCA is RO if NSACR.CP10 == 0, RES0 if the FPU is not present.
106
+ * Both are stored in the S bank.
107
+ */
108
+ if (env->v7m.secure) {
109
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
110
+ env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_SFPA_MASK;
111
+ }
112
+ if (cur_el > 0 &&
113
+ (env->v7m.secure || !arm_feature(env, ARM_FEATURE_M_SECURITY) ||
114
+ extract32(env->v7m.nsacr, 10, 1))) {
115
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
116
+ env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
117
+ }
118
+ }
119
break;
120
default:
121
bad_reg:
122
--
70
--
123
2.20.1
71
2.20.1
124
72
125
73
diff view generated by jsdifflib
1
Currently the code in v7m_push_stack() which detects a violation
1
Convert the Neon floating point VMAXNM and VMINNM insns to
2
of the v8M stack limit simply returns early if it does so. This
2
using a gvec helper and use this to implement the fp16 case.
3
is OK for the current integer-only code, but won't work for the
4
floating point handling we're about to add. We need to continue
5
executing the rest of the function so that we check for other
6
exceptions like not having permission to use the FPU and so
7
that we correctly set the FPCCR state if we are doing lazy
8
stacking. Refactor to avoid the early return.
9
3
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20190416125744.27770-10-peter.maydell@linaro.org
6
Message-id: 20200828183354.27913-30-peter.maydell@linaro.org
13
---
7
---
14
target/arm/helper.c | 23 ++++++++++++++++++-----
8
target/arm/helper.h | 6 ++++++
15
1 file changed, 18 insertions(+), 5 deletions(-)
9
target/arm/vec_helper.c | 6 ++++++
10
target/arm/translate-neon.c.inc | 23 +++++++++++++++--------
11
3 files changed, 27 insertions(+), 8 deletions(-)
16
12
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
15
--- a/target/arm/helper.h
20
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper.h
21
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmax_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
22
* should ignore further stack faults trying to process
18
DEF_HELPER_FLAGS_5(gvec_fmin_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
23
* that derived exception.)
19
DEF_HELPER_FLAGS_5(gvec_fmin_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
*/
20
25
- bool stacked_ok;
21
+DEF_HELPER_FLAGS_5(gvec_fmaxnum_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
+ bool stacked_ok = true, limitviol = false;
22
+DEF_HELPER_FLAGS_5(gvec_fmaxnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
CPUARMState *env = &cpu->env;
23
+
28
uint32_t xpsr = xpsr_read(env);
24
+DEF_HELPER_FLAGS_5(gvec_fminnum_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
29
uint32_t frameptr = env->regs[13];
25
+DEF_HELPER_FLAGS_5(gvec_fminnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
30
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
26
+
31
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
27
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
32
env->v7m.secure);
28
void, ptr, ptr, ptr, ptr, i32)
33
env->regs[13] = limit;
29
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
34
- return true;
30
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
35
+ /*
31
index XXXXXXX..XXXXXXX 100644
36
+ * We won't try to perform any further memory accesses but
32
--- a/target/arm/vec_helper.c
37
+ * we must continue through the following code to check for
33
+++ b/target/arm/vec_helper.c
38
+ * permission faults during FPU state preservation, and we
34
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_fmax_s, float32_max, float32)
39
+ * must update FPCCR if lazy stacking is enabled.
35
DO_3OP(gvec_fmin_h, float16_min, float16)
40
+ */
36
DO_3OP(gvec_fmin_s, float32_min, float32)
41
+ limitviol = true;
37
42
+ stacked_ok = false;
38
+DO_3OP(gvec_fmaxnum_h, float16_maxnum, float16)
43
}
39
+DO_3OP(gvec_fmaxnum_s, float32_maxnum, float32)
40
+
41
+DO_3OP(gvec_fminnum_h, float16_minnum, float16)
42
+DO_3OP(gvec_fminnum_s, float32_minnum, float32)
43
+
44
#ifdef TARGET_AARCH64
45
46
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
47
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate-neon.c.inc
50
+++ b/target/arm/translate-neon.c.inc
51
@@ -XXX,XX +XXX,XX @@ static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
52
DO_3S_FP(VMLA, gen_VMLA_fp_3s, true)
53
DO_3S_FP(VMLS, gen_VMLS_fp_3s, true)
54
55
+WRAP_FP_GVEC(gen_VMAXNM_fp32_3s, FPST_STD, gen_helper_gvec_fmaxnum_s)
56
+WRAP_FP_GVEC(gen_VMAXNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fmaxnum_h)
57
+WRAP_FP_GVEC(gen_VMINNM_fp32_3s, FPST_STD, gen_helper_gvec_fminnum_s)
58
+WRAP_FP_GVEC(gen_VMINNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fminnum_h)
59
+
60
static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
61
{
62
if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
63
@@ -XXX,XX +XXX,XX @@ static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
44
}
64
}
45
65
46
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
66
if (a->size != 0) {
47
* (which may be taken in preference to the one we started with
67
- /* TODO fp16 support */
48
* if it has higher priority).
68
- return false;
49
*/
69
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
50
- stacked_ok =
70
+ return false;
51
+ stacked_ok = stacked_ok &&
71
+ }
52
v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, false) &&
72
+ return do_3same(s, a, gen_VMAXNM_fp16_3s);
53
v7m_stack_write(cpu, frameptr + 4, env->regs[1], mmu_idx, false) &&
73
}
54
v7m_stack_write(cpu, frameptr + 8, env->regs[2], mmu_idx, false) &&
74
-
55
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
75
- return do_3same_fp(s, a, gen_helper_vfp_maxnums, false);
56
v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
76
+ return do_3same(s, a, gen_VMAXNM_fp32_3s);
57
v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
58
59
- /* Update SP regardless of whether any of the stack accesses failed. */
60
- env->regs[13] = frameptr;
61
+ /*
62
+ * If we broke a stack limit then SP was already updated earlier;
63
+ * otherwise we update SP regardless of whether any of the stack
64
+ * accesses failed or we took some other kind of fault.
65
+ */
66
+ if (!limitviol) {
67
+ env->regs[13] = frameptr;
68
+ }
69
70
return !stacked_ok;
71
}
77
}
78
79
static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
80
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
81
}
82
83
if (a->size != 0) {
84
- /* TODO fp16 support */
85
- return false;
86
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
87
+ return false;
88
+ }
89
+ return do_3same(s, a, gen_VMINNM_fp16_3s);
90
}
91
-
92
- return do_3same_fp(s, a, gen_helper_vfp_minnums, false);
93
+ return do_3same(s, a, gen_VMINNM_fp32_3s);
94
}
95
96
WRAP_ENV_FN(gen_VRECPS_tramp, gen_helper_recps_f32)
72
--
97
--
73
2.20.1
98
2.20.1
74
99
75
100
diff view generated by jsdifflib
1
If the floating point extension is present, then the SG instruction
1
Convert the Neon floating-point VMLA and VMLS insns over to using a
2
must clear the CONTROL_S.SFPA bit. Implement this.
2
gvec helper, and use this to implement the fp16 case.
3
4
(On a no-FPU system the bit will always be zero, so we don't need
5
to make the clearing of the bit conditional on ARM_FEATURE_VFP.)
6
3
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190416125744.27770-8-peter.maydell@linaro.org
6
Message-id: 20200828183354.27913-31-peter.maydell@linaro.org
10
---
7
---
11
target/arm/helper.c | 1 +
8
target/arm/helper.h | 6 +++++
12
1 file changed, 1 insertion(+)
9
target/arm/vec_helper.c | 42 +++++++++++++++++++++++++++++++++
10
target/arm/translate-neon.c.inc | 33 ++------------------------
11
3 files changed, 50 insertions(+), 31 deletions(-)
13
12
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
15
--- a/target/arm/helper.h
17
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper.h
18
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmaxnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i3
19
qemu_log_mask(CPU_LOG_INT, "...really an SG instruction at 0x%08" PRIx32
18
DEF_HELPER_FLAGS_5(gvec_fminnum_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
", executing it\n", env->regs[15]);
19
DEF_HELPER_FLAGS_5(gvec_fminnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
env->regs[14] &= ~1;
20
22
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
21
+DEF_HELPER_FLAGS_5(gvec_fmla_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
23
switch_v7m_security_state(env, true);
22
+DEF_HELPER_FLAGS_5(gvec_fmla_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
xpsr_write(env, 0, XPSR_IT);
23
+
25
env->regs[15] += 4;
24
+DEF_HELPER_FLAGS_5(gvec_fmls_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(gvec_fmls_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
+
27
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
28
void, ptr, ptr, ptr, ptr, i32)
29
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
30
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/vec_helper.c
33
+++ b/target/arm/vec_helper.c
34
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_rsqrts_d, helper_rsqrtsf_f64, float64)
35
#endif
36
#undef DO_3OP
37
38
+/* Non-fused multiply-add (unlike float16_muladd etc, which are fused) */
39
+static float16 float16_muladd_nf(float16 dest, float16 op1, float16 op2,
40
+ float_status *stat)
41
+{
42
+ return float16_add(dest, float16_mul(op1, op2, stat), stat);
43
+}
44
+
45
+static float32 float32_muladd_nf(float32 dest, float32 op1, float32 op2,
46
+ float_status *stat)
47
+{
48
+ return float32_add(dest, float32_mul(op1, op2, stat), stat);
49
+}
50
+
51
+static float16 float16_mulsub_nf(float16 dest, float16 op1, float16 op2,
52
+ float_status *stat)
53
+{
54
+ return float16_sub(dest, float16_mul(op1, op2, stat), stat);
55
+}
56
+
57
+static float32 float32_mulsub_nf(float32 dest, float32 op1, float32 op2,
58
+ float_status *stat)
59
+{
60
+ return float32_sub(dest, float32_mul(op1, op2, stat), stat);
61
+}
62
+
63
+#define DO_MULADD(NAME, FUNC, TYPE) \
64
+void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
65
+{ \
66
+ intptr_t i, oprsz = simd_oprsz(desc); \
67
+ TYPE *d = vd, *n = vn, *m = vm; \
68
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
69
+ d[i] = FUNC(d[i], n[i], m[i], stat); \
70
+ } \
71
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
72
+}
73
+
74
+DO_MULADD(gvec_fmla_h, float16_muladd_nf, float16)
75
+DO_MULADD(gvec_fmla_s, float32_muladd_nf, float32)
76
+
77
+DO_MULADD(gvec_fmls_h, float16_mulsub_nf, float16)
78
+DO_MULADD(gvec_fmls_s, float32_mulsub_nf, float32)
79
+
80
/* For the indexed ops, SVE applies the index per 128-bit vector segment.
81
* For AdvSIMD, there is of course only one such vector segment.
82
*/
83
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/translate-neon.c.inc
86
+++ b/target/arm/translate-neon.c.inc
87
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VACGE, gen_helper_gvec_facge_s, gen_helper_gvec_facge_h)
88
DO_3S_FP_GVEC(VACGT, gen_helper_gvec_facgt_s, gen_helper_gvec_facgt_h)
89
DO_3S_FP_GVEC(VMAX, gen_helper_gvec_fmax_s, gen_helper_gvec_fmax_h)
90
DO_3S_FP_GVEC(VMIN, gen_helper_gvec_fmin_s, gen_helper_gvec_fmin_h)
91
-
92
-/*
93
- * For all the functions using this macro, size == 1 means fp16,
94
- * which is an architecture extension we don't implement yet.
95
- */
96
-#define DO_3S_FP(INSN,FUNC,READS_VD) \
97
- static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
98
- { \
99
- if (a->size != 0) { \
100
- /* TODO fp16 support */ \
101
- return false; \
102
- } \
103
- return do_3same_fp(s, a, FUNC, READS_VD); \
104
- }
105
-
106
-static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
107
- TCGv_ptr fpstatus)
108
-{
109
- gen_helper_vfp_muls(vn, vn, vm, fpstatus);
110
- gen_helper_vfp_adds(vd, vd, vn, fpstatus);
111
-}
112
-
113
-static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
114
- TCGv_ptr fpstatus)
115
-{
116
- gen_helper_vfp_muls(vn, vn, vm, fpstatus);
117
- gen_helper_vfp_subs(vd, vd, vn, fpstatus);
118
-}
119
-
120
-DO_3S_FP(VMLA, gen_VMLA_fp_3s, true)
121
-DO_3S_FP(VMLS, gen_VMLS_fp_3s, true)
122
+DO_3S_FP_GVEC(VMLA, gen_helper_gvec_fmla_s, gen_helper_gvec_fmla_h)
123
+DO_3S_FP_GVEC(VMLS, gen_helper_gvec_fmls_s, gen_helper_gvec_fmls_h)
124
125
WRAP_FP_GVEC(gen_VMAXNM_fp32_3s, FPST_STD, gen_helper_gvec_fmaxnum_s)
126
WRAP_FP_GVEC(gen_VMAXNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fmaxnum_h)
26
--
127
--
27
2.20.1
128
2.20.1
28
129
29
130
diff view generated by jsdifflib
1
Correct the decode of the M-profile "coprocessor and
1
Convert the neon floating-point vector operations VFMA and VFMS
2
floating-point instructions" space:
2
to use a gvec helper, and use this to implement the fp16 case.
3
* op0 == 0b11 is always unallocated
3
4
* if the CPU has an FPU then all insns with op1 == 0b101
4
This is the last use of do_3same_fp() so we can now delete
5
are floating point and go to disas_vfp_insn()
5
that function.
6
7
For the moment we leave VLLDM and VLSTM as NOPs; in
8
a later commit we will fill in the proper implementation
9
for the case where an FPU is present.
10
6
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20190416125744.27770-7-peter.maydell@linaro.org
9
Message-id: 20200828183354.27913-32-peter.maydell@linaro.org
14
---
10
---
15
target/arm/translate.c | 26 ++++++++++++++++++++++----
11
target/arm/helper.h | 6 +++
16
1 file changed, 22 insertions(+), 4 deletions(-)
12
target/arm/vec_helper.c | 33 +++++++++++-
17
13
target/arm/translate-neon.c.inc | 92 +--------------------------------
18
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
3 files changed, 40 insertions(+), 91 deletions(-)
15
16
diff --git a/target/arm/helper.h b/target/arm/helper.h
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate.c
18
--- a/target/arm/helper.h
21
+++ b/target/arm/translate.c
19
+++ b/target/arm/helper.h
22
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmla_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
23
case 6: case 7: case 14: case 15:
21
DEF_HELPER_FLAGS_5(gvec_fmls_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
/* Coprocessor. */
22
DEF_HELPER_FLAGS_5(gvec_fmls_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
if (arm_dc_feature(s, ARM_FEATURE_M)) {
23
26
- /* We don't currently implement M profile FP support,
24
+DEF_HELPER_FLAGS_5(gvec_vfma_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
- * so this entire space should give a NOCP fault, with
25
+DEF_HELPER_FLAGS_5(gvec_vfma_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
28
- * the exception of the v8M VLLDM and VLSTM insns, which
26
+
29
- * must be NOPs in Secure state and UNDEF in Nonsecure state.
27
+DEF_HELPER_FLAGS_5(gvec_vfms_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
30
+ /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
28
+DEF_HELPER_FLAGS_5(gvec_vfms_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
31
+ if (extract32(insn, 24, 2) == 3) {
29
+
32
+ goto illegal_op; /* op0 = 0b11 : unallocated */
30
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
33
+ }
31
void, ptr, ptr, ptr, ptr, i32)
34
+
32
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
35
+ /*
33
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
36
+ * Decode VLLDM and VLSTM first: these are nonstandard because:
34
index XXXXXXX..XXXXXXX 100644
37
+ * * if there is no FPU then these insns must NOP in
35
--- a/target/arm/vec_helper.c
38
+ * Secure state and UNDEF in Nonsecure state
36
+++ b/target/arm/vec_helper.c
39
+ * * if there is an FPU then these insns do not have
37
@@ -XXX,XX +XXX,XX @@ static float32 float32_mulsub_nf(float32 dest, float32 op1, float32 op2,
40
+ * the usual behaviour that disas_vfp_insn() provides of
38
return float32_sub(dest, float32_mul(op1, op2, stat), stat);
41
+ * being controlled by CPACR/NSACR enable bits or the
39
}
42
+ * lazy-stacking logic.
40
43
*/
41
-#define DO_MULADD(NAME, FUNC, TYPE) \
44
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
42
+/* Fused versions; these have the semantics Neon VFMA/VFMS want */
45
(insn & 0xffa00f00) == 0xec200a00) {
43
+static float16 float16_muladd_f(float16 dest, float16 op1, float16 op2,
46
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
44
+ float_status *stat)
47
/* Just NOP since FP support is not implemented */
45
+{
48
break;
46
+ return float16_muladd(op1, op2, dest, 0, stat);
49
}
47
+}
50
+ if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
48
+
51
+ ((insn >> 8) & 0xe) == 10) {
49
+static float32 float32_muladd_f(float32 dest, float32 op1, float32 op2,
52
+ /* FP, and the CPU supports it */
50
+ float_status *stat)
53
+ if (disas_vfp_insn(s, insn)) {
51
+{
54
+ goto illegal_op;
52
+ return float32_muladd(op1, op2, dest, 0, stat);
55
+ }
53
+}
56
+ break;
54
+
57
+ }
55
+static float16 float16_mulsub_f(float16 dest, float16 op1, float16 op2,
58
+
56
+ float_status *stat)
59
/* All other insns: NOCP */
57
+{
60
gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
58
+ return float16_muladd(float16_chs(op1), op2, dest, 0, stat);
61
default_exception_el(s));
59
+}
60
+
61
+static float32 float32_mulsub_f(float32 dest, float32 op1, float32 op2,
62
+ float_status *stat)
63
+{
64
+ return float32_muladd(float32_chs(op1), op2, dest, 0, stat);
65
+}
66
+
67
+#define DO_MULADD(NAME, FUNC, TYPE) \
68
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
69
{ \
70
intptr_t i, oprsz = simd_oprsz(desc); \
71
@@ -XXX,XX +XXX,XX @@ DO_MULADD(gvec_fmla_s, float32_muladd_nf, float32)
72
DO_MULADD(gvec_fmls_h, float16_mulsub_nf, float16)
73
DO_MULADD(gvec_fmls_s, float32_mulsub_nf, float32)
74
75
+DO_MULADD(gvec_vfma_h, float16_muladd_f, float16)
76
+DO_MULADD(gvec_vfma_s, float32_muladd_f, float32)
77
+
78
+DO_MULADD(gvec_vfms_h, float16_mulsub_f, float16)
79
+DO_MULADD(gvec_vfms_s, float32_mulsub_f, float32)
80
+
81
/* For the indexed ops, SVE applies the index per 128-bit vector segment.
82
* For AdvSIMD, there is of course only one such vector segment.
83
*/
84
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/translate-neon.c.inc
87
+++ b/target/arm/translate-neon.c.inc
88
@@ -XXX,XX +XXX,XX @@ DO_3SAME_PAIR(VPADD, padd_u)
89
DO_3SAME_VQDMULH(VQDMULH, qdmulh)
90
DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
91
92
-static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn,
93
- bool reads_vd)
94
-{
95
- /*
96
- * FP operations handled elementwise 32 bits at a time.
97
- * If reads_vd is true then the old value of Vd will be
98
- * loaded before calling the callback function. This is
99
- * used for multiply-accumulate type operations.
100
- */
101
- TCGv_i32 tmp, tmp2;
102
- int pass;
103
-
104
- if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
105
- return false;
106
- }
107
-
108
- /* UNDEF accesses to D16-D31 if they don't exist. */
109
- if (!dc_isar_feature(aa32_simd_r32, s) &&
110
- ((a->vd | a->vn | a->vm) & 0x10)) {
111
- return false;
112
- }
113
-
114
- if ((a->vn | a->vm | a->vd) & a->q) {
115
- return false;
116
- }
117
-
118
- if (!vfp_access_check(s)) {
119
- return true;
120
- }
121
-
122
- TCGv_ptr fpstatus = fpstatus_ptr(FPST_STD);
123
- for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
124
- tmp = neon_load_reg(a->vn, pass);
125
- tmp2 = neon_load_reg(a->vm, pass);
126
- if (reads_vd) {
127
- TCGv_i32 tmp_rd = neon_load_reg(a->vd, pass);
128
- fn(tmp_rd, tmp, tmp2, fpstatus);
129
- neon_store_reg(a->vd, pass, tmp_rd);
130
- tcg_temp_free_i32(tmp);
131
- } else {
132
- fn(tmp, tmp, tmp2, fpstatus);
133
- neon_store_reg(a->vd, pass, tmp);
134
- }
135
- tcg_temp_free_i32(tmp2);
136
- }
137
- tcg_temp_free_ptr(fpstatus);
138
- return true;
139
-}
140
-
141
#define WRAP_FP_GVEC(WRAPNAME, FPST, FUNC) \
142
static void WRAPNAME(unsigned vece, uint32_t rd_ofs, \
143
uint32_t rn_ofs, uint32_t rm_ofs, \
144
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMAX, gen_helper_gvec_fmax_s, gen_helper_gvec_fmax_h)
145
DO_3S_FP_GVEC(VMIN, gen_helper_gvec_fmin_s, gen_helper_gvec_fmin_h)
146
DO_3S_FP_GVEC(VMLA, gen_helper_gvec_fmla_s, gen_helper_gvec_fmla_h)
147
DO_3S_FP_GVEC(VMLS, gen_helper_gvec_fmls_s, gen_helper_gvec_fmls_h)
148
+DO_3S_FP_GVEC(VFMA, gen_helper_gvec_vfma_s, gen_helper_gvec_vfma_h)
149
+DO_3S_FP_GVEC(VFMS, gen_helper_gvec_vfms_s, gen_helper_gvec_vfms_h)
150
151
WRAP_FP_GVEC(gen_VMAXNM_fp32_3s, FPST_STD, gen_helper_gvec_fmaxnum_s)
152
WRAP_FP_GVEC(gen_VMAXNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fmaxnum_h)
153
@@ -XXX,XX +XXX,XX @@ static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a)
154
return do_3same(s, a, gen_VRSQRTS_fp_3s);
155
}
156
157
-static void gen_VFMA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
158
- TCGv_ptr fpstatus)
159
-{
160
- gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus);
161
-}
162
-
163
-static bool trans_VFMA_fp_3s(DisasContext *s, arg_3same *a)
164
-{
165
- if (!dc_isar_feature(aa32_simdfmac, s)) {
166
- return false;
167
- }
168
-
169
- if (a->size != 0) {
170
- /* TODO fp16 support */
171
- return false;
172
- }
173
-
174
- return do_3same_fp(s, a, gen_VFMA_fp_3s, true);
175
-}
176
-
177
-static void gen_VFMS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
178
- TCGv_ptr fpstatus)
179
-{
180
- gen_helper_vfp_negs(vn, vn);
181
- gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus);
182
-}
183
-
184
-static bool trans_VFMS_fp_3s(DisasContext *s, arg_3same *a)
185
-{
186
- if (!dc_isar_feature(aa32_simdfmac, s)) {
187
- return false;
188
- }
189
-
190
- if (a->size != 0) {
191
- /* TODO fp16 support */
192
- return false;
193
- }
194
-
195
- return do_3same_fp(s, a, gen_VFMS_fp_3s, true);
196
-}
197
-
198
static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
199
{
200
/* FP operations handled pairwise 32 bits at a time */
62
--
201
--
63
2.20.1
202
2.20.1
64
203
65
204
diff view generated by jsdifflib
1
Handle floating point registers in exception entry.
1
Convert the neon floating-point vector compare-vs-0 insns VCEQ0,
2
This corresponds to the FP-specific parts of the pseudocode
2
VCGT0, VCLE0, VCGE0 and VCLT0 to use a gvec helper, and use this to
3
functions ActivateException() and PushStack().
3
implement the fp16 case.
4
5
We defer the code corresponding to UpdateFPCCR() to a later patch.
6
4
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190416125744.27770-11-peter.maydell@linaro.org
7
Message-id: 20200828183354.27913-33-peter.maydell@linaro.org
10
---
8
---
11
target/arm/helper.c | 98 +++++++++++++++++++++++++++++++++++++++++++--
9
target/arm/helper.h | 15 +++++++++++++++
12
1 file changed, 95 insertions(+), 3 deletions(-)
10
target/arm/vec_helper.c | 25 +++++++++++++++++++++++++
11
target/arm/translate-neon.c.inc | 33 +++++----------------------------
12
3 files changed, 45 insertions(+), 28 deletions(-)
13
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
16
--- a/target/arm/helper.h
17
+++ b/target/arm/helper.c
17
+++ b/target/arm/helper.h
18
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_frsqrte_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
19
switch_v7m_security_state(env, targets_secure);
19
DEF_HELPER_FLAGS_4(gvec_frsqrte_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
20
write_v7m_control_spsel(env, 0);
20
DEF_HELPER_FLAGS_4(gvec_frsqrte_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
21
arm_clear_exclusive(env);
21
22
+ /* Clear SFPA and FPCA (has no effect if no FPU) */
22
+DEF_HELPER_FLAGS_4(gvec_fcgt0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
+ env->v7m.control[M_REG_S] &=
23
+DEF_HELPER_FLAGS_4(gvec_fcgt0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+ ~(R_V7M_CONTROL_FPCA_MASK | R_V7M_CONTROL_SFPA_MASK);
25
/* Clear IT bits */
26
env->condexec_bits = 0;
27
env->regs[14] = lr;
28
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
29
uint32_t xpsr = xpsr_read(env);
30
uint32_t frameptr = env->regs[13];
31
ARMMMUIdx mmu_idx = arm_mmu_idx(env);
32
+ uint32_t framesize;
33
+ bool nsacr_cp10 = extract32(env->v7m.nsacr, 10, 1);
34
+
24
+
35
+ if ((env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) &&
25
+DEF_HELPER_FLAGS_4(gvec_fcge0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
36
+ (env->v7m.secure || nsacr_cp10)) {
26
+DEF_HELPER_FLAGS_4(gvec_fcge0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
+ if (env->v7m.secure &&
27
+
38
+ env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK) {
28
+DEF_HELPER_FLAGS_4(gvec_fceq0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
+ framesize = 0xa8;
29
+DEF_HELPER_FLAGS_4(gvec_fceq0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
40
+ } else {
30
+
41
+ framesize = 0x68;
31
+DEF_HELPER_FLAGS_4(gvec_fcle0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
42
+ }
32
+DEF_HELPER_FLAGS_4(gvec_fcle0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
43
+ } else {
33
+
44
+ framesize = 0x20;
34
+DEF_HELPER_FLAGS_4(gvec_fclt0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
45
+ }
35
+DEF_HELPER_FLAGS_4(gvec_fclt0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
46
36
+
47
/* Align stack pointer if the guest wants that */
37
DEF_HELPER_FLAGS_5(gvec_fadd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
48
if ((frameptr & 4) &&
38
DEF_HELPER_FLAGS_5(gvec_fadd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
49
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
39
DEF_HELPER_FLAGS_5(gvec_fadd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
50
xpsr |= XPSR_SPREALIGN;
40
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
51
}
41
index XXXXXXX..XXXXXXX 100644
52
42
--- a/target/arm/vec_helper.c
53
- frameptr -= 0x20;
43
+++ b/target/arm/vec_helper.c
54
+ xpsr &= ~XPSR_SFPA;
44
@@ -XXX,XX +XXX,XX @@ DO_2OP(gvec_frsqrte_h, helper_rsqrte_f16, float16)
55
+ if (env->v7m.secure &&
45
DO_2OP(gvec_frsqrte_s, helper_rsqrte_f32, float32)
56
+ (env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)) {
46
DO_2OP(gvec_frsqrte_d, helper_rsqrte_f64, float64)
57
+ xpsr |= XPSR_SFPA;
47
48
+#define WRAP_CMP0_FWD(FN, CMPOP, TYPE) \
49
+ static TYPE TYPE##_##FN##0(TYPE op, float_status *stat) \
50
+ { \
51
+ return TYPE##_##CMPOP(op, TYPE##_zero, stat); \
58
+ }
52
+ }
59
+
53
+
60
+ frameptr -= framesize;
54
+#define WRAP_CMP0_REV(FN, CMPOP, TYPE) \
61
55
+ static TYPE TYPE##_##FN##0(TYPE op, float_status *stat) \
62
if (arm_feature(env, ARM_FEATURE_V8)) {
56
+ { \
63
uint32_t limit = v7m_sp_limit(env);
57
+ return TYPE##_##CMPOP(TYPE##_zero, op, stat); \
64
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
65
v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
66
v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
67
68
+ if (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) {
69
+ /* FPU is active, try to save its registers */
70
+ bool fpccr_s = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
71
+ bool lspact = env->v7m.fpccr[fpccr_s] & R_V7M_FPCCR_LSPACT_MASK;
72
+
73
+ if (lspact && arm_feature(env, ARM_FEATURE_M_SECURITY)) {
74
+ qemu_log_mask(CPU_LOG_INT,
75
+ "...SecureFault because LSPACT and FPCA both set\n");
76
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
77
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
78
+ } else if (!env->v7m.secure && !nsacr_cp10) {
79
+ qemu_log_mask(CPU_LOG_INT,
80
+ "...Secure UsageFault with CFSR.NOCP because "
81
+ "NSACR.CP10 prevents stacking FP regs\n");
82
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, M_REG_S);
83
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
84
+ } else {
85
+ if (!(env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPEN_MASK)) {
86
+ /* Lazy stacking disabled, save registers now */
87
+ int i;
88
+ bool cpacr_pass = v7m_cpacr_pass(env, env->v7m.secure,
89
+ arm_current_el(env) != 0);
90
+
91
+ if (stacked_ok && !cpacr_pass) {
92
+ /*
93
+ * Take UsageFault if CPACR forbids access. The pseudocode
94
+ * here does a full CheckCPEnabled() but we know the NSACR
95
+ * check can never fail as we have already handled that.
96
+ */
97
+ qemu_log_mask(CPU_LOG_INT,
98
+ "...UsageFault with CFSR.NOCP because "
99
+ "CPACR.CP10 prevents stacking FP regs\n");
100
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
101
+ env->v7m.secure);
102
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_NOCP_MASK;
103
+ stacked_ok = false;
104
+ }
105
+
106
+ for (i = 0; i < ((framesize == 0xa8) ? 32 : 16); i += 2) {
107
+ uint64_t dn = *aa32_vfp_dreg(env, i / 2);
108
+ uint32_t faddr = frameptr + 0x20 + 4 * i;
109
+ uint32_t slo = extract64(dn, 0, 32);
110
+ uint32_t shi = extract64(dn, 32, 32);
111
+
112
+ if (i >= 16) {
113
+ faddr += 8; /* skip the slot for the FPSCR */
114
+ }
115
+ stacked_ok = stacked_ok &&
116
+ v7m_stack_write(cpu, faddr, slo, mmu_idx, false) &&
117
+ v7m_stack_write(cpu, faddr + 4, shi, mmu_idx, false);
118
+ }
119
+ stacked_ok = stacked_ok &&
120
+ v7m_stack_write(cpu, frameptr + 0x60,
121
+ vfp_get_fpscr(env), mmu_idx, false);
122
+ if (cpacr_pass) {
123
+ for (i = 0; i < ((framesize == 0xa8) ? 32 : 16); i += 2) {
124
+ *aa32_vfp_dreg(env, i / 2) = 0;
125
+ }
126
+ vfp_set_fpscr(env, 0);
127
+ }
128
+ } else {
129
+ /* Lazy stacking enabled, save necessary info to stack later */
130
+ /* TODO : equivalent of UpdateFPCCR() pseudocode */
131
+ }
132
+ }
133
+ }
58
+ }
134
+
59
+
60
+#define DO_2OP_CMP0(FN, CMPOP, DIRN) \
61
+ WRAP_CMP0_##DIRN(FN, CMPOP, float16) \
62
+ WRAP_CMP0_##DIRN(FN, CMPOP, float32) \
63
+ DO_2OP(gvec_f##FN##0_h, float16_##FN##0, float16) \
64
+ DO_2OP(gvec_f##FN##0_s, float32_##FN##0, float32)
65
+
66
+DO_2OP_CMP0(cgt, cgt, FWD)
67
+DO_2OP_CMP0(cge, cge, FWD)
68
+DO_2OP_CMP0(ceq, ceq, FWD)
69
+DO_2OP_CMP0(clt, cgt, REV)
70
+DO_2OP_CMP0(cle, cge, REV)
71
+
72
#undef DO_2OP
73
+#undef DO_2OP_CMP0
74
75
/* Floating-point trigonometric starting value.
76
* See the ARM ARM pseudocode function FPTrigSMul.
77
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
78
index XXXXXXX..XXXXXXX 100644
79
--- a/target/arm/translate-neon.c.inc
80
+++ b/target/arm/translate-neon.c.inc
81
@@ -XXX,XX +XXX,XX @@ DO_2MISC_FP(VCVT_UF, gen_helper_vfp_touizs)
82
83
DO_2MISC_FP_VEC(VRECPE_F, gen_helper_gvec_frecpe_h, gen_helper_gvec_frecpe_s)
84
DO_2MISC_FP_VEC(VRSQRTE_F, gen_helper_gvec_frsqrte_h, gen_helper_gvec_frsqrte_s)
85
+DO_2MISC_FP_VEC(VCGT0_F, gen_helper_gvec_fcgt0_h, gen_helper_gvec_fcgt0_s)
86
+DO_2MISC_FP_VEC(VCGE0_F, gen_helper_gvec_fcge0_h, gen_helper_gvec_fcge0_s)
87
+DO_2MISC_FP_VEC(VCEQ0_F, gen_helper_gvec_fceq0_h, gen_helper_gvec_fceq0_s)
88
+DO_2MISC_FP_VEC(VCLT0_F, gen_helper_gvec_fclt0_h, gen_helper_gvec_fclt0_s)
89
+DO_2MISC_FP_VEC(VCLE0_F, gen_helper_gvec_fcle0_h, gen_helper_gvec_fcle0_s)
90
91
static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
92
{
93
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
94
return do_2misc_fp(s, a, gen_helper_rints_exact);
95
}
96
97
-#define WRAP_FP_CMP0_FWD(WRAPNAME, FUNC) \
98
- static void WRAPNAME(TCGv_i32 d, TCGv_i32 m, TCGv_ptr fpst) \
99
- { \
100
- TCGv_i32 zero = tcg_const_i32(0); \
101
- FUNC(d, m, zero, fpst); \
102
- tcg_temp_free_i32(zero); \
103
- }
104
-#define WRAP_FP_CMP0_REV(WRAPNAME, FUNC) \
105
- static void WRAPNAME(TCGv_i32 d, TCGv_i32 m, TCGv_ptr fpst) \
106
- { \
107
- TCGv_i32 zero = tcg_const_i32(0); \
108
- FUNC(d, zero, m, fpst); \
109
- tcg_temp_free_i32(zero); \
110
- }
111
-
112
-#define DO_FP_CMP0(INSN, FUNC, REV) \
113
- WRAP_FP_CMP0_##REV(gen_##INSN, FUNC) \
114
- static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
115
- { \
116
- return do_2misc_fp(s, a, gen_##INSN); \
117
- }
118
-
119
-DO_FP_CMP0(VCGT0_F, gen_helper_neon_cgt_f32, FWD)
120
-DO_FP_CMP0(VCGE0_F, gen_helper_neon_cge_f32, FWD)
121
-DO_FP_CMP0(VCEQ0_F, gen_helper_neon_ceq_f32, FWD)
122
-DO_FP_CMP0(VCLE0_F, gen_helper_neon_cge_f32, REV)
123
-DO_FP_CMP0(VCLT0_F, gen_helper_neon_cgt_f32, REV)
124
-
125
static bool do_vrint(DisasContext *s, arg_2misc *a, int rmode)
126
{
135
/*
127
/*
136
* If we broke a stack limit then SP was already updated earlier;
137
* otherwise we update SP regardless of whether any of the stack
138
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
139
140
if (arm_feature(env, ARM_FEATURE_V8)) {
141
lr = R_V7M_EXCRET_RES1_MASK |
142
- R_V7M_EXCRET_DCRS_MASK |
143
- R_V7M_EXCRET_FTYPE_MASK;
144
+ R_V7M_EXCRET_DCRS_MASK;
145
/* The S bit indicates whether we should return to Secure
146
* or NonSecure (ie our current state).
147
* The ES bit indicates whether we're taking this exception
148
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
149
if (env->v7m.secure) {
150
lr |= R_V7M_EXCRET_S_MASK;
151
}
152
+ if (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK)) {
153
+ lr |= R_V7M_EXCRET_FTYPE_MASK;
154
+ }
155
} else {
156
lr = R_V7M_EXCRET_RES1_MASK |
157
R_V7M_EXCRET_S_MASK |
158
--
128
--
159
2.20.1
129
2.20.1
160
130
161
131
diff view generated by jsdifflib
1
Pushing registers to the stack for v7M needs to handle three cases:
1
Convert the Neon VRECPS insn to using a gvec helper, and
2
* the "normal" case where we pend exceptions
2
use this to implement the fp16 case.
3
* an "ignore faults" case where we set FSR bits but
4
do not pend exceptions (this is used when we are
5
handling some kinds of derived exception on exception entry)
6
* a "lazy FP stacking" case, where different FSR bits
7
are set and the exception is pended differently
8
3
9
Implement this by changing the existing flag argument that
4
The phrasing of the new float32_recps_nf() is slightly different from
10
tells us whether to ignore faults or not into an enum that
5
the old recps_f32() so that it parallels the f16 version; for f16 we
11
specifies which of the 3 modes we should handle.
6
can't assume that flush-to-zero is always enabled.
12
7
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20190416125744.27770-23-peter.maydell@linaro.org
10
Message-id: 20200828183354.27913-34-peter.maydell@linaro.org
16
---
11
---
17
target/arm/helper.c | 118 +++++++++++++++++++++++++++++---------------
12
target/arm/helper.h | 4 +++-
18
1 file changed, 79 insertions(+), 39 deletions(-)
13
target/arm/vec_helper.c | 31 +++++++++++++++++++++++++++++++
14
target/arm/vfp_helper.c | 13 -------------
15
target/arm/translate-neon.c.inc | 21 +--------------------
16
4 files changed, 35 insertions(+), 34 deletions(-)
19
17
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
diff --git a/target/arm/helper.h b/target/arm/helper.h
21
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
20
--- a/target/arm/helper.h
23
+++ b/target/arm/helper.c
21
+++ b/target/arm/helper.h
24
@@ -XXX,XX +XXX,XX @@ static bool v7m_cpacr_pass(CPUARMState *env, bool is_secure, bool is_priv)
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
25
}
23
DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
24
DEF_HELPER_4(vfp_muladdh, f16, f16, f16, f16, ptr)
25
26
-DEF_HELPER_3(recps_f32, f32, env, f32, f32)
27
DEF_HELPER_3(rsqrts_f32, f32, env, f32, f32)
28
DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
29
DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
30
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmaxnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i3
31
DEF_HELPER_FLAGS_5(gvec_fminnum_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_5(gvec_fminnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
33
34
+DEF_HELPER_FLAGS_5(gvec_recps_nf_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_5(gvec_recps_nf_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
36
+
37
DEF_HELPER_FLAGS_5(gvec_fmla_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
38
DEF_HELPER_FLAGS_5(gvec_fmla_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
39
40
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/vec_helper.c
43
+++ b/target/arm/vec_helper.c
44
@@ -XXX,XX +XXX,XX @@ static float32 float32_abd(float32 op1, float32 op2, float_status *stat)
45
return float32_abs(float32_sub(op1, op2, stat));
26
}
46
}
27
47
28
+/*
48
+/*
29
+ * What kind of stack write are we doing? This affects how exceptions
49
+ * Reciprocal step. These are the AArch32 version which uses a
30
+ * generated during the stacking are treated.
50
+ * non-fused multiply-and-subtract.
31
+ */
51
+ */
32
+typedef enum StackingMode {
52
+static float16 float16_recps_nf(float16 op1, float16 op2, float_status *stat)
33
+ STACK_NORMAL,
53
+{
34
+ STACK_IGNFAULTS,
54
+ op1 = float16_squash_input_denormal(op1, stat);
35
+ STACK_LAZYFP,
55
+ op2 = float16_squash_input_denormal(op2, stat);
36
+} StackingMode;
37
+
56
+
38
static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
57
+ if ((float16_is_infinity(op1) && float16_is_zero(op2)) ||
39
- ARMMMUIdx mmu_idx, bool ignfault)
58
+ (float16_is_infinity(op2) && float16_is_zero(op1))) {
40
+ ARMMMUIdx mmu_idx, StackingMode mode)
59
+ return float16_two;
60
+ }
61
+ return float16_sub(float16_two, float16_mul(op1, op2, stat), stat);
62
+}
63
+
64
+static float32 float32_recps_nf(float32 op1, float32 op2, float_status *stat)
65
+{
66
+ op1 = float32_squash_input_denormal(op1, stat);
67
+ op2 = float32_squash_input_denormal(op2, stat);
68
+
69
+ if ((float32_is_infinity(op1) && float32_is_zero(op2)) ||
70
+ (float32_is_infinity(op2) && float32_is_zero(op1))) {
71
+ return float32_two;
72
+ }
73
+ return float32_sub(float32_two, float32_mul(op1, op2, stat), stat);
74
+}
75
+
76
#define DO_3OP(NAME, FUNC, TYPE) \
77
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
78
{ \
79
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_fmaxnum_s, float32_maxnum, float32)
80
DO_3OP(gvec_fminnum_h, float16_minnum, float16)
81
DO_3OP(gvec_fminnum_s, float32_minnum, float32)
82
83
+DO_3OP(gvec_recps_nf_h, float16_recps_nf, float16)
84
+DO_3OP(gvec_recps_nf_s, float32_recps_nf, float32)
85
+
86
#ifdef TARGET_AARCH64
87
88
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
89
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/vfp_helper.c
92
+++ b/target/arm/vfp_helper.c
93
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
94
return r;
95
}
96
97
-float32 HELPER(recps_f32)(CPUARMState *env, float32 a, float32 b)
98
-{
99
- float_status *s = &env->vfp.standard_fp_status;
100
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
101
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
102
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
103
- float_raise(float_flag_input_denormal, s);
104
- }
105
- return float32_two;
106
- }
107
- return float32_sub(float32_two, float32_mul(a, b, s), s);
108
-}
109
-
110
float32 HELPER(rsqrts_f32)(CPUARMState *env, float32 a, float32 b)
41
{
111
{
42
CPUState *cs = CPU(cpu);
112
float_status *s = &env->vfp.standard_fp_status;
43
CPUARMState *env = &cpu->env;
113
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
44
@@ -XXX,XX +XXX,XX @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
114
index XXXXXXX..XXXXXXX 100644
45
&attrs, &prot, &page_size, &fi, NULL)) {
115
--- a/target/arm/translate-neon.c.inc
46
/* MPU/SAU lookup failed */
116
+++ b/target/arm/translate-neon.c.inc
47
if (fi.type == ARMFault_QEMU_SFault) {
117
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMLA, gen_helper_gvec_fmla_s, gen_helper_gvec_fmla_h)
48
- qemu_log_mask(CPU_LOG_INT,
118
DO_3S_FP_GVEC(VMLS, gen_helper_gvec_fmls_s, gen_helper_gvec_fmls_h)
49
- "...SecureFault with SFSR.AUVIOL during stacking\n");
119
DO_3S_FP_GVEC(VFMA, gen_helper_gvec_vfma_s, gen_helper_gvec_vfma_h)
50
- env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
120
DO_3S_FP_GVEC(VFMS, gen_helper_gvec_vfms_s, gen_helper_gvec_vfms_h)
51
+ if (mode == STACK_LAZYFP) {
121
+DO_3S_FP_GVEC(VRECPS, gen_helper_gvec_recps_nf_s, gen_helper_gvec_recps_nf_h)
52
+ qemu_log_mask(CPU_LOG_INT,
122
53
+ "...SecureFault with SFSR.LSPERR "
123
WRAP_FP_GVEC(gen_VMAXNM_fp32_3s, FPST_STD, gen_helper_gvec_fmaxnum_s)
54
+ "during lazy stacking\n");
124
WRAP_FP_GVEC(gen_VMAXNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fmaxnum_h)
55
+ env->v7m.sfsr |= R_V7M_SFSR_LSPERR_MASK;
125
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
56
+ } else {
126
return do_3same(s, a, gen_VMINNM_fp32_3s);
57
+ qemu_log_mask(CPU_LOG_INT,
58
+ "...SecureFault with SFSR.AUVIOL "
59
+ "during stacking\n");
60
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK;
61
+ }
62
+ env->v7m.sfsr |= R_V7M_SFSR_SFARVALID_MASK;
63
env->v7m.sfar = addr;
64
exc = ARMV7M_EXCP_SECURE;
65
exc_secure = false;
66
} else {
67
- qemu_log_mask(CPU_LOG_INT, "...MemManageFault with CFSR.MSTKERR\n");
68
- env->v7m.cfsr[secure] |= R_V7M_CFSR_MSTKERR_MASK;
69
+ if (mode == STACK_LAZYFP) {
70
+ qemu_log_mask(CPU_LOG_INT,
71
+ "...MemManageFault with CFSR.MLSPERR\n");
72
+ env->v7m.cfsr[secure] |= R_V7M_CFSR_MLSPERR_MASK;
73
+ } else {
74
+ qemu_log_mask(CPU_LOG_INT,
75
+ "...MemManageFault with CFSR.MSTKERR\n");
76
+ env->v7m.cfsr[secure] |= R_V7M_CFSR_MSTKERR_MASK;
77
+ }
78
exc = ARMV7M_EXCP_MEM;
79
exc_secure = secure;
80
}
81
@@ -XXX,XX +XXX,XX @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
82
attrs, &txres);
83
if (txres != MEMTX_OK) {
84
/* BusFault trying to write the data */
85
- qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.STKERR\n");
86
- env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_STKERR_MASK;
87
+ if (mode == STACK_LAZYFP) {
88
+ qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.LSPERR\n");
89
+ env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_LSPERR_MASK;
90
+ } else {
91
+ qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.STKERR\n");
92
+ env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_STKERR_MASK;
93
+ }
94
exc = ARMV7M_EXCP_BUS;
95
exc_secure = false;
96
goto pend_fault;
97
@@ -XXX,XX +XXX,XX @@ pend_fault:
98
* later if we have two derived exceptions.
99
* The only case when we must not pend the exception but instead
100
* throw it away is if we are doing the push of the callee registers
101
- * and we've already generated a derived exception. Even in this
102
- * case we will still update the fault status registers.
103
+ * and we've already generated a derived exception (this is indicated
104
+ * by the caller passing STACK_IGNFAULTS). Even in this case we will
105
+ * still update the fault status registers.
106
*/
107
- if (!ignfault) {
108
+ switch (mode) {
109
+ case STACK_NORMAL:
110
armv7m_nvic_set_pending_derived(env->nvic, exc, exc_secure);
111
+ break;
112
+ case STACK_LAZYFP:
113
+ armv7m_nvic_set_pending_lazyfp(env->nvic, exc, exc_secure);
114
+ break;
115
+ case STACK_IGNFAULTS:
116
+ break;
117
}
118
return false;
119
}
127
}
120
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
128
121
uint32_t limit;
129
-WRAP_ENV_FN(gen_VRECPS_tramp, gen_helper_recps_f32)
122
bool want_psp;
130
-
123
uint32_t sig;
131
-static void gen_VRECPS_fp_3s(unsigned vece, uint32_t rd_ofs,
124
+ StackingMode smode = ignore_faults ? STACK_IGNFAULTS : STACK_NORMAL;
132
- uint32_t rn_ofs, uint32_t rm_ofs,
125
133
- uint32_t oprsz, uint32_t maxsz)
126
if (dotailchain) {
134
-{
127
bool mode = lr & R_V7M_EXCRET_MODE_MASK;
135
- static const GVecGen3 ops = { .fni4 = gen_VRECPS_tramp };
128
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
136
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops);
129
*/
137
-}
130
sig = v7m_integrity_sig(env, lr);
138
-
131
stacked_ok =
139
-static bool trans_VRECPS_fp_3s(DisasContext *s, arg_3same *a)
132
- v7m_stack_write(cpu, frameptr, sig, mmu_idx, ignore_faults) &&
140
-{
133
- v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx,
141
- if (a->size != 0) {
134
- ignore_faults) &&
142
- /* TODO fp16 support */
135
- v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx,
143
- return false;
136
- ignore_faults) &&
144
- }
137
- v7m_stack_write(cpu, frameptr + 0x10, env->regs[6], mmu_idx,
145
-
138
- ignore_faults) &&
146
- return do_3same(s, a, gen_VRECPS_fp_3s);
139
- v7m_stack_write(cpu, frameptr + 0x14, env->regs[7], mmu_idx,
147
-}
140
- ignore_faults) &&
148
-
141
- v7m_stack_write(cpu, frameptr + 0x18, env->regs[8], mmu_idx,
149
WRAP_ENV_FN(gen_VRSQRTS_tramp, gen_helper_rsqrts_f32)
142
- ignore_faults) &&
150
143
- v7m_stack_write(cpu, frameptr + 0x1c, env->regs[9], mmu_idx,
151
static void gen_VRSQRTS_fp_3s(unsigned vece, uint32_t rd_ofs,
144
- ignore_faults) &&
145
- v7m_stack_write(cpu, frameptr + 0x20, env->regs[10], mmu_idx,
146
- ignore_faults) &&
147
- v7m_stack_write(cpu, frameptr + 0x24, env->regs[11], mmu_idx,
148
- ignore_faults);
149
+ v7m_stack_write(cpu, frameptr, sig, mmu_idx, smode) &&
150
+ v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx, smode) &&
151
+ v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx, smode) &&
152
+ v7m_stack_write(cpu, frameptr + 0x10, env->regs[6], mmu_idx, smode) &&
153
+ v7m_stack_write(cpu, frameptr + 0x14, env->regs[7], mmu_idx, smode) &&
154
+ v7m_stack_write(cpu, frameptr + 0x18, env->regs[8], mmu_idx, smode) &&
155
+ v7m_stack_write(cpu, frameptr + 0x1c, env->regs[9], mmu_idx, smode) &&
156
+ v7m_stack_write(cpu, frameptr + 0x20, env->regs[10], mmu_idx, smode) &&
157
+ v7m_stack_write(cpu, frameptr + 0x24, env->regs[11], mmu_idx, smode);
158
159
/* Update SP regardless of whether any of the stack accesses failed. */
160
*frame_sp_p = frameptr;
161
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
162
* if it has higher priority).
163
*/
164
stacked_ok = stacked_ok &&
165
- v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, false) &&
166
- v7m_stack_write(cpu, frameptr + 4, env->regs[1], mmu_idx, false) &&
167
- v7m_stack_write(cpu, frameptr + 8, env->regs[2], mmu_idx, false) &&
168
- v7m_stack_write(cpu, frameptr + 12, env->regs[3], mmu_idx, false) &&
169
- v7m_stack_write(cpu, frameptr + 16, env->regs[12], mmu_idx, false) &&
170
- v7m_stack_write(cpu, frameptr + 20, env->regs[14], mmu_idx, false) &&
171
- v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
172
- v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
173
+ v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, STACK_NORMAL) &&
174
+ v7m_stack_write(cpu, frameptr + 4, env->regs[1],
175
+ mmu_idx, STACK_NORMAL) &&
176
+ v7m_stack_write(cpu, frameptr + 8, env->regs[2],
177
+ mmu_idx, STACK_NORMAL) &&
178
+ v7m_stack_write(cpu, frameptr + 12, env->regs[3],
179
+ mmu_idx, STACK_NORMAL) &&
180
+ v7m_stack_write(cpu, frameptr + 16, env->regs[12],
181
+ mmu_idx, STACK_NORMAL) &&
182
+ v7m_stack_write(cpu, frameptr + 20, env->regs[14],
183
+ mmu_idx, STACK_NORMAL) &&
184
+ v7m_stack_write(cpu, frameptr + 24, env->regs[15],
185
+ mmu_idx, STACK_NORMAL) &&
186
+ v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, STACK_NORMAL);
187
188
if (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) {
189
/* FPU is active, try to save its registers */
190
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
191
faddr += 8; /* skip the slot for the FPSCR */
192
}
193
stacked_ok = stacked_ok &&
194
- v7m_stack_write(cpu, faddr, slo, mmu_idx, false) &&
195
- v7m_stack_write(cpu, faddr + 4, shi, mmu_idx, false);
196
+ v7m_stack_write(cpu, faddr, slo,
197
+ mmu_idx, STACK_NORMAL) &&
198
+ v7m_stack_write(cpu, faddr + 4, shi,
199
+ mmu_idx, STACK_NORMAL);
200
}
201
stacked_ok = stacked_ok &&
202
v7m_stack_write(cpu, frameptr + 0x60,
203
- vfp_get_fpscr(env), mmu_idx, false);
204
+ vfp_get_fpscr(env), mmu_idx, STACK_NORMAL);
205
if (cpacr_pass) {
206
for (i = 0; i < ((framesize == 0xa8) ? 32 : 16); i += 2) {
207
*aa32_vfp_dreg(env, i / 2) = 0;
208
--
152
--
209
2.20.1
153
2.20.1
210
154
211
155
diff view generated by jsdifflib
1
The magic value pushed onto the callee stack as an integrity
1
Convert the Neon VRSQRTS insn to using a gvec helper,
2
check is different if floating point is present.
2
and use this to implement the fp16 case.
3
4
As with VRECPS, we adjust the phrasing of the new implementation
5
slightly so that the fp32 version parallels the fp16 one.
3
6
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20190416125744.27770-15-peter.maydell@linaro.org
9
Message-id: 20200828183354.27913-35-peter.maydell@linaro.org
7
---
10
---
8
target/arm/helper.c | 22 +++++++++++++++++++---
11
target/arm/helper.h | 4 +++-
9
1 file changed, 19 insertions(+), 3 deletions(-)
12
target/arm/vec_helper.c | 30 ++++++++++++++++++++++++++++++
13
target/arm/vfp_helper.c | 15 ---------------
14
target/arm/translate-neon.c.inc | 21 +--------------------
15
4 files changed, 34 insertions(+), 36 deletions(-)
10
16
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/helper.c
19
--- a/target/arm/helper.h
14
+++ b/target/arm/helper.c
20
+++ b/target/arm/helper.h
15
@@ -XXX,XX +XXX,XX @@ load_fail:
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
16
return false;
22
DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
23
DEF_HELPER_4(vfp_muladdh, f16, f16, f16, f16, ptr)
24
25
-DEF_HELPER_3(rsqrts_f32, f32, env, f32, f32)
26
DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
27
DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
28
DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
29
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fminnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i3
30
DEF_HELPER_FLAGS_5(gvec_recps_nf_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_5(gvec_recps_nf_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
32
33
+DEF_HELPER_FLAGS_5(gvec_rsqrts_nf_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_5(gvec_rsqrts_nf_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
35
+
36
DEF_HELPER_FLAGS_5(gvec_fmla_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
37
DEF_HELPER_FLAGS_5(gvec_fmla_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
38
39
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/vec_helper.c
42
+++ b/target/arm/vec_helper.c
43
@@ -XXX,XX +XXX,XX @@ static float32 float32_recps_nf(float32 op1, float32 op2, float_status *stat)
44
return float32_sub(float32_two, float32_mul(op1, op2, stat), stat);
17
}
45
}
18
46
19
+static uint32_t v7m_integrity_sig(CPUARMState *env, uint32_t lr)
47
+/* Reciprocal square-root step. AArch32 non-fused semantics. */
48
+static float16 float16_rsqrts_nf(float16 op1, float16 op2, float_status *stat)
20
+{
49
+{
21
+ /*
50
+ op1 = float16_squash_input_denormal(op1, stat);
22
+ * Return the integrity signature value for the callee-saves
51
+ op2 = float16_squash_input_denormal(op2, stat);
23
+ * stack frame section. @lr is the exception return payload/LR value
24
+ * whose FType bit forms bit 0 of the signature if FP is present.
25
+ */
26
+ uint32_t sig = 0xfefa125a;
27
+
52
+
28
+ if (!arm_feature(env, ARM_FEATURE_VFP) || (lr & R_V7M_EXCRET_FTYPE_MASK)) {
53
+ if ((float16_is_infinity(op1) && float16_is_zero(op2)) ||
29
+ sig |= 1;
54
+ (float16_is_infinity(op2) && float16_is_zero(op1))) {
55
+ return float16_one_point_five;
30
+ }
56
+ }
31
+ return sig;
57
+ op1 = float16_sub(float16_three, float16_mul(op1, op2, stat), stat);
58
+ return float16_div(op1, float16_two, stat);
32
+}
59
+}
33
+
60
+
34
static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
61
+static float32 float32_rsqrts_nf(float32 op1, float32 op2, float_status *stat)
35
bool ignore_faults)
62
+{
63
+ op1 = float32_squash_input_denormal(op1, stat);
64
+ op2 = float32_squash_input_denormal(op2, stat);
65
+
66
+ if ((float32_is_infinity(op1) && float32_is_zero(op2)) ||
67
+ (float32_is_infinity(op2) && float32_is_zero(op1))) {
68
+ return float32_one_point_five;
69
+ }
70
+ op1 = float32_sub(float32_three, float32_mul(op1, op2, stat), stat);
71
+ return float32_div(op1, float32_two, stat);
72
+}
73
+
74
#define DO_3OP(NAME, FUNC, TYPE) \
75
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
76
{ \
77
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_fminnum_s, float32_minnum, float32)
78
DO_3OP(gvec_recps_nf_h, float16_recps_nf, float16)
79
DO_3OP(gvec_recps_nf_s, float32_recps_nf, float32)
80
81
+DO_3OP(gvec_rsqrts_nf_h, float16_rsqrts_nf, float16)
82
+DO_3OP(gvec_rsqrts_nf_s, float32_rsqrts_nf, float32)
83
+
84
#ifdef TARGET_AARCH64
85
86
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
87
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/vfp_helper.c
90
+++ b/target/arm/vfp_helper.c
91
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
92
return r;
93
}
94
95
-float32 HELPER(rsqrts_f32)(CPUARMState *env, float32 a, float32 b)
96
-{
97
- float_status *s = &env->vfp.standard_fp_status;
98
- float32 product;
99
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
100
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
101
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
102
- float_raise(float_flag_input_denormal, s);
103
- }
104
- return float32_one_point_five;
105
- }
106
- product = float32_mul(a, b, s);
107
- return float32_div(float32_sub(float32_three, product, s), float32_two, s);
108
-}
109
-
110
/* NEON helpers. */
111
112
/* Constants 256 and 512 are used in some helpers; we avoid relying on
113
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/translate-neon.c.inc
116
+++ b/target/arm/translate-neon.c.inc
117
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMLS, gen_helper_gvec_fmls_s, gen_helper_gvec_fmls_h)
118
DO_3S_FP_GVEC(VFMA, gen_helper_gvec_vfma_s, gen_helper_gvec_vfma_h)
119
DO_3S_FP_GVEC(VFMS, gen_helper_gvec_vfms_s, gen_helper_gvec_vfms_h)
120
DO_3S_FP_GVEC(VRECPS, gen_helper_gvec_recps_nf_s, gen_helper_gvec_recps_nf_h)
121
+DO_3S_FP_GVEC(VRSQRTS, gen_helper_gvec_rsqrts_nf_s, gen_helper_gvec_rsqrts_nf_h)
122
123
WRAP_FP_GVEC(gen_VMAXNM_fp32_3s, FPST_STD, gen_helper_gvec_fmaxnum_s)
124
WRAP_FP_GVEC(gen_VMAXNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fmaxnum_h)
125
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
126
return do_3same(s, a, gen_VMINNM_fp32_3s);
127
}
128
129
-WRAP_ENV_FN(gen_VRSQRTS_tramp, gen_helper_rsqrts_f32)
130
-
131
-static void gen_VRSQRTS_fp_3s(unsigned vece, uint32_t rd_ofs,
132
- uint32_t rn_ofs, uint32_t rm_ofs,
133
- uint32_t oprsz, uint32_t maxsz)
134
-{
135
- static const GVecGen3 ops = { .fni4 = gen_VRSQRTS_tramp };
136
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops);
137
-}
138
-
139
-static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a)
140
-{
141
- if (a->size != 0) {
142
- /* TODO fp16 support */
143
- return false;
144
- }
145
-
146
- return do_3same(s, a, gen_VRSQRTS_fp_3s);
147
-}
148
-
149
static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
36
{
150
{
37
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
151
/* FP operations handled pairwise 32 bits at a time */
38
bool stacked_ok;
39
uint32_t limit;
40
bool want_psp;
41
+ uint32_t sig;
42
43
if (dotailchain) {
44
bool mode = lr & R_V7M_EXCRET_MODE_MASK;
45
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
46
/* Write as much of the stack frame as we can. A write failure may
47
* cause us to pend a derived exception.
48
*/
49
+ sig = v7m_integrity_sig(env, lr);
50
stacked_ok =
51
- v7m_stack_write(cpu, frameptr, 0xfefa125b, mmu_idx, ignore_faults) &&
52
+ v7m_stack_write(cpu, frameptr, sig, mmu_idx, ignore_faults) &&
53
v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx,
54
ignore_faults) &&
55
v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx,
56
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
57
if (return_to_secure &&
58
((excret & R_V7M_EXCRET_ES_MASK) == 0 ||
59
(excret & R_V7M_EXCRET_DCRS_MASK) == 0)) {
60
- uint32_t expected_sig = 0xfefa125b;
61
uint32_t actual_sig;
62
63
pop_ok = v7m_stack_read(cpu, &actual_sig, frameptr, mmu_idx);
64
65
- if (pop_ok && expected_sig != actual_sig) {
66
+ if (pop_ok && v7m_integrity_sig(env, excret) != actual_sig) {
67
/* Take a SecureFault on the current stack */
68
env->v7m.sfsr |= R_V7M_SFSR_INVIS_MASK;
69
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
70
--
152
--
71
2.20.1
153
2.20.1
72
154
73
155
diff view generated by jsdifflib
1
The M-profile FPCCR.ASPEN bit indicates that automatic floating-point
1
Convert the Neon pairwise fp ops to use a single gvic-style
2
context preservation is enabled. Before executing any floating-point
2
helper to do the full operation instead of one helper call
3
instruction, if FPCCR.ASPEN is set and the CONTROL FPCA/SFPA bits
3
for each 32-bit part. This allows us to use the same
4
indicate that there is no active floating point context then we
4
framework to implement the fp16.
5
must create a new context (by initializing FPSCR and setting
6
FPCA/SFPA to indicate that the context is now active). In the
7
pseudocode this is handled by ExecuteFPCheck().
8
9
Implement this with a new TB flag which tracks whether we
10
need to create a new FP context.
11
5
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20190416125744.27770-20-peter.maydell@linaro.org
8
Message-id: 20200828183354.27913-36-peter.maydell@linaro.org
15
---
9
---
16
target/arm/cpu.h | 2 ++
10
target/arm/helper.h | 7 +++++
17
target/arm/translate.h | 1 +
11
target/arm/vec_helper.c | 45 +++++++++++++++++++++++++++++++++
18
target/arm/helper.c | 13 +++++++++++++
12
target/arm/translate-neon.c.inc | 42 ++++++++++++------------------
19
target/arm/translate.c | 29 +++++++++++++++++++++++++++++
13
3 files changed, 68 insertions(+), 26 deletions(-)
20
4 files changed, 45 insertions(+)
21
14
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
23
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpu.h
17
--- a/target/arm/helper.h
25
+++ b/target/arm/cpu.h
18
+++ b/target/arm/helper.h
26
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fcmlas_idx, TCG_CALL_NO_RWG,
27
FIELD(TBFLAG_A32, VFPEN, 7, 1)
20
DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG,
28
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
21
void, ptr, ptr, ptr, ptr, i32)
29
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
22
30
+/* For M profile only, set if we must create a new FP context */
23
+DEF_HELPER_FLAGS_5(neon_paddh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
31
+FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1)
24
+DEF_HELPER_FLAGS_5(neon_pmaxh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
32
/* For M profile only, set if FPCCR.S does not match current security state */
25
+DEF_HELPER_FLAGS_5(neon_pminh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
33
FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1)
26
+DEF_HELPER_FLAGS_5(neon_padds, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
34
/* For M profile only, Handler (ie not Thread) mode */
27
+DEF_HELPER_FLAGS_5(neon_pmaxs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
35
diff --git a/target/arm/translate.h b/target/arm/translate.h
28
+DEF_HELPER_FLAGS_5(neon_pmins, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
29
+
30
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
36
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/translate.h
35
--- a/target/arm/vec_helper.c
38
+++ b/target/arm/translate.h
36
+++ b/target/arm/vec_helper.c
39
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
37
@@ -XXX,XX +XXX,XX @@ DO_ABA(gvec_uaba_s, uint32_t)
40
bool v8m_secure; /* true if v8M and we're in Secure mode */
38
DO_ABA(gvec_uaba_d, uint64_t)
41
bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
39
42
bool v8m_fpccr_s_wrong; /* true if v8M FPCCR.S != v8m_secure */
40
#undef DO_ABA
43
+ bool v7m_new_fp_ctxt_needed; /* ASPEN set but no active FP context */
41
+
44
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
42
+#define DO_NEON_PAIRWISE(NAME, OP) \
45
* so that top level loop can generate correct syndrome information.
43
+ void HELPER(NAME##s)(void *vd, void *vn, void *vm, \
46
*/
44
+ void *stat, uint32_t oprsz) \
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
45
+ { \
48
index XXXXXXX..XXXXXXX 100644
46
+ float_status *fpst = stat; \
49
--- a/target/arm/helper.c
47
+ float32 *d = vd; \
50
+++ b/target/arm/helper.c
48
+ float32 *n = vn; \
51
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
49
+ float32 *m = vm; \
52
flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
50
+ float32 r0, r1; \
53
}
51
+ \
54
52
+ /* Read all inputs before writing outputs in case vm == vd */ \
55
+ if (arm_feature(env, ARM_FEATURE_M) &&
53
+ r0 = float32_##OP(n[H4(0)], n[H4(1)], fpst); \
56
+ (env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
54
+ r1 = float32_##OP(m[H4(0)], m[H4(1)], fpst); \
57
+ (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) ||
55
+ \
58
+ (env->v7m.secure &&
56
+ d[H4(0)] = r0; \
59
+ !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) {
57
+ d[H4(1)] = r1; \
60
+ /*
58
+ } \
61
+ * ASPEN is set, but FPCA/SFPA indicate that there is no active
59
+ \
62
+ * FP context; we must create a new FP context before executing
60
+ void HELPER(NAME##h)(void *vd, void *vn, void *vm, \
63
+ * any FP insn.
61
+ void *stat, uint32_t oprsz) \
64
+ */
62
+ { \
65
+ flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
63
+ float_status *fpst = stat; \
64
+ float16 *d = vd; \
65
+ float16 *n = vn; \
66
+ float16 *m = vm; \
67
+ float16 r0, r1, r2, r3; \
68
+ \
69
+ /* Read all inputs before writing outputs in case vm == vd */ \
70
+ r0 = float16_##OP(n[H2(0)], n[H2(1)], fpst); \
71
+ r1 = float16_##OP(n[H2(2)], n[H2(3)], fpst); \
72
+ r2 = float16_##OP(m[H2(0)], m[H2(1)], fpst); \
73
+ r3 = float16_##OP(m[H2(2)], m[H2(3)], fpst); \
74
+ \
75
+ d[H4(0)] = r0; \
76
+ d[H4(1)] = r1; \
77
+ d[H4(2)] = r2; \
78
+ d[H4(3)] = r3; \
66
+ }
79
+ }
67
+
80
+
68
*pflags = flags;
81
+DO_NEON_PAIRWISE(neon_padd, add)
69
*cs_base = 0;
82
+DO_NEON_PAIRWISE(neon_pmax, max)
83
+DO_NEON_PAIRWISE(neon_pmin, min)
84
+
85
+#undef DO_NEON_PAIRWISE
86
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
87
index XXXXXXX..XXXXXXX 100644
88
--- a/target/arm/translate-neon.c.inc
89
+++ b/target/arm/translate-neon.c.inc
90
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
91
return do_3same(s, a, gen_VMINNM_fp32_3s);
70
}
92
}
71
diff --git a/target/arm/translate.c b/target/arm/translate.c
93
72
index XXXXXXX..XXXXXXX 100644
94
-static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
73
--- a/target/arm/translate.c
95
+static bool do_3same_fp_pair(DisasContext *s, arg_3same *a,
74
+++ b/target/arm/translate.c
96
+ gen_helper_gvec_3_ptr *fn)
75
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
97
{
76
/* Don't need to do this for any further FP insns in this TB */
98
- /* FP operations handled pairwise 32 bits at a time */
77
s->v8m_fpccr_s_wrong = false;
99
- TCGv_i32 tmp, tmp2, tmp3;
78
}
100
+ /* FP pairwise operations */
79
+
101
TCGv_ptr fpstatus;
80
+ if (s->v7m_new_fp_ctxt_needed) {
102
81
+ /*
103
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
82
+ * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA
104
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
83
+ * and the FPSCR.
105
84
+ */
106
assert(a->q == 0); /* enforced by decode patterns */
85
+ TCGv_i32 control, fpscr;
107
86
+ uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
108
- /*
87
+
109
- * Note that we have to be careful not to clobber the source operands
88
+ fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
110
- * in the "vm == vd" case by storing the result of the first pass too
89
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
111
- * early. Since Q is 0 there are always just two passes, so instead
90
+ tcg_temp_free_i32(fpscr);
112
- * of a complicated loop over each pass we just unroll.
91
+ /*
113
- */
92
+ * We don't need to arrange to end the TB, because the only
114
- fpstatus = fpstatus_ptr(FPST_STD);
93
+ * parts of FPSCR which we cache in the TB flags are the VECLEN
115
- tmp = neon_load_reg(a->vn, 0);
94
+ * and VECSTRIDE, and those don't exist for M-profile.
116
- tmp2 = neon_load_reg(a->vn, 1);
95
+ */
117
- fn(tmp, tmp, tmp2, fpstatus);
96
+
118
- tcg_temp_free_i32(tmp2);
97
+ if (s->v8m_secure) {
119
98
+ bits |= R_V7M_CONTROL_SFPA_MASK;
120
- tmp3 = neon_load_reg(a->vm, 0);
99
+ }
121
- tmp2 = neon_load_reg(a->vm, 1);
100
+ control = load_cpu_field(v7m.control[M_REG_S]);
122
- fn(tmp3, tmp3, tmp2, fpstatus);
101
+ tcg_gen_ori_i32(control, control, bits);
123
- tcg_temp_free_i32(tmp2);
102
+ store_cpu_field(control, v7m.control[M_REG_S]);
124
+ fpstatus = fpstatus_ptr(a->size != 0 ? FPST_STD_F16 : FPST_STD);
103
+ /* Don't need to do this for any further FP insns in this TB */
125
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
104
+ s->v7m_new_fp_ctxt_needed = false;
126
+ vfp_reg_offset(1, a->vn),
105
+ }
127
+ vfp_reg_offset(1, a->vm),
128
+ fpstatus, 8, 8, 0, fn);
129
tcg_temp_free_ptr(fpstatus);
130
131
- neon_store_reg(a->vd, 0, tmp);
132
- neon_store_reg(a->vd, 1, tmp3);
133
return true;
134
}
135
136
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
137
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
138
{ \
139
if (a->size != 0) { \
140
- /* TODO fp16 support */ \
141
- return false; \
142
+ if (!dc_isar_feature(aa32_fp16_arith, s)) { \
143
+ return false; \
144
+ } \
145
+ return do_3same_fp_pair(s, a, FUNC##h); \
146
} \
147
- return do_3same_fp_pair(s, a, FUNC); \
148
+ return do_3same_fp_pair(s, a, FUNC##s); \
106
}
149
}
107
150
108
if (extract32(insn, 28, 4) == 0xf) {
151
-DO_3S_FP_PAIR(VPADD, gen_helper_vfp_adds)
109
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
152
-DO_3S_FP_PAIR(VPMAX, gen_helper_vfp_maxs)
110
regime_is_secure(env, dc->mmu_idx);
153
-DO_3S_FP_PAIR(VPMIN, gen_helper_vfp_mins)
111
dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
154
+DO_3S_FP_PAIR(VPADD, gen_helper_neon_padd)
112
dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
155
+DO_3S_FP_PAIR(VPMAX, gen_helper_neon_pmax)
113
+ dc->v7m_new_fp_ctxt_needed =
156
+DO_3S_FP_PAIR(VPMIN, gen_helper_neon_pmin)
114
+ FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
157
115
dc->cp_regs = cpu->cp_regs;
158
static bool do_vector_2sh(DisasContext *s, arg_2reg_shift *a, GVecGen2iFn *fn)
116
dc->features = env->features;
159
{
117
118
--
160
--
119
2.20.1
161
2.20.1
120
162
121
163
diff view generated by jsdifflib
1
The only "system register" that M-profile floating point exposes
1
Convert the Neon float-integer VCVT insns to gvec, and use this
2
via the VMRS/VMRS instructions is FPSCR, and it does not have
2
to implement fp16 support for them.
3
the odd special case for rd==15. Add a check to ensure we only
3
4
expose FPSCR.
4
Note that unlike the VFP int<->fp16 VCVT insns we converted
5
earlier and which convert to/from a 32-bit integer, these
6
Neon insns convert to/from 16-bit integers. So we can use
7
the existing vfp conversion helpers for the f32<->u32/i32
8
case but need to provide our own for f16<->u16/i16.
5
9
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190416125744.27770-5-peter.maydell@linaro.org
12
Message-id: 20200828183354.27913-37-peter.maydell@linaro.org
9
---
13
---
10
target/arm/translate.c | 19 +++++++++++++++++--
14
target/arm/helper.h | 9 +++++++++
11
1 file changed, 17 insertions(+), 2 deletions(-)
15
target/arm/vec_helper.c | 29 +++++++++++++++++++++++++++++
16
target/arm/translate-neon.c.inc | 15 ++++-----------
17
3 files changed, 42 insertions(+), 11 deletions(-)
12
18
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
19
diff --git a/target/arm/helper.h b/target/arm/helper.h
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
21
--- a/target/arm/helper.h
16
+++ b/target/arm/translate.c
22
+++ b/target/arm/helper.h
17
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(neon_padds, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
18
}
24
DEF_HELPER_FLAGS_5(neon_pmaxs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
}
25
DEF_HELPER_FLAGS_5(neon_pmins, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
} else { /* !dp */
26
21
+ bool is_sysreg;
27
+DEF_HELPER_FLAGS_4(gvec_sstoh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
+DEF_HELPER_FLAGS_4(gvec_sitos, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_4(gvec_ustoh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
30
+DEF_HELPER_FLAGS_4(gvec_uitos, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_4(gvec_tosszh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
32
+DEF_HELPER_FLAGS_4(gvec_tosizs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_4(gvec_touszh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(gvec_touizs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
+
35
+
23
if ((insn & 0x6f) != 0x00)
36
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
return 1;
37
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
rn = VFP_SREG_N(insn);
38
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/vec_helper.c
42
+++ b/target/arm/vec_helper.c
43
@@ -XXX,XX +XXX,XX @@ static uint32_t float32_acgt(float32 op1, float32 op2, float_status *stat)
44
return -float32_lt(float32_abs(op2), float32_abs(op1), stat);
45
}
46
47
+static int16_t vfp_tosszh(float16 x, void *fpstp)
48
+{
49
+ float_status *fpst = fpstp;
50
+ if (float16_is_any_nan(x)) {
51
+ float_raise(float_flag_invalid, fpst);
52
+ return 0;
53
+ }
54
+ return float16_to_int16_round_to_zero(x, fpst);
55
+}
26
+
56
+
27
+ is_sysreg = extract32(insn, 21, 1);
57
+static uint16_t vfp_touszh(float16 x, void *fpstp)
58
+{
59
+ float_status *fpst = fpstp;
60
+ if (float16_is_any_nan(x)) {
61
+ float_raise(float_flag_invalid, fpst);
62
+ return 0;
63
+ }
64
+ return float16_to_uint16_round_to_zero(x, fpst);
65
+}
28
+
66
+
29
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
67
#define DO_2OP(NAME, FUNC, TYPE) \
30
+ /*
68
void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
31
+ * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
69
{ \
32
+ * Writes to R15 are UNPREDICTABLE; we choose to undef.
70
@@ -XXX,XX +XXX,XX @@ DO_2OP(gvec_frsqrte_h, helper_rsqrte_f16, float16)
33
+ */
71
DO_2OP(gvec_frsqrte_s, helper_rsqrte_f32, float32)
34
+ if (is_sysreg && (rd == 15 || (rn >> 1) != ARM_VFP_FPSCR)) {
72
DO_2OP(gvec_frsqrte_d, helper_rsqrte_f64, float64)
35
+ return 1;
73
36
+ }
74
+DO_2OP(gvec_sitos, helper_vfp_sitos, int32_t)
37
+ }
75
+DO_2OP(gvec_uitos, helper_vfp_uitos, uint32_t)
76
+DO_2OP(gvec_tosizs, helper_vfp_tosizs, float32)
77
+DO_2OP(gvec_touizs, helper_vfp_touizs, float32)
78
+DO_2OP(gvec_sstoh, int16_to_float16, int16_t)
79
+DO_2OP(gvec_ustoh, uint16_to_float16, uint16_t)
80
+DO_2OP(gvec_tosszh, vfp_tosszh, float16)
81
+DO_2OP(gvec_touszh, vfp_touszh, float16)
38
+
82
+
39
if (insn & ARM_CP_RW_BIT) {
83
#define WRAP_CMP0_FWD(FN, CMPOP, TYPE) \
40
/* vfp->arm */
84
static TYPE TYPE##_##FN##0(TYPE op, float_status *stat) \
41
- if (insn & (1 << 21)) {
85
{ \
42
+ if (is_sysreg) {
86
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
43
/* system register */
87
index XXXXXXX..XXXXXXX 100644
44
rn >>= 1;
88
--- a/target/arm/translate-neon.c.inc
45
89
+++ b/target/arm/translate-neon.c.inc
46
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
90
@@ -XXX,XX +XXX,XX @@ static bool do_2misc_fp(DisasContext *s, arg_2misc *a,
47
}
91
return true;
48
} else {
92
}
49
/* arm->vfp */
93
50
- if (insn & (1 << 21)) {
94
-#define DO_2MISC_FP(INSN, FUNC) \
51
+ if (is_sysreg) {
95
- static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
52
rn >>= 1;
96
- { \
53
/* system register */
97
- return do_2misc_fp(s, a, FUNC); \
54
switch (rn) {
98
- }
99
-
100
-DO_2MISC_FP(VCVT_FS, gen_helper_vfp_sitos)
101
-DO_2MISC_FP(VCVT_FU, gen_helper_vfp_uitos)
102
-DO_2MISC_FP(VCVT_SF, gen_helper_vfp_tosizs)
103
-DO_2MISC_FP(VCVT_UF, gen_helper_vfp_touizs)
104
-
105
#define DO_2MISC_FP_VEC(INSN, HFUNC, SFUNC) \
106
static void gen_##INSN(unsigned vece, uint32_t rd_ofs, \
107
uint32_t rm_ofs, \
108
@@ -XXX,XX +XXX,XX @@ DO_2MISC_FP_VEC(VCGE0_F, gen_helper_gvec_fcge0_h, gen_helper_gvec_fcge0_s)
109
DO_2MISC_FP_VEC(VCEQ0_F, gen_helper_gvec_fceq0_h, gen_helper_gvec_fceq0_s)
110
DO_2MISC_FP_VEC(VCLT0_F, gen_helper_gvec_fclt0_h, gen_helper_gvec_fclt0_s)
111
DO_2MISC_FP_VEC(VCLE0_F, gen_helper_gvec_fcle0_h, gen_helper_gvec_fcle0_s)
112
+DO_2MISC_FP_VEC(VCVT_FS, gen_helper_gvec_sstoh, gen_helper_gvec_sitos)
113
+DO_2MISC_FP_VEC(VCVT_FU, gen_helper_gvec_ustoh, gen_helper_gvec_uitos)
114
+DO_2MISC_FP_VEC(VCVT_SF, gen_helper_gvec_tosszh, gen_helper_gvec_tosizs)
115
+DO_2MISC_FP_VEC(VCVT_UF, gen_helper_gvec_touszh, gen_helper_gvec_touizs)
116
117
static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
118
{
55
--
119
--
56
2.20.1
120
2.20.1
57
121
58
122
diff view generated by jsdifflib
1
The M-profile FPCCR.S bit indicates the security status of
1
Convert the Neon VCVT float<->fixed-point insns to a
2
the floating point context. In the pseudocode ExecuteFPCheck()
2
gvec style, in preparation for adding fp16 support.
3
function it is unconditionally set to match the current
4
security state whenever a floating point instruction is
5
executed.
6
7
Implement this by adding a new TB flag which tracks whether
8
FPCCR.S is different from the current security state, so
9
that we only need to emit the code to update it in the
10
less-common case when it is not already set correctly.
11
12
Note that we will add the handling for the other work done
13
by ExecuteFPCheck() in later commits.
14
3
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20190416125744.27770-19-peter.maydell@linaro.org
6
Message-id: 20200828183354.27913-38-peter.maydell@linaro.org
18
---
7
---
19
target/arm/cpu.h | 2 ++
8
target/arm/helper.h | 5 +++++
20
target/arm/translate.h | 1 +
9
target/arm/vec_helper.c | 20 +++++++++++++++++++
21
target/arm/helper.c | 5 +++++
10
target/arm/translate-neon.c.inc | 35 +++++++++++++++++----------------
22
target/arm/translate.c | 20 ++++++++++++++++++++
11
3 files changed, 43 insertions(+), 17 deletions(-)
23
4 files changed, 28 insertions(+)
24
12
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
26
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/cpu.h
15
--- a/target/arm/helper.h
28
+++ b/target/arm/cpu.h
16
+++ b/target/arm/helper.h
29
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_tosizs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
30
FIELD(TBFLAG_A32, VFPEN, 7, 1)
18
DEF_HELPER_FLAGS_4(gvec_touszh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
19
DEF_HELPER_FLAGS_4(gvec_touizs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
32
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
20
33
+/* For M profile only, set if FPCCR.S does not match current security state */
21
+DEF_HELPER_FLAGS_4(gvec_vcvt_sf, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
+FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1)
22
+DEF_HELPER_FLAGS_4(gvec_vcvt_uf, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
35
/* For M profile only, Handler (ie not Thread) mode */
23
+DEF_HELPER_FLAGS_4(gvec_vcvt_fs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
36
FIELD(TBFLAG_A32, HANDLER, 21, 1)
24
+DEF_HELPER_FLAGS_4(gvec_vcvt_fu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
/* For M profile only, whether we should generate stack-limit checks */
25
+
38
diff --git a/target/arm/translate.h b/target/arm/translate.h
26
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
39
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/translate.h
31
--- a/target/arm/vec_helper.c
41
+++ b/target/arm/translate.h
32
+++ b/target/arm/vec_helper.c
42
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
33
@@ -XXX,XX +XXX,XX @@ DO_NEON_PAIRWISE(neon_pmax, max)
43
bool v7m_handler_mode;
34
DO_NEON_PAIRWISE(neon_pmin, min)
44
bool v8m_secure; /* true if v8M and we're in Secure mode */
35
45
bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
36
#undef DO_NEON_PAIRWISE
46
+ bool v8m_fpccr_s_wrong; /* true if v8M FPCCR.S != v8m_secure */
37
+
47
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
38
+#define DO_VCVT_FIXED(NAME, FUNC, TYPE) \
48
* so that top level loop can generate correct syndrome information.
39
+ void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
49
*/
40
+ { \
50
diff --git a/target/arm/helper.c b/target/arm/helper.c
41
+ intptr_t i, oprsz = simd_oprsz(desc); \
51
index XXXXXXX..XXXXXXX 100644
42
+ int shift = simd_data(desc); \
52
--- a/target/arm/helper.c
43
+ TYPE *d = vd, *n = vn; \
53
+++ b/target/arm/helper.c
44
+ float_status *fpst = stat; \
54
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
45
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
55
flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
46
+ d[i] = FUNC(n[i], shift, fpst); \
56
}
47
+ } \
57
48
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
58
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
59
+ FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) {
60
+ flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
61
+ }
49
+ }
62
+
50
+
63
*pflags = flags;
51
+DO_VCVT_FIXED(gvec_vcvt_sf, helper_vfp_sltos, uint32_t)
64
*cs_base = 0;
52
+DO_VCVT_FIXED(gvec_vcvt_uf, helper_vfp_ultos, uint32_t)
53
+DO_VCVT_FIXED(gvec_vcvt_fs, helper_vfp_tosls_round_to_zero, uint32_t)
54
+DO_VCVT_FIXED(gvec_vcvt_fu, helper_vfp_touls_round_to_zero, uint32_t)
55
+
56
+#undef DO_VCVT_FIXED
57
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/translate-neon.c.inc
60
+++ b/target/arm/translate-neon.c.inc
61
@@ -XXX,XX +XXX,XX @@ static bool trans_VSHLL_U_2sh(DisasContext *s, arg_2reg_shift *a)
65
}
62
}
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
63
67
index XXXXXXX..XXXXXXX 100644
64
static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
68
--- a/target/arm/translate.c
65
- NeonGenTwoSingleOpFn *fn)
69
+++ b/target/arm/translate.c
66
+ gen_helper_gvec_2_ptr *fn)
70
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
67
{
71
}
68
/* FP operations in 2-reg-and-shift group */
69
- TCGv_i32 tmp, shiftv;
70
- TCGv_ptr fpstatus;
71
- int pass;
72
+ int vec_size = a->q ? 16 : 8;
73
+ int rd_ofs = neon_reg_offset(a->vd, 0);
74
+ int rm_ofs = neon_reg_offset(a->vm, 0);
75
+ TCGv_ptr fpst;
76
77
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
78
return false;
72
}
79
}
73
80
74
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
81
+ if (a->size != 0) {
75
+ /* Handle M-profile lazy FP state mechanics */
82
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
76
+
83
+ return false;
77
+ /* Update ownership of FP context: set FPCCR.S to match current state */
78
+ if (s->v8m_fpccr_s_wrong) {
79
+ TCGv_i32 tmp;
80
+
81
+ tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
82
+ if (s->v8m_secure) {
83
+ tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
84
+ } else {
85
+ tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
86
+ }
87
+ store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
88
+ /* Don't need to do this for any further FP insns in this TB */
89
+ s->v8m_fpccr_s_wrong = false;
90
+ }
84
+ }
91
+ }
85
+ }
92
+
86
+
93
if (extract32(insn, 28, 4) == 0xf) {
87
/* UNDEF accesses to D16-D31 if they don't exist. */
94
/*
88
if (!dc_isar_feature(aa32_simd_r32, s) &&
95
* Encodings with T=1 (Thumb) or unconditional (ARM):
89
((a->vd | a->vm) & 0x10)) {
96
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
90
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
97
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
91
return true;
98
regime_is_secure(env, dc->mmu_idx);
92
}
99
dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
93
100
+ dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
94
- fpstatus = fpstatus_ptr(FPST_STD);
101
dc->cp_regs = cpu->cp_regs;
95
- shiftv = tcg_const_i32(a->shift);
102
dc->features = env->features;
96
- for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
103
97
- tmp = neon_load_reg(a->vm, pass);
98
- fn(tmp, tmp, shiftv, fpstatus);
99
- neon_store_reg(a->vd, pass, tmp);
100
- }
101
- tcg_temp_free_ptr(fpstatus);
102
- tcg_temp_free_i32(shiftv);
103
+ fpst = fpstatus_ptr(a->size ? FPST_STD_F16 : FPST_STD);
104
+ tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, vec_size, vec_size, a->shift, fn);
105
+ tcg_temp_free_ptr(fpst);
106
return true;
107
}
108
109
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
110
return do_fp_2sh(s, a, FUNC); \
111
}
112
113
-DO_FP_2SH(VCVT_SF, gen_helper_vfp_sltos)
114
-DO_FP_2SH(VCVT_UF, gen_helper_vfp_ultos)
115
-DO_FP_2SH(VCVT_FS, gen_helper_vfp_tosls_round_to_zero)
116
-DO_FP_2SH(VCVT_FU, gen_helper_vfp_touls_round_to_zero)
117
+DO_FP_2SH(VCVT_SF, gen_helper_gvec_vcvt_sf)
118
+DO_FP_2SH(VCVT_UF, gen_helper_gvec_vcvt_uf)
119
+DO_FP_2SH(VCVT_FS, gen_helper_gvec_vcvt_fs)
120
+DO_FP_2SH(VCVT_FU, gen_helper_gvec_vcvt_fu)
121
122
static uint64_t asimd_imm_const(uint32_t imm, int cmode, int op)
123
{
104
--
124
--
105
2.20.1
125
2.20.1
106
126
107
127
diff view generated by jsdifflib
1
For M-profile the MVFR* ID registers are memory mapped, in the
1
Implement fp16 for the Neon VCVT insns which convert between
2
range we implement via the NVIC. Allow them to be read.
2
float and fixed-point.
3
(If the CPU has no FPU, these registers are defined to be RAZ.)
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190416125744.27770-3-peter.maydell@linaro.org
6
Message-id: 20200828183354.27913-39-peter.maydell@linaro.org
8
---
7
---
9
hw/intc/armv7m_nvic.c | 6 ++++++
8
target/arm/helper.h | 5 +++++
10
1 file changed, 6 insertions(+)
9
target/arm/neon-dp.decode | 8 +++++++-
10
target/arm/vec_helper.c | 4 ++++
11
target/arm/translate-neon.c.inc | 5 +++++
12
4 files changed, 21 insertions(+), 1 deletion(-)
11
13
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
16
--- a/target/arm/helper.h
15
+++ b/hw/intc/armv7m_nvic.c
17
+++ b/target/arm/helper.h
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_vcvt_uf, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
17
return 0;
19
DEF_HELPER_FLAGS_4(gvec_vcvt_fs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
18
}
20
DEF_HELPER_FLAGS_4(gvec_vcvt_fu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
19
return cpu->env.v7m.sfar;
21
20
+ case 0xf40: /* MVFR0 */
22
+DEF_HELPER_FLAGS_4(gvec_vcvt_sh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
21
+ return cpu->isar.mvfr0;
23
+DEF_HELPER_FLAGS_4(gvec_vcvt_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
+ case 0xf44: /* MVFR1 */
24
+DEF_HELPER_FLAGS_4(gvec_vcvt_hs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
+ return cpu->isar.mvfr1;
25
+DEF_HELPER_FLAGS_4(gvec_vcvt_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+ case 0xf48: /* MVFR2 */
26
+
25
+ return cpu->isar.mvfr2;
27
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
default:
28
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
bad_offset:
29
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
30
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/neon-dp.decode
33
+++ b/target/arm/neon-dp.decode
34
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
35
# We use size=0 for fp32 and size=1 for fp16 to match the 3-same encodings.
36
@2reg_vcvt .... ... . . . 1 ..... .... .... . q:1 . . .... \
37
&2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i5
38
+@2reg_vcvt_f16 .... ... . . . 11 .... .... .... . q:1 . . .... \
39
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4
40
41
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
42
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
43
@@ -XXX,XX +XXX,XX @@ VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_h
44
VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b
45
46
# VCVT fixed<->float conversions
47
-# TODO: FP16 fixed<->float conversions are opc==0b1100 and 0b1101
48
+VCVT_SH_2sh 1111 001 0 1 . ...... .... 1100 0 . . 1 .... @2reg_vcvt_f16
49
+VCVT_UH_2sh 1111 001 1 1 . ...... .... 1100 0 . . 1 .... @2reg_vcvt_f16
50
+VCVT_HS_2sh 1111 001 0 1 . ...... .... 1101 0 . . 1 .... @2reg_vcvt_f16
51
+VCVT_HU_2sh 1111 001 1 1 . ...... .... 1101 0 . . 1 .... @2reg_vcvt_f16
52
+
53
VCVT_SF_2sh 1111 001 0 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
54
VCVT_UF_2sh 1111 001 1 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
55
VCVT_FS_2sh 1111 001 0 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
56
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/vec_helper.c
59
+++ b/target/arm/vec_helper.c
60
@@ -XXX,XX +XXX,XX @@ DO_VCVT_FIXED(gvec_vcvt_sf, helper_vfp_sltos, uint32_t)
61
DO_VCVT_FIXED(gvec_vcvt_uf, helper_vfp_ultos, uint32_t)
62
DO_VCVT_FIXED(gvec_vcvt_fs, helper_vfp_tosls_round_to_zero, uint32_t)
63
DO_VCVT_FIXED(gvec_vcvt_fu, helper_vfp_touls_round_to_zero, uint32_t)
64
+DO_VCVT_FIXED(gvec_vcvt_sh, helper_vfp_shtoh, uint16_t)
65
+DO_VCVT_FIXED(gvec_vcvt_uh, helper_vfp_uhtoh, uint16_t)
66
+DO_VCVT_FIXED(gvec_vcvt_hs, helper_vfp_toshh_round_to_zero, uint16_t)
67
+DO_VCVT_FIXED(gvec_vcvt_hu, helper_vfp_touhh_round_to_zero, uint16_t)
68
69
#undef DO_VCVT_FIXED
70
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/translate-neon.c.inc
73
+++ b/target/arm/translate-neon.c.inc
74
@@ -XXX,XX +XXX,XX @@ DO_FP_2SH(VCVT_UF, gen_helper_gvec_vcvt_uf)
75
DO_FP_2SH(VCVT_FS, gen_helper_gvec_vcvt_fs)
76
DO_FP_2SH(VCVT_FU, gen_helper_gvec_vcvt_fu)
77
78
+DO_FP_2SH(VCVT_SH, gen_helper_gvec_vcvt_sh)
79
+DO_FP_2SH(VCVT_UH, gen_helper_gvec_vcvt_uh)
80
+DO_FP_2SH(VCVT_HS, gen_helper_gvec_vcvt_hs)
81
+DO_FP_2SH(VCVT_HU, gen_helper_gvec_vcvt_hu)
82
+
83
static uint64_t asimd_imm_const(uint32_t imm, int cmode, int op)
84
{
85
/*
29
--
86
--
30
2.20.1
87
2.20.1
31
88
32
89
diff view generated by jsdifflib
1
The TailChain() pseudocode specifies that a tail chaining
1
Convert the Neon VCVT with-specified-rounding-mode instructions
2
exception should sanitize the excReturn all-ones bits and
2
to gvec, and use this to implement fp16 support for them.
3
(if there is no FPU) the excReturn FType bits; we weren't
4
doing this.
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190416125744.27770-14-peter.maydell@linaro.org
6
Message-id: 20200828183354.27913-40-peter.maydell@linaro.org
9
---
7
---
10
target/arm/helper.c | 8 ++++++++
8
target/arm/helper.h | 5 ++
11
1 file changed, 8 insertions(+)
9
target/arm/vec_helper.c | 23 +++++++
10
target/arm/translate-neon.c.inc | 105 ++++++++++++--------------------
11
3 files changed, 66 insertions(+), 67 deletions(-)
12
12
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
15
--- a/target/arm/helper.h
16
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper.h
17
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_vcvt_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
18
qemu_log_mask(CPU_LOG_INT, "...taking pending %s exception %d\n",
18
DEF_HELPER_FLAGS_4(gvec_vcvt_hs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
19
targets_secure ? "secure" : "nonsecure", exc);
19
DEF_HELPER_FLAGS_4(gvec_vcvt_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
20
20
21
+ if (dotailchain) {
21
+DEF_HELPER_FLAGS_4(gvec_vcvt_rm_ss, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
+ /* Sanitize LR FType and PREFIX bits */
22
+DEF_HELPER_FLAGS_4(gvec_vcvt_rm_us, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
+ if (!arm_feature(env, ARM_FEATURE_VFP)) {
23
+DEF_HELPER_FLAGS_4(gvec_vcvt_rm_sh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+ lr |= R_V7M_EXCRET_FTYPE_MASK;
24
+DEF_HELPER_FLAGS_4(gvec_vcvt_rm_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+ }
25
+
26
+ lr = deposit32(lr, 24, 8, 0xff);
26
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/vec_helper.c
32
+++ b/target/arm/vec_helper.c
33
@@ -XXX,XX +XXX,XX @@ DO_VCVT_FIXED(gvec_vcvt_hs, helper_vfp_toshh_round_to_zero, uint16_t)
34
DO_VCVT_FIXED(gvec_vcvt_hu, helper_vfp_touhh_round_to_zero, uint16_t)
35
36
#undef DO_VCVT_FIXED
37
+
38
+#define DO_VCVT_RMODE(NAME, FUNC, TYPE) \
39
+ void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
40
+ { \
41
+ float_status *fpst = stat; \
42
+ intptr_t i, oprsz = simd_oprsz(desc); \
43
+ uint32_t rmode = simd_data(desc); \
44
+ uint32_t prev_rmode = get_float_rounding_mode(fpst); \
45
+ TYPE *d = vd, *n = vn; \
46
+ set_float_rounding_mode(rmode, fpst); \
47
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
48
+ d[i] = FUNC(n[i], 0, fpst); \
49
+ } \
50
+ set_float_rounding_mode(prev_rmode, fpst); \
51
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
27
+ }
52
+ }
28
+
53
+
29
if (arm_feature(env, ARM_FEATURE_V8)) {
54
+DO_VCVT_RMODE(gvec_vcvt_rm_ss, helper_vfp_tosls, uint32_t)
30
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
55
+DO_VCVT_RMODE(gvec_vcvt_rm_us, helper_vfp_touls, uint32_t)
31
(lr & R_V7M_EXCRET_S_MASK)) {
56
+DO_VCVT_RMODE(gvec_vcvt_rm_sh, helper_vfp_toshh, uint16_t)
57
+DO_VCVT_RMODE(gvec_vcvt_rm_uh, helper_vfp_touhh, uint16_t)
58
+
59
+#undef DO_VCVT_RMODE
60
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/translate-neon.c.inc
63
+++ b/target/arm/translate-neon.c.inc
64
@@ -XXX,XX +XXX,XX @@ DO_VRINT(VRINTZ, FPROUNDING_ZERO)
65
DO_VRINT(VRINTM, FPROUNDING_NEGINF)
66
DO_VRINT(VRINTP, FPROUNDING_POSINF)
67
68
-static bool do_vcvt(DisasContext *s, arg_2misc *a, int rmode, bool is_signed)
69
-{
70
- /*
71
- * Handle a VCVT* operation by iterating 32 bits at a time,
72
- * with a specified rounding mode in operation.
73
- */
74
- int pass;
75
- TCGv_ptr fpst;
76
- TCGv_i32 tcg_rmode, tcg_shift;
77
-
78
- if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
79
- !arm_dc_feature(s, ARM_FEATURE_V8)) {
80
- return false;
81
+#define DO_VEC_RMODE(INSN, RMODE, OP) \
82
+ static void gen_##INSN(unsigned vece, uint32_t rd_ofs, \
83
+ uint32_t rm_ofs, \
84
+ uint32_t oprsz, uint32_t maxsz) \
85
+ { \
86
+ static gen_helper_gvec_2_ptr * const fns[4] = { \
87
+ NULL, \
88
+ gen_helper_gvec_##OP##h, \
89
+ gen_helper_gvec_##OP##s, \
90
+ NULL, \
91
+ }; \
92
+ TCGv_ptr fpst; \
93
+ fpst = fpstatus_ptr(vece == 1 ? FPST_STD_F16 : FPST_STD); \
94
+ tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, oprsz, maxsz, \
95
+ arm_rmode_to_sf(RMODE), fns[vece]); \
96
+ tcg_temp_free_ptr(fpst); \
97
+ } \
98
+ static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
99
+ { \
100
+ if (!arm_dc_feature(s, ARM_FEATURE_V8)) { \
101
+ return false; \
102
+ } \
103
+ if (a->size == MO_16) { \
104
+ if (!dc_isar_feature(aa32_fp16_arith, s)) { \
105
+ return false; \
106
+ } \
107
+ } else if (a->size != MO_32) { \
108
+ return false; \
109
+ } \
110
+ return do_2misc_vec(s, a, gen_##INSN); \
111
}
112
113
- /* UNDEF accesses to D16-D31 if they don't exist. */
114
- if (!dc_isar_feature(aa32_simd_r32, s) &&
115
- ((a->vd | a->vm) & 0x10)) {
116
- return false;
117
- }
118
-
119
- if (a->size != 2) {
120
- /* TODO: FP16 will be the size == 1 case */
121
- return false;
122
- }
123
-
124
- if ((a->vd | a->vm) & a->q) {
125
- return false;
126
- }
127
-
128
- if (!vfp_access_check(s)) {
129
- return true;
130
- }
131
-
132
- fpst = fpstatus_ptr(FPST_STD);
133
- tcg_shift = tcg_const_i32(0);
134
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
135
- gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
136
- for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
137
- TCGv_i32 tmp = neon_load_reg(a->vm, pass);
138
- if (is_signed) {
139
- gen_helper_vfp_tosls(tmp, tmp, tcg_shift, fpst);
140
- } else {
141
- gen_helper_vfp_touls(tmp, tmp, tcg_shift, fpst);
142
- }
143
- neon_store_reg(a->vd, pass, tmp);
144
- }
145
- gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
146
- tcg_temp_free_i32(tcg_rmode);
147
- tcg_temp_free_i32(tcg_shift);
148
- tcg_temp_free_ptr(fpst);
149
-
150
- return true;
151
-}
152
-
153
-#define DO_VCVT(INSN, RMODE, SIGNED) \
154
- static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
155
- { \
156
- return do_vcvt(s, a, RMODE, SIGNED); \
157
- }
158
-
159
-DO_VCVT(VCVTAU, FPROUNDING_TIEAWAY, false)
160
-DO_VCVT(VCVTAS, FPROUNDING_TIEAWAY, true)
161
-DO_VCVT(VCVTNU, FPROUNDING_TIEEVEN, false)
162
-DO_VCVT(VCVTNS, FPROUNDING_TIEEVEN, true)
163
-DO_VCVT(VCVTPU, FPROUNDING_POSINF, false)
164
-DO_VCVT(VCVTPS, FPROUNDING_POSINF, true)
165
-DO_VCVT(VCVTMU, FPROUNDING_NEGINF, false)
166
-DO_VCVT(VCVTMS, FPROUNDING_NEGINF, true)
167
+DO_VEC_RMODE(VCVTAU, FPROUNDING_TIEAWAY, vcvt_rm_u)
168
+DO_VEC_RMODE(VCVTAS, FPROUNDING_TIEAWAY, vcvt_rm_s)
169
+DO_VEC_RMODE(VCVTNU, FPROUNDING_TIEEVEN, vcvt_rm_u)
170
+DO_VEC_RMODE(VCVTNS, FPROUNDING_TIEEVEN, vcvt_rm_s)
171
+DO_VEC_RMODE(VCVTPU, FPROUNDING_POSINF, vcvt_rm_u)
172
+DO_VEC_RMODE(VCVTPS, FPROUNDING_POSINF, vcvt_rm_s)
173
+DO_VEC_RMODE(VCVTMU, FPROUNDING_NEGINF, vcvt_rm_u)
174
+DO_VEC_RMODE(VCVTMS, FPROUNDING_NEGINF, vcvt_rm_s)
175
176
static bool trans_VSWP(DisasContext *s, arg_2misc *a)
177
{
32
--
178
--
33
2.20.1
179
2.20.1
34
180
35
181
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
Convert the Neon VRINT-with-specified-rounding-mode insns to gvec,
2
and use this to implement the fp16 versions.
2
3
3
No code used the tc6393xb_gpio_in_get() and tc6393xb_gpio_out_set()
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
functions since their introduction in commit 88d2c950b002. Time to
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
remove them.
6
Message-id: 20200828183354.27913-41-peter.maydell@linaro.org
7
---
8
target/arm/helper.h | 4 +-
9
target/arm/vec_helper.c | 21 +++++++++++
10
target/arm/vfp_helper.c | 17 ---------
11
target/arm/translate-neon.c.inc | 67 +++------------------------------
12
4 files changed, 30 insertions(+), 79 deletions(-)
6
13
7
Suggested-by: Markus Armbruster <armbru@redhat.com>
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20190412165416.7977-4-philmd@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/hw/devices.h | 3 ---
14
hw/display/tc6393xb.c | 16 ----------------
15
2 files changed, 19 deletions(-)
16
17
diff --git a/include/hw/devices.h b/include/hw/devices.h
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/devices.h
16
--- a/target/arm/helper.h
20
+++ b/include/hw/devices.h
17
+++ b/target/arm/helper.h
21
@@ -XXX,XX +XXX,XX @@ void retu_key_event(void *retu, int state);
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
22
typedef struct TC6393xbState TC6393xbState;
19
DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
23
TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
20
24
uint32_t base, qemu_irq irq);
21
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
25
-void tc6393xb_gpio_out_set(TC6393xbState *s, int line,
22
-DEF_HELPER_FLAGS_2(set_neon_rmode, TCG_CALL_NO_RWG, i32, i32, env)
26
- qemu_irq handler);
23
27
-qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s);
24
DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f32, TCG_CALL_NO_RWG, f32, f16, ptr, i32)
28
qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
25
DEF_HELPER_FLAGS_3(vfp_fcvt_f32_to_f16, TCG_CALL_NO_RWG, f16, f32, ptr, i32)
29
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_vcvt_rm_us, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
30
#endif
27
DEF_HELPER_FLAGS_4(gvec_vcvt_rm_sh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
28
DEF_HELPER_FLAGS_4(gvec_vcvt_rm_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
30
+DEF_HELPER_FLAGS_4(gvec_vrint_rm_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_4(gvec_vrint_rm_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
32
+
33
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
35
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
36
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
32
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/display/tc6393xb.c
38
--- a/target/arm/vec_helper.c
34
+++ b/hw/display/tc6393xb.c
39
+++ b/target/arm/vec_helper.c
35
@@ -XXX,XX +XXX,XX @@ struct TC6393xbState {
40
@@ -XXX,XX +XXX,XX @@ DO_VCVT_RMODE(gvec_vcvt_rm_sh, helper_vfp_toshh, uint16_t)
36
blanked : 1;
41
DO_VCVT_RMODE(gvec_vcvt_rm_uh, helper_vfp_touhh, uint16_t)
37
};
42
38
43
#undef DO_VCVT_RMODE
39
-qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s)
44
+
45
+#define DO_VRINT_RMODE(NAME, FUNC, TYPE) \
46
+ void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
47
+ { \
48
+ float_status *fpst = stat; \
49
+ intptr_t i, oprsz = simd_oprsz(desc); \
50
+ uint32_t rmode = simd_data(desc); \
51
+ uint32_t prev_rmode = get_float_rounding_mode(fpst); \
52
+ TYPE *d = vd, *n = vn; \
53
+ set_float_rounding_mode(rmode, fpst); \
54
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
55
+ d[i] = FUNC(n[i], fpst); \
56
+ } \
57
+ set_float_rounding_mode(prev_rmode, fpst); \
58
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
59
+ }
60
+
61
+DO_VRINT_RMODE(gvec_vrint_rm_h, helper_rinth, uint16_t)
62
+DO_VRINT_RMODE(gvec_vrint_rm_s, helper_rints, uint32_t)
63
+
64
+#undef DO_VRINT_RMODE
65
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/vfp_helper.c
68
+++ b/target/arm/vfp_helper.c
69
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
70
return prev_rmode;
71
}
72
73
-/* Set the current fp rounding mode in the standard fp status and return
74
- * the old one. This is for NEON instructions that need to change the
75
- * rounding mode but wish to use the standard FPSCR values for everything
76
- * else. Always set the rounding mode back to the correct value after
77
- * modifying it.
78
- * The argument is a softfloat float_round_ value.
79
- */
80
-uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
40
-{
81
-{
41
- return s->gpio_in;
82
- float_status *fp_status = &env->vfp.standard_fp_status;
83
-
84
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
85
- set_float_rounding_mode(rmode, fp_status);
86
-
87
- return prev_rmode;
42
-}
88
-}
43
-
89
-
44
static void tc6393xb_gpio_set(void *opaque, int line, int level)
90
/* Half precision conversions. */
91
float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode)
45
{
92
{
46
// TC6393xbState *s = opaque;
93
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
47
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_gpio_set(void *opaque, int line, int level)
94
index XXXXXXX..XXXXXXX 100644
48
// FIXME: how does the chip reflect the GPIO input level change?
95
--- a/target/arm/translate-neon.c.inc
96
+++ b/target/arm/translate-neon.c.inc
97
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
98
return do_2misc_fp(s, a, gen_helper_rints_exact);
49
}
99
}
50
100
51
-void tc6393xb_gpio_out_set(TC6393xbState *s, int line,
101
-static bool do_vrint(DisasContext *s, arg_2misc *a, int rmode)
52
- qemu_irq handler)
53
-{
102
-{
54
- if (line >= TC6393XB_GPIOS) {
103
- /*
55
- fprintf(stderr, "TC6393xb: no GPIO pin %d\n", line);
104
- * Handle a VRINT* operation by iterating 32 bits at a time,
56
- return;
105
- * with a specified rounding mode in operation.
106
- */
107
- int pass;
108
- TCGv_ptr fpst;
109
- TCGv_i32 tcg_rmode;
110
-
111
- if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
112
- !arm_dc_feature(s, ARM_FEATURE_V8)) {
113
- return false;
57
- }
114
- }
58
-
115
-
59
- s->handler[line] = handler;
116
- /* UNDEF accesses to D16-D31 if they don't exist. */
117
- if (!dc_isar_feature(aa32_simd_r32, s) &&
118
- ((a->vd | a->vm) & 0x10)) {
119
- return false;
120
- }
121
-
122
- if (a->size != 2) {
123
- /* TODO: FP16 will be the size == 1 case */
124
- return false;
125
- }
126
-
127
- if ((a->vd | a->vm) & a->q) {
128
- return false;
129
- }
130
-
131
- if (!vfp_access_check(s)) {
132
- return true;
133
- }
134
-
135
- fpst = fpstatus_ptr(FPST_STD);
136
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
137
- gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
138
- for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
139
- TCGv_i32 tmp = neon_load_reg(a->vm, pass);
140
- gen_helper_rints(tmp, tmp, fpst);
141
- neon_store_reg(a->vd, pass, tmp);
142
- }
143
- gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
144
- tcg_temp_free_i32(tcg_rmode);
145
- tcg_temp_free_ptr(fpst);
146
-
147
- return true;
60
-}
148
-}
61
-
149
-
62
static void tc6393xb_gpio_handler_update(TC6393xbState *s)
150
-#define DO_VRINT(INSN, RMODE) \
151
- static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
152
- { \
153
- return do_vrint(s, a, RMODE); \
154
- }
155
-
156
-DO_VRINT(VRINTN, FPROUNDING_TIEEVEN)
157
-DO_VRINT(VRINTA, FPROUNDING_TIEAWAY)
158
-DO_VRINT(VRINTZ, FPROUNDING_ZERO)
159
-DO_VRINT(VRINTM, FPROUNDING_NEGINF)
160
-DO_VRINT(VRINTP, FPROUNDING_POSINF)
161
-
162
#define DO_VEC_RMODE(INSN, RMODE, OP) \
163
static void gen_##INSN(unsigned vece, uint32_t rd_ofs, \
164
uint32_t rm_ofs, \
165
@@ -XXX,XX +XXX,XX @@ DO_VEC_RMODE(VCVTPS, FPROUNDING_POSINF, vcvt_rm_s)
166
DO_VEC_RMODE(VCVTMU, FPROUNDING_NEGINF, vcvt_rm_u)
167
DO_VEC_RMODE(VCVTMS, FPROUNDING_NEGINF, vcvt_rm_s)
168
169
+DO_VEC_RMODE(VRINTN, FPROUNDING_TIEEVEN, vrint_rm_)
170
+DO_VEC_RMODE(VRINTA, FPROUNDING_TIEAWAY, vrint_rm_)
171
+DO_VEC_RMODE(VRINTZ, FPROUNDING_ZERO, vrint_rm_)
172
+DO_VEC_RMODE(VRINTM, FPROUNDING_NEGINF, vrint_rm_)
173
+DO_VEC_RMODE(VRINTP, FPROUNDING_POSINF, vrint_rm_)
174
+
175
static bool trans_VSWP(DisasContext *s, arg_2misc *a)
63
{
176
{
64
uint32_t level, diff;
177
TCGv_i64 rm, rd;
65
--
178
--
66
2.20.1
179
2.20.1
67
180
68
181
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
Convert the Neon VRINTX insn to use gvec, and use this to implement
2
fp16 support for it.
2
3
3
The SMMUNotifierNode struct is not necessary and brings extra
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
complexity so let's remove it. We now directly track the SMMUDevices
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
which have registered IOMMU MR notifiers.
6
Message-id: 20200828183354.27913-42-peter.maydell@linaro.org
7
---
8
target/arm/helper.h | 3 +++
9
target/arm/vec_helper.c | 3 +++
10
target/arm/translate-neon.c.inc | 45 +++------------------------------
11
3 files changed, 9 insertions(+), 42 deletions(-)
6
12
7
This is inspired from the same transformation on intel-iommu
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
8
done in commit b4a4ba0d68f50f218ee3957b6638dbee32a5eeef
9
("intel-iommu: remove IntelIOMMUNotifierNode")
10
11
Signed-off-by: Eric Auger <eric.auger@redhat.com>
12
Reviewed-by: Peter Xu <peterx@redhat.com>
13
Message-id: 20190409160219.19026-1-eric.auger@redhat.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
include/hw/arm/smmu-common.h | 8 ++------
17
hw/arm/smmu-common.c | 6 +++---
18
hw/arm/smmuv3.c | 28 +++++++---------------------
19
3 files changed, 12 insertions(+), 30 deletions(-)
20
21
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/arm/smmu-common.h
15
--- a/target/arm/helper.h
24
+++ b/include/hw/arm/smmu-common.h
16
+++ b/target/arm/helper.h
25
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUDevice {
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_vcvt_rm_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
AddressSpace as;
18
DEF_HELPER_FLAGS_4(gvec_vrint_rm_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
uint32_t cfg_cache_hits;
19
DEF_HELPER_FLAGS_4(gvec_vrint_rm_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
uint32_t cfg_cache_misses;
20
29
+ QLIST_ENTRY(SMMUDevice) next;
21
+DEF_HELPER_FLAGS_4(gvec_vrintx_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
30
} SMMUDevice;
22
+DEF_HELPER_FLAGS_4(gvec_vrintx_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
23
+
32
-typedef struct SMMUNotifierNode {
24
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
- SMMUDevice *sdev;
25
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
- QLIST_ENTRY(SMMUNotifierNode) next;
26
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
35
-} SMMUNotifierNode;
27
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/vec_helper.c
30
+++ b/target/arm/vec_helper.c
31
@@ -XXX,XX +XXX,XX @@ DO_2OP(gvec_frsqrte_h, helper_rsqrte_f16, float16)
32
DO_2OP(gvec_frsqrte_s, helper_rsqrte_f32, float32)
33
DO_2OP(gvec_frsqrte_d, helper_rsqrte_f64, float64)
34
35
+DO_2OP(gvec_vrintx_h, float16_round_to_int, float16)
36
+DO_2OP(gvec_vrintx_s, float32_round_to_int, float32)
37
+
38
DO_2OP(gvec_sitos, helper_vfp_sitos, int32_t)
39
DO_2OP(gvec_uitos, helper_vfp_uitos, uint32_t)
40
DO_2OP(gvec_tosizs, helper_vfp_tosizs, float32)
41
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
42
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/translate-neon.c.inc
44
+++ b/target/arm/translate-neon.c.inc
45
@@ -XXX,XX +XXX,XX @@ static bool trans_VQNEG(DisasContext *s, arg_2misc *a)
46
return do_2misc(s, a, fn[a->size]);
47
}
48
49
-static bool do_2misc_fp(DisasContext *s, arg_2misc *a,
50
- NeonGenOneSingleOpFn *fn)
51
-{
52
- int pass;
53
- TCGv_ptr fpst;
36
-
54
-
37
typedef struct SMMUPciBus {
55
- /* Handle a 2-reg-misc operation by iterating 32 bits at a time */
38
PCIBus *bus;
56
- if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
39
SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */
57
- return false;
40
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUState {
41
GHashTable *iotlb;
42
SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX];
43
PCIBus *pci_bus;
44
- QLIST_HEAD(, SMMUNotifierNode) notifiers_list;
45
+ QLIST_HEAD(, SMMUDevice) devices_with_notifiers;
46
uint8_t bus_num;
47
PCIBus *primary_bus;
48
} SMMUState;
49
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/smmu-common.c
52
+++ b/hw/arm/smmu-common.c
53
@@ -XXX,XX +XXX,XX @@ inline void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr)
54
/* Unmap all notifiers of all mr's */
55
void smmu_inv_notifiers_all(SMMUState *s)
56
{
57
- SMMUNotifierNode *node;
58
+ SMMUDevice *sdev;
59
60
- QLIST_FOREACH(node, &s->notifiers_list, next) {
61
- smmu_inv_notifiers_mr(&node->sdev->iommu);
62
+ QLIST_FOREACH(sdev, &s->devices_with_notifiers, next) {
63
+ smmu_inv_notifiers_mr(&sdev->iommu);
64
}
65
}
66
67
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/arm/smmuv3.c
70
+++ b/hw/arm/smmuv3.c
71
@@ -XXX,XX +XXX,XX @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
72
/* invalidate an asid/iova tuple in all mr's */
73
static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova)
74
{
75
- SMMUNotifierNode *node;
76
+ SMMUDevice *sdev;
77
78
- QLIST_FOREACH(node, &s->notifiers_list, next) {
79
- IOMMUMemoryRegion *mr = &node->sdev->iommu;
80
+ QLIST_FOREACH(sdev, &s->devices_with_notifiers, next) {
81
+ IOMMUMemoryRegion *mr = &sdev->iommu;
82
IOMMUNotifier *n;
83
84
trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova);
85
@@ -XXX,XX +XXX,XX @@ static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
86
SMMUDevice *sdev = container_of(iommu, SMMUDevice, iommu);
87
SMMUv3State *s3 = sdev->smmu;
88
SMMUState *s = &(s3->smmu_state);
89
- SMMUNotifierNode *node = NULL;
90
- SMMUNotifierNode *next_node = NULL;
91
92
if (new & IOMMU_NOTIFIER_MAP) {
93
int bus_num = pci_bus_num(sdev->bus);
94
@@ -XXX,XX +XXX,XX @@ static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
95
96
if (old == IOMMU_NOTIFIER_NONE) {
97
trace_smmuv3_notify_flag_add(iommu->parent_obj.name);
98
- node = g_malloc0(sizeof(*node));
99
- node->sdev = sdev;
100
- QLIST_INSERT_HEAD(&s->notifiers_list, node, next);
101
- return;
102
- }
58
- }
103
-
59
-
104
- /* update notifier node with new flags */
60
- /* UNDEF accesses to D16-D31 if they don't exist. */
105
- QLIST_FOREACH_SAFE(node, &s->notifiers_list, next, next_node) {
61
- if (!dc_isar_feature(aa32_simd_r32, s) &&
106
- if (node->sdev == sdev) {
62
- ((a->vd | a->vm) & 0x10)) {
107
- if (new == IOMMU_NOTIFIER_NONE) {
63
- return false;
108
- trace_smmuv3_notify_flag_del(iommu->parent_obj.name);
64
- }
109
- QLIST_REMOVE(node, next);
65
-
110
- g_free(node);
66
- if (a->size != 2) {
111
- }
67
- /* TODO: FP16 will be the size == 1 case */
112
- return;
68
- return false;
113
- }
69
- }
114
+ QLIST_INSERT_HEAD(&s->devices_with_notifiers, sdev, next);
70
-
115
+ } else if (new == IOMMU_NOTIFIER_NONE) {
71
- if ((a->vd | a->vm) & a->q) {
116
+ trace_smmuv3_notify_flag_del(iommu->parent_obj.name);
72
- return false;
117
+ QLIST_REMOVE(sdev, next);
73
- }
74
-
75
- if (!vfp_access_check(s)) {
76
- return true;
77
- }
78
-
79
- fpst = fpstatus_ptr(FPST_STD);
80
- for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
81
- TCGv_i32 tmp = neon_load_reg(a->vm, pass);
82
- fn(tmp, tmp, fpst);
83
- neon_store_reg(a->vd, pass, tmp);
84
- }
85
- tcg_temp_free_ptr(fpst);
86
-
87
- return true;
88
-}
89
-
90
#define DO_2MISC_FP_VEC(INSN, HFUNC, SFUNC) \
91
static void gen_##INSN(unsigned vece, uint32_t rd_ofs, \
92
uint32_t rm_ofs, \
93
@@ -XXX,XX +XXX,XX @@ DO_2MISC_FP_VEC(VCVT_FU, gen_helper_gvec_ustoh, gen_helper_gvec_uitos)
94
DO_2MISC_FP_VEC(VCVT_SF, gen_helper_gvec_tosszh, gen_helper_gvec_tosizs)
95
DO_2MISC_FP_VEC(VCVT_UF, gen_helper_gvec_touszh, gen_helper_gvec_touizs)
96
97
+DO_2MISC_FP_VEC(VRINTX_impl, gen_helper_gvec_vrintx_h, gen_helper_gvec_vrintx_s)
98
+
99
static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
100
{
101
if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
102
return false;
118
}
103
}
104
- return do_2misc_fp(s, a, gen_helper_rints_exact);
105
+ return trans_VRINTX_impl(s, a);
119
}
106
}
120
107
108
#define DO_VEC_RMODE(INSN, RMODE, OP) \
121
--
109
--
122
2.20.1
110
2.20.1
123
111
124
112
diff view generated by jsdifflib
1
Normally configure identifies the source path by looking
1
In the gvec helper functions for indexed operations, for AArch32
2
at the location where the configure script itself exists.
2
Neon the oprsz (total size of the vector) can be less than 16 bytes
3
We also provide a --source-path option which lets the user
3
if the operation is on a D reg. Since the inner loop in these
4
manually override this.
4
helpers always goes from 0 to segment, we must clamp it based
5
5
on oprsz to avoid processing a full 16 byte segment when asked to
6
There isn't really an obvious use case for the --source-path
6
handle an 8 byte wide vector.
7
option, and in commit 927128222b0a91f56c13a in 2017 we
8
accidentally added some logic that looks at $source_path
9
before the command line option that overrides it has been
10
processed.
11
12
The fact that nobody complained suggests that there isn't
13
any use of this option and we aren't testing it either;
14
remove it. This allows us to move the "make $source_path
15
absolute" logic up so that there is no window in the script
16
where $source_path is set but not yet absolute.
17
7
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20190318134019.23729-1-peter.maydell@linaro.org
10
Message-id: 20200828183354.27913-43-peter.maydell@linaro.org
21
---
11
---
22
configure | 10 ++--------
12
target/arm/vec_helper.c | 12 ++++++++----
23
1 file changed, 2 insertions(+), 8 deletions(-)
13
1 file changed, 8 insertions(+), 4 deletions(-)
24
14
25
diff --git a/configure b/configure
15
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
26
index XXXXXXX..XXXXXXX 100755
16
index XXXXXXX..XXXXXXX 100644
27
--- a/configure
17
--- a/target/arm/vec_helper.c
28
+++ b/configure
18
+++ b/target/arm/vec_helper.c
29
@@ -XXX,XX +XXX,XX @@ ld_has() {
19
@@ -XXX,XX +XXX,XX @@ DO_MULADD(gvec_vfms_s, float32_mulsub_f, float32)
30
20
#define DO_MUL_IDX(NAME, TYPE, H) \
31
# default parameters
21
void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
32
source_path=$(dirname "$0")
22
{ \
33
+# make source path absolute
23
- intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \
34
+source_path=$(cd "$source_path"; pwd)
24
+ intptr_t i, j, oprsz = simd_oprsz(desc); \
35
cpu=""
25
+ intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \
36
iasl="iasl"
26
intptr_t idx = simd_data(desc); \
37
interp_prefix="/usr/gnemul/qemu-%M"
27
TYPE *d = vd, *n = vn, *m = vm; \
38
@@ -XXX,XX +XXX,XX @@ for opt do
28
for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \
39
;;
29
@@ -XXX,XX +XXX,XX @@ DO_MUL_IDX(gvec_mul_idx_d, uint64_t, )
40
--cxx=*) CXX="$optarg"
30
#define DO_MLA_IDX(NAME, TYPE, OP, H) \
41
;;
31
void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \
42
- --source-path=*) source_path="$optarg"
32
{ \
43
- ;;
33
- intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \
44
--cpu=*) cpu="$optarg"
34
+ intptr_t i, j, oprsz = simd_oprsz(desc); \
45
;;
35
+ intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \
46
--extra-cflags=*) QEMU_CFLAGS="$QEMU_CFLAGS $optarg"
36
intptr_t idx = simd_data(desc); \
47
@@ -XXX,XX +XXX,XX @@ if test "$debug_info" = "yes"; then
37
TYPE *d = vd, *n = vn, *m = vm, *a = va; \
48
LDFLAGS="-g $LDFLAGS"
38
for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \
49
fi
39
@@ -XXX,XX +XXX,XX @@ DO_MLA_IDX(gvec_mls_idx_d, uint64_t, -, )
50
40
#define DO_FMUL_IDX(NAME, TYPE, H) \
51
-# make source path absolute
41
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
52
-source_path=$(cd "$source_path"; pwd)
42
{ \
53
-
43
- intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \
54
# running configure in the source tree?
44
+ intptr_t i, j, oprsz = simd_oprsz(desc); \
55
# we know that's the case if configure is there.
45
+ intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \
56
if test -f "./configure"; then
46
intptr_t idx = simd_data(desc); \
57
@@ -XXX,XX +XXX,XX @@ for opt do
47
TYPE *d = vd, *n = vn, *m = vm; \
58
;;
48
for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \
59
--interp-prefix=*) interp_prefix="$optarg"
49
@@ -XXX,XX +XXX,XX @@ DO_FMUL_IDX(gvec_fmul_idx_d, float64, )
60
;;
50
void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, \
61
- --source-path=*)
51
void *stat, uint32_t desc) \
62
- ;;
52
{ \
63
--cross-prefix=*)
53
- intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \
64
;;
54
+ intptr_t i, j, oprsz = simd_oprsz(desc); \
65
--cc=*)
55
+ intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \
66
@@ -XXX,XX +XXX,XX @@ $(echo Available targets: $default_target_list | \
56
TYPE op1_neg = extract32(desc, SIMD_DATA_SHIFT, 1); \
67
--target-list-exclude=LIST exclude a set of targets from the default target-list
57
intptr_t idx = desc >> (SIMD_DATA_SHIFT + 1); \
68
58
TYPE *d = vd, *n = vn, *m = vm, *a = va; \
69
Advanced options (experts only):
70
- --source-path=PATH path of source code [$source_path]
71
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
72
--cc=CC use C compiler CC [$cc]
73
--iasl=IASL use ACPI compiler IASL [$iasl]
74
--
59
--
75
2.20.1
60
2.20.1
76
61
77
62
diff view generated by jsdifflib
1
In the stripe8() function we use a variable length array; however
1
Add gvec helpers for doing Neon-style indexed non-fused fp
2
we know that the maximum length required is MAX_NUM_BUSSES. Use
2
multiply-and-accumulate operations.
3
a fixed-length array and an assert instead.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 20200828183354.27913-44-peter.maydell@linaro.org
7
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
10
Message-id: 20190328152635.2794-1-peter.maydell@linaro.org
11
---
6
---
12
hw/ssi/xilinx_spips.c | 6 ++++--
7
target/arm/helper.h | 10 ++++++++++
13
1 file changed, 4 insertions(+), 2 deletions(-)
8
target/arm/vec_helper.c | 27 ++++++++++++++++++++++-----
9
2 files changed, 32 insertions(+), 5 deletions(-)
14
10
15
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
11
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/ssi/xilinx_spips.c
13
--- a/target/arm/helper.h
18
+++ b/hw/ssi/xilinx_spips.c
14
+++ b/target/arm/helper.h
19
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
15
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmul_idx_s, TCG_CALL_NO_RWG,
20
16
DEF_HELPER_FLAGS_5(gvec_fmul_idx_d, TCG_CALL_NO_RWG,
21
static inline void stripe8(uint8_t *x, int num, bool dir)
17
void, ptr, ptr, ptr, ptr, i32)
22
{
18
23
- uint8_t r[num];
19
+DEF_HELPER_FLAGS_5(gvec_fmla_nf_idx_h, TCG_CALL_NO_RWG,
24
- memset(r, 0, sizeof(uint8_t) * num);
20
+ void, ptr, ptr, ptr, ptr, i32)
25
+ uint8_t r[MAX_NUM_BUSSES];
21
+DEF_HELPER_FLAGS_5(gvec_fmla_nf_idx_s, TCG_CALL_NO_RWG,
26
int idx[2] = {0, 0};
22
+ void, ptr, ptr, ptr, ptr, i32)
27
int bit[2] = {0, 7};
28
int d = dir;
29
30
+ assert(num <= MAX_NUM_BUSSES);
31
+ memset(r, 0, sizeof(uint8_t) * num);
32
+
23
+
33
for (idx[0] = 0; idx[0] < num; ++idx[0]) {
24
+DEF_HELPER_FLAGS_5(gvec_fmls_nf_idx_h, TCG_CALL_NO_RWG,
34
for (bit[0] = 7; bit[0] >= 0; bit[0]--) {
25
+ void, ptr, ptr, ptr, ptr, i32)
35
r[idx[!d]] |= x[idx[d]] & 1 << bit[d] ? 1 << bit[!d] : 0;
26
+DEF_HELPER_FLAGS_5(gvec_fmls_nf_idx_s, TCG_CALL_NO_RWG,
27
+ void, ptr, ptr, ptr, ptr, i32)
28
+
29
DEF_HELPER_FLAGS_6(gvec_fmla_idx_h, TCG_CALL_NO_RWG,
30
void, ptr, ptr, ptr, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_6(gvec_fmla_idx_s, TCG_CALL_NO_RWG,
32
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/vec_helper.c
35
+++ b/target/arm/vec_helper.c
36
@@ -XXX,XX +XXX,XX @@ DO_MLA_IDX(gvec_mls_idx_d, uint64_t, -, )
37
38
#undef DO_MLA_IDX
39
40
-#define DO_FMUL_IDX(NAME, TYPE, H) \
41
+#define DO_FMUL_IDX(NAME, ADD, TYPE, H) \
42
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
43
{ \
44
intptr_t i, j, oprsz = simd_oprsz(desc); \
45
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
46
for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \
47
TYPE mm = m[H(i + idx)]; \
48
for (j = 0; j < segment; j++) { \
49
- d[i + j] = TYPE##_mul(n[i + j], mm, stat); \
50
+ d[i + j] = TYPE##_##ADD(d[i + j], \
51
+ TYPE##_mul(n[i + j], mm, stat), stat); \
52
} \
53
} \
54
clear_tail(d, oprsz, simd_maxsz(desc)); \
55
}
56
57
-DO_FMUL_IDX(gvec_fmul_idx_h, float16, H2)
58
-DO_FMUL_IDX(gvec_fmul_idx_s, float32, H4)
59
-DO_FMUL_IDX(gvec_fmul_idx_d, float64, )
60
+#define float16_nop(N, M, S) (M)
61
+#define float32_nop(N, M, S) (M)
62
+#define float64_nop(N, M, S) (M)
63
64
+DO_FMUL_IDX(gvec_fmul_idx_h, nop, float16, H2)
65
+DO_FMUL_IDX(gvec_fmul_idx_s, nop, float32, H4)
66
+DO_FMUL_IDX(gvec_fmul_idx_d, nop, float64, )
67
+
68
+/*
69
+ * Non-fused multiply-accumulate operations, for Neon. NB that unlike
70
+ * the fused ops below they assume accumulate both from and into Vd.
71
+ */
72
+DO_FMUL_IDX(gvec_fmla_nf_idx_h, add, float16, H2)
73
+DO_FMUL_IDX(gvec_fmla_nf_idx_s, add, float32, H4)
74
+DO_FMUL_IDX(gvec_fmls_nf_idx_h, sub, float16, H2)
75
+DO_FMUL_IDX(gvec_fmls_nf_idx_s, sub, float32, H4)
76
+
77
+#undef float16_nop
78
+#undef float32_nop
79
+#undef float64_nop
80
#undef DO_FMUL_IDX
81
82
#define DO_FMLA_IDX(NAME, TYPE, H) \
36
--
83
--
37
2.20.1
84
2.20.1
38
85
39
86
diff view generated by jsdifflib
1
Handle floating point registers in exception return.
1
Convert the Neon floating-point VMUL, VMLA and VMLS to use gvec,
2
This corresponds to pseudocode functions ValidateExceptionReturn(),
2
and use this to implement fp16 support.
3
ExceptionReturn(), PopStack() and ConsumeExcStackFrame().
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190416125744.27770-16-peter.maydell@linaro.org
6
Message-id: 20200828183354.27913-45-peter.maydell@linaro.org
8
---
7
---
9
target/arm/helper.c | 142 +++++++++++++++++++++++++++++++++++++++++++-
8
target/arm/translate-neon.c.inc | 114 ++++++++++++++++----------------
10
1 file changed, 141 insertions(+), 1 deletion(-)
9
1 file changed, 57 insertions(+), 57 deletions(-)
11
10
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
11
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
13
--- a/target/arm/translate-neon.c.inc
15
+++ b/target/arm/helper.c
14
+++ b/target/arm/translate-neon.c.inc
16
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLS_2sc(DisasContext *s, arg_2scalar *a)
17
bool rettobase = false;
16
return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
18
bool exc_secure = false;
17
}
19
bool return_to_secure;
18
20
+ bool ftype;
19
-/*
21
+ bool restore_s16_s31;
20
- * Rather than have a float-specific version of do_2scalar just for
22
21
- * three insns, we wrap a NeonGenTwoSingleOpFn to turn it into
23
/* If we're not in Handler mode then jumps to magic exception-exit
22
- * a NeonGenTwoOpFn.
24
* addresses don't have magic behaviour. However for the v8M
23
- */
25
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
24
-#define WRAP_FP_FN(WRAPNAME, FUNC) \
26
excret);
25
- static void WRAPNAME(TCGv_i32 rd, TCGv_i32 rn, TCGv_i32 rm) \
26
- { \
27
- TCGv_ptr fpstatus = fpstatus_ptr(FPST_STD); \
28
- FUNC(rd, rn, rm, fpstatus); \
29
- tcg_temp_free_ptr(fpstatus); \
30
+static bool do_2scalar_fp_vec(DisasContext *s, arg_2scalar *a,
31
+ gen_helper_gvec_3_ptr *fn)
32
+{
33
+ /* Two registers and a scalar, using gvec */
34
+ int vec_size = a->q ? 16 : 8;
35
+ int rd_ofs = neon_reg_offset(a->vd, 0);
36
+ int rn_ofs = neon_reg_offset(a->vn, 0);
37
+ int rm_ofs;
38
+ int idx;
39
+ TCGv_ptr fpstatus;
40
+
41
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
42
+ return false;
27
}
43
}
28
44
29
+ ftype = excret & R_V7M_EXCRET_FTYPE_MASK;
45
-WRAP_FP_FN(gen_VMUL_F_mul, gen_helper_vfp_muls)
30
+
46
-WRAP_FP_FN(gen_VMUL_F_add, gen_helper_vfp_adds)
31
+ if (!arm_feature(env, ARM_FEATURE_VFP) && !ftype) {
47
-WRAP_FP_FN(gen_VMUL_F_sub, gen_helper_vfp_subs)
32
+ qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero FTYPE in exception "
48
+ /* UNDEF accesses to D16-D31 if they don't exist. */
33
+ "exit PC value 0x%" PRIx32 " is UNPREDICTABLE "
49
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
34
+ "if FPU not present\n",
50
+ ((a->vd | a->vn | a->vm) & 0x10)) {
35
+ excret);
51
+ return false;
36
+ ftype = true;
52
+ }
53
54
-static bool trans_VMUL_F_2sc(DisasContext *s, arg_2scalar *a)
55
-{
56
- static NeonGenTwoOpFn * const opfn[] = {
57
- NULL,
58
- NULL, /* TODO: fp16 support */
59
- gen_VMUL_F_mul,
60
- NULL,
61
- };
62
+ if (!fn) {
63
+ /* Bad size (including size == 3, which is a different insn group) */
64
+ return false;
65
+ }
66
67
- return do_2scalar(s, a, opfn[a->size], NULL);
68
+ if (a->q && ((a->vd | a->vn) & 1)) {
69
+ return false;
37
+ }
70
+ }
38
+
71
+
39
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
72
+ if (!vfp_access_check(s)) {
40
/* EXC_RETURN.ES validation check (R_SMFL). We must do this before
73
+ return true;
41
* we pick which FAULTMASK to clear.
42
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
43
*/
44
write_v7m_control_spsel_for_secstate(env, return_to_sp_process, exc_secure);
45
46
+ /*
47
+ * Clear scratch FP values left in caller saved registers; this
48
+ * must happen before any kind of tail chaining.
49
+ */
50
+ if ((env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_CLRONRET_MASK) &&
51
+ (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK)) {
52
+ if (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPACT_MASK) {
53
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
54
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
55
+ qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
56
+ "stackframe: error during lazy state deactivation\n");
57
+ v7m_exception_taken(cpu, excret, true, false);
58
+ return;
59
+ } else {
60
+ /* Clear s0..s15 and FPSCR */
61
+ int i;
62
+
63
+ for (i = 0; i < 16; i += 2) {
64
+ *aa32_vfp_dreg(env, i / 2) = 0;
65
+ }
66
+ vfp_set_fpscr(env, 0);
67
+ }
68
+ }
74
+ }
69
+
75
+
70
if (sfault) {
76
+ /* a->vm is M:Vm, which encodes both register and index */
71
env->v7m.sfsr |= R_V7M_SFSR_INVER_MASK;
77
+ idx = extract32(a->vm, a->size + 2, 2);
72
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
78
+ a->vm = extract32(a->vm, 0, a->size + 2);
73
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
79
+ rm_ofs = neon_reg_offset(a->vm, 0);
74
}
75
}
76
77
+ if (!ftype) {
78
+ /* FP present and we need to handle it */
79
+ if (!return_to_secure &&
80
+ (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPACT_MASK)) {
81
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
82
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
83
+ qemu_log_mask(CPU_LOG_INT,
84
+ "...taking SecureFault on existing stackframe: "
85
+ "Secure LSPACT set but exception return is "
86
+ "not to secure state\n");
87
+ v7m_exception_taken(cpu, excret, true, false);
88
+ return;
89
+ }
90
+
80
+
91
+ restore_s16_s31 = return_to_secure &&
81
+ fpstatus = fpstatus_ptr(a->size == 1 ? FPST_STD_F16 : FPST_STD);
92
+ (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK);
82
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpstatus,
93
+
83
+ vec_size, vec_size, idx, fn);
94
+ if (env->v7m.fpccr[return_to_secure] & R_V7M_FPCCR_LSPACT_MASK) {
84
+ tcg_temp_free_ptr(fpstatus);
95
+ /* State in FPU is still valid, just clear LSPACT */
85
+ return true;
96
+ env->v7m.fpccr[return_to_secure] &= ~R_V7M_FPCCR_LSPACT_MASK;
86
}
97
+ } else {
87
98
+ int i;
88
-static bool trans_VMLA_F_2sc(DisasContext *s, arg_2scalar *a)
99
+ uint32_t fpscr;
89
-{
100
+ bool cpacr_pass, nsacr_pass;
90
- static NeonGenTwoOpFn * const opfn[] = {
101
+
91
- NULL,
102
+ cpacr_pass = v7m_cpacr_pass(env, return_to_secure,
92
- NULL, /* TODO: fp16 support */
103
+ return_to_priv);
93
- gen_VMUL_F_mul,
104
+ nsacr_pass = return_to_secure ||
94
- NULL,
105
+ extract32(env->v7m.nsacr, 10, 1);
95
- };
106
+
96
- static NeonGenTwoOpFn * const accfn[] = {
107
+ if (!cpacr_pass) {
97
- NULL,
108
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
98
- NULL, /* TODO: fp16 support */
109
+ return_to_secure);
99
- gen_VMUL_F_add,
110
+ env->v7m.cfsr[return_to_secure] |= R_V7M_CFSR_NOCP_MASK;
100
- NULL,
111
+ qemu_log_mask(CPU_LOG_INT,
101
- };
112
+ "...taking UsageFault on existing "
102
+#define DO_VMUL_F_2sc(NAME, FUNC) \
113
+ "stackframe: CPACR.CP10 prevents unstacking "
103
+ static bool trans_##NAME##_F_2sc(DisasContext *s, arg_2scalar *a) \
114
+ "FP regs\n");
104
+ { \
115
+ v7m_exception_taken(cpu, excret, true, false);
105
+ static gen_helper_gvec_3_ptr * const opfn[] = { \
116
+ return;
106
+ NULL, \
117
+ } else if (!nsacr_pass) {
107
+ gen_helper_##FUNC##_h, \
118
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
108
+ gen_helper_##FUNC##_s, \
119
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_INVPC_MASK;
109
+ NULL, \
120
+ qemu_log_mask(CPU_LOG_INT,
110
+ }; \
121
+ "...taking Secure UsageFault on existing "
111
+ if (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s)) { \
122
+ "stackframe: NSACR.CP10 prevents unstacking "
112
+ return false; \
123
+ "FP regs\n");
113
+ } \
124
+ v7m_exception_taken(cpu, excret, true, false);
114
+ return do_2scalar_fp_vec(s, a, opfn[a->size]); \
125
+ return;
126
+ }
127
+
128
+ for (i = 0; i < (restore_s16_s31 ? 32 : 16); i += 2) {
129
+ uint32_t slo, shi;
130
+ uint64_t dn;
131
+ uint32_t faddr = frameptr + 0x20 + 4 * i;
132
+
133
+ if (i >= 16) {
134
+ faddr += 8; /* Skip the slot for the FPSCR */
135
+ }
136
+
137
+ pop_ok = pop_ok &&
138
+ v7m_stack_read(cpu, &slo, faddr, mmu_idx) &&
139
+ v7m_stack_read(cpu, &shi, faddr + 4, mmu_idx);
140
+
141
+ if (!pop_ok) {
142
+ break;
143
+ }
144
+
145
+ dn = (uint64_t)shi << 32 | slo;
146
+ *aa32_vfp_dreg(env, i / 2) = dn;
147
+ }
148
+ pop_ok = pop_ok &&
149
+ v7m_stack_read(cpu, &fpscr, frameptr + 0x60, mmu_idx);
150
+ if (pop_ok) {
151
+ vfp_set_fpscr(env, fpscr);
152
+ }
153
+ if (!pop_ok) {
154
+ /*
155
+ * These regs are 0 if security extension present;
156
+ * otherwise merely UNKNOWN. We zero always.
157
+ */
158
+ for (i = 0; i < (restore_s16_s31 ? 32 : 16); i += 2) {
159
+ *aa32_vfp_dreg(env, i / 2) = 0;
160
+ }
161
+ vfp_set_fpscr(env, 0);
162
+ }
163
+ }
164
+ }
165
+ env->v7m.control[M_REG_S] = FIELD_DP32(env->v7m.control[M_REG_S],
166
+ V7M_CONTROL, FPCA, !ftype);
167
+
168
/* Commit to consuming the stack frame */
169
frameptr += 0x20;
170
+ if (!ftype) {
171
+ frameptr += 0x48;
172
+ if (restore_s16_s31) {
173
+ frameptr += 0x40;
174
+ }
175
+ }
176
/* Undo stack alignment (the SPREALIGN bit indicates that the original
177
* pre-exception SP was not 8-aligned and we added a padding word to
178
* align it, so we undo this by ORing in the bit that increases it
179
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
180
*frame_sp_p = frameptr;
181
}
182
/* This xpsr_write() will invalidate frame_sp_p as it may switch stack */
183
- xpsr_write(env, xpsr, ~XPSR_SPREALIGN);
184
+ xpsr_write(env, xpsr, ~(XPSR_SPREALIGN | XPSR_SFPA));
185
+
186
+ if (env->v7m.secure) {
187
+ bool sfpa = xpsr & XPSR_SFPA;
188
+
189
+ env->v7m.control[M_REG_S] = FIELD_DP32(env->v7m.control[M_REG_S],
190
+ V7M_CONTROL, SFPA, sfpa);
191
+ }
115
+ }
192
116
193
/* The restored xPSR exception field will be zero if we're
117
- return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
194
* resuming in Thread mode. If that doesn't match what the
118
-}
119
-
120
-static bool trans_VMLS_F_2sc(DisasContext *s, arg_2scalar *a)
121
-{
122
- static NeonGenTwoOpFn * const opfn[] = {
123
- NULL,
124
- NULL, /* TODO: fp16 support */
125
- gen_VMUL_F_mul,
126
- NULL,
127
- };
128
- static NeonGenTwoOpFn * const accfn[] = {
129
- NULL,
130
- NULL, /* TODO: fp16 support */
131
- gen_VMUL_F_sub,
132
- NULL,
133
- };
134
-
135
- return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
136
-}
137
+DO_VMUL_F_2sc(VMUL, gvec_fmul_idx)
138
+DO_VMUL_F_2sc(VMLA, gvec_fmla_nf_idx)
139
+DO_VMUL_F_2sc(VMLS, gvec_fmls_nf_idx)
140
141
WRAP_ENV_FN(gen_VQDMULH_16, gen_helper_neon_qdmulh_s16)
142
WRAP_ENV_FN(gen_VQDMULH_32, gen_helper_neon_qdmulh_s32)
195
--
143
--
196
2.20.1
144
2.20.1
197
145
198
146
diff view generated by jsdifflib
1
Enable the FPU by default for the Cortex-M4 and Cortex-M33.
1
Set the MVFR1 ID register FPHP and SIMDHP fields to indicate
2
that our "-cpu max" has v8.2-FP16.
2
3
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190416125744.27770-27-peter.maydell@linaro.org
6
Message-id: 20200828183354.27913-46-peter.maydell@linaro.org
6
---
7
---
7
target/arm/cpu.c | 8 ++++++++
8
target/arm/cpu.c | 3 ++-
8
1 file changed, 8 insertions(+)
9
target/arm/cpu64.c | 10 ++++------
10
2 files changed, 6 insertions(+), 7 deletions(-)
9
11
10
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
11
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/cpu.c
14
--- a/target/arm/cpu.c
13
+++ b/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
16
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
15
set_feature(&cpu->env, ARM_FEATURE_M);
17
cpu->isar.id_isar6 = t;
16
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
18
17
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
19
t = cpu->isar.mvfr1;
18
+ set_feature(&cpu->env, ARM_FEATURE_VFP4);
20
- t = FIELD_DP32(t, MVFR1, FPHP, 2); /* v8.0 FP support */
19
cpu->midr = 0x410fc240; /* r0p0 */
21
+ t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
20
cpu->pmsav7_dregion = 8;
22
+ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
21
+ cpu->isar.mvfr0 = 0x10110021;
23
cpu->isar.mvfr1 = t;
22
+ cpu->isar.mvfr1 = 0x11000011;
24
23
+ cpu->isar.mvfr2 = 0x00000000;
25
t = cpu->isar.mvfr2;
24
cpu->id_pfr0 = 0x00000030;
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
25
cpu->id_pfr1 = 0x00000200;
27
index XXXXXXX..XXXXXXX 100644
26
cpu->id_dfr0 = 0x00100000;
28
--- a/target/arm/cpu64.c
27
@@ -XXX,XX +XXX,XX @@ static void cortex_m33_initfn(Object *obj)
29
+++ b/target/arm/cpu64.c
28
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
29
set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
31
u = FIELD_DP32(u, ID_DFR0, PERFMON, 5); /* v8.4-PMU */
30
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
32
cpu->isar.id_dfr0 = u;
31
+ set_feature(&cpu->env, ARM_FEATURE_VFP4);
33
32
cpu->midr = 0x410fd213; /* r0p3 */
34
- /*
33
cpu->pmsav7_dregion = 16;
35
- * FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet,
34
cpu->sau_sregion = 8;
36
- * so do not set MVFR1.FPHP. Strictly speaking this is not legal,
35
+ cpu->isar.mvfr0 = 0x10110021;
37
- * but it is also not legal to enable SVE without support for FP16,
36
+ cpu->isar.mvfr1 = 0x11000011;
38
- * and enabling SVE in system mode is more useful in the short term.
37
+ cpu->isar.mvfr2 = 0x00000040;
39
- */
38
cpu->id_pfr0 = 0x00000030;
40
+ u = cpu->isar.mvfr1;
39
cpu->id_pfr1 = 0x00000210;
41
+ u = FIELD_DP32(u, MVFR1, FPHP, 3); /* v8.2-FP16 */
40
cpu->id_dfr0 = 0x00200000;
42
+ u = FIELD_DP32(u, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
43
+ cpu->isar.mvfr1 = u;
44
45
#ifdef CONFIG_USER_ONLY
46
/* For usermode -cpu max we can use a larger and more efficient DCZ
41
--
47
--
42
2.20.1
48
2.20.1
43
49
44
50
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Reviewed-by: Thomas Huth <thuth@redhat.com>
3
The sbsa-ref platform uses a minimal device tree to pass amount of memory
4
Reviewed-by: Cédric Le Goater <clg@kaod.org>
4
as well as number of cpus to the firmware. However, when dumping that
5
Reviewed-by: Markus Armbruster <armbru@redhat.com>
5
minimal dtb (with -M sbsa-virt,dumpdtb=<file>), the resulting blob
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
generates a warning when decompiled by dtc due to lack of reg property.
7
Message-id: 20190412165416.7977-2-philmd@redhat.com
7
8
Add a simple reg property per cpu, representing a 64-bit MPIDR_EL1.
9
10
This also ends up being cleaner than having the firmware calculating its
11
own IDs for generating APCI.
12
13
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20200827124335.30586-1-leif@nuviainc.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
17
---
10
hw/arm/aspeed.c | 13 +++++++++----
18
hw/arm/sbsa-ref.c | 29 +++++++++++++++++++++++------
11
1 file changed, 9 insertions(+), 4 deletions(-)
19
1 file changed, 23 insertions(+), 6 deletions(-)
12
20
13
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
21
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
14
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/aspeed.c
23
--- a/hw/arm/sbsa-ref.c
16
+++ b/hw/arm/aspeed.c
24
+++ b/hw/arm/sbsa-ref.c
17
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
18
#include "hw/arm/aspeed_soc.h"
26
[SBSA_EHCI] = 11,
19
#include "hw/boards.h"
27
};
20
#include "hw/i2c/smbus_eeprom.h"
28
21
+#include "hw/misc/pca9552.h"
29
+static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
22
+#include "hw/misc/tmp105.h"
30
+{
23
#include "qemu/log.h"
31
+ uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
24
#include "sysemu/block-backend.h"
32
+ return arm_cpu_mp_affinity(idx, clustersz);
25
#include "hw/loader.h"
33
+}
26
@@ -XXX,XX +XXX,XX @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
34
+
27
eeprom_buf);
35
/*
28
36
* Firmware on this machine only uses ACPI table to load OS, these limited
29
/* The AST2500 EVB expects a LM75 but a TMP105 is compatible */
37
* device tree nodes are just to let firmware know the info which varies from
30
- i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "tmp105", 0x4d);
38
@@ -XXX,XX +XXX,XX @@ static void create_fdt(SBSAMachineState *sms)
31
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7),
39
g_free(matrix);
32
+ TYPE_TMP105, 0x4d);
40
}
33
41
34
/* The AST2500 EVB does not have an RTC. Let's pretend that one is
42
+ /*
35
* plugged on the I2C bus header */
43
+ * From Documentation/devicetree/bindings/arm/cpus.yaml
36
@@ -XXX,XX +XXX,XX @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
44
+ * On ARM v8 64-bit systems this property is required
37
AspeedSoCState *soc = &bmc->soc;
45
+ * and matches the MPIDR_EL1 register affinity bits.
38
uint8_t *eeprom_buf = g_malloc0(8 * 1024);
46
+ *
39
47
+ * * If cpus node's #address-cells property is set to 2
40
- i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), "pca9552", 0x60);
48
+ *
41
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), TYPE_PCA9552,
49
+ * The first reg cell bits [7:0] must be set to
42
+ 0x60);
50
+ * bits [39:32] of MPIDR_EL1.
43
51
+ *
44
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "tmp423", 0x4c);
52
+ * The second reg cell bits [23:0] must be set to
45
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 5), "tmp423", 0x4c);
53
+ * bits [23:0] of MPIDR_EL1.
46
54
+ */
47
/* The Witherspoon expects a TMP275 but a TMP105 is compatible */
55
qemu_fdt_add_subnode(sms->fdt, "/cpus");
48
- i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), "tmp105", 0x4a);
56
+ qemu_fdt_setprop_cell(sms->fdt, "/cpus", "#address-cells", 2);
49
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), TYPE_TMP105,
57
+ qemu_fdt_setprop_cell(sms->fdt, "/cpus", "#size-cells", 0x0);
50
+ 0x4a);
58
51
59
for (cpu = sms->smp_cpus - 1; cpu >= 0; cpu--) {
52
/* The witherspoon board expects Epson RX8900 I2C RTC but a ds1338 is
60
char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
53
* good enough */
61
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
54
@@ -XXX,XX +XXX,XX @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
62
CPUState *cs = CPU(armcpu);
55
63
+ uint64_t mpidr = sbsa_ref_cpu_mp_affinity(sms, cpu);
56
smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), 0x51,
64
57
eeprom_buf);
65
qemu_fdt_add_subnode(sms->fdt, nodename);
58
- i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "pca9552",
66
+ qemu_fdt_setprop_u64(sms->fdt, nodename, "reg", mpidr);
59
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), TYPE_PCA9552,
67
60
0x60);
68
if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) {
69
qemu_fdt_setprop_cell(sms->fdt, nodename, "numa-node-id",
70
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
71
arm_load_kernel(ARM_CPU(first_cpu), machine, &sms->bootinfo);
61
}
72
}
62
73
74
-static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
75
-{
76
- uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
77
- return arm_cpu_mp_affinity(idx, clustersz);
78
-}
79
-
80
static const CPUArchIdList *sbsa_ref_possible_cpu_arch_ids(MachineState *ms)
81
{
82
unsigned int max_cpus = ms->smp.max_cpus;
63
--
83
--
64
2.20.1
84
2.20.1
65
85
66
86
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Graeme Gregory <graeme@nuviainc.com>
2
2
3
Reviewed-by: Thomas Huth <thuth@redhat.com>
3
A difference between sbsa platform and the virt platform is PSCI is
4
Reviewed-by: Markus Armbruster <armbru@redhat.com>
4
handled by ARM-TF in the sbsa platform. This means that the PSCI code
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
there needs to communicate some of the platform power changes down
6
Message-id: 20190412165416.7977-7-philmd@redhat.com
6
to the qemu code for things like shutdown/reset control.
7
8
Space has been left to extend the EC if we find other use cases in
9
future where ARM-TF and qemu need to communicate.
10
11
Signed-off-by: Graeme Gregory <graeme@nuviainc.com>
12
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
13
Tested-by: Leif Lindholm <leif@nuviainc.com>
14
Message-id: 20200826141952.136164-2-graeme@nuviainc.com
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
17
---
9
include/hw/devices.h | 14 --------------
18
hw/misc/sbsa_ec.c | 98 +++++++++++++++++++++++++++++++++++++++++++++
10
include/hw/misc/cbus.h | 32 ++++++++++++++++++++++++++++++++
19
hw/misc/meson.build | 2 +
11
hw/arm/nseries.c | 1 +
20
2 files changed, 100 insertions(+)
12
hw/misc/cbus.c | 2 +-
21
create mode 100644 hw/misc/sbsa_ec.c
13
MAINTAINERS | 1 +
14
5 files changed, 35 insertions(+), 15 deletions(-)
15
create mode 100644 include/hw/misc/cbus.h
16
22
17
diff --git a/include/hw/devices.h b/include/hw/devices.h
23
diff --git a/hw/misc/sbsa_ec.c b/hw/misc/sbsa_ec.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/devices.h
20
+++ b/include/hw/devices.h
21
@@ -XXX,XX +XXX,XX @@ void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
22
/* stellaris_input.c */
23
void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
24
25
-/* cbus.c */
26
-typedef struct {
27
- qemu_irq clk;
28
- qemu_irq dat;
29
- qemu_irq sel;
30
-} CBus;
31
-CBus *cbus_init(qemu_irq dat_out);
32
-void cbus_attach(CBus *bus, void *slave_opaque);
33
-
34
-void *retu_init(qemu_irq irq, int vilma);
35
-void *tahvo_init(qemu_irq irq, int betty);
36
-
37
-void retu_key_event(void *retu, int state);
38
-
39
#endif
40
diff --git a/include/hw/misc/cbus.h b/include/hw/misc/cbus.h
41
new file mode 100644
24
new file mode 100644
42
index XXXXXXX..XXXXXXX
25
index XXXXXXX..XXXXXXX
43
--- /dev/null
26
--- /dev/null
44
+++ b/include/hw/misc/cbus.h
27
+++ b/hw/misc/sbsa_ec.c
45
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@
46
+/*
29
+/*
47
+ * CBUS three-pin bus and the Retu / Betty / Tahvo / Vilma / Avilma /
30
+ * ARM SBSA Reference Platform Embedded Controller
48
+ * Hinku / Vinku / Ahne / Pihi chips used in various Nokia platforms.
49
+ * Based on reverse-engineering of a linux driver.
50
+ *
31
+ *
51
+ * Copyright (C) 2008 Nokia Corporation
32
+ * A device to allow PSCI running in the secure side of sbsa-ref machine
52
+ * Written by Andrzej Zaborowski
33
+ * to communicate platform power states to qemu.
53
+ *
34
+ *
54
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
35
+ * Copyright (c) 2020 Nuvia Inc
55
+ * See the COPYING file in the top-level directory.
36
+ * Written by Graeme Gregory <graeme@nuviainc.com>
37
+ *
38
+ * SPDX-License-Identifer: GPL-2.0-or-later
56
+ */
39
+ */
57
+
40
+
58
+#ifndef HW_MISC_CBUS_H
41
+#include "qemu/osdep.h"
59
+#define HW_MISC_CBUS_H
42
+#include "qemu-common.h"
60
+
43
+#include "qemu/log.h"
61
+#include "hw/irq.h"
44
+#include "hw/sysbus.h"
45
+#include "sysemu/runstate.h"
62
+
46
+
63
+typedef struct {
47
+typedef struct {
64
+ qemu_irq clk;
48
+ SysBusDevice parent_obj;
65
+ qemu_irq dat;
49
+ MemoryRegion iomem;
66
+ qemu_irq sel;
50
+} SECUREECState;
67
+} CBus;
68
+
51
+
69
+CBus *cbus_init(qemu_irq dat_out);
52
+#define TYPE_SBSA_EC "sbsa-ec"
70
+void cbus_attach(CBus *bus, void *slave_opaque);
53
+#define SECURE_EC(obj) OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_EC)
71
+
54
+
72
+void *retu_init(qemu_irq irq, int vilma);
55
+enum sbsa_ec_powerstates {
73
+void *tahvo_init(qemu_irq irq, int betty);
56
+ SBSA_EC_CMD_POWEROFF = 0x01,
57
+ SBSA_EC_CMD_REBOOT = 0x02,
58
+};
74
+
59
+
75
+void retu_key_event(void *retu, int state);
60
+static uint64_t sbsa_ec_read(void *opaque, hwaddr offset, unsigned size)
61
+{
62
+ /* No use for this currently */
63
+ qemu_log_mask(LOG_GUEST_ERROR, "sbsa-ec: no readable registers");
64
+ return 0;
65
+}
76
+
66
+
77
+#endif
67
+static void sbsa_ec_write(void *opaque, hwaddr offset,
78
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
68
+ uint64_t value, unsigned size)
69
+{
70
+ if (offset == 0) { /* PSCI machine power command register */
71
+ switch (value) {
72
+ case SBSA_EC_CMD_POWEROFF:
73
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
74
+ break;
75
+ case SBSA_EC_CMD_REBOOT:
76
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
77
+ break;
78
+ default:
79
+ qemu_log_mask(LOG_GUEST_ERROR,
80
+ "sbsa-ec: unknown power command");
81
+ }
82
+ } else {
83
+ qemu_log_mask(LOG_GUEST_ERROR, "sbsa-ec: unknown EC register");
84
+ }
85
+}
86
+
87
+static const MemoryRegionOps sbsa_ec_ops = {
88
+ .read = sbsa_ec_read,
89
+ .write = sbsa_ec_write,
90
+ .endianness = DEVICE_NATIVE_ENDIAN,
91
+ .valid.min_access_size = 4,
92
+ .valid.max_access_size = 4,
93
+};
94
+
95
+static void sbsa_ec_init(Object *obj)
96
+{
97
+ SECUREECState *s = SECURE_EC(obj);
98
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
99
+
100
+ memory_region_init_io(&s->iomem, obj, &sbsa_ec_ops, s, "sbsa-ec",
101
+ 0x1000);
102
+ sysbus_init_mmio(dev, &s->iomem);
103
+}
104
+
105
+static void sbsa_ec_class_init(ObjectClass *klass, void *data)
106
+{
107
+ DeviceClass *dc = DEVICE_CLASS(klass);
108
+
109
+ /* No vmstate or reset required: device has no internal state */
110
+ dc->user_creatable = false;
111
+}
112
+
113
+static const TypeInfo sbsa_ec_info = {
114
+ .name = TYPE_SBSA_EC,
115
+ .parent = TYPE_SYS_BUS_DEVICE,
116
+ .instance_size = sizeof(SECUREECState),
117
+ .instance_init = sbsa_ec_init,
118
+ .class_init = sbsa_ec_class_init,
119
+};
120
+
121
+static void sbsa_ec_register_type(void)
122
+{
123
+ type_register_static(&sbsa_ec_info);
124
+}
125
+
126
+type_init(sbsa_ec_register_type);
127
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
79
index XXXXXXX..XXXXXXX 100644
128
index XXXXXXX..XXXXXXX 100644
80
--- a/hw/arm/nseries.c
129
--- a/hw/misc/meson.build
81
+++ b/hw/arm/nseries.c
130
+++ b/hw/misc/meson.build
82
@@ -XXX,XX +XXX,XX @@
131
@@ -XXX,XX +XXX,XX @@ specific_ss.add(when: 'CONFIG_MAC_VIA', if_true: files('mac_via.c'))
83
#include "hw/i2c/i2c.h"
132
84
#include "hw/devices.h"
133
specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_cmgcr.c', 'mips_cpc.c'))
85
#include "hw/display/blizzard.h"
134
specific_ss.add(when: 'CONFIG_MIPS_ITU', if_true: files('mips_itu.c'))
86
+#include "hw/misc/cbus.h"
135
+
87
#include "hw/misc/tmp105.h"
136
+specific_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c'))
88
#include "hw/block/flash.h"
89
#include "hw/hw.h"
90
diff --git a/hw/misc/cbus.c b/hw/misc/cbus.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/hw/misc/cbus.c
93
+++ b/hw/misc/cbus.c
94
@@ -XXX,XX +XXX,XX @@
95
#include "qemu/osdep.h"
96
#include "hw/hw.h"
97
#include "hw/irq.h"
98
-#include "hw/devices.h"
99
+#include "hw/misc/cbus.h"
100
#include "sysemu/sysemu.h"
101
102
//#define DEBUG
103
diff --git a/MAINTAINERS b/MAINTAINERS
104
index XXXXXXX..XXXXXXX 100644
105
--- a/MAINTAINERS
106
+++ b/MAINTAINERS
107
@@ -XXX,XX +XXX,XX @@ F: hw/input/tsc2005.c
108
F: hw/misc/cbus.c
109
F: hw/timer/twl92230.c
110
F: include/hw/display/blizzard.h
111
+F: include/hw/misc/cbus.h
112
113
Palm
114
M: Andrzej Zaborowski <balrogg@gmail.com>
115
--
137
--
116
2.20.1
138
2.20.1
117
139
118
140
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Graeme Gregory <graeme@nuviainc.com>
2
2
3
This device is used by both ARM (BCM2836, for raspi2) and AArch64
3
Add the previously created sbsa-ec device to the sbsa-ref machine in
4
(BCM2837, for raspi3) targets, and is not CPU-specific.
4
secure memory so the PSCI implementation in ARM-TF can access it, but
5
Move it to common object, so we build it once for all targets.
5
not expose it to non secure firmware or OS except by via ARM-TF.
6
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Graeme Gregory <graeme@nuviainc.com>
8
Message-id: 20190427133028.12874-1-philmd@redhat.com
8
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
9
Tested-by: Leif Lindholm <leif@nuviainc.com>
10
Message-id: 20200826141952.136164-3-graeme@nuviainc.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
hw/dma/Makefile.objs | 2 +-
14
hw/arm/sbsa-ref.c | 14 ++++++++++++++
13
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 14 insertions(+)
14
16
15
diff --git a/hw/dma/Makefile.objs b/hw/dma/Makefile.objs
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/dma/Makefile.objs
19
--- a/hw/arm/sbsa-ref.c
18
+++ b/hw/dma/Makefile.objs
20
+++ b/hw/arm/sbsa-ref.c
19
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zdma.o
21
@@ -XXX,XX +XXX,XX @@ enum {
20
22
SBSA_CPUPERIPHS,
21
obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o
23
SBSA_GIC_DIST,
22
obj-$(CONFIG_PXA2XX) += pxa2xx_dma.o
24
SBSA_GIC_REDIST,
23
-obj-$(CONFIG_RASPI) += bcm2835_dma.o
25
+ SBSA_SECURE_EC,
24
+common-obj-$(CONFIG_RASPI) += bcm2835_dma.o
26
SBSA_SMMU,
27
SBSA_UART,
28
SBSA_RTC,
29
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry sbsa_ref_memmap[] = {
30
[SBSA_CPUPERIPHS] = { 0x40000000, 0x00040000 },
31
[SBSA_GIC_DIST] = { 0x40060000, 0x00010000 },
32
[SBSA_GIC_REDIST] = { 0x40080000, 0x04000000 },
33
+ [SBSA_SECURE_EC] = { 0x50000000, 0x00001000 },
34
[SBSA_UART] = { 0x60000000, 0x00001000 },
35
[SBSA_RTC] = { 0x60010000, 0x00001000 },
36
[SBSA_GPIO] = { 0x60020000, 0x00001000 },
37
@@ -XXX,XX +XXX,XX @@ static void *sbsa_ref_dtb(const struct arm_boot_info *binfo, int *fdt_size)
38
return board->fdt;
39
}
40
41
+static void create_secure_ec(MemoryRegion *mem)
42
+{
43
+ hwaddr base = sbsa_ref_memmap[SBSA_SECURE_EC].base;
44
+ DeviceState *dev = qdev_new("sbsa-ec");
45
+ SysBusDevice *s = SYS_BUS_DEVICE(dev);
46
+
47
+ memory_region_add_subregion(mem, base,
48
+ sysbus_mmio_get_region(s, 0));
49
+}
50
+
51
static void sbsa_ref_init(MachineState *machine)
52
{
53
unsigned int smp_cpus = machine->smp.cpus;
54
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
55
56
create_pcie(sms);
57
58
+ create_secure_ec(secure_sysmem);
59
+
60
sms->bootinfo.ram_size = machine->ram_size;
61
sms->bootinfo.nb_cpus = smp_cpus;
62
sms->bootinfo.board_id = -1;
25
--
63
--
26
2.20.1
64
2.20.1
27
65
28
66
diff view generated by jsdifflib