1
First arm pullreq for 5.2: Eric's SMMU stuff, and a bunch of
1
First arm pullreq of the cycle; this is mostly my softfloat NaN
2
cleanup/refactoring from me.
2
handling series. (Lots more in my to-review queue, but I don't
3
like pullreqs growing too close to a hundred patches at a time :-))
3
4
4
thanks
5
thanks
5
-- PMM
6
-- PMM
6
7
7
The following changes since commit 8367a77c4d3f6e1e60890f5510304feb2c621611:
8
The following changes since commit 97f2796a3736ed37a1b85dc1c76a6c45b829dd17:
8
9
9
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.2-pull-request' into staging (2020-08-23 16:34:43 +0100)
10
Open 10.0 development tree (2024-12-10 17:41:17 +0000)
10
11
11
are available in the Git repository at:
12
are available in the Git repository at:
12
13
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200824
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20241211
14
15
15
for you to fetch changes up to b34aa5129e9c3aff890b4f4bcc84962e94185629:
16
for you to fetch changes up to 1abe28d519239eea5cf9620bb13149423e5665f8:
16
17
17
target/arm: Use correct FPST for VCMLA, VCADD on fp16 (2020-08-24 10:15:12 +0100)
18
MAINTAINERS: Add correct email address for Vikram Garhwal (2024-12-11 15:31:09 +0000)
18
19
19
----------------------------------------------------------------
20
----------------------------------------------------------------
20
target-arm queue:
21
target-arm queue:
21
* hw/cpu/a9mpcore: Verify the machine use Cortex-A9 cores
22
* hw/net/lan9118: Extract PHY model, reuse with imx_fec, fix bugs
22
* hw/arm/smmuv3: Implement SMMUv3.2 range-invalidation
23
* fpu: Make muladd NaN handling runtime-selected, not compile-time
23
* docs/system/arm: Document the Xilinx Versal Virt board
24
* fpu: Make default NaN pattern runtime-selected, not compile-time
24
* target/arm: Make M-profile NOCP take precedence over UNDEF
25
* fpu: Minor NaN-related cleanups
25
* target/arm: Use correct FPST for VCMLA, VCADD on fp16
26
* MAINTAINERS: email address updates
26
* target/arm: Various cleanups preparing for fp16 support
27
27
28
----------------------------------------------------------------
28
----------------------------------------------------------------
29
Edgar E. Iglesias (1):
29
Bernhard Beschow (5):
30
docs/system/arm: Document the Xilinx Versal Virt board
30
hw/net/lan9118: Extract lan9118_phy
31
hw/net/lan9118_phy: Reuse in imx_fec and consolidate implementations
32
hw/net/lan9118_phy: Fix off-by-one error in MII_ANLPAR register
33
hw/net/lan9118_phy: Reuse MII constants
34
hw/net/lan9118_phy: Add missing 100 mbps full duplex advertisement
31
35
32
Eric Auger (11):
36
Leif Lindholm (1):
33
hw/arm/smmu-common: Factorize some code in smmu_ptw_64()
37
MAINTAINERS: update email address for Leif Lindholm
34
hw/arm/smmu-common: Add IOTLB helpers
35
hw/arm/smmu: Introduce smmu_get_iotlb_key()
36
hw/arm/smmu: Introduce SMMUTLBEntry for PTW and IOTLB value
37
hw/arm/smmu-common: Manage IOTLB block entries
38
hw/arm/smmuv3: Introduce smmuv3_s1_range_inval() helper
39
hw/arm/smmuv3: Get prepared for range invalidation
40
hw/arm/smmuv3: Fix IIDR offset
41
hw/arm/smmuv3: Let AIDR advertise SMMUv3.0 support
42
hw/arm/smmuv3: Support HAD and advertise SMMUv3.1 support
43
hw/arm/smmuv3: Advertise SMMUv3.2 range invalidation
44
38
45
Peter Maydell (14):
39
Peter Maydell (54):
46
target/arm: Pull handling of XScale insns out of disas_coproc_insn()
40
fpu: handle raising Invalid for infzero in pick_nan_muladd
47
target/arm: Separate decode from handling of coproc insns
41
fpu: Check for default_nan_mode before calling pickNaNMulAdd
48
target/arm: Convert A32 coprocessor insns to decodetree
42
softfloat: Allow runtime choice of inf * 0 + NaN result
49
target/arm: Tidy up disas_arm_insn()
43
tests/fp: Explicitly set inf-zero-nan rule
50
target/arm: Do M-profile NOCP checks early and via decodetree
44
target/arm: Set FloatInfZeroNaNRule explicitly
51
target/arm: Convert T32 coprocessor insns to decodetree
45
target/s390: Set FloatInfZeroNaNRule explicitly
52
target/arm: Remove ARCH macro
46
target/ppc: Set FloatInfZeroNaNRule explicitly
53
target/arm: Delete unused VFP_DREG macros
47
target/mips: Set FloatInfZeroNaNRule explicitly
54
target/arm/translate.c: Delete/amend incorrect comments
48
target/sparc: Set FloatInfZeroNaNRule explicitly
55
target/arm: Delete unused ARM_FEATURE_CRC
49
target/xtensa: Set FloatInfZeroNaNRule explicitly
56
target/arm: Replace A64 get_fpstatus_ptr() with generic fpstatus_ptr()
50
target/x86: Set FloatInfZeroNaNRule explicitly
57
target/arm: Make A32/T32 use new fpstatus_ptr() API
51
target/loongarch: Set FloatInfZeroNaNRule explicitly
58
target/arm: Implement FPST_STD_F16 fpstatus
52
target/hppa: Set FloatInfZeroNaNRule explicitly
59
target/arm: Use correct FPST for VCMLA, VCADD on fp16
53
softfloat: Pass have_snan to pickNaNMulAdd
54
softfloat: Allow runtime choice of NaN propagation for muladd
55
tests/fp: Explicitly set 3-NaN propagation rule
56
target/arm: Set Float3NaNPropRule explicitly
57
target/loongarch: Set Float3NaNPropRule explicitly
58
target/ppc: Set Float3NaNPropRule explicitly
59
target/s390x: Set Float3NaNPropRule explicitly
60
target/sparc: Set Float3NaNPropRule explicitly
61
target/mips: Set Float3NaNPropRule explicitly
62
target/xtensa: Set Float3NaNPropRule explicitly
63
target/i386: Set Float3NaNPropRule explicitly
64
target/hppa: Set Float3NaNPropRule explicitly
65
fpu: Remove use_first_nan field from float_status
66
target/m68k: Don't pass NULL float_status to floatx80_default_nan()
67
softfloat: Create floatx80 default NaN from parts64_default_nan
68
target/loongarch: Use normal float_status in fclass_s and fclass_d helpers
69
target/m68k: In frem helper, initialize local float_status from env->fp_status
70
target/m68k: Init local float_status from env fp_status in gdb get/set reg
71
target/sparc: Initialize local scratch float_status from env->fp_status
72
target/ppc: Use env->fp_status in helper_compute_fprf functions
73
fpu: Allow runtime choice of default NaN value
74
tests/fp: Set default NaN pattern explicitly
75
target/microblaze: Set default NaN pattern explicitly
76
target/i386: Set default NaN pattern explicitly
77
target/hppa: Set default NaN pattern explicitly
78
target/alpha: Set default NaN pattern explicitly
79
target/arm: Set default NaN pattern explicitly
80
target/loongarch: Set default NaN pattern explicitly
81
target/m68k: Set default NaN pattern explicitly
82
target/mips: Set default NaN pattern explicitly
83
target/openrisc: Set default NaN pattern explicitly
84
target/ppc: Set default NaN pattern explicitly
85
target/sh4: Set default NaN pattern explicitly
86
target/rx: Set default NaN pattern explicitly
87
target/s390x: Set default NaN pattern explicitly
88
target/sparc: Set default NaN pattern explicitly
89
target/xtensa: Set default NaN pattern explicitly
90
target/hexagon: Set default NaN pattern explicitly
91
target/riscv: Set default NaN pattern explicitly
92
target/tricore: Set default NaN pattern explicitly
93
fpu: Remove default handling for dnan_pattern
60
94
61
Philippe Mathieu-Daudé (1):
95
Richard Henderson (11):
62
hw/cpu/a9mpcore: Verify the machine use Cortex-A9 cores
96
target/arm: Copy entire float_status in is_ebf
97
softfloat: Inline pickNaNMulAdd
98
softfloat: Use goto for default nan case in pick_nan_muladd
99
softfloat: Remove which from parts_pick_nan_muladd
100
softfloat: Pad array size in pick_nan_muladd
101
softfloat: Move propagateFloatx80NaN to softfloat.c
102
softfloat: Use parts_pick_nan in propagateFloatx80NaN
103
softfloat: Inline pickNaN
104
softfloat: Share code between parts_pick_nan cases
105
softfloat: Sink frac_cmp in parts_pick_nan until needed
106
softfloat: Replace WHICH with RET in parts_pick_nan
63
107
64
docs/system/arm/xlnx-versal-virt.rst | 176 +++++++++++++++++++++++
108
Vikram Garhwal (1):
65
docs/system/target-arm.rst | 1 +
109
MAINTAINERS: Add correct email address for Vikram Garhwal
66
hw/arm/smmu-internal.h | 8 ++
67
hw/arm/smmuv3-internal.h | 10 +-
68
include/hw/arm/smmu-common.h | 19 ++-
69
include/hw/arm/smmuv3.h | 1 +
70
target/arm/cpu.h | 10 +-
71
target/arm/translate-a64.h | 1 -
72
target/arm/translate.h | 52 +++++++
73
target/arm/a32.decode | 19 +++
74
target/arm/m-nocp.decode | 42 ++++++
75
target/arm/t32.decode | 19 +++
76
target/arm/vfp.decode | 2 -
77
hw/arm/smmu-common.c | 214 ++++++++++++++++++---------
78
hw/arm/smmuv3.c | 142 +++++++++---------
79
hw/cpu/a9mpcore.c | 12 +-
80
target/arm/cpu.c | 3 +
81
target/arm/helper.c | 29 ++++
82
target/arm/translate-a64.c | 89 +++++-------
83
target/arm/translate-sve.c | 34 ++---
84
target/arm/translate.c | 272 +++++++++++++++++------------------
85
target/arm/vfp_helper.c | 5 +
86
MAINTAINERS | 3 +-
87
hw/arm/trace-events | 12 +-
88
target/arm/meson.build | 1 +
89
target/arm/translate-neon.c.inc | 28 ++--
90
target/arm/translate-vfp.c.inc | 96 ++++++++-----
91
27 files changed, 885 insertions(+), 415 deletions(-)
92
create mode 100644 docs/system/arm/xlnx-versal-virt.rst
93
create mode 100644 target/arm/m-nocp.decode
94
110
111
MAINTAINERS | 4 +-
112
include/fpu/softfloat-helpers.h | 38 +++-
113
include/fpu/softfloat-types.h | 89 +++++++-
114
include/hw/net/imx_fec.h | 9 +-
115
include/hw/net/lan9118_phy.h | 37 ++++
116
include/hw/net/mii.h | 6 +
117
target/mips/fpu_helper.h | 20 ++
118
target/sparc/helper.h | 4 +-
119
fpu/softfloat.c | 19 ++
120
hw/net/imx_fec.c | 146 ++------------
121
hw/net/lan9118.c | 137 ++-----------
122
hw/net/lan9118_phy.c | 222 ++++++++++++++++++++
123
linux-user/arm/nwfpe/fpa11.c | 5 +
124
target/alpha/cpu.c | 2 +
125
target/arm/cpu.c | 10 +
126
target/arm/tcg/vec_helper.c | 20 +-
127
target/hexagon/cpu.c | 2 +
128
target/hppa/fpu_helper.c | 12 ++
129
target/i386/tcg/fpu_helper.c | 12 ++
130
target/loongarch/tcg/fpu_helper.c | 14 +-
131
target/m68k/cpu.c | 14 +-
132
target/m68k/fpu_helper.c | 6 +-
133
target/m68k/helper.c | 6 +-
134
target/microblaze/cpu.c | 2 +
135
target/mips/msa.c | 10 +
136
target/openrisc/cpu.c | 2 +
137
target/ppc/cpu_init.c | 19 ++
138
target/ppc/fpu_helper.c | 3 +-
139
target/riscv/cpu.c | 2 +
140
target/rx/cpu.c | 2 +
141
target/s390x/cpu.c | 5 +
142
target/sh4/cpu.c | 2 +
143
target/sparc/cpu.c | 6 +
144
target/sparc/fop_helper.c | 8 +-
145
target/sparc/translate.c | 4 +-
146
target/tricore/helper.c | 2 +
147
target/xtensa/cpu.c | 4 +
148
target/xtensa/fpu_helper.c | 3 +-
149
tests/fp/fp-bench.c | 7 +
150
tests/fp/fp-test-log2.c | 1 +
151
tests/fp/fp-test.c | 7 +
152
fpu/softfloat-parts.c.inc | 152 +++++++++++---
153
fpu/softfloat-specialize.c.inc | 412 ++------------------------------------
154
.mailmap | 5 +-
155
hw/net/Kconfig | 5 +
156
hw/net/meson.build | 1 +
157
hw/net/trace-events | 10 +-
158
47 files changed, 778 insertions(+), 730 deletions(-)
159
create mode 100644 include/hw/net/lan9118_phy.h
160
create mode 100644 hw/net/lan9118_phy.c
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Enhance the smmu_iotlb_inv_iova() helper with range invalidation.
3
A very similar implementation of the same device exists in imx_fec. Prepare for
4
This uses the new fields passed in the NH_VA and NH_VAA commands:
4
a common implementation by extracting a device model into its own files.
5
the size of the range, the level and the granule.
6
5
7
As NH_VA and NH_VAA both use those fields, their decoding and
6
Some migration state has been moved into the new device model which breaks
8
handling is factorized in a new smmuv3_s1_range_inval() helper.
7
migration compatibility for the following machines:
8
* smdkc210
9
* realview-*
10
* vexpress-*
11
* kzm
12
* mps2-*
9
13
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
14
While breaking migration ABI, fix the size of the MII registers to be 16 bit,
15
as defined by IEEE 802.3u.
16
17
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
18
Tested-by: Guenter Roeck <linux@roeck-us.net>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20200728150815.11446-8-eric.auger@redhat.com
20
Message-id: 20241102125724.532843-2-shentey@gmail.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
22
---
15
hw/arm/smmuv3-internal.h | 4 +++
23
include/hw/net/lan9118_phy.h | 37 ++++++++
16
include/hw/arm/smmu-common.h | 3 +-
24
hw/net/lan9118.c | 137 +++++-----------------------
17
hw/arm/smmu-common.c | 25 +++++++++++---
25
hw/net/lan9118_phy.c | 169 +++++++++++++++++++++++++++++++++++
18
hw/arm/smmuv3.c | 64 +++++++++++++++++++++++-------------
26
hw/net/Kconfig | 4 +
19
hw/arm/trace-events | 4 +--
27
hw/net/meson.build | 1 +
20
5 files changed, 69 insertions(+), 31 deletions(-)
28
5 files changed, 233 insertions(+), 115 deletions(-)
29
create mode 100644 include/hw/net/lan9118_phy.h
30
create mode 100644 hw/net/lan9118_phy.c
21
31
22
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
32
diff --git a/include/hw/net/lan9118_phy.h b/include/hw/net/lan9118_phy.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/net/lan9118_phy.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * SMSC LAN9118 PHY emulation
40
+ *
41
+ * Copyright (c) 2009 CodeSourcery, LLC.
42
+ * Written by Paul Brook
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
+
48
+#ifndef HW_NET_LAN9118_PHY_H
49
+#define HW_NET_LAN9118_PHY_H
50
+
51
+#include "qom/object.h"
52
+#include "hw/sysbus.h"
53
+
54
+#define TYPE_LAN9118_PHY "lan9118-phy"
55
+OBJECT_DECLARE_SIMPLE_TYPE(Lan9118PhyState, LAN9118_PHY)
56
+
57
+typedef struct Lan9118PhyState {
58
+ SysBusDevice parent_obj;
59
+
60
+ uint16_t status;
61
+ uint16_t control;
62
+ uint16_t advertise;
63
+ uint16_t ints;
64
+ uint16_t int_mask;
65
+ qemu_irq irq;
66
+ bool link_down;
67
+} Lan9118PhyState;
68
+
69
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down);
70
+void lan9118_phy_reset(Lan9118PhyState *s);
71
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg);
72
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val);
73
+
74
+#endif
75
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
23
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/arm/smmuv3-internal.h
77
--- a/hw/net/lan9118.c
25
+++ b/hw/arm/smmuv3-internal.h
78
+++ b/hw/net/lan9118.c
26
@@ -XXX,XX +XXX,XX @@ enum { /* Command completion notification */
79
@@ -XXX,XX +XXX,XX @@
27
};
80
#include "net/net.h"
28
81
#include "net/eth.h"
29
#define CMD_TYPE(x) extract32((x)->word[0], 0 , 8)
82
#include "hw/irq.h"
30
+#define CMD_NUM(x) extract32((x)->word[0], 12 , 5)
83
+#include "hw/net/lan9118_phy.h"
31
+#define CMD_SCALE(x) extract32((x)->word[0], 20 , 5)
84
#include "hw/net/lan9118.h"
32
#define CMD_SSEC(x) extract32((x)->word[0], 10, 1)
85
#include "hw/ptimer.h"
33
#define CMD_SSV(x) extract32((x)->word[0], 11, 1)
86
#include "hw/qdev-properties.h"
34
#define CMD_RESUME_AC(x) extract32((x)->word[0], 12, 1)
87
@@ -XXX,XX +XXX,XX @@ do { printf("lan9118: " fmt , ## __VA_ARGS__); } while (0)
35
@@ -XXX,XX +XXX,XX @@ enum { /* Command completion notification */
88
#define MAC_CR_RXEN 0x00000004
36
#define CMD_RESUME_STAG(x) extract32((x)->word[2], 0 , 16)
89
#define MAC_CR_RESERVED 0x7f404213
37
#define CMD_RESP(x) extract32((x)->word[2], 11, 2)
90
38
#define CMD_LEAF(x) extract32((x)->word[2], 0 , 1)
91
-#define PHY_INT_ENERGYON 0x80
39
+#define CMD_TTL(x) extract32((x)->word[2], 8 , 2)
92
-#define PHY_INT_AUTONEG_COMPLETE 0x40
40
+#define CMD_TG(x) extract32((x)->word[2], 10, 2)
93
-#define PHY_INT_FAULT 0x20
41
#define CMD_STE_RANGE(x) extract32((x)->word[2], 0 , 5)
94
-#define PHY_INT_DOWN 0x10
42
#define CMD_ADDR(x) ({ \
95
-#define PHY_INT_AUTONEG_LP 0x08
43
uint64_t high = (uint64_t)(x)->word[3]; \
96
-#define PHY_INT_PARFAULT 0x04
44
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
97
-#define PHY_INT_AUTONEG_PAGE 0x02
45
index XXXXXXX..XXXXXXX 100644
98
-
46
--- a/include/hw/arm/smmu-common.h
99
#define GPT_TIMER_EN 0x20000000
47
+++ b/include/hw/arm/smmu-common.h
100
48
@@ -XXX,XX +XXX,XX @@ SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova,
101
/*
49
uint8_t tg, uint8_t level);
102
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
50
void smmu_iotlb_inv_all(SMMUState *s);
103
uint32_t mac_mii_data;
51
void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
104
uint32_t mac_flow;
52
-void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova);
105
53
+void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
106
- uint32_t phy_status;
54
+ uint8_t tg, uint64_t num_pages, uint8_t ttl);
107
- uint32_t phy_control;
55
108
- uint32_t phy_advertise;
56
/* Unmap the range of all the notifiers registered to any IOMMU mr */
109
- uint32_t phy_int;
57
void smmu_inv_notifiers_all(SMMUState *s);
110
- uint32_t phy_int_mask;
58
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
111
+ Lan9118PhyState mii;
59
index XXXXXXX..XXXXXXX 100644
112
+ IRQState mii_irq;
60
--- a/hw/arm/smmu-common.c
113
61
+++ b/hw/arm/smmu-common.c
114
int32_t eeprom_writable;
62
@@ -XXX,XX +XXX,XX @@ static gboolean smmu_hash_remove_by_asid_iova(gpointer key, gpointer value,
115
uint8_t eeprom[128];
63
if (info->asid >= 0 && info->asid != SMMU_IOTLB_ASID(iotlb_key)) {
116
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
64
return false;
117
65
}
118
static const VMStateDescription vmstate_lan9118 = {
66
- return (info->iova & ~entry->addr_mask) == entry->iova;
119
.name = "lan9118",
67
+ return ((info->iova & ~entry->addr_mask) == entry->iova) ||
120
- .version_id = 2,
68
+ ((entry->iova & ~info->mask) == info->iova);
121
- .minimum_version_id = 1,
122
+ .version_id = 3,
123
+ .minimum_version_id = 3,
124
.fields = (const VMStateField[]) {
125
VMSTATE_PTIMER(timer, lan9118_state),
126
VMSTATE_UINT32(irq_cfg, lan9118_state),
127
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118 = {
128
VMSTATE_UINT32(mac_mii_acc, lan9118_state),
129
VMSTATE_UINT32(mac_mii_data, lan9118_state),
130
VMSTATE_UINT32(mac_flow, lan9118_state),
131
- VMSTATE_UINT32(phy_status, lan9118_state),
132
- VMSTATE_UINT32(phy_control, lan9118_state),
133
- VMSTATE_UINT32(phy_advertise, lan9118_state),
134
- VMSTATE_UINT32(phy_int, lan9118_state),
135
- VMSTATE_UINT32(phy_int_mask, lan9118_state),
136
VMSTATE_INT32(eeprom_writable, lan9118_state),
137
VMSTATE_UINT8_ARRAY(eeprom, lan9118_state, 128),
138
VMSTATE_INT32(tx_fifo_size, lan9118_state),
139
@@ -XXX,XX +XXX,XX @@ static void lan9118_reload_eeprom(lan9118_state *s)
140
lan9118_mac_changed(s);
69
}
141
}
70
142
71
-inline void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova)
143
-static void phy_update_irq(lan9118_state *s)
72
+inline void
144
+static void lan9118_update_irq(void *opaque, int n, int level)
73
+smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
74
+ uint8_t tg, uint64_t num_pages, uint8_t ttl)
75
{
145
{
76
- SMMUIOTLBPageInvInfo info = {.asid = asid, .iova = iova};
146
- if (s->phy_int & s->phy_int_mask) {
77
+ if (ttl && (num_pages == 1)) {
147
+ lan9118_state *s = opaque;
78
+ SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
148
+
79
149
+ if (level) {
80
- trace_smmu_iotlb_inv_iova(asid, iova);
150
s->int_sts |= PHY_INT;
81
- g_hash_table_foreach_remove(s->iotlb, smmu_hash_remove_by_asid_iova, &info);
151
} else {
82
+ g_hash_table_remove(s->iotlb, &key);
152
s->int_sts &= ~PHY_INT;
83
+ } else {
153
@@ -XXX,XX +XXX,XX @@ static void phy_update_irq(lan9118_state *s)
84
+ /* if tg is not set we use 4KB range invalidation */
154
lan9118_update(s);
85
+ uint8_t granule = tg ? tg * 2 + 10 : 12;
86
+
87
+ SMMUIOTLBPageInvInfo info = {
88
+ .asid = asid, .iova = iova,
89
+ .mask = (num_pages * 1 << granule) - 1};
90
+
91
+ g_hash_table_foreach_remove(s->iotlb,
92
+ smmu_hash_remove_by_asid_iova,
93
+ &info);
94
+ }
95
}
155
}
96
156
97
inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid)
157
-static void phy_update_link(lan9118_state *s)
98
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
158
-{
99
index XXXXXXX..XXXXXXX 100644
159
- /* Autonegotiation status mirrors link status. */
100
--- a/hw/arm/smmuv3.c
160
- if (qemu_get_queue(s->nic)->link_down) {
101
+++ b/hw/arm/smmuv3.c
161
- s->phy_status &= ~0x0024;
102
@@ -XXX,XX +XXX,XX @@ epilogue:
162
- s->phy_int |= PHY_INT_DOWN;
103
* @n: notifier to be called
163
- } else {
104
* @asid: address space ID or negative value if we don't care
164
- s->phy_status |= 0x0024;
105
* @iova: iova
165
- s->phy_int |= PHY_INT_ENERGYON;
106
+ * @tg: translation granule (if communicated through range invalidation)
166
- s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
107
+ * @num_pages: number of @granule sized pages (if tg != 0), otherwise 1
167
- }
108
*/
168
- phy_update_irq(s);
109
static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
169
-}
110
IOMMUNotifier *n,
170
-
111
- int asid,
171
static void lan9118_set_link(NetClientState *nc)
112
- dma_addr_t iova)
113
+ int asid, dma_addr_t iova,
114
+ uint8_t tg, uint64_t num_pages)
115
{
172
{
116
SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
173
- phy_update_link(qemu_get_nic_opaque(nc));
117
- SMMUEventInfo event = {.inval_ste_allowed = true};
174
-}
118
- SMMUTransTableInfo *tt;
175
-
119
- SMMUTransCfg *cfg;
176
-static void phy_reset(lan9118_state *s)
120
IOMMUTLBEntry entry;
177
-{
121
+ uint8_t granule = tg;
178
- s->phy_status = 0x7809;
122
179
- s->phy_control = 0x3000;
123
- cfg = smmuv3_get_config(sdev, &event);
180
- s->phy_advertise = 0x01e1;
124
- if (!cfg) {
181
- s->phy_int_mask = 0;
125
- return;
182
- s->phy_int = 0;
126
- }
183
- phy_update_link(s);
127
+ if (!tg) {
184
+ lan9118_phy_update_link(&LAN9118(qemu_get_nic_opaque(nc))->mii,
128
+ SMMUEventInfo event = {.inval_ste_allowed = true};
185
+ nc->link_down);
129
+ SMMUTransCfg *cfg = smmuv3_get_config(sdev, &event);
130
+ SMMUTransTableInfo *tt;
131
132
- if (asid >= 0 && cfg->asid != asid) {
133
- return;
134
- }
135
+ if (!cfg) {
136
+ return;
137
+ }
138
139
- tt = select_tt(cfg, iova);
140
- if (!tt) {
141
- return;
142
+ if (asid >= 0 && cfg->asid != asid) {
143
+ return;
144
+ }
145
+
146
+ tt = select_tt(cfg, iova);
147
+ if (!tt) {
148
+ return;
149
+ }
150
+ granule = tt->granule_sz;
151
}
152
153
entry.target_as = &address_space_memory;
154
entry.iova = iova;
155
- entry.addr_mask = (1 << tt->granule_sz) - 1;
156
+ entry.addr_mask = num_pages * (1 << granule) - 1;
157
entry.perm = IOMMU_NONE;
158
159
memory_region_notify_one(n, &entry);
160
}
186
}
161
187
162
-/* invalidate an asid/iova tuple in all mr's */
188
static void lan9118_reset(DeviceState *d)
163
-static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova)
189
@@ -XXX,XX +XXX,XX @@ static void lan9118_reset(DeviceState *d)
164
+/* invalidate an asid/iova range tuple in all mr's */
190
s->read_word_n = 0;
165
+static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova,
191
s->write_word_n = 0;
166
+ uint8_t tg, uint64_t num_pages)
192
167
{
193
- phy_reset(s);
168
SMMUDevice *sdev;
194
-
169
195
s->eeprom_writable = 0;
170
@@ -XXX,XX +XXX,XX @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova)
196
lan9118_reload_eeprom(s);
171
IOMMUMemoryRegion *mr = &sdev->iommu;
197
}
172
IOMMUNotifier *n;
198
@@ -XXX,XX +XXX,XX @@ static void do_tx_packet(lan9118_state *s)
173
199
uint32_t status;
174
- trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova);
200
175
+ trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova,
201
/* FIXME: Honor TX disable, and allow queueing of packets. */
176
+ tg, num_pages);
202
- if (s->phy_control & 0x4000) {
177
203
+ if (s->mii.control & 0x4000) {
178
IOMMU_NOTIFIER_FOREACH(n, mr) {
204
/* This assumes the receive routine doesn't touch the VLANClient. */
179
- smmuv3_notify_iova(mr, n, asid, iova);
205
qemu_receive_packet(qemu_get_queue(s->nic), s->txp->data, s->txp->len);
180
+ smmuv3_notify_iova(mr, n, asid, iova, tg, num_pages);
206
} else {
181
}
207
@@ -XXX,XX +XXX,XX @@ static void tx_fifo_push(lan9118_state *s, uint32_t val)
182
}
208
}
183
}
209
}
184
210
185
static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
211
-static uint32_t do_phy_read(lan9118_state *s, int reg)
212
-{
213
- uint32_t val;
214
-
215
- switch (reg) {
216
- case 0: /* Basic Control */
217
- return s->phy_control;
218
- case 1: /* Basic Status */
219
- return s->phy_status;
220
- case 2: /* ID1 */
221
- return 0x0007;
222
- case 3: /* ID2 */
223
- return 0xc0d1;
224
- case 4: /* Auto-neg advertisement */
225
- return s->phy_advertise;
226
- case 5: /* Auto-neg Link Partner Ability */
227
- return 0x0f71;
228
- case 6: /* Auto-neg Expansion */
229
- return 1;
230
- /* TODO 17, 18, 27, 29, 30, 31 */
231
- case 29: /* Interrupt source. */
232
- val = s->phy_int;
233
- s->phy_int = 0;
234
- phy_update_irq(s);
235
- return val;
236
- case 30: /* Interrupt mask */
237
- return s->phy_int_mask;
238
- default:
239
- qemu_log_mask(LOG_GUEST_ERROR,
240
- "do_phy_read: PHY read reg %d\n", reg);
241
- return 0;
242
- }
243
-}
244
-
245
-static void do_phy_write(lan9118_state *s, int reg, uint32_t val)
246
-{
247
- switch (reg) {
248
- case 0: /* Basic Control */
249
- if (val & 0x8000) {
250
- phy_reset(s);
251
- break;
252
- }
253
- s->phy_control = val & 0x7980;
254
- /* Complete autonegotiation immediately. */
255
- if (val & 0x1000) {
256
- s->phy_status |= 0x0020;
257
- }
258
- break;
259
- case 4: /* Auto-neg advertisement */
260
- s->phy_advertise = (val & 0x2d7f) | 0x80;
261
- break;
262
- /* TODO 17, 18, 27, 31 */
263
- case 30: /* Interrupt mask */
264
- s->phy_int_mask = val & 0xff;
265
- phy_update_irq(s);
266
- break;
267
- default:
268
- qemu_log_mask(LOG_GUEST_ERROR,
269
- "do_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
270
- }
271
-}
272
-
273
static void do_mac_write(lan9118_state *s, int reg, uint32_t val)
186
{
274
{
187
+ uint8_t scale = 0, num = 0, ttl = 0;
275
switch (reg) {
188
dma_addr_t addr = CMD_ADDR(cmd);
276
@@ -XXX,XX +XXX,XX @@ static void do_mac_write(lan9118_state *s, int reg, uint32_t val)
189
uint8_t type = CMD_TYPE(cmd);
277
if (val & 2) {
190
uint16_t vmid = CMD_VMID(cmd);
278
DPRINTF("PHY write %d = 0x%04x\n",
191
bool leaf = CMD_LEAF(cmd);
279
(val >> 6) & 0x1f, s->mac_mii_data);
192
+ uint8_t tg = CMD_TG(cmd);
280
- do_phy_write(s, (val >> 6) & 0x1f, s->mac_mii_data);
193
+ hwaddr num_pages = 1;
281
+ lan9118_phy_write(&s->mii, (val >> 6) & 0x1f, s->mac_mii_data);
194
int asid = -1;
282
} else {
195
283
- s->mac_mii_data = do_phy_read(s, (val >> 6) & 0x1f);
196
+ if (tg) {
284
+ s->mac_mii_data = lan9118_phy_read(&s->mii, (val >> 6) & 0x1f);
197
+ scale = CMD_SCALE(cmd);
285
DPRINTF("PHY read %d = 0x%04x\n",
198
+ num = CMD_NUM(cmd);
286
(val >> 6) & 0x1f, s->mac_mii_data);
199
+ ttl = CMD_TTL(cmd);
287
}
200
+ num_pages = (num + 1) * (1 << (scale));
288
@@ -XXX,XX +XXX,XX @@ static void lan9118_writel(void *opaque, hwaddr offset,
289
break;
290
case CSR_PMT_CTRL:
291
if (val & 0x400) {
292
- phy_reset(s);
293
+ lan9118_phy_reset(&s->mii);
294
}
295
s->pmt_ctrl &= ~0x34e;
296
s->pmt_ctrl |= (val & 0x34e);
297
@@ -XXX,XX +XXX,XX @@ static void lan9118_realize(DeviceState *dev, Error **errp)
298
const MemoryRegionOps *mem_ops =
299
s->mode_16bit ? &lan9118_16bit_mem_ops : &lan9118_mem_ops;
300
301
+ qemu_init_irq(&s->mii_irq, lan9118_update_irq, s, 0);
302
+ object_initialize_child(OBJECT(s), "mii", &s->mii, TYPE_LAN9118_PHY);
303
+ if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->mii), errp)) {
304
+ return;
201
+ }
305
+ }
202
+
306
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
203
if (type == SMMU_CMD_TLBI_NH_VA) {
307
+
204
asid = CMD_ASID(cmd);
308
memory_region_init_io(&s->mmio, OBJECT(dev), mem_ops, s,
205
}
309
"lan9118-mmio", 0x100);
206
- trace_smmuv3_s1_range_inval(vmid, asid, addr, leaf);
310
sysbus_init_mmio(sbd, &s->mmio);
207
- smmuv3_inv_notifiers_iova(s, asid, addr);
311
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
208
- smmu_iotlb_inv_iova(s, asid, addr);
312
new file mode 100644
209
+ trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf);
313
index XXXXXXX..XXXXXXX
210
+ smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages);
314
--- /dev/null
211
+ smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl);
315
+++ b/hw/net/lan9118_phy.c
212
}
316
@@ -XXX,XX +XXX,XX @@
213
317
+/*
214
static int smmuv3_cmdq_consume(SMMUv3State *s)
318
+ * SMSC LAN9118 PHY emulation
215
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
319
+ *
320
+ * Copyright (c) 2009 CodeSourcery, LLC.
321
+ * Written by Paul Brook
322
+ *
323
+ * This code is licensed under the GNU GPL v2
324
+ *
325
+ * Contributions after 2012-01-13 are licensed under the terms of the
326
+ * GNU GPL, version 2 or (at your option) any later version.
327
+ */
328
+
329
+#include "qemu/osdep.h"
330
+#include "hw/net/lan9118_phy.h"
331
+#include "hw/irq.h"
332
+#include "hw/resettable.h"
333
+#include "migration/vmstate.h"
334
+#include "qemu/log.h"
335
+
336
+#define PHY_INT_ENERGYON (1 << 7)
337
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
338
+#define PHY_INT_FAULT (1 << 5)
339
+#define PHY_INT_DOWN (1 << 4)
340
+#define PHY_INT_AUTONEG_LP (1 << 3)
341
+#define PHY_INT_PARFAULT (1 << 2)
342
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
343
+
344
+static void lan9118_phy_update_irq(Lan9118PhyState *s)
345
+{
346
+ qemu_set_irq(s->irq, !!(s->ints & s->int_mask));
347
+}
348
+
349
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
350
+{
351
+ uint16_t val;
352
+
353
+ switch (reg) {
354
+ case 0: /* Basic Control */
355
+ return s->control;
356
+ case 1: /* Basic Status */
357
+ return s->status;
358
+ case 2: /* ID1 */
359
+ return 0x0007;
360
+ case 3: /* ID2 */
361
+ return 0xc0d1;
362
+ case 4: /* Auto-neg advertisement */
363
+ return s->advertise;
364
+ case 5: /* Auto-neg Link Partner Ability */
365
+ return 0x0f71;
366
+ case 6: /* Auto-neg Expansion */
367
+ return 1;
368
+ /* TODO 17, 18, 27, 29, 30, 31 */
369
+ case 29: /* Interrupt source. */
370
+ val = s->ints;
371
+ s->ints = 0;
372
+ lan9118_phy_update_irq(s);
373
+ return val;
374
+ case 30: /* Interrupt mask */
375
+ return s->int_mask;
376
+ default:
377
+ qemu_log_mask(LOG_GUEST_ERROR,
378
+ "lan9118_phy_read: PHY read reg %d\n", reg);
379
+ return 0;
380
+ }
381
+}
382
+
383
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
384
+{
385
+ switch (reg) {
386
+ case 0: /* Basic Control */
387
+ if (val & 0x8000) {
388
+ lan9118_phy_reset(s);
389
+ break;
390
+ }
391
+ s->control = val & 0x7980;
392
+ /* Complete autonegotiation immediately. */
393
+ if (val & 0x1000) {
394
+ s->status |= 0x0020;
395
+ }
396
+ break;
397
+ case 4: /* Auto-neg advertisement */
398
+ s->advertise = (val & 0x2d7f) | 0x80;
399
+ break;
400
+ /* TODO 17, 18, 27, 31 */
401
+ case 30: /* Interrupt mask */
402
+ s->int_mask = val & 0xff;
403
+ lan9118_phy_update_irq(s);
404
+ break;
405
+ default:
406
+ qemu_log_mask(LOG_GUEST_ERROR,
407
+ "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
408
+ }
409
+}
410
+
411
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
412
+{
413
+ s->link_down = link_down;
414
+
415
+ /* Autonegotiation status mirrors link status. */
416
+ if (link_down) {
417
+ s->status &= ~0x0024;
418
+ s->ints |= PHY_INT_DOWN;
419
+ } else {
420
+ s->status |= 0x0024;
421
+ s->ints |= PHY_INT_ENERGYON;
422
+ s->ints |= PHY_INT_AUTONEG_COMPLETE;
423
+ }
424
+ lan9118_phy_update_irq(s);
425
+}
426
+
427
+void lan9118_phy_reset(Lan9118PhyState *s)
428
+{
429
+ s->control = 0x3000;
430
+ s->status = 0x7809;
431
+ s->advertise = 0x01e1;
432
+ s->int_mask = 0;
433
+ s->ints = 0;
434
+ lan9118_phy_update_link(s, s->link_down);
435
+}
436
+
437
+static void lan9118_phy_reset_hold(Object *obj, ResetType type)
438
+{
439
+ Lan9118PhyState *s = LAN9118_PHY(obj);
440
+
441
+ lan9118_phy_reset(s);
442
+}
443
+
444
+static void lan9118_phy_init(Object *obj)
445
+{
446
+ Lan9118PhyState *s = LAN9118_PHY(obj);
447
+
448
+ qdev_init_gpio_out(DEVICE(s), &s->irq, 1);
449
+}
450
+
451
+static const VMStateDescription vmstate_lan9118_phy = {
452
+ .name = "lan9118-phy",
453
+ .version_id = 1,
454
+ .minimum_version_id = 1,
455
+ .fields = (const VMStateField[]) {
456
+ VMSTATE_UINT16(control, Lan9118PhyState),
457
+ VMSTATE_UINT16(status, Lan9118PhyState),
458
+ VMSTATE_UINT16(advertise, Lan9118PhyState),
459
+ VMSTATE_UINT16(ints, Lan9118PhyState),
460
+ VMSTATE_UINT16(int_mask, Lan9118PhyState),
461
+ VMSTATE_BOOL(link_down, Lan9118PhyState),
462
+ VMSTATE_END_OF_LIST()
463
+ }
464
+};
465
+
466
+static void lan9118_phy_class_init(ObjectClass *klass, void *data)
467
+{
468
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
469
+ DeviceClass *dc = DEVICE_CLASS(klass);
470
+
471
+ rc->phases.hold = lan9118_phy_reset_hold;
472
+ dc->vmsd = &vmstate_lan9118_phy;
473
+}
474
+
475
+static const TypeInfo types[] = {
476
+ {
477
+ .name = TYPE_LAN9118_PHY,
478
+ .parent = TYPE_SYS_BUS_DEVICE,
479
+ .instance_size = sizeof(Lan9118PhyState),
480
+ .instance_init = lan9118_phy_init,
481
+ .class_init = lan9118_phy_class_init,
482
+ }
483
+};
484
+
485
+DEFINE_TYPES(types)
486
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
216
index XXXXXXX..XXXXXXX 100644
487
index XXXXXXX..XXXXXXX 100644
217
--- a/hw/arm/trace-events
488
--- a/hw/net/Kconfig
218
+++ b/hw/arm/trace-events
489
+++ b/hw/net/Kconfig
219
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%d - end=0x%d"
490
@@ -XXX,XX +XXX,XX @@ config VMXNET3_PCI
220
smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d"
491
config SMC91C111
221
smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)"
492
bool
222
smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)"
493
223
-smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" leaf=%d"
494
+config LAN9118_PHY
224
+smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d"
495
+ bool
225
smmuv3_cmdq_tlbi_nh(void) ""
496
+
226
smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d"
497
config LAN9118
227
smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d"
498
bool
228
smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
499
+ select LAN9118_PHY
229
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
500
select PTIMER
230
-smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova) "iommu mr=%s asid=%d iova=0x%"PRIx64
501
231
+smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64
502
config NE2000_ISA
232
503
diff --git a/hw/net/meson.build b/hw/net/meson.build
504
index XXXXXXX..XXXXXXX 100644
505
--- a/hw/net/meson.build
506
+++ b/hw/net/meson.build
507
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('vmxnet3.c'))
508
509
system_ss.add(when: 'CONFIG_SMC91C111', if_true: files('smc91c111.c'))
510
system_ss.add(when: 'CONFIG_LAN9118', if_true: files('lan9118.c'))
511
+system_ss.add(when: 'CONFIG_LAN9118_PHY', if_true: files('lan9118_phy.c'))
512
system_ss.add(when: 'CONFIG_NE2000_ISA', if_true: files('ne2000-isa.c'))
513
system_ss.add(when: 'CONFIG_OPENCORES_ETH', if_true: files('opencores_eth.c'))
514
system_ss.add(when: 'CONFIG_XGMAC', if_true: files('xgmac.c'))
233
--
515
--
234
2.20.1
516
2.34.1
235
236
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
The 'Cortex-A9MPCore internal peripheral' block can only be
3
imx_fec models the same PHY as lan9118_phy. The code is almost the same with
4
used with Cortex A5 and A9 cores. As we don't model the A5
4
imx_fec having more logging and tracing. Merge these improvements into
5
yet, simply check the machine cpu core is a Cortex A9. If
5
lan9118_phy and reuse in imx_fec to fix the code duplication.
6
not return an error.
7
6
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Some migration state how resides in the new device model which breaks migration
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
compatibility for the following machines:
10
Message-id: 20200709152337.15533-1-f4bug@amsat.org
9
* imx25-pdk
10
* sabrelite
11
* mcimx7d-sabre
12
* mcimx6ul-evk
13
14
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
15
Tested-by: Guenter Roeck <linux@roeck-us.net>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Message-id: 20241102125724.532843-3-shentey@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
19
---
13
hw/cpu/a9mpcore.c | 12 +++++++++++-
20
include/hw/net/imx_fec.h | 9 ++-
14
1 file changed, 11 insertions(+), 1 deletion(-)
21
hw/net/imx_fec.c | 146 ++++-----------------------------------
22
hw/net/lan9118_phy.c | 82 ++++++++++++++++------
23
hw/net/Kconfig | 1 +
24
hw/net/trace-events | 10 +--
25
5 files changed, 85 insertions(+), 163 deletions(-)
15
26
16
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
27
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
17
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/cpu/a9mpcore.c
29
--- a/include/hw/net/imx_fec.h
19
+++ b/hw/cpu/a9mpcore.c
30
+++ b/include/hw/net/imx_fec.h
20
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC)
21
#include "hw/irq.h"
32
#define TYPE_IMX_ENET "imx.enet"
22
#include "hw/qdev-properties.h"
33
23
#include "hw/core/cpu.h"
34
#include "hw/sysbus.h"
24
+#include "cpu.h"
35
+#include "hw/net/lan9118_phy.h"
25
36
+#include "hw/irq.h"
26
#define A9_GIC_NUM_PRIORITY_BITS 5
37
#include "net/net.h"
27
38
28
@@ -XXX,XX +XXX,XX @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
39
#define ENET_EIR 1
29
*wdtbusdev;
40
@@ -XXX,XX +XXX,XX @@ struct IMXFECState {
30
int i;
41
uint32_t tx_descriptor[ENET_TX_RING_NUM];
31
bool has_el3;
42
uint32_t tx_ring_num;
32
+ CPUState *cpu0;
43
33
Object *cpuobj;
44
- uint32_t phy_status;
34
45
- uint32_t phy_control;
35
+ cpu0 = qemu_get_cpu(0);
46
- uint32_t phy_advertise;
36
+ cpuobj = OBJECT(cpu0);
47
- uint32_t phy_int;
37
+ if (strcmp(object_get_typename(cpuobj), ARM_CPU_TYPE_NAME("cortex-a9"))) {
48
- uint32_t phy_int_mask;
38
+ /* We might allow Cortex-A5 once we model it */
49
+ Lan9118PhyState mii;
39
+ error_setg(errp,
50
+ IRQState mii_irq;
40
+ "Cortex-A9MPCore peripheral can only use Cortex-A9 CPU");
51
uint32_t phy_num;
52
bool phy_connected;
53
struct IMXFECState *phy_consumer;
54
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/net/imx_fec.c
57
+++ b/hw/net/imx_fec.c
58
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_eth_txdescs = {
59
60
static const VMStateDescription vmstate_imx_eth = {
61
.name = TYPE_IMX_FEC,
62
- .version_id = 2,
63
- .minimum_version_id = 2,
64
+ .version_id = 3,
65
+ .minimum_version_id = 3,
66
.fields = (const VMStateField[]) {
67
VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
68
VMSTATE_UINT32(rx_descriptor, IMXFECState),
69
VMSTATE_UINT32(tx_descriptor[0], IMXFECState),
70
- VMSTATE_UINT32(phy_status, IMXFECState),
71
- VMSTATE_UINT32(phy_control, IMXFECState),
72
- VMSTATE_UINT32(phy_advertise, IMXFECState),
73
- VMSTATE_UINT32(phy_int, IMXFECState),
74
- VMSTATE_UINT32(phy_int_mask, IMXFECState),
75
VMSTATE_END_OF_LIST()
76
},
77
.subsections = (const VMStateDescription * const []) {
78
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_eth = {
79
},
80
};
81
82
-#define PHY_INT_ENERGYON (1 << 7)
83
-#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
84
-#define PHY_INT_FAULT (1 << 5)
85
-#define PHY_INT_DOWN (1 << 4)
86
-#define PHY_INT_AUTONEG_LP (1 << 3)
87
-#define PHY_INT_PARFAULT (1 << 2)
88
-#define PHY_INT_AUTONEG_PAGE (1 << 1)
89
-
90
static void imx_eth_update(IMXFECState *s);
91
92
/*
93
@@ -XXX,XX +XXX,XX @@ static void imx_eth_update(IMXFECState *s);
94
* For now we don't handle any GPIO/interrupt line, so the OS will
95
* have to poll for the PHY status.
96
*/
97
-static void imx_phy_update_irq(IMXFECState *s)
98
+static void imx_phy_update_irq(void *opaque, int n, int level)
99
{
100
- imx_eth_update(s);
101
-}
102
-
103
-static void imx_phy_update_link(IMXFECState *s)
104
-{
105
- /* Autonegotiation status mirrors link status. */
106
- if (qemu_get_queue(s->nic)->link_down) {
107
- trace_imx_phy_update_link("down");
108
- s->phy_status &= ~0x0024;
109
- s->phy_int |= PHY_INT_DOWN;
110
- } else {
111
- trace_imx_phy_update_link("up");
112
- s->phy_status |= 0x0024;
113
- s->phy_int |= PHY_INT_ENERGYON;
114
- s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
115
- }
116
- imx_phy_update_irq(s);
117
+ imx_eth_update(opaque);
118
}
119
120
static void imx_eth_set_link(NetClientState *nc)
121
{
122
- imx_phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
123
-}
124
-
125
-static void imx_phy_reset(IMXFECState *s)
126
-{
127
- trace_imx_phy_reset();
128
-
129
- s->phy_status = 0x7809;
130
- s->phy_control = 0x3000;
131
- s->phy_advertise = 0x01e1;
132
- s->phy_int_mask = 0;
133
- s->phy_int = 0;
134
- imx_phy_update_link(s);
135
+ lan9118_phy_update_link(&IMX_FEC(qemu_get_nic_opaque(nc))->mii,
136
+ nc->link_down);
137
}
138
139
static uint32_t imx_phy_read(IMXFECState *s, int reg)
140
{
141
- uint32_t val;
142
uint32_t phy = reg / 32;
143
144
if (!s->phy_connected) {
145
@@ -XXX,XX +XXX,XX @@ static uint32_t imx_phy_read(IMXFECState *s, int reg)
146
147
reg %= 32;
148
149
- switch (reg) {
150
- case 0: /* Basic Control */
151
- val = s->phy_control;
152
- break;
153
- case 1: /* Basic Status */
154
- val = s->phy_status;
155
- break;
156
- case 2: /* ID1 */
157
- val = 0x0007;
158
- break;
159
- case 3: /* ID2 */
160
- val = 0xc0d1;
161
- break;
162
- case 4: /* Auto-neg advertisement */
163
- val = s->phy_advertise;
164
- break;
165
- case 5: /* Auto-neg Link Partner Ability */
166
- val = 0x0f71;
167
- break;
168
- case 6: /* Auto-neg Expansion */
169
- val = 1;
170
- break;
171
- case 29: /* Interrupt source. */
172
- val = s->phy_int;
173
- s->phy_int = 0;
174
- imx_phy_update_irq(s);
175
- break;
176
- case 30: /* Interrupt mask */
177
- val = s->phy_int_mask;
178
- break;
179
- case 17:
180
- case 18:
181
- case 27:
182
- case 31:
183
- qemu_log_mask(LOG_UNIMP, "[%s.phy]%s: reg %d not implemented\n",
184
- TYPE_IMX_FEC, __func__, reg);
185
- val = 0;
186
- break;
187
- default:
188
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
189
- TYPE_IMX_FEC, __func__, reg);
190
- val = 0;
191
- break;
192
- }
193
-
194
- trace_imx_phy_read(val, phy, reg);
195
-
196
- return val;
197
+ return lan9118_phy_read(&s->mii, reg);
198
}
199
200
static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
201
@@ -XXX,XX +XXX,XX @@ static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
202
203
reg %= 32;
204
205
- trace_imx_phy_write(val, phy, reg);
206
-
207
- switch (reg) {
208
- case 0: /* Basic Control */
209
- if (val & 0x8000) {
210
- imx_phy_reset(s);
211
- } else {
212
- s->phy_control = val & 0x7980;
213
- /* Complete autonegotiation immediately. */
214
- if (val & 0x1000) {
215
- s->phy_status |= 0x0020;
216
- }
217
- }
218
- break;
219
- case 4: /* Auto-neg advertisement */
220
- s->phy_advertise = (val & 0x2d7f) | 0x80;
221
- break;
222
- case 30: /* Interrupt mask */
223
- s->phy_int_mask = val & 0xff;
224
- imx_phy_update_irq(s);
225
- break;
226
- case 17:
227
- case 18:
228
- case 27:
229
- case 31:
230
- qemu_log_mask(LOG_UNIMP, "[%s.phy)%s: reg %d not implemented\n",
231
- TYPE_IMX_FEC, __func__, reg);
232
- break;
233
- default:
234
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
235
- TYPE_IMX_FEC, __func__, reg);
236
- break;
237
- }
238
+ lan9118_phy_write(&s->mii, reg, val);
239
}
240
241
static void imx_fec_read_bd(IMXFECBufDesc *bd, dma_addr_t addr)
242
@@ -XXX,XX +XXX,XX @@ static void imx_eth_reset(DeviceState *d)
243
244
s->rx_descriptor = 0;
245
memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor));
246
-
247
- /* We also reset the PHY */
248
- imx_phy_reset(s);
249
}
250
251
static uint32_t imx_default_read(IMXFECState *s, uint32_t index)
252
@@ -XXX,XX +XXX,XX @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
253
sysbus_init_irq(sbd, &s->irq[0]);
254
sysbus_init_irq(sbd, &s->irq[1]);
255
256
+ qemu_init_irq(&s->mii_irq, imx_phy_update_irq, s, 0);
257
+ object_initialize_child(OBJECT(s), "mii", &s->mii, TYPE_LAN9118_PHY);
258
+ if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->mii), errp)) {
41
+ return;
259
+ return;
42
+ }
260
+ }
43
+
261
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
44
scudev = DEVICE(&s->scu);
262
+
45
qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
263
qemu_macaddr_default_if_unset(&s->conf.macaddr);
46
if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
264
47
@@ -XXX,XX +XXX,XX @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
265
s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
48
/* Make the GIC's TZ support match the CPUs. We assume that
266
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
49
* either all the CPUs have TZ, or none do.
267
index XXXXXXX..XXXXXXX 100644
50
*/
268
--- a/hw/net/lan9118_phy.c
51
- cpuobj = OBJECT(qemu_get_cpu(0));
269
+++ b/hw/net/lan9118_phy.c
52
has_el3 = object_property_find(cpuobj, "has_el3", NULL) &&
270
@@ -XXX,XX +XXX,XX @@
53
object_property_get_bool(cpuobj, "has_el3", &error_abort);
271
* Copyright (c) 2009 CodeSourcery, LLC.
54
qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3);
272
* Written by Paul Brook
273
*
274
+ * Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
275
+ *
276
* This code is licensed under the GNU GPL v2
277
*
278
* Contributions after 2012-01-13 are licensed under the terms of the
279
@@ -XXX,XX +XXX,XX @@
280
#include "hw/resettable.h"
281
#include "migration/vmstate.h"
282
#include "qemu/log.h"
283
+#include "trace.h"
284
285
#define PHY_INT_ENERGYON (1 << 7)
286
#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
287
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
288
289
switch (reg) {
290
case 0: /* Basic Control */
291
- return s->control;
292
+ val = s->control;
293
+ break;
294
case 1: /* Basic Status */
295
- return s->status;
296
+ val = s->status;
297
+ break;
298
case 2: /* ID1 */
299
- return 0x0007;
300
+ val = 0x0007;
301
+ break;
302
case 3: /* ID2 */
303
- return 0xc0d1;
304
+ val = 0xc0d1;
305
+ break;
306
case 4: /* Auto-neg advertisement */
307
- return s->advertise;
308
+ val = s->advertise;
309
+ break;
310
case 5: /* Auto-neg Link Partner Ability */
311
- return 0x0f71;
312
+ val = 0x0f71;
313
+ break;
314
case 6: /* Auto-neg Expansion */
315
- return 1;
316
- /* TODO 17, 18, 27, 29, 30, 31 */
317
+ val = 1;
318
+ break;
319
case 29: /* Interrupt source. */
320
val = s->ints;
321
s->ints = 0;
322
lan9118_phy_update_irq(s);
323
- return val;
324
+ break;
325
case 30: /* Interrupt mask */
326
- return s->int_mask;
327
+ val = s->int_mask;
328
+ break;
329
+ case 17:
330
+ case 18:
331
+ case 27:
332
+ case 31:
333
+ qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
334
+ __func__, reg);
335
+ val = 0;
336
+ break;
337
default:
338
- qemu_log_mask(LOG_GUEST_ERROR,
339
- "lan9118_phy_read: PHY read reg %d\n", reg);
340
- return 0;
341
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
342
+ __func__, reg);
343
+ val = 0;
344
+ break;
345
}
346
+
347
+ trace_lan9118_phy_read(val, reg);
348
+
349
+ return val;
350
}
351
352
void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
353
{
354
+ trace_lan9118_phy_write(val, reg);
355
+
356
switch (reg) {
357
case 0: /* Basic Control */
358
if (val & 0x8000) {
359
lan9118_phy_reset(s);
360
- break;
361
- }
362
- s->control = val & 0x7980;
363
- /* Complete autonegotiation immediately. */
364
- if (val & 0x1000) {
365
- s->status |= 0x0020;
366
+ } else {
367
+ s->control = val & 0x7980;
368
+ /* Complete autonegotiation immediately. */
369
+ if (val & 0x1000) {
370
+ s->status |= 0x0020;
371
+ }
372
}
373
break;
374
case 4: /* Auto-neg advertisement */
375
s->advertise = (val & 0x2d7f) | 0x80;
376
break;
377
- /* TODO 17, 18, 27, 31 */
378
case 30: /* Interrupt mask */
379
s->int_mask = val & 0xff;
380
lan9118_phy_update_irq(s);
381
break;
382
+ case 17:
383
+ case 18:
384
+ case 27:
385
+ case 31:
386
+ qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
387
+ __func__, reg);
388
+ break;
389
default:
390
- qemu_log_mask(LOG_GUEST_ERROR,
391
- "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
392
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
393
+ __func__, reg);
394
+ break;
395
}
396
}
397
398
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
399
400
/* Autonegotiation status mirrors link status. */
401
if (link_down) {
402
+ trace_lan9118_phy_update_link("down");
403
s->status &= ~0x0024;
404
s->ints |= PHY_INT_DOWN;
405
} else {
406
+ trace_lan9118_phy_update_link("up");
407
s->status |= 0x0024;
408
s->ints |= PHY_INT_ENERGYON;
409
s->ints |= PHY_INT_AUTONEG_COMPLETE;
410
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
411
412
void lan9118_phy_reset(Lan9118PhyState *s)
413
{
414
+ trace_lan9118_phy_reset();
415
+
416
s->control = 0x3000;
417
s->status = 0x7809;
418
s->advertise = 0x01e1;
419
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118_phy = {
420
.version_id = 1,
421
.minimum_version_id = 1,
422
.fields = (const VMStateField[]) {
423
- VMSTATE_UINT16(control, Lan9118PhyState),
424
VMSTATE_UINT16(status, Lan9118PhyState),
425
+ VMSTATE_UINT16(control, Lan9118PhyState),
426
VMSTATE_UINT16(advertise, Lan9118PhyState),
427
VMSTATE_UINT16(ints, Lan9118PhyState),
428
VMSTATE_UINT16(int_mask, Lan9118PhyState),
429
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
430
index XXXXXXX..XXXXXXX 100644
431
--- a/hw/net/Kconfig
432
+++ b/hw/net/Kconfig
433
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_SUN8I_EMAC
434
435
config IMX_FEC
436
bool
437
+ select LAN9118_PHY
438
439
config CADENCE
440
bool
441
diff --git a/hw/net/trace-events b/hw/net/trace-events
442
index XXXXXXX..XXXXXXX 100644
443
--- a/hw/net/trace-events
444
+++ b/hw/net/trace-events
445
@@ -XXX,XX +XXX,XX @@ allwinner_sun8i_emac_set_link(bool active) "Set link: active=%u"
446
allwinner_sun8i_emac_read(uint64_t offset, uint64_t val) "MMIO read: offset=0x%" PRIx64 " value=0x%" PRIx64
447
allwinner_sun8i_emac_write(uint64_t offset, uint64_t val) "MMIO write: offset=0x%" PRIx64 " value=0x%" PRIx64
448
449
+# lan9118_phy.c
450
+lan9118_phy_read(uint16_t val, int reg) "[0x%02x] -> 0x%04" PRIx16
451
+lan9118_phy_write(uint16_t val, int reg) "[0x%02x] <- 0x%04" PRIx16
452
+lan9118_phy_update_link(const char *s) "%s"
453
+lan9118_phy_reset(void) ""
454
+
455
# lance.c
456
lance_mem_readw(uint64_t addr, uint32_t ret) "addr=0x%"PRIx64"val=0x%04x"
457
lance_mem_writew(uint64_t addr, uint32_t val) "addr=0x%"PRIx64"val=0x%04x"
458
@@ -XXX,XX +XXX,XX @@ i82596_set_multicast(uint16_t count) "Added %d multicast entries"
459
i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION"
460
461
# imx_fec.c
462
-imx_phy_read(uint32_t val, int phy, int reg) "0x%04"PRIx32" <= phy[%d].reg[%d]"
463
imx_phy_read_num(int phy, int configured) "read request from unconfigured phy %d (configured %d)"
464
-imx_phy_write(uint32_t val, int phy, int reg) "0x%04"PRIx32" => phy[%d].reg[%d]"
465
imx_phy_write_num(int phy, int configured) "write request to unconfigured phy %d (configured %d)"
466
-imx_phy_update_link(const char *s) "%s"
467
-imx_phy_reset(void) ""
468
imx_fec_read_bd(uint64_t addr, int flags, int len, int data) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x"
469
imx_enet_read_bd(uint64_t addr, int flags, int len, int data, int options, int status) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x option 0x%04x status 0x%04x"
470
imx_eth_tx_bd_busy(void) "tx_bd ran out of descriptors to transmit"
55
--
471
--
56
2.20.1
472
2.34.1
57
58
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Turns 0x70 into 0xe0 (== 0x70 << 1) which adds the missing MII_ANLPAR_TX and
4
fixes the MSB of selector field to be zero, as specified in the datasheet.
5
6
Fixes: 2a424990170b "LAN9118 emulation"
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Tested-by: Guenter Roeck <linux@roeck-us.net>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20241102125724.532843-4-shentey@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/net/lan9118_phy.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/lan9118_phy.c
19
+++ b/hw/net/lan9118_phy.c
20
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
21
val = s->advertise;
22
break;
23
case 5: /* Auto-neg Link Partner Ability */
24
- val = 0x0f71;
25
+ val = 0x0fe1;
26
break;
27
case 6: /* Auto-neg Expansion */
28
val = 1;
29
--
30
2.34.1
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Prefer named constants over magic values for better readability.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
7
Tested-by: Guenter Roeck <linux@roeck-us.net>
8
Message-id: 20241102125724.532843-5-shentey@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/net/mii.h | 6 +++++
12
hw/net/lan9118_phy.c | 63 ++++++++++++++++++++++++++++----------------
13
2 files changed, 46 insertions(+), 23 deletions(-)
14
15
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/net/mii.h
18
+++ b/include/hw/net/mii.h
19
@@ -XXX,XX +XXX,XX @@
20
#define MII_BMSR_JABBER (1 << 1) /* Jabber detected */
21
#define MII_BMSR_EXTCAP (1 << 0) /* Ext-reg capability */
22
23
+#define MII_ANAR_RFAULT (1 << 13) /* Say we can detect faults */
24
#define MII_ANAR_PAUSE_ASYM (1 << 11) /* Try for asymmetric pause */
25
#define MII_ANAR_PAUSE (1 << 10) /* Try for pause */
26
#define MII_ANAR_TXFD (1 << 8)
27
@@ -XXX,XX +XXX,XX @@
28
#define MII_ANAR_10FD (1 << 6)
29
#define MII_ANAR_10 (1 << 5)
30
#define MII_ANAR_CSMACD (1 << 0)
31
+#define MII_ANAR_SELECT (0x001f) /* Selector bits */
32
33
#define MII_ANLPAR_ACK (1 << 14)
34
#define MII_ANLPAR_PAUSEASY (1 << 11) /* can pause asymmetrically */
35
@@ -XXX,XX +XXX,XX @@
36
#define RTL8201CP_PHYID1 0x0000
37
#define RTL8201CP_PHYID2 0x8201
38
39
+/* SMSC LAN9118 */
40
+#define SMSCLAN9118_PHYID1 0x0007
41
+#define SMSCLAN9118_PHYID2 0xc0d1
42
+
43
/* RealTek 8211E */
44
#define RTL8211E_PHYID1 0x001c
45
#define RTL8211E_PHYID2 0xc915
46
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/net/lan9118_phy.c
49
+++ b/hw/net/lan9118_phy.c
50
@@ -XXX,XX +XXX,XX @@
51
52
#include "qemu/osdep.h"
53
#include "hw/net/lan9118_phy.h"
54
+#include "hw/net/mii.h"
55
#include "hw/irq.h"
56
#include "hw/resettable.h"
57
#include "migration/vmstate.h"
58
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
59
uint16_t val;
60
61
switch (reg) {
62
- case 0: /* Basic Control */
63
+ case MII_BMCR:
64
val = s->control;
65
break;
66
- case 1: /* Basic Status */
67
+ case MII_BMSR:
68
val = s->status;
69
break;
70
- case 2: /* ID1 */
71
- val = 0x0007;
72
+ case MII_PHYID1:
73
+ val = SMSCLAN9118_PHYID1;
74
break;
75
- case 3: /* ID2 */
76
- val = 0xc0d1;
77
+ case MII_PHYID2:
78
+ val = SMSCLAN9118_PHYID2;
79
break;
80
- case 4: /* Auto-neg advertisement */
81
+ case MII_ANAR:
82
val = s->advertise;
83
break;
84
- case 5: /* Auto-neg Link Partner Ability */
85
- val = 0x0fe1;
86
+ case MII_ANLPAR:
87
+ val = MII_ANLPAR_PAUSEASY | MII_ANLPAR_PAUSE | MII_ANLPAR_T4 |
88
+ MII_ANLPAR_TXFD | MII_ANLPAR_TX | MII_ANLPAR_10FD |
89
+ MII_ANLPAR_10 | MII_ANLPAR_CSMACD;
90
break;
91
- case 6: /* Auto-neg Expansion */
92
- val = 1;
93
+ case MII_ANER:
94
+ val = MII_ANER_NWAY;
95
break;
96
case 29: /* Interrupt source. */
97
val = s->ints;
98
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
99
trace_lan9118_phy_write(val, reg);
100
101
switch (reg) {
102
- case 0: /* Basic Control */
103
- if (val & 0x8000) {
104
+ case MII_BMCR:
105
+ if (val & MII_BMCR_RESET) {
106
lan9118_phy_reset(s);
107
} else {
108
- s->control = val & 0x7980;
109
+ s->control = val & (MII_BMCR_LOOPBACK | MII_BMCR_SPEED100 |
110
+ MII_BMCR_AUTOEN | MII_BMCR_PDOWN | MII_BMCR_FD |
111
+ MII_BMCR_CTST);
112
/* Complete autonegotiation immediately. */
113
- if (val & 0x1000) {
114
- s->status |= 0x0020;
115
+ if (val & MII_BMCR_AUTOEN) {
116
+ s->status |= MII_BMSR_AN_COMP;
117
}
118
}
119
break;
120
- case 4: /* Auto-neg advertisement */
121
- s->advertise = (val & 0x2d7f) | 0x80;
122
+ case MII_ANAR:
123
+ s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
124
+ MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
125
+ MII_ANAR_SELECT))
126
+ | MII_ANAR_TX;
127
break;
128
case 30: /* Interrupt mask */
129
s->int_mask = val & 0xff;
130
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
131
/* Autonegotiation status mirrors link status. */
132
if (link_down) {
133
trace_lan9118_phy_update_link("down");
134
- s->status &= ~0x0024;
135
+ s->status &= ~(MII_BMSR_AN_COMP | MII_BMSR_LINK_ST);
136
s->ints |= PHY_INT_DOWN;
137
} else {
138
trace_lan9118_phy_update_link("up");
139
- s->status |= 0x0024;
140
+ s->status |= MII_BMSR_AN_COMP | MII_BMSR_LINK_ST;
141
s->ints |= PHY_INT_ENERGYON;
142
s->ints |= PHY_INT_AUTONEG_COMPLETE;
143
}
144
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_reset(Lan9118PhyState *s)
145
{
146
trace_lan9118_phy_reset();
147
148
- s->control = 0x3000;
149
- s->status = 0x7809;
150
- s->advertise = 0x01e1;
151
+ s->control = MII_BMCR_AUTOEN | MII_BMCR_SPEED100;
152
+ s->status = MII_BMSR_100TX_FD
153
+ | MII_BMSR_100TX_HD
154
+ | MII_BMSR_10T_FD
155
+ | MII_BMSR_10T_HD
156
+ | MII_BMSR_AUTONEG
157
+ | MII_BMSR_EXTCAP;
158
+ s->advertise = MII_ANAR_TXFD
159
+ | MII_ANAR_TX
160
+ | MII_ANAR_10FD
161
+ | MII_ANAR_10
162
+ | MII_ANAR_CSMACD;
163
s->int_mask = 0;
164
s->ints = 0;
165
lan9118_phy_update_link(s, s->link_down);
166
--
167
2.34.1
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
The real device advertises this mode and the device model already advertises
4
100 mbps half duplex and 10 mbps full+half duplex. So advertise this mode to
5
make the model more realistic.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
Message-id: 20241102125724.532843-6-shentey@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/net/lan9118_phy.c | 4 ++--
14
1 file changed, 2 insertions(+), 2 deletions(-)
15
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/lan9118_phy.c
19
+++ b/hw/net/lan9118_phy.c
20
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
21
break;
22
case MII_ANAR:
23
s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
24
- MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
25
- MII_ANAR_SELECT))
26
+ MII_ANAR_PAUSE | MII_ANAR_TXFD | MII_ANAR_10FD |
27
+ MII_ANAR_10 | MII_ANAR_SELECT))
28
| MII_ANAR_TX;
29
break;
30
case 30: /* Interrupt mask */
31
--
32
2.34.1
diff view generated by jsdifflib
New patch
1
For IEEE fused multiply-add, the (0 * inf) + NaN case should raise
2
Invalid for the multiplication of 0 by infinity. Currently we handle
3
this in the per-architecture ifdef ladder in pickNaNMulAdd().
4
However, since this isn't really architecture specific we can hoist
5
it up to the generic code.
1
6
7
For the cases where the infzero test in pickNaNMulAdd was
8
returning 2, we can delete the check entirely and allow the
9
code to fall into the normal pick-a-NaN handling, because this
10
will return 2 anyway (input 'c' being the only NaN in this case).
11
For the cases where infzero was returning 3 to indicate "return
12
the default NaN", we must retain that "return 3".
13
14
For Arm, this looks like it might be a behaviour change because we
15
used to set float_flag_invalid | float_flag_invalid_imz only if C is
16
a quiet NaN. However, it is not, because Arm target code never looks
17
at float_flag_invalid_imz, and for the (0 * inf) + SNaN case we
18
already raised float_flag_invalid via the "abc_mask &
19
float_cmask_snan" check in pick_nan_muladd.
20
21
For any target architecture using the "default implementation" at the
22
bottom of the ifdef, this is a behaviour change but will be fixing a
23
bug (where we failed to raise the Invalid exception for (0 * inf +
24
QNaN). The architectures using the default case are:
25
* hppa
26
* i386
27
* sh4
28
* tricore
29
30
The x86, Tricore and SH4 CPU architecture manuals are clear that this
31
should have raised Invalid; HPPA is a bit vaguer but still seems
32
clear enough.
33
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
36
Message-id: 20241202131347.498124-2-peter.maydell@linaro.org
37
---
38
fpu/softfloat-parts.c.inc | 13 +++++++------
39
fpu/softfloat-specialize.c.inc | 29 +----------------------------
40
2 files changed, 8 insertions(+), 34 deletions(-)
41
42
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
43
index XXXXXXX..XXXXXXX 100644
44
--- a/fpu/softfloat-parts.c.inc
45
+++ b/fpu/softfloat-parts.c.inc
46
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
47
int ab_mask, int abc_mask)
48
{
49
int which;
50
+ bool infzero = (ab_mask == float_cmask_infzero);
51
52
if (unlikely(abc_mask & float_cmask_snan)) {
53
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
54
}
55
56
- which = pickNaNMulAdd(a->cls, b->cls, c->cls,
57
- ab_mask == float_cmask_infzero, s);
58
+ if (infzero) {
59
+ /* This is (0 * inf) + NaN or (inf * 0) + NaN */
60
+ float_raise(float_flag_invalid | float_flag_invalid_imz, s);
61
+ }
62
+
63
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
64
65
if (s->default_nan_mode || which == 3) {
66
- /*
67
- * Note that this check is after pickNaNMulAdd so that function
68
- * has an opportunity to set the Invalid flag for infzero.
69
- */
70
parts_default_nan(a, s);
71
return a;
72
}
73
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
74
index XXXXXXX..XXXXXXX 100644
75
--- a/fpu/softfloat-specialize.c.inc
76
+++ b/fpu/softfloat-specialize.c.inc
77
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
78
* the default NaN
79
*/
80
if (infzero && is_qnan(c_cls)) {
81
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
82
return 3;
83
}
84
85
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
86
* case sets InvalidOp and returns the default NaN
87
*/
88
if (infzero) {
89
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
90
return 3;
91
}
92
/* Prefer sNaN over qNaN, in the a, b, c order. */
93
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
94
* For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
95
* case sets InvalidOp and returns the input value 'c'
96
*/
97
- if (infzero) {
98
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
99
- return 2;
100
- }
101
/* Prefer sNaN over qNaN, in the c, a, b order. */
102
if (is_snan(c_cls)) {
103
return 2;
104
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
105
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
106
* case sets InvalidOp and returns the input value 'c'
107
*/
108
- if (infzero) {
109
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
110
- return 2;
111
- }
112
+
113
/* Prefer sNaN over qNaN, in the c, a, b order. */
114
if (is_snan(c_cls)) {
115
return 2;
116
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
117
* to return an input NaN if we have one (ie c) rather than generating
118
* a default NaN
119
*/
120
- if (infzero) {
121
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
122
- return 2;
123
- }
124
125
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
126
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
127
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
128
return 1;
129
}
130
#elif defined(TARGET_RISCV)
131
- /* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
132
- if (infzero) {
133
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
134
- }
135
return 3; /* default NaN */
136
#elif defined(TARGET_S390X)
137
if (infzero) {
138
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
139
return 3;
140
}
141
142
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
143
return 2;
144
}
145
#elif defined(TARGET_SPARC)
146
- /* For (inf,0,nan) return c. */
147
- if (infzero) {
148
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
149
- return 2;
150
- }
151
/* Prefer SNaN over QNaN, order C, B, A. */
152
if (is_snan(c_cls)) {
153
return 2;
154
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
155
* For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
156
* an input NaN if we have one (ie c).
157
*/
158
- if (infzero) {
159
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
160
- return 2;
161
- }
162
if (status->use_first_nan) {
163
if (is_nan(a_cls)) {
164
return 0;
165
--
166
2.34.1
diff view generated by jsdifflib
New patch
1
If the target sets default_nan_mode then we're always going to return
2
the default NaN, and pickNaNMulAdd() no longer has any side effects.
3
For consistency with pickNaN(), check for default_nan_mode before
4
calling pickNaNMulAdd().
1
5
6
When we convert pickNaNMulAdd() to allow runtime selection of the NaN
7
propagation rule, this means we won't have to make the targets which
8
use default_nan_mode also set a propagation rule.
9
10
Since RiscV always uses default_nan_mode, this allows us to remove
11
its ifdef case from pickNaNMulAdd().
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20241202131347.498124-3-peter.maydell@linaro.org
16
---
17
fpu/softfloat-parts.c.inc | 8 ++++++--
18
fpu/softfloat-specialize.c.inc | 9 +++++++--
19
2 files changed, 13 insertions(+), 4 deletions(-)
20
21
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
22
index XXXXXXX..XXXXXXX 100644
23
--- a/fpu/softfloat-parts.c.inc
24
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
26
float_raise(float_flag_invalid | float_flag_invalid_imz, s);
27
}
28
29
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
30
+ if (s->default_nan_mode) {
31
+ which = 3;
32
+ } else {
33
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
34
+ }
35
36
- if (s->default_nan_mode || which == 3) {
37
+ if (which == 3) {
38
parts_default_nan(a, s);
39
return a;
40
}
41
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
42
index XXXXXXX..XXXXXXX 100644
43
--- a/fpu/softfloat-specialize.c.inc
44
+++ b/fpu/softfloat-specialize.c.inc
45
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
46
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
47
bool infzero, float_status *status)
48
{
49
+ /*
50
+ * We guarantee not to require the target to tell us how to
51
+ * pick a NaN if we're always returning the default NaN.
52
+ * But if we're not in default-NaN mode then the target must
53
+ * specify.
54
+ */
55
+ assert(!status->default_nan_mode);
56
#if defined(TARGET_ARM)
57
/* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
58
* the default NaN
59
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
60
} else {
61
return 1;
62
}
63
-#elif defined(TARGET_RISCV)
64
- return 3; /* default NaN */
65
#elif defined(TARGET_S390X)
66
if (infzero) {
67
return 3;
68
--
69
2.34.1
diff view generated by jsdifflib
1
For M-profile CPUs, the architecture specifies that the NOCP
1
IEEE 758 does not define a fixed rule for what NaN to return in
2
exception when a coprocessor is not present or disabled should cover
2
the case of a fused multiply-add of inf * 0 + NaN. Different
3
the entire wide range of coprocessor-space encodings, and should take
3
architectures thus do different things:
4
precedence over UNDEF exceptions. (This is the opposite of
4
* some return the default NaN
5
A-profile, where checking for a disabled FPU has to happen last.)
5
* some return the input NaN
6
6
* Arm returns the default NaN if the input NaN is quiet,
7
Implement this with decodetree patterns that cover the specified
7
and the input NaN if it is signalling
8
ranges of the encoding space. There are a few instructions (VLLDM,
8
9
VLSTM, and in v8.1 also VSCCLRM) which are in copro-space but must
9
We want to make this logic be runtime selected rather than
10
not be NOCP'd: these must be handled also in the new m-nocp.decode so
10
hardcoded into the binary, because:
11
they take precedence.
11
* this will let us have multiple targets in one QEMU binary
12
12
* the Arm FEAT_AFP architectural feature includes letting
13
This is a minor behaviour change: for unallocated insn patterns in
13
the guest select a NaN propagation rule at runtime
14
the VFP area (cp=10,11) we will now NOCP rather than UNDEF when the
14
15
FPU is disabled.
15
In this commit we add an enum for the propagation rule, the field in
16
16
float_status, and the corresponding getters and setters. We change
17
As well as giving us the correct architectural behaviour for v8.1M
17
pickNaNMulAdd to honour this, but because all targets still leave
18
and the recommended behaviour for v8.0M, this refactoring also
18
this field at its default 0 value, the fallback logic will pick the
19
removes the old NOCP handling from the remains of the 'legacy
19
rule type with the old ifdef ladder.
20
decoder' in disas_thumb2_insn(), paving the way for cleaning that up.
20
21
21
Note that four architectures both use the muladd softfloat functions
22
Since we don't currently have a v8.1M feature bit or any v8.1M CPUs,
22
and did not have a branch of the ifdef ladder to specify their
23
the minor changes to this logic that we'll need for v8.1M are marked
23
behaviour (and so were ending up with the "default" case, probably
24
up with TODO comments.
24
wrongly): i386, HPPA, SH4 and Tricore. SH4 and Tricore both set
25
default_nan_mode, and so will never get into pickNaNMulAdd(). For
26
HPPA and i386 we retain the same behaviour as the old default-case,
27
which is to not ever return the default NaN. This might not be
28
correct but it is not a behaviour change.
25
29
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Message-id: 20200803111849.13368-6-peter.maydell@linaro.org
32
Message-id: 20241202131347.498124-4-peter.maydell@linaro.org
29
---
33
---
30
target/arm/m-nocp.decode | 42 +++++++++++++++++++++++++++
34
include/fpu/softfloat-helpers.h | 11 ++++
31
target/arm/vfp.decode | 2 --
35
include/fpu/softfloat-types.h | 23 +++++++++
32
target/arm/translate.c | 30 ++++++++++----------
36
fpu/softfloat-specialize.c.inc | 91 ++++++++++++++++++++++-----------
33
target/arm/meson.build | 1 +
37
3 files changed, 95 insertions(+), 30 deletions(-)
34
target/arm/translate-vfp.c.inc | 52 +++++++++++++++++++++++++++-------
38
35
5 files changed, 100 insertions(+), 27 deletions(-)
39
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
36
create mode 100644 target/arm/m-nocp.decode
40
index XXXXXXX..XXXXXXX 100644
37
41
--- a/include/fpu/softfloat-helpers.h
38
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
42
+++ b/include/fpu/softfloat-helpers.h
39
new file mode 100644
43
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
40
index XXXXXXX..XXXXXXX
44
status->float_2nan_prop_rule = rule;
41
--- /dev/null
45
}
42
+++ b/target/arm/m-nocp.decode
46
43
@@ -XXX,XX +XXX,XX @@
47
+static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
44
+# M-profile UserFault.NOCP exception handling
48
+ float_status *status)
45
+#
46
+# Copyright (c) 2020 Linaro, Ltd
47
+#
48
+# This library is free software; you can redistribute it and/or
49
+# modify it under the terms of the GNU Lesser General Public
50
+# License as published by the Free Software Foundation; either
51
+# version 2.1 of the License, or (at your option) any later version.
52
+#
53
+# This library is distributed in the hope that it will be useful,
54
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
55
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
56
+# Lesser General Public License for more details.
57
+#
58
+# You should have received a copy of the GNU Lesser General Public
59
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
60
+
61
+#
62
+# This file is processed by scripts/decodetree.py
63
+#
64
+# For M-profile, the architecture specifies that NOCP UsageFaults
65
+# should take precedence over UNDEF faults over the whole wide
66
+# range of coprocessor-space encodings, with the exception of
67
+# VLLDM and VLSTM. (Compare v8.1M IsCPInstruction() pseudocode and
68
+# v8M Arm ARM rule R_QLGM.) This isn't mandatory for v8.0M but we choose
69
+# to behave the same as v8.1M.
70
+# This decode is handled before any others (and in particular before
71
+# decoding FP instructions which are in the coprocessor space).
72
+# If the coprocessor is not present or disabled then we will generate
73
+# the NOCP exception; otherwise we let the insn through to the main decode.
74
+
75
+{
49
+{
76
+ # Special cases which do not take an early NOCP: VLLDM and VLSTM
50
+ status->float_infzeronan_rule = rule;
77
+ VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
78
+ # TODO: VSCCLRM (new in v8.1M) is similar:
79
+ #VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
80
+
81
+ NOCP 111- 1110 ---- ---- ---- cp:4 ---- ----
82
+ NOCP 111- 110- ---- ---- ---- cp:4 ---- ----
83
+ # TODO: From v8.1M onwards we will also want this range to NOCP
84
+ #NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- cp=10
85
+}
51
+}
86
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
52
+
53
static inline void set_flush_to_zero(bool val, float_status *status)
54
{
55
status->flush_to_zero = val;
56
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
57
return status->float_2nan_prop_rule;
58
}
59
60
+static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
61
+{
62
+ return status->float_infzeronan_rule;
63
+}
64
+
65
static inline bool get_flush_to_zero(float_status *status)
66
{
67
return status->flush_to_zero;
68
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
87
index XXXXXXX..XXXXXXX 100644
69
index XXXXXXX..XXXXXXX 100644
88
--- a/target/arm/vfp.decode
70
--- a/include/fpu/softfloat-types.h
89
+++ b/target/arm/vfp.decode
71
+++ b/include/fpu/softfloat-types.h
90
@@ -XXX,XX +XXX,XX @@ VCVT_sp_int ---- 1110 1.11 110 s:1 .... 1010 rz:1 1.0 .... \
72
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
91
vd=%vd_sp vm=%vm_sp
73
float_2nan_prop_x87,
92
VCVT_dp_int ---- 1110 1.11 110 s:1 .... 1011 rz:1 1.0 .... \
74
} Float2NaNPropRule;
93
vd=%vd_sp vm=%vm_dp
75
94
-
76
+/*
95
-VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
77
+ * Rule for result of fused multiply-add 0 * Inf + NaN.
96
diff --git a/target/arm/translate.c b/target/arm/translate.c
78
+ * This must be a NaN, but implementations differ on whether this
79
+ * is the input NaN or the default NaN.
80
+ *
81
+ * You don't need to set this if default_nan_mode is enabled.
82
+ * When not in default-NaN mode, it is an error for the target
83
+ * not to set the rule in float_status if it uses muladd, and we
84
+ * will assert if we need to handle an input NaN and no rule was
85
+ * selected.
86
+ */
87
+typedef enum __attribute__((__packed__)) {
88
+ /* No propagation rule specified */
89
+ float_infzeronan_none = 0,
90
+ /* Result is never the default NaN (so always the input NaN) */
91
+ float_infzeronan_dnan_never,
92
+ /* Result is always the default NaN */
93
+ float_infzeronan_dnan_always,
94
+ /* Result is the default NaN if the input NaN is quiet */
95
+ float_infzeronan_dnan_if_qnan,
96
+} FloatInfZeroNaNRule;
97
+
98
/*
99
* Floating Point Status. Individual architectures may maintain
100
* several versions of float_status for different functions. The
101
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
102
FloatRoundMode float_rounding_mode;
103
FloatX80RoundPrec floatx80_rounding_precision;
104
Float2NaNPropRule float_2nan_prop_rule;
105
+ FloatInfZeroNaNRule float_infzeronan_rule;
106
bool tininess_before_rounding;
107
/* should denormalised results go to zero and set the inexact flag? */
108
bool flush_to_zero;
109
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
97
index XXXXXXX..XXXXXXX 100644
110
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate.c
111
--- a/fpu/softfloat-specialize.c.inc
99
+++ b/target/arm/translate.c
112
+++ b/fpu/softfloat-specialize.c.inc
100
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
113
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
101
#define ARM_CP_RW_BIT (1 << 20)
114
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
102
115
bool infzero, float_status *status)
103
/* Include the VFP and Neon decoders */
116
{
104
+#include "decode-m-nocp.c.inc"
117
+ FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
105
#include "translate-vfp.c.inc"
118
+
106
#include "translate-neon.c.inc"
119
/*
107
120
* We guarantee not to require the target to tell us how to
108
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
121
* pick a NaN if we're always returning the default NaN.
109
ARCH(6T2);
122
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
110
}
123
* specify.
111
124
*/
112
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
125
assert(!status->default_nan_mode);
113
+ /*
126
+
114
+ * NOCP takes precedence over any UNDEF for (almost) the
127
+ if (rule == float_infzeronan_none) {
115
+ * entire wide range of coprocessor-space encodings, so check
128
+ /*
116
+ * for it first before proceeding to actually decode eg VFP
129
+ * Temporarily fall back to ifdef ladder
117
+ * insns. This decode also handles the few insns which are
130
+ */
118
+ * in copro space but do not have NOCP checks (eg VLLDM, VLSTM).
131
#if defined(TARGET_ARM)
119
+ */
132
- /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
120
+ if (disas_m_nocp(s, insn)) {
133
- * the default NaN
121
+ return;
134
- */
135
- if (infzero && is_qnan(c_cls)) {
136
- return 3;
137
+ /*
138
+ * For ARM, the (inf,zero,qnan) case returns the default NaN,
139
+ * but (inf,zero,snan) returns the input NaN.
140
+ */
141
+ rule = float_infzeronan_dnan_if_qnan;
142
+#elif defined(TARGET_MIPS)
143
+ if (snan_bit_is_one(status)) {
144
+ /*
145
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
146
+ * case sets InvalidOp and returns the default NaN
147
+ */
148
+ rule = float_infzeronan_dnan_always;
149
+ } else {
150
+ /*
151
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
152
+ * case sets InvalidOp and returns the input value 'c'
153
+ */
154
+ rule = float_infzeronan_dnan_never;
155
+ }
156
+#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
157
+ defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
158
+ defined(TARGET_I386) || defined(TARGET_LOONGARCH)
159
+ /*
160
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
161
+ * case sets InvalidOp and returns the input value 'c'
162
+ */
163
+ /*
164
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
165
+ * to return an input NaN if we have one (ie c) rather than generating
166
+ * a default NaN
167
+ */
168
+ rule = float_infzeronan_dnan_never;
169
+#elif defined(TARGET_S390X)
170
+ rule = float_infzeronan_dnan_always;
171
+#endif
172
}
173
174
+ if (infzero) {
175
+ /*
176
+ * Inf * 0 + NaN -- some implementations return the default NaN here,
177
+ * and some return the input NaN.
178
+ */
179
+ switch (rule) {
180
+ case float_infzeronan_dnan_never:
181
+ return 2;
182
+ case float_infzeronan_dnan_always:
183
+ return 3;
184
+ case float_infzeronan_dnan_if_qnan:
185
+ return is_qnan(c_cls) ? 3 : 2;
186
+ default:
187
+ g_assert_not_reached();
122
+ }
188
+ }
123
+ }
189
+ }
124
+
190
+
125
if ((insn & 0xef000000) == 0xef000000) {
191
+#if defined(TARGET_ARM)
126
/*
192
+
127
* T32 encodings 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
193
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
128
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
194
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
129
/* Coprocessor. */
195
*/
130
if (arm_dc_feature(s, ARM_FEATURE_M)) {
196
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
131
/* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
197
}
132
- if (extract32(insn, 24, 2) == 3) {
198
#elif defined(TARGET_MIPS)
133
- goto illegal_op; /* op0 = 0b11 : unallocated */
199
if (snan_bit_is_one(status)) {
134
- }
200
- /*
201
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
202
- * case sets InvalidOp and returns the default NaN
203
- */
204
- if (infzero) {
205
- return 3;
206
- }
207
/* Prefer sNaN over qNaN, in the a, b, c order. */
208
if (is_snan(a_cls)) {
209
return 0;
210
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
211
return 2;
212
}
213
} else {
214
- /*
215
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
216
- * case sets InvalidOp and returns the input value 'c'
217
- */
218
/* Prefer sNaN over qNaN, in the c, a, b order. */
219
if (is_snan(c_cls)) {
220
return 2;
221
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
222
}
223
}
224
#elif defined(TARGET_LOONGARCH64)
225
- /*
226
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
227
- * case sets InvalidOp and returns the input value 'c'
228
- */
135
-
229
-
136
- if (((insn >> 8) & 0xe) == 10 &&
230
/* Prefer sNaN over qNaN, in the c, a, b order. */
137
- dc_isar_feature(aa32_fpsp_v2, s)) {
231
if (is_snan(c_cls)) {
138
- /* FP, and the CPU supports it */
232
return 2;
139
- goto illegal_op;
233
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
140
- } else {
234
return 1;
141
- /* All other insns: NOCP */
235
}
142
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
236
#elif defined(TARGET_PPC)
143
- syn_uncategorized(),
237
- /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
144
- default_exception_el(s));
238
- * to return an input NaN if we have one (ie c) rather than generating
145
- }
239
- * a default NaN
146
- break;
240
- */
147
+ goto illegal_op;
241
-
148
}
242
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
149
if (((insn >> 24) & 3) == 3) {
243
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
150
/* Neon DP, but failed disas_neon_dp() */
244
*/
151
diff --git a/target/arm/meson.build b/target/arm/meson.build
245
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
152
index XXXXXXX..XXXXXXX 100644
246
return 1;
153
--- a/target/arm/meson.build
247
}
154
+++ b/target/arm/meson.build
248
#elif defined(TARGET_S390X)
155
@@ -XXX,XX +XXX,XX @@ gen = [
249
- if (infzero) {
156
decodetree.process('neon-ls.decode', extra_args: '--static-decode=disas_neon_ls'),
250
- return 3;
157
decodetree.process('vfp.decode', extra_args: '--static-decode=disas_vfp'),
251
- }
158
decodetree.process('vfp-uncond.decode', extra_args: '--static-decode=disas_vfp_uncond'),
252
-
159
+ decodetree.process('m-nocp.decode', extra_args: '--static-decode=disas_m_nocp'),
253
if (is_snan(a_cls)) {
160
decodetree.process('a32.decode', extra_args: '--static-decode=disas_a32'),
254
return 0;
161
decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'),
255
} else if (is_snan(b_cls)) {
162
decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'),
163
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
164
index XXXXXXX..XXXXXXX 100644
165
--- a/target/arm/translate-vfp.c.inc
166
+++ b/target/arm/translate-vfp.c.inc
167
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
168
static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
169
{
170
if (s->fp_excp_el) {
171
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
172
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized(),
173
- s->fp_excp_el);
174
- } else {
175
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
176
- syn_fp_access_trap(1, 0xe, false),
177
- s->fp_excp_el);
178
- }
179
+ /* M-profile handled this earlier, in disas_m_nocp() */
180
+ assert (!arm_dc_feature(s, ARM_FEATURE_M));
181
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
182
+ syn_fp_access_trap(1, 0xe, false),
183
+ s->fp_excp_el);
184
return false;
185
}
186
187
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
188
!arm_dc_feature(s, ARM_FEATURE_V8)) {
189
return false;
190
}
191
- /* If not secure, UNDEF. */
192
+ /*
193
+ * If not secure, UNDEF. We must emit code for this
194
+ * rather than returning false so that this takes
195
+ * precedence over the m-nocp.decode NOCP fallback.
196
+ */
197
if (!s->v8m_secure) {
198
- return false;
199
+ unallocated_encoding(s);
200
+ return true;
201
}
202
/* If no fpu, NOP. */
203
if (!dc_isar_feature(aa32_vfp, s)) {
204
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
205
s->base.is_jmp = DISAS_UPDATE_EXIT;
206
return true;
207
}
208
+
209
+static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
210
+{
211
+ /*
212
+ * Handle M-profile early check for disabled coprocessor:
213
+ * all we need to do here is emit the NOCP exception if
214
+ * the coprocessor is disabled. Otherwise we return false
215
+ * and the real VFP/etc decode will handle the insn.
216
+ */
217
+ assert(arm_dc_feature(s, ARM_FEATURE_M));
218
+
219
+ if (a->cp == 11) {
220
+ a->cp = 10;
221
+ }
222
+ /* TODO: in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
223
+
224
+ if (a->cp != 10) {
225
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
226
+ syn_uncategorized(), default_exception_el(s));
227
+ return true;
228
+ }
229
+
230
+ if (s->fp_excp_el != 0) {
231
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
232
+ syn_uncategorized(), s->fp_excp_el);
233
+ return true;
234
+ }
235
+
236
+ return false;
237
+}
238
--
256
--
239
2.20.1
257
2.34.1
240
241
diff view generated by jsdifflib
New patch
1
Explicitly set a rule in the softfloat tests for the inf-zero-nan
2
muladd special case. In meson.build we put -DTARGET_ARM in fpcflags,
3
and so we should select here the Arm rule of
4
float_infzeronan_dnan_if_qnan.
1
5
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241202131347.498124-5-peter.maydell@linaro.org
9
---
10
tests/fp/fp-bench.c | 5 +++++
11
tests/fp/fp-test.c | 5 +++++
12
2 files changed, 10 insertions(+)
13
14
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/fp/fp-bench.c
17
+++ b/tests/fp/fp-bench.c
18
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
19
{
20
bench_func_t f;
21
22
+ /*
23
+ * These implementation-defined choices for various things IEEE
24
+ * doesn't specify match those used by the Arm architecture.
25
+ */
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
28
29
f = bench_funcs[operation][precision];
30
g_assert(f);
31
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/tests/fp/fp-test.c
34
+++ b/tests/fp/fp-test.c
35
@@ -XXX,XX +XXX,XX @@ void run_test(void)
36
{
37
unsigned int i;
38
39
+ /*
40
+ * These implementation-defined choices for various things IEEE
41
+ * doesn't specify match those used by the Arm architecture.
42
+ */
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
44
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
45
46
genCases_setLevel(test_level);
47
verCases_maxErrorCount = n_max_errors;
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the Arm target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-6-peter.maydell@linaro.org
7
---
8
target/arm/cpu.c | 3 +++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 4 insertions(+), 7 deletions(-)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
17
* * tininess-before-rounding
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
21
+ * and the input NaN if it is signalling
22
*/
23
static void arm_set_default_fp_behaviours(float_status *s)
24
{
25
set_float_detect_tininess(float_tininess_before_rounding, s);
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
28
}
29
30
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
/*
37
* Temporarily fall back to ifdef ladder
38
*/
39
-#if defined(TARGET_ARM)
40
- /*
41
- * For ARM, the (inf,zero,qnan) case returns the default NaN,
42
- * but (inf,zero,snan) returns the input NaN.
43
- */
44
- rule = float_infzeronan_dnan_if_qnan;
45
-#elif defined(TARGET_MIPS)
46
+#if defined(TARGET_MIPS)
47
if (snan_bit_is_one(status)) {
48
/*
49
* For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
50
--
51
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for s390, so we
2
can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-7-peter.maydell@linaro.org
7
---
8
target/s390x/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/s390x/cpu.c
15
+++ b/target/s390x/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
17
set_float_detect_tininess(float_tininess_before_rounding,
18
&env->fpu_status);
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
20
+ set_float_infzeronan_rule(float_infzeronan_dnan_always,
21
+ &env->fpu_status);
22
/* fall through */
23
case RESET_TYPE_S390_CPU_NORMAL:
24
env->psw.mask &= ~PSW_MASK_RI;
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
* a default NaN
31
*/
32
rule = float_infzeronan_dnan_never;
33
-#elif defined(TARGET_S390X)
34
- rule = float_infzeronan_dnan_always;
35
#endif
36
}
37
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the PPC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-8-peter.maydell@linaro.org
7
---
8
target/ppc/cpu_init.c | 7 +++++++
9
fpu/softfloat-specialize.c.inc | 7 +------
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
15
+++ b/target/ppc/cpu_init.c
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
21
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
22
+ * to return an input NaN if we have one (ie c) rather than generating
23
+ * a default NaN
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
27
28
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
29
ppc_spr_t *spr = &env->spr_cb[i];
30
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
index XXXXXXX..XXXXXXX 100644
32
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
*/
36
rule = float_infzeronan_dnan_never;
37
}
38
-#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
39
+#elif defined(TARGET_SPARC) || \
40
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
41
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
42
/*
43
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
44
* case sets InvalidOp and returns the input value 'c'
45
*/
46
- /*
47
- * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
48
- * to return an input NaN if we have one (ie c) rather than generating
49
- * a default NaN
50
- */
51
rule = float_infzeronan_dnan_never;
52
#endif
53
}
54
--
55
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the MIPS target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-9-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 9 +++++++++
9
target/mips/msa.c | 4 ++++
10
fpu/softfloat-specialize.c.inc | 16 +---------------
11
3 files changed, 14 insertions(+), 15 deletions(-)
12
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_flush_mode(CPUMIPSState *env)
18
static inline void restore_snan_bit_mode(CPUMIPSState *env)
19
{
20
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
21
+ FloatInfZeroNaNRule izn_rule;
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
set_snan_bit_is_one(!nan2008, &env->active_fpu.fp_status);
28
set_default_nan_mode(!nan2008, &env->active_fpu.fp_status);
29
+ /*
30
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
31
+ * case sets InvalidOp and returns the default NaN.
32
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
33
+ * case sets InvalidOp and returns the input value 'c'.
34
+ */
35
+ izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
36
+ set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
37
}
38
39
static inline void restore_fp_status(CPUMIPSState *env)
40
diff --git a/target/mips/msa.c b/target/mips/msa.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/mips/msa.c
43
+++ b/target/mips/msa.c
44
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
45
46
/* set proper signanling bit meaning ("1" means "quiet") */
47
set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
48
+
49
+ /* Inf * 0 + NaN returns the input NaN */
50
+ set_float_infzeronan_rule(float_infzeronan_dnan_never,
51
+ &env->active_tc.msa_fp_status);
52
}
53
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
54
index XXXXXXX..XXXXXXX 100644
55
--- a/fpu/softfloat-specialize.c.inc
56
+++ b/fpu/softfloat-specialize.c.inc
57
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
58
/*
59
* Temporarily fall back to ifdef ladder
60
*/
61
-#if defined(TARGET_MIPS)
62
- if (snan_bit_is_one(status)) {
63
- /*
64
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
65
- * case sets InvalidOp and returns the default NaN
66
- */
67
- rule = float_infzeronan_dnan_always;
68
- } else {
69
- /*
70
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
71
- * case sets InvalidOp and returns the input value 'c'
72
- */
73
- rule = float_infzeronan_dnan_never;
74
- }
75
-#elif defined(TARGET_SPARC) || \
76
+#if defined(TARGET_SPARC) || \
77
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
78
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
79
/*
80
--
81
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the SPARC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-10-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 +--
10
2 files changed, 3 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
23
cpu_exec_realizefn(cs, &local_err);
24
if (local_err != NULL) {
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_SPARC) || \
34
- defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
35
+#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
36
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
37
/*
38
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the xtensa target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-11-peter.maydell@linaro.org
7
---
8
target/xtensa/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 +-
10
2 files changed, 3 insertions(+), 1 deletion(-)
11
12
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/xtensa/cpu.c
15
+++ b/target/xtensa/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
17
reset_mmu(env);
18
cs->halted = env->runstall;
19
#endif
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
set_no_signaling_nans(!dfpu, &env->fp_status);
23
xtensa_use_first_nan(env, !dfpu);
24
}
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
34
+#if defined(TARGET_HPPA) || \
35
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
36
/*
37
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the x86 target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-12-peter.maydell@linaro.org
6
---
7
target/i386/tcg/fpu_helper.c | 7 +++++++
8
fpu/softfloat-specialize.c.inc | 2 +-
9
2 files changed, 8 insertions(+), 1 deletion(-)
10
11
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/i386/tcg/fpu_helper.c
14
+++ b/target/i386/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->mmx_status);
18
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->sse_status);
19
+ /*
20
+ * Only SSE has multiply-add instructions. In the SDM Section 14.5.2
21
+ * "Fused-Multiply-ADD (FMA) Numeric Behavior" the NaN handling is
22
+ * specified -- for 0 * inf + NaN the input NaN is selected, and if
23
+ * there are multiple input NaNs they are selected in the order a, b, c.
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
26
}
27
28
static inline uint8_t save_exception_flags(CPUX86State *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
34
* Temporarily fall back to ifdef ladder
35
*/
36
#if defined(TARGET_HPPA) || \
37
- defined(TARGET_I386) || defined(TARGET_LOONGARCH)
38
+ defined(TARGET_LOONGARCH)
39
/*
40
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
41
* case sets InvalidOp and returns the input value 'c'
42
--
43
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the loongarch target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-13-peter.maydell@linaro.org
6
---
7
target/loongarch/tcg/fpu_helper.c | 5 +++++
8
fpu/softfloat-specialize.c.inc | 7 +------
9
2 files changed, 6 insertions(+), 6 deletions(-)
10
11
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/loongarch/tcg/fpu_helper.c
14
+++ b/target/loongarch/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
16
&env->fp_status);
17
set_flush_to_zero(0, &env->fp_status);
18
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
19
+ /*
20
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
21
+ * case sets InvalidOp and returns the input value 'c'
22
+ */
23
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
}
25
26
int ieee_ex_to_loongarch(int xcpt)
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
index XXXXXXX..XXXXXXX 100644
29
--- a/fpu/softfloat-specialize.c.inc
30
+++ b/fpu/softfloat-specialize.c.inc
31
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
32
/*
33
* Temporarily fall back to ifdef ladder
34
*/
35
-#if defined(TARGET_HPPA) || \
36
- defined(TARGET_LOONGARCH)
37
- /*
38
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
- * case sets InvalidOp and returns the input value 'c'
40
- */
41
+#if defined(TARGET_HPPA)
42
rule = float_infzeronan_dnan_never;
43
#endif
44
}
45
--
46
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the HPPA target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
As this is the last target to be converted to explicitly setting
5
the rule, we can remove the fallback code in pickNaNMulAdd()
6
entirely.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241202131347.498124-14-peter.maydell@linaro.org
11
---
12
target/hppa/fpu_helper.c | 2 ++
13
fpu/softfloat-specialize.c.inc | 13 +------------
14
2 files changed, 3 insertions(+), 12 deletions(-)
15
16
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/hppa/fpu_helper.c
19
+++ b/target/hppa/fpu_helper.c
20
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
21
* HPPA does note implement a CPU reset method at all...
22
*/
23
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
24
+ /* For inf * 0 + NaN, return the input NaN */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
}
27
28
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
34
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
bool infzero, float_status *status)
36
{
37
- FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
38
-
39
/*
40
* We guarantee not to require the target to tell us how to
41
* pick a NaN if we're always returning the default NaN.
42
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
43
*/
44
assert(!status->default_nan_mode);
45
46
- if (rule == float_infzeronan_none) {
47
- /*
48
- * Temporarily fall back to ifdef ladder
49
- */
50
-#if defined(TARGET_HPPA)
51
- rule = float_infzeronan_dnan_never;
52
-#endif
53
- }
54
-
55
if (infzero) {
56
/*
57
* Inf * 0 + NaN -- some implementations return the default NaN here,
58
* and some return the input NaN.
59
*/
60
- switch (rule) {
61
+ switch (status->float_infzeronan_rule) {
62
case float_infzeronan_dnan_never:
63
return 2;
64
case float_infzeronan_dnan_always:
65
--
66
2.34.1
diff view generated by jsdifflib
1
When we implemented the VCMLA and VCADD insns we put in the
1
The new implementation of pickNaNMulAdd() will find it convenient
2
code to handle fp16, but left it using the standard fp status
2
to know whether at least one of the three arguments to the muladd
3
flags. Correct them to use FPST_STD_F16 for fp16 operations.
3
was a signaling NaN. We already calculate that in the caller,
4
so pass it in as a new bool have_snan.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 20241202131347.498124-15-peter.maydell@linaro.org
8
Message-id: 20200806104453.30393-5-peter.maydell@linaro.org
9
---
9
---
10
target/arm/translate-neon.c.inc | 6 +++---
10
fpu/softfloat-parts.c.inc | 5 +++--
11
1 file changed, 3 insertions(+), 3 deletions(-)
11
fpu/softfloat-specialize.c.inc | 2 +-
12
2 files changed, 4 insertions(+), 3 deletions(-)
12
13
13
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-neon.c.inc
16
--- a/fpu/softfloat-parts.c.inc
16
+++ b/target/arm/translate-neon.c.inc
17
+++ b/fpu/softfloat-parts.c.inc
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
{
20
int which;
21
bool infzero = (ab_mask == float_cmask_infzero);
22
+ bool have_snan = (abc_mask & float_cmask_snan);
23
24
- if (unlikely(abc_mask & float_cmask_snan)) {
25
+ if (unlikely(have_snan)) {
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
18
}
27
}
19
28
20
opr_sz = (1 + a->q) * 8;
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
21
- fpst = fpstatus_ptr(FPST_STD);
30
if (s->default_nan_mode) {
22
+ fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
31
which = 3;
23
fn_gvec_ptr = a->size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
32
} else {
24
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
33
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
25
vfp_reg_offset(1, a->vn),
34
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
27
}
35
}
28
36
29
opr_sz = (1 + a->q) * 8;
37
if (which == 3) {
30
- fpst = fpstatus_ptr(FPST_STD);
38
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
+ fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
39
index XXXXXXX..XXXXXXX 100644
32
fn_gvec_ptr = a->size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
40
--- a/fpu/softfloat-specialize.c.inc
33
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
41
+++ b/fpu/softfloat-specialize.c.inc
34
vfp_reg_offset(1, a->vn),
42
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
35
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
43
| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
36
fn_gvec_ptr = (a->size ? gen_helper_gvec_fcmlas_idx
44
*----------------------------------------------------------------------------*/
37
: gen_helper_gvec_fcmlah_idx);
45
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
38
opr_sz = (1 + a->q) * 8;
46
- bool infzero, float_status *status)
39
- fpst = fpstatus_ptr(FPST_STD);
47
+ bool infzero, bool have_snan, float_status *status)
40
+ fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
48
{
41
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
49
/*
42
vfp_reg_offset(1, a->vn),
50
* We guarantee not to require the target to tell us how to
43
vfp_reg_offset(1, a->vm),
44
--
51
--
45
2.20.1
52
2.34.1
46
47
diff view generated by jsdifflib
1
As a prelude to making coproc insns use decodetree, split out the
1
IEEE 758 does not define a fixed rule for which NaN to pick as the
2
part of disas_coproc_insn() which does instruction decoding from the
2
result if both operands of a 3-operand fused multiply-add operation
3
part which does the actual work, and make do_coproc_insn() handle the
3
are NaNs. As a result different architectures have ended up with
4
UNDEF-on-bad-permissions and similar cases itself rather than
4
different rules for propagating NaNs.
5
returning 1 to eventually percolate up to a callsite that calls
5
6
unallocated_encoding() for it.
6
QEMU currently hardcodes the NaN propagation logic into the binary
7
because pickNaNMulAdd() has an ifdef ladder for different targets.
8
We want to make the propagation rule instead be selectable at
9
runtime, because:
10
* this will let us have multiple targets in one QEMU binary
11
* the Arm FEAT_AFP architectural feature includes letting
12
the guest select a NaN propagation rule at runtime
13
14
In this commit we add an enum for the propagation rule, the field in
15
float_status, and the corresponding getters and setters. We change
16
pickNaNMulAdd to honour this, but because all targets still leave
17
this field at its default 0 value, the fallback logic will pick the
18
rule type with the old ifdef ladder.
19
20
It's valid not to set a propagation rule if default_nan_mode is
21
enabled, because in that case there's no need to pick a NaN; all the
22
callers of pickNaNMulAdd() catch this case and skip calling it.
7
23
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200803111849.13368-3-peter.maydell@linaro.org
26
Message-id: 20241202131347.498124-16-peter.maydell@linaro.org
11
---
27
---
12
target/arm/translate.c | 76 ++++++++++++++++++++++++------------------
28
include/fpu/softfloat-helpers.h | 11 +++
13
1 file changed, 44 insertions(+), 32 deletions(-)
29
include/fpu/softfloat-types.h | 55 +++++++++++
14
30
fpu/softfloat-specialize.c.inc | 167 ++++++++------------------------
15
diff --git a/target/arm/translate.c b/target/arm/translate.c
31
3 files changed, 107 insertions(+), 126 deletions(-)
32
33
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
16
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.c
35
--- a/include/fpu/softfloat-helpers.h
18
+++ b/target/arm/translate.c
36
+++ b/include/fpu/softfloat-helpers.h
19
@@ -XXX,XX +XXX,XX @@ void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
37
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
20
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
38
status->float_2nan_prop_rule = rule;
21
}
39
}
22
40
23
-static int disas_coproc_insn(DisasContext *s, uint32_t insn)
41
+static inline void set_float_3nan_prop_rule(Float3NaNPropRule rule,
24
+static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
42
+ float_status *status)
25
+ int opc1, int crn, int crm, int opc2,
43
+{
26
+ bool isread, int rt, int rt2)
44
+ status->float_3nan_prop_rule = rule;
45
+}
46
+
47
static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
float_status *status)
27
{
49
{
28
- int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
50
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
29
const ARMCPRegInfo *ri;
51
return status->float_2nan_prop_rule;
30
52
}
31
- cpnum = (insn >> 8) & 0xf;
53
54
+static inline Float3NaNPropRule get_float_3nan_prop_rule(float_status *status)
55
+{
56
+ return status->float_3nan_prop_rule;
57
+}
58
+
59
static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
60
{
61
return status->float_infzeronan_rule;
62
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
63
index XXXXXXX..XXXXXXX 100644
64
--- a/include/fpu/softfloat-types.h
65
+++ b/include/fpu/softfloat-types.h
66
@@ -XXX,XX +XXX,XX @@ this code that are retained.
67
#ifndef SOFTFLOAT_TYPES_H
68
#define SOFTFLOAT_TYPES_H
69
70
+#include "hw/registerfields.h"
71
+
72
/*
73
* Software IEC/IEEE floating-point types.
74
*/
75
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
76
float_2nan_prop_x87,
77
} Float2NaNPropRule;
78
79
+/*
80
+ * 3-input NaN propagation rule, for fused multiply-add. Individual
81
+ * architectures have different rules for which input NaN is
82
+ * propagated to the output when there is more than one NaN on the
83
+ * input.
84
+ *
85
+ * If default_nan_mode is enabled then it is valid not to set a NaN
86
+ * propagation rule, because the softfloat code guarantees not to try
87
+ * to pick a NaN to propagate in default NaN mode. When not in
88
+ * default-NaN mode, it is an error for the target not to set the rule
89
+ * in float_status if it uses a muladd, and we will assert if we need
90
+ * to handle an input NaN and no rule was selected.
91
+ *
92
+ * The naming scheme for Float3NaNPropRule values is:
93
+ * float_3nan_prop_s_abc:
94
+ * = "Prefer SNaN over QNaN, then operand A over B over C"
95
+ * float_3nan_prop_abc:
96
+ * = "Prefer A over B over C regardless of SNaN vs QNAN"
97
+ *
98
+ * For QEMU, the multiply-add operation is A * B + C.
99
+ */
100
+
101
+/*
102
+ * We set the Float3NaNPropRule enum values up so we can select the
103
+ * right value in pickNaNMulAdd in a data driven way.
104
+ */
105
+FIELD(3NAN, 1ST, 0, 2) /* which operand is most preferred ? */
106
+FIELD(3NAN, 2ND, 2, 2) /* which operand is next most preferred ? */
107
+FIELD(3NAN, 3RD, 4, 2) /* which operand is least preferred ? */
108
+FIELD(3NAN, SNAN, 6, 1) /* do we prefer SNaN over QNaN ? */
109
+
110
+#define PROPRULE(X, Y, Z) \
111
+ ((X << R_3NAN_1ST_SHIFT) | (Y << R_3NAN_2ND_SHIFT) | (Z << R_3NAN_3RD_SHIFT))
112
+
113
+typedef enum __attribute__((__packed__)) {
114
+ float_3nan_prop_none = 0, /* No propagation rule specified */
115
+ float_3nan_prop_abc = PROPRULE(0, 1, 2),
116
+ float_3nan_prop_acb = PROPRULE(0, 2, 1),
117
+ float_3nan_prop_bac = PROPRULE(1, 0, 2),
118
+ float_3nan_prop_bca = PROPRULE(1, 2, 0),
119
+ float_3nan_prop_cab = PROPRULE(2, 0, 1),
120
+ float_3nan_prop_cba = PROPRULE(2, 1, 0),
121
+ float_3nan_prop_s_abc = float_3nan_prop_abc | R_3NAN_SNAN_MASK,
122
+ float_3nan_prop_s_acb = float_3nan_prop_acb | R_3NAN_SNAN_MASK,
123
+ float_3nan_prop_s_bac = float_3nan_prop_bac | R_3NAN_SNAN_MASK,
124
+ float_3nan_prop_s_bca = float_3nan_prop_bca | R_3NAN_SNAN_MASK,
125
+ float_3nan_prop_s_cab = float_3nan_prop_cab | R_3NAN_SNAN_MASK,
126
+ float_3nan_prop_s_cba = float_3nan_prop_cba | R_3NAN_SNAN_MASK,
127
+} Float3NaNPropRule;
128
+
129
+#undef PROPRULE
130
+
131
/*
132
* Rule for result of fused multiply-add 0 * Inf + NaN.
133
* This must be a NaN, but implementations differ on whether this
134
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
135
FloatRoundMode float_rounding_mode;
136
FloatX80RoundPrec floatx80_rounding_precision;
137
Float2NaNPropRule float_2nan_prop_rule;
138
+ Float3NaNPropRule float_3nan_prop_rule;
139
FloatInfZeroNaNRule float_infzeronan_rule;
140
bool tininess_before_rounding;
141
/* should denormalised results go to zero and set the inexact flag? */
142
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
143
index XXXXXXX..XXXXXXX 100644
144
--- a/fpu/softfloat-specialize.c.inc
145
+++ b/fpu/softfloat-specialize.c.inc
146
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
147
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
148
bool infzero, bool have_snan, float_status *status)
149
{
150
+ FloatClass cls[3] = { a_cls, b_cls, c_cls };
151
+ Float3NaNPropRule rule = status->float_3nan_prop_rule;
152
+ int which;
153
+
154
/*
155
* We guarantee not to require the target to tell us how to
156
* pick a NaN if we're always returning the default NaN.
157
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
158
}
159
}
160
161
+ if (rule == float_3nan_prop_none) {
162
#if defined(TARGET_ARM)
32
-
163
-
33
- is64 = (insn & (1 << 25)) == 0;
164
- /* This looks different from the ARM ARM pseudocode, because the ARM ARM
34
- if (!is64 && ((insn & (1 << 4)) == 0)) {
165
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
35
- /* cdp */
166
- */
36
- return 1;
167
- if (is_snan(c_cls)) {
37
- }
168
- return 2;
38
-
169
- } else if (is_snan(a_cls)) {
39
- crm = insn & 0xf;
170
- return 0;
40
- if (is64) {
171
- } else if (is_snan(b_cls)) {
41
- crn = 0;
172
- return 1;
42
- opc1 = (insn >> 4) & 0xf;
173
- } else if (is_qnan(c_cls)) {
43
- opc2 = 0;
174
- return 2;
44
- rt2 = (insn >> 16) & 0xf;
175
- } else if (is_qnan(a_cls)) {
45
- } else {
176
- return 0;
46
- crn = (insn >> 16) & 0xf;
177
- } else {
47
- opc1 = (insn >> 21) & 7;
178
- return 1;
48
- opc2 = (insn >> 5) & 7;
179
- }
49
- rt2 = 0;
180
+ /*
50
- }
181
+ * This looks different from the ARM ARM pseudocode, because the ARM ARM
51
- isread = (insn >> 20) & 1;
182
+ * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
52
- rt = (insn >> 12) & 0xf;
183
+ */
53
-
184
+ rule = float_3nan_prop_s_cab;
54
ri = get_arm_cp_reginfo(s->cp_regs,
185
#elif defined(TARGET_MIPS)
55
ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
186
- if (snan_bit_is_one(status)) {
56
if (ri) {
187
- /* Prefer sNaN over qNaN, in the a, b, c order. */
57
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
188
- if (is_snan(a_cls)) {
58
189
- return 0;
59
/* Check access permissions */
190
- } else if (is_snan(b_cls)) {
60
if (!cp_access_ok(s->current_el, ri, isread)) {
191
- return 1;
61
- return 1;
192
- } else if (is_snan(c_cls)) {
62
+ unallocated_encoding(s);
193
- return 2;
63
+ return;
194
- } else if (is_qnan(a_cls)) {
195
- return 0;
196
- } else if (is_qnan(b_cls)) {
197
- return 1;
198
+ if (snan_bit_is_one(status)) {
199
+ rule = float_3nan_prop_s_abc;
200
} else {
201
- return 2;
202
+ rule = float_3nan_prop_s_cab;
64
}
203
}
65
204
- } else {
66
if (s->hstr_active || ri->accessfn ||
205
- /* Prefer sNaN over qNaN, in the c, a, b order. */
67
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
206
- if (is_snan(c_cls)) {
68
/* Handle special cases first */
207
- return 2;
69
switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
208
- } else if (is_snan(a_cls)) {
70
case ARM_CP_NOP:
209
- return 0;
71
- return 0;
210
- } else if (is_snan(b_cls)) {
72
+ return;
211
- return 1;
73
case ARM_CP_WFI:
212
- } else if (is_qnan(c_cls)) {
74
if (isread) {
213
- return 2;
75
- return 1;
214
- } else if (is_qnan(a_cls)) {
76
+ unallocated_encoding(s);
215
- return 0;
77
+ return;
216
- } else {
78
}
217
- return 1;
79
gen_set_pc_im(s, s->base.pc_next);
218
- }
80
s->base.is_jmp = DISAS_WFI;
219
- }
81
- return 0;
220
#elif defined(TARGET_LOONGARCH64)
82
+ return;
221
- /* Prefer sNaN over qNaN, in the c, a, b order. */
83
default:
222
- if (is_snan(c_cls)) {
84
break;
223
- return 2;
224
- } else if (is_snan(a_cls)) {
225
- return 0;
226
- } else if (is_snan(b_cls)) {
227
- return 1;
228
- } else if (is_qnan(c_cls)) {
229
- return 2;
230
- } else if (is_qnan(a_cls)) {
231
- return 0;
232
- } else {
233
- return 1;
234
- }
235
+ rule = float_3nan_prop_s_cab;
236
#elif defined(TARGET_PPC)
237
- /* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
238
- * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
239
- */
240
- if (is_nan(a_cls)) {
241
- return 0;
242
- } else if (is_nan(c_cls)) {
243
- return 2;
244
- } else {
245
- return 1;
246
- }
247
+ /*
248
+ * If fRA is a NaN return it; otherwise if fRB is a NaN return it;
249
+ * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
250
+ */
251
+ rule = float_3nan_prop_acb;
252
#elif defined(TARGET_S390X)
253
- if (is_snan(a_cls)) {
254
- return 0;
255
- } else if (is_snan(b_cls)) {
256
- return 1;
257
- } else if (is_snan(c_cls)) {
258
- return 2;
259
- } else if (is_qnan(a_cls)) {
260
- return 0;
261
- } else if (is_qnan(b_cls)) {
262
- return 1;
263
- } else {
264
- return 2;
265
- }
266
+ rule = float_3nan_prop_s_abc;
267
#elif defined(TARGET_SPARC)
268
- /* Prefer SNaN over QNaN, order C, B, A. */
269
- if (is_snan(c_cls)) {
270
- return 2;
271
- } else if (is_snan(b_cls)) {
272
- return 1;
273
- } else if (is_snan(a_cls)) {
274
- return 0;
275
- } else if (is_qnan(c_cls)) {
276
- return 2;
277
- } else if (is_qnan(b_cls)) {
278
- return 1;
279
- } else {
280
- return 0;
281
- }
282
+ rule = float_3nan_prop_s_cba;
283
#elif defined(TARGET_XTENSA)
284
- /*
285
- * For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
286
- * an input NaN if we have one (ie c).
287
- */
288
- if (status->use_first_nan) {
289
- if (is_nan(a_cls)) {
290
- return 0;
291
- } else if (is_nan(b_cls)) {
292
- return 1;
293
+ if (status->use_first_nan) {
294
+ rule = float_3nan_prop_abc;
295
} else {
296
- return 2;
297
+ rule = float_3nan_prop_cba;
85
}
298
}
86
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
299
- } else {
87
/* Write */
300
- if (is_nan(c_cls)) {
88
if (ri->type & ARM_CP_CONST) {
301
- return 2;
89
/* If not forbidden by access permissions, treat as WI */
302
- } else if (is_nan(b_cls)) {
90
- return 0;
303
- return 1;
91
+ return;
304
- } else {
92
}
305
- return 0;
93
306
- }
94
if (is64) {
307
- }
95
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
308
#else
96
gen_lookup_tb(s);
309
- /* A default implementation: prefer a to b to c.
97
}
310
- * This is unlikely to actually match any real implementation.
98
311
- */
99
- return 0;
312
- if (is_nan(a_cls)) {
100
+ return;
313
- return 0;
101
}
314
- } else if (is_nan(b_cls)) {
102
315
- return 1;
103
/* Unknown register; this might be a guest error or a QEMU
316
- } else {
104
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
317
- return 2;
105
s->ns ? "non-secure" : "secure");
318
- }
106
}
319
+ rule = float_3nan_prop_abc;
107
320
#endif
108
- return 1;
109
+ unallocated_encoding(s);
110
+ return;
111
+}
112
+
113
+static int disas_coproc_insn(DisasContext *s, uint32_t insn)
114
+{
115
+ int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
116
+
117
+ cpnum = (insn >> 8) & 0xf;
118
+
119
+ is64 = (insn & (1 << 25)) == 0;
120
+ if (!is64 && ((insn & (1 << 4)) == 0)) {
121
+ /* cdp */
122
+ return 1;
123
+ }
321
+ }
124
+
322
+
125
+ crm = insn & 0xf;
323
+ assert(rule != float_3nan_prop_none);
126
+ if (is64) {
324
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
127
+ crn = 0;
325
+ /* We have at least one SNaN input and should prefer it */
128
+ opc1 = (insn >> 4) & 0xf;
326
+ do {
129
+ opc2 = 0;
327
+ which = rule & R_3NAN_1ST_MASK;
130
+ rt2 = (insn >> 16) & 0xf;
328
+ rule >>= R_3NAN_1ST_LENGTH;
329
+ } while (!is_snan(cls[which]));
131
+ } else {
330
+ } else {
132
+ crn = (insn >> 16) & 0xf;
331
+ do {
133
+ opc1 = (insn >> 21) & 7;
332
+ which = rule & R_3NAN_1ST_MASK;
134
+ opc2 = (insn >> 5) & 7;
333
+ rule >>= R_3NAN_1ST_LENGTH;
135
+ rt2 = 0;
334
+ } while (!is_nan(cls[which]));
136
+ }
335
+ }
137
+ isread = (insn >> 20) & 1;
336
+ return which;
138
+ rt = (insn >> 12) & 0xf;
139
+
140
+ do_coproc_insn(s, cpnum, is64, opc1, crn, crm, opc2, isread, rt, rt2);
141
+ return 0;
142
}
337
}
143
338
144
/* Decode XScale DSP or iWMMXt insn (in the copro space, cp=0 or 1) */
339
/*----------------------------------------------------------------------------
145
--
340
--
146
2.20.1
341
2.34.1
147
148
diff view generated by jsdifflib
New patch
1
Explicitly set a rule in the softfloat tests for propagating NaNs in
2
the muladd case. In meson.build we put -DTARGET_ARM in fpcflags, and
3
so we should select here the Arm rule of float_3nan_prop_s_cab.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241202131347.498124-17-peter.maydell@linaro.org
8
---
9
tests/fp/fp-bench.c | 1 +
10
tests/fp/fp-test.c | 1 +
11
2 files changed, 2 insertions(+)
12
13
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/fp/fp-bench.c
16
+++ b/tests/fp/fp-bench.c
17
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
18
* doesn't specify match those used by the Arm architecture.
19
*/
20
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
21
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &soft_status);
22
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
23
24
f = bench_funcs[operation][precision];
25
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/tests/fp/fp-test.c
28
+++ b/tests/fp/fp-test.c
29
@@ -XXX,XX +XXX,XX @@ void run_test(void)
30
* doesn't specify match those used by the Arm architecture.
31
*/
32
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
33
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &qsf);
34
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
35
36
genCases_setLevel(test_level);
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-18-peter.maydell@linaro.org
7
---
8
target/arm/cpu.c | 5 +++++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 6 insertions(+), 7 deletions(-)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
17
* * tininess-before-rounding
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
21
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
22
+ * but note that for QEMU muladd is a * b + c, whereas for
23
+ * the pseudocode function the arguments are in the order c, a, b.
24
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
25
* and the input NaN if it is signalling
26
*/
27
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
28
{
29
set_float_detect_tininess(float_tininess_before_rounding, s);
30
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
31
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
32
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
33
}
34
35
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
36
index XXXXXXX..XXXXXXX 100644
37
--- a/fpu/softfloat-specialize.c.inc
38
+++ b/fpu/softfloat-specialize.c.inc
39
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
40
}
41
42
if (rule == float_3nan_prop_none) {
43
-#if defined(TARGET_ARM)
44
- /*
45
- * This looks different from the ARM ARM pseudocode, because the ARM ARM
46
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
47
- */
48
- rule = float_3nan_prop_s_cab;
49
-#elif defined(TARGET_MIPS)
50
+#if defined(TARGET_MIPS)
51
if (snan_bit_is_one(status)) {
52
rule = float_3nan_prop_s_abc;
53
} else {
54
--
55
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for loongarch, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-19-peter.maydell@linaro.org
7
---
8
target/loongarch/tcg/fpu_helper.c | 1 +
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 1 insertion(+), 2 deletions(-)
11
12
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/loongarch/tcg/fpu_helper.c
15
+++ b/target/loongarch/tcg/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
17
* case sets InvalidOp and returns the input value 'c'
18
*/
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
21
}
22
23
int ieee_ex_to_loongarch(int xcpt)
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
29
} else {
30
rule = float_3nan_prop_s_cab;
31
}
32
-#elif defined(TARGET_LOONGARCH64)
33
- rule = float_3nan_prop_s_cab;
34
#elif defined(TARGET_PPC)
35
/*
36
* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for PPC, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-20-peter.maydell@linaro.org
7
---
8
target/ppc/cpu_init.c | 8 ++++++++
9
fpu/softfloat-specialize.c.inc | 6 ------
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
15
+++ b/target/ppc/cpu_init.c
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
21
+ * NaN propagation for fused multiply-add:
22
+ * if fRA is a NaN return it; otherwise if fRB is a NaN return it;
23
+ * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
24
+ * whereas QEMU labels the operands as (a * b) + c.
25
+ */
26
+ set_float_3nan_prop_rule(float_3nan_prop_acb, &env->fp_status);
27
+ set_float_3nan_prop_rule(float_3nan_prop_acb, &env->vec_status);
28
/*
29
* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
30
* to return an input NaN if we have one (ie c) rather than generating
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
} else {
37
rule = float_3nan_prop_s_cab;
38
}
39
-#elif defined(TARGET_PPC)
40
- /*
41
- * If fRA is a NaN return it; otherwise if fRB is a NaN return it;
42
- * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
43
- */
44
- rule = float_3nan_prop_acb;
45
#elif defined(TARGET_S390X)
46
rule = float_3nan_prop_s_abc;
47
#elif defined(TARGET_SPARC)
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for s390x, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-21-peter.maydell@linaro.org
7
---
8
target/s390x/cpu.c | 1 +
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 1 insertion(+), 2 deletions(-)
11
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/s390x/cpu.c
15
+++ b/target/s390x/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
17
set_float_detect_tininess(float_tininess_before_rounding,
18
&env->fpu_status);
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
20
+ set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
21
set_float_infzeronan_rule(float_infzeronan_dnan_always,
22
&env->fpu_status);
23
/* fall through */
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
29
} else {
30
rule = float_3nan_prop_s_cab;
31
}
32
-#elif defined(TARGET_S390X)
33
- rule = float_3nan_prop_s_abc;
34
#elif defined(TARGET_SPARC)
35
rule = float_3nan_prop_s_cba;
36
#elif defined(TARGET_XTENSA)
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for SPARC, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-22-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For fused-multiply add, prefer SNaN over QNaN, then C->B->A */
21
+ set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
22
/* For inf * 0 + NaN, return the input NaN */
23
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
} else {
31
rule = float_3nan_prop_s_cab;
32
}
33
-#elif defined(TARGET_SPARC)
34
- rule = float_3nan_prop_s_cba;
35
#elif defined(TARGET_XTENSA)
36
if (status->use_first_nan) {
37
rule = float_3nan_prop_abc;
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-23-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 4 ++++
9
target/mips/msa.c | 3 +++
10
fpu/softfloat-specialize.c.inc | 8 +-------
11
3 files changed, 8 insertions(+), 7 deletions(-)
12
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
18
{
19
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
20
FloatInfZeroNaNRule izn_rule;
21
+ Float3NaNPropRule nan3_rule;
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
28
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
29
+ nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
30
+ set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
31
+
32
}
33
34
static inline void restore_fp_status(CPUMIPSState *env)
35
diff --git a/target/mips/msa.c b/target/mips/msa.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/mips/msa.c
38
+++ b/target/mips/msa.c
39
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
40
set_float_2nan_prop_rule(float_2nan_prop_s_ab,
41
&env->active_tc.msa_fp_status);
42
43
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab,
44
+ &env->active_tc.msa_fp_status);
45
+
46
/* clear float_status exception flags */
47
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
48
49
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
50
index XXXXXXX..XXXXXXX 100644
51
--- a/fpu/softfloat-specialize.c.inc
52
+++ b/fpu/softfloat-specialize.c.inc
53
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
54
}
55
56
if (rule == float_3nan_prop_none) {
57
-#if defined(TARGET_MIPS)
58
- if (snan_bit_is_one(status)) {
59
- rule = float_3nan_prop_s_abc;
60
- } else {
61
- rule = float_3nan_prop_s_cab;
62
- }
63
-#elif defined(TARGET_XTENSA)
64
+#if defined(TARGET_XTENSA)
65
if (status->use_first_nan) {
66
rule = float_3nan_prop_abc;
67
} else {
68
--
69
2.34.1
diff view generated by jsdifflib
1
Make A32/T32 code use the new fpstatus_ptr() API:
1
Set the Float3NaNPropRule explicitly for xtensa, and remove the
2
get_fpstatus_ptr(0) -> fpstatus_ptr(FPST_FPCR)
2
ifdef from pickNaNMulAdd().
3
get_fpstatus_ptr(1) -> fpstatus_ptr(FPST_STD)
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
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 20241202131347.498124-24-peter.maydell@linaro.org
8
Message-id: 20200806104453.30393-3-peter.maydell@linaro.org
9
---
7
---
10
target/arm/translate.c | 13 ----------
8
target/xtensa/fpu_helper.c | 2 ++
11
target/arm/translate-neon.c.inc | 28 ++++++++++-----------
9
fpu/softfloat-specialize.c.inc | 8 --------
12
target/arm/translate-vfp.c.inc | 44 ++++++++++++++++-----------------
10
2 files changed, 2 insertions(+), 8 deletions(-)
13
3 files changed, 36 insertions(+), 49 deletions(-)
14
11
15
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.c
14
--- a/target/xtensa/fpu_helper.c
18
+++ b/target/arm/translate.c
15
+++ b/target/xtensa/fpu_helper.c
19
@@ -XXX,XX +XXX,XX @@ static inline void gen_hlt(DisasContext *s, int imm)
16
@@ -XXX,XX +XXX,XX @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
20
unallocated_encoding(s);
17
set_use_first_nan(use_first, &env->fp_status);
18
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
19
&env->fp_status);
20
+ set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
21
+ &env->fp_status);
21
}
22
}
22
23
23
-static TCGv_ptr get_fpstatus_ptr(int neon)
24
void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
24
-{
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
- TCGv_ptr statusptr = tcg_temp_new_ptr();
26
- int offset;
27
- if (neon) {
28
- offset = offsetof(CPUARMState, vfp.standard_fp_status);
29
- } else {
30
- offset = offsetof(CPUARMState, vfp.fp_status);
31
- }
32
- tcg_gen_addi_ptr(statusptr, cpu_env, offset);
33
- return statusptr;
34
-}
35
-
36
static inline long vfp_reg_offset(bool dp, unsigned reg)
37
{
38
if (dp) {
39
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
40
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/translate-neon.c.inc
27
--- a/fpu/softfloat-specialize.c.inc
42
+++ b/target/arm/translate-neon.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
43
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
44
}
30
}
45
31
46
opr_sz = (1 + a->q) * 8;
32
if (rule == float_3nan_prop_none) {
47
- fpst = get_fpstatus_ptr(1);
33
-#if defined(TARGET_XTENSA)
48
+ fpst = fpstatus_ptr(FPST_STD);
34
- if (status->use_first_nan) {
49
fn_gvec_ptr = a->size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
35
- rule = float_3nan_prop_abc;
50
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
36
- } else {
51
vfp_reg_offset(1, a->vn),
37
- rule = float_3nan_prop_cba;
52
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
38
- }
39
-#else
40
rule = float_3nan_prop_abc;
41
-#endif
53
}
42
}
54
43
55
opr_sz = (1 + a->q) * 8;
44
assert(rule != float_3nan_prop_none);
56
- fpst = get_fpstatus_ptr(1);
57
+ fpst = fpstatus_ptr(FPST_STD);
58
fn_gvec_ptr = a->size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
59
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
60
vfp_reg_offset(1, a->vn),
61
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
62
fn_gvec_ptr = (a->size ? gen_helper_gvec_fcmlas_idx
63
: gen_helper_gvec_fcmlah_idx);
64
opr_sz = (1 + a->q) * 8;
65
- fpst = get_fpstatus_ptr(1);
66
+ fpst = fpstatus_ptr(FPST_STD);
67
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
68
vfp_reg_offset(1, a->vn),
69
vfp_reg_offset(1, a->vm),
70
@@ -XXX,XX +XXX,XX @@ static bool trans_VDOT_scalar(DisasContext *s, arg_VDOT_scalar *a)
71
72
fn_gvec = a->u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
73
opr_sz = (1 + a->q) * 8;
74
- fpst = get_fpstatus_ptr(1);
75
+ fpst = fpstatus_ptr(FPST_STD);
76
tcg_gen_gvec_3_ool(vfp_reg_offset(1, a->vd),
77
vfp_reg_offset(1, a->vn),
78
vfp_reg_offset(1, a->rm),
79
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn,
80
return true;
81
}
82
83
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
84
+ TCGv_ptr fpstatus = fpstatus_ptr(FPST_STD);
85
for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
86
tmp = neon_load_reg(a->vn, pass);
87
tmp2 = neon_load_reg(a->vm, pass);
88
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn,
89
uint32_t rn_ofs, uint32_t rm_ofs, \
90
uint32_t oprsz, uint32_t maxsz) \
91
{ \
92
- TCGv_ptr fpst = get_fpstatus_ptr(1); \
93
+ TCGv_ptr fpst = fpstatus_ptr(FPST_STD); \
94
tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpst, \
95
oprsz, maxsz, 0, FUNC); \
96
tcg_temp_free_ptr(fpst); \
97
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
98
* early. Since Q is 0 there are always just two passes, so instead
99
* of a complicated loop over each pass we just unroll.
100
*/
101
- fpstatus = get_fpstatus_ptr(1);
102
+ fpstatus = fpstatus_ptr(FPST_STD);
103
tmp = neon_load_reg(a->vn, 0);
104
tmp2 = neon_load_reg(a->vn, 1);
105
fn(tmp, tmp, tmp2, fpstatus);
106
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
107
return true;
108
}
109
110
- fpstatus = get_fpstatus_ptr(1);
111
+ fpstatus = fpstatus_ptr(FPST_STD);
112
shiftv = tcg_const_i32(a->shift);
113
for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
114
tmp = neon_load_reg(a->vm, pass);
115
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLS_2sc(DisasContext *s, arg_2scalar *a)
116
#define WRAP_FP_FN(WRAPNAME, FUNC) \
117
static void WRAPNAME(TCGv_i32 rd, TCGv_i32 rn, TCGv_i32 rm) \
118
{ \
119
- TCGv_ptr fpstatus = get_fpstatus_ptr(1); \
120
+ TCGv_ptr fpstatus = fpstatus_ptr(FPST_STD); \
121
FUNC(rd, rn, rm, fpstatus); \
122
tcg_temp_free_ptr(fpstatus); \
123
}
124
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_F16_F32(DisasContext *s, arg_2misc *a)
125
return true;
126
}
127
128
- fpst = get_fpstatus_ptr(true);
129
+ fpst = fpstatus_ptr(FPST_STD);
130
ahp = get_ahp_flag();
131
tmp = neon_load_reg(a->vm, 0);
132
gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
133
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_F32_F16(DisasContext *s, arg_2misc *a)
134
return true;
135
}
136
137
- fpst = get_fpstatus_ptr(true);
138
+ fpst = fpstatus_ptr(FPST_STD);
139
ahp = get_ahp_flag();
140
tmp3 = tcg_temp_new_i32();
141
tmp = neon_load_reg(a->vm, 0);
142
@@ -XXX,XX +XXX,XX @@ static bool do_2misc_fp(DisasContext *s, arg_2misc *a,
143
return true;
144
}
145
146
- fpst = get_fpstatus_ptr(1);
147
+ fpst = fpstatus_ptr(FPST_STD);
148
for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
149
TCGv_i32 tmp = neon_load_reg(a->vm, pass);
150
fn(tmp, tmp, fpst);
151
@@ -XXX,XX +XXX,XX @@ static bool do_vrint(DisasContext *s, arg_2misc *a, int rmode)
152
return true;
153
}
154
155
- fpst = get_fpstatus_ptr(1);
156
+ fpst = fpstatus_ptr(FPST_STD);
157
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
158
gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
159
for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
160
@@ -XXX,XX +XXX,XX @@ static bool do_vcvt(DisasContext *s, arg_2misc *a, int rmode, bool is_signed)
161
return true;
162
}
163
164
- fpst = get_fpstatus_ptr(1);
165
+ fpst = fpstatus_ptr(FPST_STD);
166
tcg_shift = tcg_const_i32(0);
167
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
168
gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
169
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
170
index XXXXXXX..XXXXXXX 100644
171
--- a/target/arm/translate-vfp.c.inc
172
+++ b/target/arm/translate-vfp.c.inc
173
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
174
return true;
175
}
176
177
- fpst = get_fpstatus_ptr(0);
178
+ fpst = fpstatus_ptr(FPST_FPCR);
179
180
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
181
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
182
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
183
return true;
184
}
185
186
- fpst = get_fpstatus_ptr(0);
187
+ fpst = fpstatus_ptr(FPST_FPCR);
188
189
tcg_shift = tcg_const_i32(0);
190
191
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn,
192
f0 = tcg_temp_new_i32();
193
f1 = tcg_temp_new_i32();
194
fd = tcg_temp_new_i32();
195
- fpst = get_fpstatus_ptr(0);
196
+ fpst = fpstatus_ptr(FPST_FPCR);
197
198
neon_load_reg32(f0, vn);
199
neon_load_reg32(f1, vm);
200
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
201
f0 = tcg_temp_new_i64();
202
f1 = tcg_temp_new_i64();
203
fd = tcg_temp_new_i64();
204
- fpst = get_fpstatus_ptr(0);
205
+ fpst = fpstatus_ptr(FPST_FPCR);
206
207
neon_load_reg64(f0, vn);
208
neon_load_reg64(f1, vm);
209
@@ -XXX,XX +XXX,XX @@ static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
210
/* VFNMA, VFNMS */
211
gen_helper_vfp_negs(vd, vd);
212
}
213
- fpst = get_fpstatus_ptr(0);
214
+ fpst = fpstatus_ptr(FPST_FPCR);
215
gen_helper_vfp_muladds(vd, vn, vm, vd, fpst);
216
neon_store_reg32(vd, a->vd);
217
218
@@ -XXX,XX +XXX,XX @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
219
/* VFNMA, VFNMS */
220
gen_helper_vfp_negd(vd, vd);
221
}
222
- fpst = get_fpstatus_ptr(0);
223
+ fpst = fpstatus_ptr(FPST_FPCR);
224
gen_helper_vfp_muladdd(vd, vn, vm, vd, fpst);
225
neon_store_reg64(vd, a->vd);
226
227
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f32_f16(DisasContext *s, arg_VCVT_f32_f16 *a)
228
return true;
229
}
230
231
- fpst = get_fpstatus_ptr(false);
232
+ fpst = fpstatus_ptr(FPST_FPCR);
233
ahp_mode = get_ahp_flag();
234
tmp = tcg_temp_new_i32();
235
/* The T bit tells us if we want the low or high 16 bits of Vm */
236
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
237
return true;
238
}
239
240
- fpst = get_fpstatus_ptr(false);
241
+ fpst = fpstatus_ptr(FPST_FPCR);
242
ahp_mode = get_ahp_flag();
243
tmp = tcg_temp_new_i32();
244
/* The T bit tells us if we want the low or high 16 bits of Vm */
245
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f32(DisasContext *s, arg_VCVT_f16_f32 *a)
246
return true;
247
}
248
249
- fpst = get_fpstatus_ptr(false);
250
+ fpst = fpstatus_ptr(FPST_FPCR);
251
ahp_mode = get_ahp_flag();
252
tmp = tcg_temp_new_i32();
253
254
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
255
return true;
256
}
257
258
- fpst = get_fpstatus_ptr(false);
259
+ fpst = fpstatus_ptr(FPST_FPCR);
260
ahp_mode = get_ahp_flag();
261
tmp = tcg_temp_new_i32();
262
vm = tcg_temp_new_i64();
263
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_sp(DisasContext *s, arg_VRINTR_sp *a)
264
265
tmp = tcg_temp_new_i32();
266
neon_load_reg32(tmp, a->vm);
267
- fpst = get_fpstatus_ptr(false);
268
+ fpst = fpstatus_ptr(FPST_FPCR);
269
gen_helper_rints(tmp, tmp, fpst);
270
neon_store_reg32(tmp, a->vd);
271
tcg_temp_free_ptr(fpst);
272
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
273
274
tmp = tcg_temp_new_i64();
275
neon_load_reg64(tmp, a->vm);
276
- fpst = get_fpstatus_ptr(false);
277
+ fpst = fpstatus_ptr(FPST_FPCR);
278
gen_helper_rintd(tmp, tmp, fpst);
279
neon_store_reg64(tmp, a->vd);
280
tcg_temp_free_ptr(fpst);
281
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a)
282
283
tmp = tcg_temp_new_i32();
284
neon_load_reg32(tmp, a->vm);
285
- fpst = get_fpstatus_ptr(false);
286
+ fpst = fpstatus_ptr(FPST_FPCR);
287
tcg_rmode = tcg_const_i32(float_round_to_zero);
288
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
289
gen_helper_rints(tmp, tmp, fpst);
290
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
291
292
tmp = tcg_temp_new_i64();
293
neon_load_reg64(tmp, a->vm);
294
- fpst = get_fpstatus_ptr(false);
295
+ fpst = fpstatus_ptr(FPST_FPCR);
296
tcg_rmode = tcg_const_i32(float_round_to_zero);
297
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
298
gen_helper_rintd(tmp, tmp, fpst);
299
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_sp(DisasContext *s, arg_VRINTX_sp *a)
300
301
tmp = tcg_temp_new_i32();
302
neon_load_reg32(tmp, a->vm);
303
- fpst = get_fpstatus_ptr(false);
304
+ fpst = fpstatus_ptr(FPST_FPCR);
305
gen_helper_rints_exact(tmp, tmp, fpst);
306
neon_store_reg32(tmp, a->vd);
307
tcg_temp_free_ptr(fpst);
308
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
309
310
tmp = tcg_temp_new_i64();
311
neon_load_reg64(tmp, a->vm);
312
- fpst = get_fpstatus_ptr(false);
313
+ fpst = fpstatus_ptr(FPST_FPCR);
314
gen_helper_rintd_exact(tmp, tmp, fpst);
315
neon_store_reg64(tmp, a->vd);
316
tcg_temp_free_ptr(fpst);
317
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a)
318
319
vm = tcg_temp_new_i32();
320
neon_load_reg32(vm, a->vm);
321
- fpst = get_fpstatus_ptr(false);
322
+ fpst = fpstatus_ptr(FPST_FPCR);
323
if (a->s) {
324
/* i32 -> f32 */
325
gen_helper_vfp_sitos(vm, vm, fpst);
326
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
327
vm = tcg_temp_new_i32();
328
vd = tcg_temp_new_i64();
329
neon_load_reg32(vm, a->vm);
330
- fpst = get_fpstatus_ptr(false);
331
+ fpst = fpstatus_ptr(FPST_FPCR);
332
if (a->s) {
333
/* i32 -> f64 */
334
gen_helper_vfp_sitod(vd, vm, fpst);
335
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
336
vd = tcg_temp_new_i32();
337
neon_load_reg32(vd, a->vd);
338
339
- fpst = get_fpstatus_ptr(false);
340
+ fpst = fpstatus_ptr(FPST_FPCR);
341
shift = tcg_const_i32(frac_bits);
342
343
/* Switch on op:U:sx bits */
344
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
345
vd = tcg_temp_new_i64();
346
neon_load_reg64(vd, a->vd);
347
348
- fpst = get_fpstatus_ptr(false);
349
+ fpst = fpstatus_ptr(FPST_FPCR);
350
shift = tcg_const_i32(frac_bits);
351
352
/* Switch on op:U:sx bits */
353
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a)
354
return true;
355
}
356
357
- fpst = get_fpstatus_ptr(false);
358
+ fpst = fpstatus_ptr(FPST_FPCR);
359
vm = tcg_temp_new_i32();
360
neon_load_reg32(vm, a->vm);
361
362
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
363
return true;
364
}
365
366
- fpst = get_fpstatus_ptr(false);
367
+ fpst = fpstatus_ptr(FPST_FPCR);
368
vm = tcg_temp_new_i64();
369
vd = tcg_temp_new_i32();
370
neon_load_reg64(vm, a->vm);
371
--
45
--
372
2.20.1
46
2.34.1
373
374
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for i386. We had no
2
i386-specific behaviour in the old ifdef ladder, so we were using the
3
default "prefer a then b then c" fallback; this is actually the
4
correct per-the-spec handling for i386.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241202131347.498124-25-peter.maydell@linaro.org
9
---
10
target/i386/tcg/fpu_helper.c | 1 +
11
1 file changed, 1 insertion(+)
12
13
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/i386/tcg/fpu_helper.c
16
+++ b/target/i386/tcg/fpu_helper.c
17
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
18
* there are multiple input NaNs they are selected in the order a, b, c.
19
*/
20
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
21
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
22
}
23
24
static inline uint8_t save_exception_flags(CPUX86State *env)
25
--
26
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for HPPA, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
HPPA is the only target that was using the default branch of the
5
ifdef ladder (other targets either do not use muladd or set
6
default_nan_mode), so we can remove the ifdef fallback entirely now
7
(allowing the "rule not set" case to fall into the default of the
8
switch statement and assert).
9
10
We add a TODO note that the HPPA rule is probably wrong; this is
11
not a behavioural change for this refactoring.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20241202131347.498124-26-peter.maydell@linaro.org
16
---
17
target/hppa/fpu_helper.c | 8 ++++++++
18
fpu/softfloat-specialize.c.inc | 4 ----
19
2 files changed, 8 insertions(+), 4 deletions(-)
20
21
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/hppa/fpu_helper.c
24
+++ b/target/hppa/fpu_helper.c
25
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
26
* HPPA does note implement a CPU reset method at all...
27
*/
28
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
29
+ /*
30
+ * TODO: The HPPA architecture reference only documents its NaN
31
+ * propagation rule for 2-operand operations. Testing on real hardware
32
+ * might be necessary to confirm whether this order for muladd is correct.
33
+ * Not preferring the SNaN is almost certainly incorrect as it diverges
34
+ * from the documented rules for 2-operand operations.
35
+ */
36
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
37
/* For inf * 0 + NaN, return the input NaN */
38
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
39
}
40
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
41
index XXXXXXX..XXXXXXX 100644
42
--- a/fpu/softfloat-specialize.c.inc
43
+++ b/fpu/softfloat-specialize.c.inc
44
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
45
}
46
}
47
48
- if (rule == float_3nan_prop_none) {
49
- rule = float_3nan_prop_abc;
50
- }
51
-
52
assert(rule != float_3nan_prop_none);
53
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
54
/* We have at least one SNaN input and should prefer it */
55
--
56
2.34.1
diff view generated by jsdifflib
1
Convert the T32 coprocessor instructions to decodetree.
1
The use_first_nan field in float_status was an xtensa-specific way to
2
As with the A32 conversion, this corrects an underdecoding
2
select at runtime from two different NaN propagation rules. Now that
3
where we did not check that MRRC/MCRR [24:21] were 0b0010
3
xtensa is using the target-agnostic NaN propagation rule selection
4
and so treated some kinds of LDC/STC and MRRC/MCRR rather
4
that we've just added, we can remove use_first_nan, because there is
5
than UNDEFing them.
5
no longer any code that reads it.
6
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200803111849.13368-7-peter.maydell@linaro.org
9
Message-id: 20241202131347.498124-27-peter.maydell@linaro.org
10
---
10
---
11
target/arm/t32.decode | 19 +++++++++++++
11
include/fpu/softfloat-helpers.h | 5 -----
12
target/arm/translate.c | 64 ++----------------------------------------
12
include/fpu/softfloat-types.h | 1 -
13
2 files changed, 21 insertions(+), 62 deletions(-)
13
target/xtensa/fpu_helper.c | 1 -
14
3 files changed, 7 deletions(-)
14
15
15
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
16
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/t32.decode
18
--- a/include/fpu/softfloat-helpers.h
18
+++ b/target/arm/t32.decode
19
+++ b/include/fpu/softfloat-helpers.h
19
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static inline void set_snan_bit_is_one(bool val, float_status *status)
20
&sat !extern rd rn satimm imm sh
21
status->snan_bit_is_one = val;
21
&pkh !extern rd rn rm imm tb
22
&cps !extern mode imod M A I F
23
+&mcr !extern cp opc1 crn crm opc2 rt
24
+&mcrr !extern cp opc1 crm rt rt2
25
26
# Data-processing (register)
27
28
@@ -XXX,XX +XXX,XX @@ RFE 1110 1001 10.1 .... 1100000000000000 @rfe pu=1
29
SRS 1110 1000 00.0 1101 1100 0000 000. .... @srs pu=2
30
SRS 1110 1001 10.0 1101 1100 0000 000. .... @srs pu=1
31
32
+# Coprocessor instructions
33
+
34
+# We decode MCR, MCR, MRRC and MCRR only, because for QEMU the
35
+# other coprocessor instructions always UNDEF.
36
+# The trans_ functions for these will ignore cp values 8..13 for v7 or
37
+# earlier, and 0..13 for v8 and later, because those areas of the
38
+# encoding space may be used for other things, such as VFP or Neon.
39
+
40
+@mcr .... .... opc1:3 . crn:4 rt:4 cp:4 opc2:3 . crm:4
41
+@mcrr .... .... .... rt2:4 rt:4 cp:4 opc1:4 crm:4
42
+
43
+MCRR 1110 1100 0100 .... .... .... .... .... @mcrr
44
+MRRC 1110 1100 0101 .... .... .... .... .... @mcrr
45
+
46
+MCR 1110 1110 ... 0 .... .... .... ... 1 .... @mcr
47
+MRC 1110 1110 ... 1 .... .... .... ... 1 .... @mcr
48
+
49
# Branches
50
51
%imm24 26:s1 13:1 11:1 16:10 0:11 !function=t32_branch24
52
diff --git a/target/arm/translate.c b/target/arm/translate.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/translate.c
55
+++ b/target/arm/translate.c
56
@@ -XXX,XX +XXX,XX @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
57
return;
58
}
22
}
59
23
60
-static int disas_coproc_insn(DisasContext *s, uint32_t insn)
24
-static inline void set_use_first_nan(bool val, float_status *status)
61
-{
25
-{
62
- int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
26
- status->use_first_nan = val;
63
-
64
- cpnum = (insn >> 8) & 0xf;
65
-
66
- is64 = (insn & (1 << 25)) == 0;
67
- if (!is64 && ((insn & (1 << 4)) == 0)) {
68
- /* cdp */
69
- return 1;
70
- }
71
-
72
- crm = insn & 0xf;
73
- if (is64) {
74
- crn = 0;
75
- opc1 = (insn >> 4) & 0xf;
76
- opc2 = 0;
77
- rt2 = (insn >> 16) & 0xf;
78
- } else {
79
- crn = (insn >> 16) & 0xf;
80
- opc1 = (insn >> 21) & 7;
81
- opc2 = (insn >> 5) & 7;
82
- rt2 = 0;
83
- }
84
- isread = (insn >> 20) & 1;
85
- rt = (insn >> 12) & 0xf;
86
-
87
- do_coproc_insn(s, cpnum, is64, opc1, crn, crm, opc2, isread, rt, rt2);
88
- return 0;
89
-}
27
-}
90
-
28
-
91
/* Decode XScale DSP or iWMMXt insn (in the copro space, cp=0 or 1) */
29
static inline void set_no_signaling_nans(bool val, float_status *status)
92
static void disas_xscale_insn(DisasContext *s, uint32_t insn)
93
{
30
{
94
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
31
status->no_signaling_nans = val;
95
((insn >> 28) == 0xe && disas_vfp(s, insn))) {
32
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
96
return;
33
index XXXXXXX..XXXXXXX 100644
97
}
34
--- a/include/fpu/softfloat-types.h
98
- /* fall back to legacy decoder */
35
+++ b/include/fpu/softfloat-types.h
99
36
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
100
- switch ((insn >> 25) & 0xf) {
37
* softfloat-specialize.inc.c)
101
- case 0: case 1: case 2: case 3:
38
*/
102
- /* 16-bit instructions. Should never happen. */
39
bool snan_bit_is_one;
103
- abort();
40
- bool use_first_nan;
104
- case 6: case 7: case 14: case 15:
41
bool no_signaling_nans;
105
- /* Coprocessor. */
42
/* should overflowed results subtract re_bias to its exponent? */
106
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
43
bool rebias_overflow;
107
- /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
44
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
108
- goto illegal_op;
45
index XXXXXXX..XXXXXXX 100644
109
- }
46
--- a/target/xtensa/fpu_helper.c
110
- if (((insn >> 24) & 3) == 3) {
47
+++ b/target/xtensa/fpu_helper.c
111
- /* Neon DP, but failed disas_neon_dp() */
48
@@ -XXX,XX +XXX,XX @@ static const struct {
112
- goto illegal_op;
49
113
- } else if (((insn >> 8) & 0xe) == 10) {
50
void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
114
- /* VFP, but failed disas_vfp. */
51
{
115
- goto illegal_op;
52
- set_use_first_nan(use_first, &env->fp_status);
116
- } else {
53
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
117
- if (insn & (1 << 28))
54
&env->fp_status);
118
- goto illegal_op;
55
set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
119
- if (disas_coproc_insn(s, insn)) {
120
- goto illegal_op;
121
- }
122
- }
123
- break;
124
- case 12:
125
- goto illegal_op;
126
- default:
127
- illegal_op:
128
- unallocated_encoding(s);
129
- }
130
+illegal_op:
131
+ unallocated_encoding(s);
132
}
133
134
static void disas_thumb_insn(DisasContext *s, uint32_t insn)
135
--
56
--
136
2.20.1
57
2.34.1
137
138
diff view generated by jsdifflib
New patch
1
Currently m68k_cpu_reset_hold() calls floatx80_default_nan(NULL)
2
to get the NaN bit pattern to reset the FPU registers. This
3
works because it happens that our implementation of
4
floatx80_default_nan() doesn't actually look at the float_status
5
pointer except for TARGET_MIPS. However, this isn't guaranteed,
6
and to be able to remove the ifdef in floatx80_default_nan()
7
we're going to need a real float_status here.
1
8
9
Rearrange m68k_cpu_reset_hold() so that we initialize env->fp_status
10
earlier, and thus can pass it to floatx80_default_nan().
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20241202131347.498124-28-peter.maydell@linaro.org
15
---
16
target/m68k/cpu.c | 12 +++++++-----
17
1 file changed, 7 insertions(+), 5 deletions(-)
18
19
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/m68k/cpu.c
22
+++ b/target/m68k/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
24
CPUState *cs = CPU(obj);
25
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(obj);
26
CPUM68KState *env = cpu_env(cs);
27
- floatx80 nan = floatx80_default_nan(NULL);
28
+ floatx80 nan;
29
int i;
30
31
if (mcc->parent_phases.hold) {
32
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
33
#else
34
cpu_m68k_set_sr(env, SR_S | SR_I);
35
#endif
36
- for (i = 0; i < 8; i++) {
37
- env->fregs[i].d = nan;
38
- }
39
- cpu_m68k_set_fpcr(env, 0);
40
/*
41
* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
42
* 3.4 FLOATING-POINT INSTRUCTION DETAILS
43
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
44
* preceding paragraph for nonsignaling NaNs.
45
*/
46
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
47
+
48
+ nan = floatx80_default_nan(&env->fp_status);
49
+ for (i = 0; i < 8; i++) {
50
+ env->fregs[i].d = nan;
51
+ }
52
+ cpu_m68k_set_fpcr(env, 0);
53
env->fpsr = 0;
54
55
/* TODO: We should set PC from the interrupt vector. */
56
--
57
2.34.1
diff view generated by jsdifflib
New patch
1
We create our 128-bit default NaN by calling parts64_default_nan()
2
and then adjusting the result. We can do the same trick for creating
3
the floatx80 default NaN, which lets us drop a target ifdef.
1
4
5
floatx80 is used only by:
6
i386
7
m68k
8
arm nwfpe old floating-point emulation emulation support
9
(which is essentially dead, especially the parts involving floatx80)
10
PPC (only in the xsrqpxp instruction, which just rounds an input
11
value by converting to floatx80 and back, so will never generate
12
the default NaN)
13
14
The floatx80 default NaN as currently implemented is:
15
m68k: sign = 0, exp = 1...1, int = 1, frac = 1....1
16
i386: sign = 1, exp = 1...1, int = 1, frac = 10...0
17
18
These are the same as the parts64_default_nan for these architectures.
19
20
This is technically a possible behaviour change for arm linux-user
21
nwfpe emulation emulation, because the default NaN will now have the
22
sign bit clear. But we were already generating a different floatx80
23
default NaN from the real kernel emulation we are supposedly
24
following, which appears to use an all-bits-1 value:
25
https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L267
26
27
This won't affect the only "real" use of the nwfpe emulation, which
28
is ancient binaries that used it as part of the old floating point
29
calling convention; that only uses loads and stores of 32 and 64 bit
30
floats, not any of the floatx80 behaviour the original hardware had.
31
We also get the nwfpe float64 default NaN value wrong:
32
https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L166
33
so if we ever cared about this obscure corner the right fix would be
34
to correct that so nwfpe used its own default-NaN setting rather
35
than the Arm VFP one.
36
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
39
Message-id: 20241202131347.498124-29-peter.maydell@linaro.org
40
---
41
fpu/softfloat-specialize.c.inc | 20 ++++++++++----------
42
1 file changed, 10 insertions(+), 10 deletions(-)
43
44
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
45
index XXXXXXX..XXXXXXX 100644
46
--- a/fpu/softfloat-specialize.c.inc
47
+++ b/fpu/softfloat-specialize.c.inc
48
@@ -XXX,XX +XXX,XX @@ static void parts128_silence_nan(FloatParts128 *p, float_status *status)
49
floatx80 floatx80_default_nan(float_status *status)
50
{
51
floatx80 r;
52
+ /*
53
+ * Extrapolate from the choices made by parts64_default_nan to fill
54
+ * in the floatx80 format. We assume that floatx80's explicit
55
+ * integer bit is always set (this is true for i386 and m68k,
56
+ * which are the only real users of this format).
57
+ */
58
+ FloatParts64 p64;
59
+ parts64_default_nan(&p64, status);
60
61
- /* None of the targets that have snan_bit_is_one use floatx80. */
62
- assert(!snan_bit_is_one(status));
63
-#if defined(TARGET_M68K)
64
- r.low = UINT64_C(0xFFFFFFFFFFFFFFFF);
65
- r.high = 0x7FFF;
66
-#else
67
- /* X86 */
68
- r.low = UINT64_C(0xC000000000000000);
69
- r.high = 0xFFFF;
70
-#endif
71
+ r.high = 0x7FFF | (p64.sign << 15);
72
+ r.low = (1ULL << DECOMPOSED_BINARY_POINT) | p64.frac;
73
return r;
74
}
75
76
--
77
2.34.1
diff view generated by jsdifflib
New patch
1
In target/loongarch's helper_fclass_s() and helper_fclass_d() we pass
2
a zero-initialized float_status struct to float32_is_quiet_nan() and
3
float64_is_quiet_nan(), with the cryptic comment "for
4
snan_bit_is_one".
1
5
6
This pattern appears to have been copied from target/riscv, where it
7
is used because the functions there do not have ready access to the
8
CPU state struct. The comment presumably refers to the fact that the
9
main reason the is_quiet_nan() functions want the float_state is
10
because they want to know about the snan_bit_is_one config.
11
12
In the loongarch helpers, though, we have the CPU state struct
13
to hand. Use the usual env->fp_status here. This avoids our needing
14
to track that we need to update the initializer of the local
15
float_status structs when the core softfloat code adds new
16
options for targets to configure their behaviour.
17
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20241202131347.498124-30-peter.maydell@linaro.org
21
---
22
target/loongarch/tcg/fpu_helper.c | 6 ++----
23
1 file changed, 2 insertions(+), 4 deletions(-)
24
25
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/loongarch/tcg/fpu_helper.c
28
+++ b/target/loongarch/tcg/fpu_helper.c
29
@@ -XXX,XX +XXX,XX @@ uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj)
30
} else if (float32_is_zero_or_denormal(f)) {
31
return sign ? 1 << 4 : 1 << 8;
32
} else if (float32_is_any_nan(f)) {
33
- float_status s = { }; /* for snan_bit_is_one */
34
- return float32_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
35
+ return float32_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0;
36
} else {
37
return sign ? 1 << 3 : 1 << 7;
38
}
39
@@ -XXX,XX +XXX,XX @@ uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj)
40
} else if (float64_is_zero_or_denormal(f)) {
41
return sign ? 1 << 4 : 1 << 8;
42
} else if (float64_is_any_nan(f)) {
43
- float_status s = { }; /* for snan_bit_is_one */
44
- return float64_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
45
+ return float64_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0;
46
} else {
47
return sign ? 1 << 3 : 1 << 7;
48
}
49
--
50
2.34.1
diff view generated by jsdifflib
New patch
1
In the frem helper, we have a local float_status because we want to
2
execute the floatx80_div() with a custom rounding mode. Instead of
3
zero-initializing the local float_status and then having to set it up
4
with the m68k standard behaviour (including the NaN propagation rule
5
and copying the rounding precision from env->fp_status), initialize
6
it as a complete copy of env->fp_status. This will avoid our having
7
to add new code in this function for every new config knob we add
8
to fp_status.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-31-peter.maydell@linaro.org
13
---
14
target/m68k/fpu_helper.c | 6 ++----
15
1 file changed, 2 insertions(+), 4 deletions(-)
16
17
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/m68k/fpu_helper.c
20
+++ b/target/m68k/fpu_helper.c
21
@@ -XXX,XX +XXX,XX @@ void HELPER(frem)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
22
23
fp_rem = floatx80_rem(val1->d, val0->d, &env->fp_status);
24
if (!floatx80_is_any_nan(fp_rem)) {
25
- float_status fp_status = { };
26
+ /* Use local temporary fp_status to set different rounding mode */
27
+ float_status fp_status = env->fp_status;
28
uint32_t quotient;
29
int sign;
30
31
/* Calculate quotient directly using round to nearest mode */
32
- set_float_2nan_prop_rule(float_2nan_prop_ab, &fp_status);
33
set_float_rounding_mode(float_round_nearest_even, &fp_status);
34
- set_floatx80_rounding_precision(
35
- get_floatx80_rounding_precision(&env->fp_status), &fp_status);
36
fp_quot.d = floatx80_div(val1->d, val0->d, &fp_status);
37
38
sign = extractFloatx80Sign(fp_quot.d);
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
In cf_fpu_gdb_get_reg() and cf_fpu_gdb_set_reg() we do the conversion
2
from float64 to floatx80 using a scratch float_status, because we
3
don't want the conversion to affect the CPU's floating point exception
4
status. Currently we use a zero-initialized float_status. This will
5
get steadily more awkward as we add config knobs to float_status
6
that the target must initialize. Avoid having to add any of that
7
configuration here by instead initializing our local float_status
8
from the env->fp_status.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-32-peter.maydell@linaro.org
13
---
14
target/m68k/helper.c | 6 ++++--
15
1 file changed, 4 insertions(+), 2 deletions(-)
16
17
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/m68k/helper.c
20
+++ b/target/m68k/helper.c
21
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_get_reg(CPUState *cs, GByteArray *mem_buf, int n)
22
CPUM68KState *env = &cpu->env;
23
24
if (n < 8) {
25
- float_status s = {};
26
+ /* Use scratch float_status so any exceptions don't change CPU state */
27
+ float_status s = env->fp_status;
28
return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
29
}
30
switch (n) {
31
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n)
32
CPUM68KState *env = &cpu->env;
33
34
if (n < 8) {
35
- float_status s = {};
36
+ /* Use scratch float_status so any exceptions don't change CPU state */
37
+ float_status s = env->fp_status;
38
env->fregs[n].d = float64_to_floatx80(ldq_be_p(mem_buf), &s);
39
return 8;
40
}
41
--
42
2.34.1
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
In the helper functions flcmps and flcmpd we use a scratch float_status
2
so that we don't change the CPU state if the comparison raises any
3
floating point exception flags. Instead of zero-initializing this
4
scratch float_status, initialize it as a copy of env->fp_status. This
5
avoids the need to explicitly initialize settings like the NaN
6
propagation rule or others we might add to softfloat in future.
2
7
3
Introduce a specialized SMMUTLBEntry to store the result of
8
To do this we need to pass the CPU env pointer in to the helper.
4
the PTW and cache in the IOTLB. This structure extends the
5
generic IOMMUTLBEntry struct with the level of the entry and
6
the granule size.
7
9
8
Those latter will be useful when implementing range invalidation.
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-33-peter.maydell@linaro.org
13
---
14
target/sparc/helper.h | 4 ++--
15
target/sparc/fop_helper.c | 8 ++++----
16
target/sparc/translate.c | 4 ++--
17
3 files changed, 8 insertions(+), 8 deletions(-)
9
18
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
19
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20200728150815.11446-5-eric.auger@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
include/hw/arm/smmu-common.h | 12 +++++++++---
16
hw/arm/smmu-common.c | 32 +++++++++++++++++---------------
17
hw/arm/smmuv3.c | 10 +++++-----
18
3 files changed, 31 insertions(+), 23 deletions(-)
19
20
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/smmu-common.h
21
--- a/target/sparc/helper.h
23
+++ b/include/hw/arm/smmu-common.h
22
+++ b/target/sparc/helper.h
24
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUTransTableInfo {
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
25
uint8_t granule_sz; /* granule page shift */
24
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
26
} SMMUTransTableInfo;
25
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128)
27
26
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128)
28
+typedef struct SMMUTLBEntry {
27
-DEF_HELPER_FLAGS_2(flcmps, TCG_CALL_NO_RWG_SE, i32, f32, f32)
29
+ IOMMUTLBEntry entry;
28
-DEF_HELPER_FLAGS_2(flcmpd, TCG_CALL_NO_RWG_SE, i32, f64, f64)
30
+ uint8_t level;
29
+DEF_HELPER_FLAGS_3(flcmps, TCG_CALL_NO_RWG_SE, i32, env, f32, f32)
31
+ uint8_t granule;
30
+DEF_HELPER_FLAGS_3(flcmpd, TCG_CALL_NO_RWG_SE, i32, env, f64, f64)
32
+} SMMUTLBEntry;
31
DEF_HELPER_2(raise_exception, noreturn, env, int)
33
+
32
34
/*
33
DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64)
35
* Generic structure populated by derived SMMU devices
34
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
36
* after decoding the configuration information and used as
37
@@ -XXX,XX +XXX,XX @@ static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
38
* pair, according to @cfg translation config
39
*/
40
int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
41
- IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
42
+ SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
43
44
/**
45
* select_tt - compute which translation table shall be used according to
46
@@ -XXX,XX +XXX,XX @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid);
47
48
#define SMMU_IOTLB_MAX_SIZE 256
49
50
-IOMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, hwaddr iova);
51
-void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, IOMMUTLBEntry *entry);
52
+SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, hwaddr iova);
53
+void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *entry);
54
SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova);
55
void smmu_iotlb_inv_all(SMMUState *s);
56
void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
57
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
58
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/arm/smmu-common.c
36
--- a/target/sparc/fop_helper.c
60
+++ b/hw/arm/smmu-common.c
37
+++ b/target/sparc/fop_helper.c
61
@@ -XXX,XX +XXX,XX @@ SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova)
38
@@ -XXX,XX +XXX,XX @@ uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
62
return key;
39
return finish_fcmp(env, r, GETPC());
63
}
40
}
64
41
65
-IOMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
42
-uint32_t helper_flcmps(float32 src1, float32 src2)
66
- hwaddr iova)
43
+uint32_t helper_flcmps(CPUSPARCState *env, float32 src1, float32 src2)
67
+SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
68
+ hwaddr iova)
69
{
44
{
70
SMMUIOTLBKey key = smmu_get_iotlb_key(cfg->asid, iova);
45
/*
71
- IOMMUTLBEntry *entry = g_hash_table_lookup(bs->iotlb, &key);
46
* FLCMP never raises an exception nor modifies any FSR fields.
72
+ SMMUTLBEntry *entry = g_hash_table_lookup(bs->iotlb, &key);
47
* Perform the comparison with a dummy fp environment.
73
48
*/
74
if (entry) {
49
- float_status discard = { };
75
cfg->iotlb_hits++;
50
+ float_status discard = env->fp_status;
76
@@ -XXX,XX +XXX,XX @@ IOMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
51
FloatRelation r;
77
return entry;
52
53
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
54
@@ -XXX,XX +XXX,XX @@ uint32_t helper_flcmps(float32 src1, float32 src2)
55
g_assert_not_reached();
78
}
56
}
79
57
80
-void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, IOMMUTLBEntry *entry)
58
-uint32_t helper_flcmpd(float64 src1, float64 src2)
81
+void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *new)
59
+uint32_t helper_flcmpd(CPUSPARCState *env, float64 src1, float64 src2)
82
{
60
{
83
SMMUIOTLBKey *key = g_new0(SMMUIOTLBKey, 1);
61
- float_status discard = { };
84
62
+ float_status discard = env->fp_status;
85
@@ -XXX,XX +XXX,XX @@ void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, IOMMUTLBEntry *entry)
63
FloatRelation r;
86
smmu_iotlb_inv_all(bs);
64
87
}
65
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
88
66
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
89
- *key = smmu_get_iotlb_key(cfg->asid, entry->iova);
67
index XXXXXXX..XXXXXXX 100644
90
- trace_smmu_iotlb_insert(cfg->asid, entry->iova);
68
--- a/target/sparc/translate.c
91
- g_hash_table_insert(bs->iotlb, key, entry);
69
+++ b/target/sparc/translate.c
92
+ *key = smmu_get_iotlb_key(cfg->asid, new->entry.iova);
70
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a)
93
+ trace_smmu_iotlb_insert(cfg->asid, new->entry.iova);
71
94
+ g_hash_table_insert(bs->iotlb, key, new);
72
src1 = gen_load_fpr_F(dc, a->rs1);
73
src2 = gen_load_fpr_F(dc, a->rs2);
74
- gen_helper_flcmps(cpu_fcc[a->cc], src1, src2);
75
+ gen_helper_flcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
76
return advance_pc(dc);
95
}
77
}
96
78
97
inline void smmu_iotlb_inv_all(SMMUState *s)
79
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
98
@@ -XXX,XX +XXX,XX @@ SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova)
80
99
* @cfg: translation config
81
src1 = gen_load_fpr_D(dc, a->rs1);
100
* @iova: iova to translate
82
src2 = gen_load_fpr_D(dc, a->rs2);
101
* @perm: access type
83
- gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
102
- * @tlbe: IOMMUTLBEntry (out)
84
+ gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
103
+ * @tlbe: SMMUTLBEntry (out)
85
return advance_pc(dc);
104
* @info: handle to an error info
105
*
106
* Return 0 on success, < 0 on error. In case of error, @info is filled
107
@@ -XXX,XX +XXX,XX @@ SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova)
108
*/
109
static int smmu_ptw_64(SMMUTransCfg *cfg,
110
dma_addr_t iova, IOMMUAccessFlags perm,
111
- IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
112
+ SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
113
{
114
dma_addr_t baseaddr, indexmask;
115
int stage = cfg->stage;
116
@@ -XXX,XX +XXX,XX @@ static int smmu_ptw_64(SMMUTransCfg *cfg,
117
baseaddr = extract64(tt->ttb, 0, 48);
118
baseaddr &= ~indexmask;
119
120
- tlbe->iova = iova;
121
- tlbe->addr_mask = (1 << granule_sz) - 1;
122
+ tlbe->entry.iova = iova;
123
+ tlbe->entry.addr_mask = (1 << granule_sz) - 1;
124
125
while (level <= 3) {
126
uint64_t subpage_size = 1ULL << level_shift(level, granule_sz);
127
@@ -XXX,XX +XXX,XX @@ static int smmu_ptw_64(SMMUTransCfg *cfg,
128
goto error;
129
}
130
131
- tlbe->translated_addr = gpa + (iova & mask);
132
- tlbe->perm = PTE_AP_TO_PERM(ap);
133
+ tlbe->entry.translated_addr = gpa + (iova & mask);
134
+ tlbe->entry.perm = PTE_AP_TO_PERM(ap);
135
+ tlbe->level = level;
136
+ tlbe->granule = granule_sz;
137
return 0;
138
}
139
info->type = SMMU_PTW_ERR_TRANSLATION;
140
141
error:
142
- tlbe->perm = IOMMU_NONE;
143
+ tlbe->entry.perm = IOMMU_NONE;
144
return -EINVAL;
145
}
86
}
146
87
147
@@ -XXX,XX +XXX,XX @@ error:
148
* return 0 on success
149
*/
150
inline int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
151
- IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
152
+ SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info)
153
{
154
if (!cfg->aa64) {
155
/*
156
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
157
index XXXXXXX..XXXXXXX 100644
158
--- a/hw/arm/smmuv3.c
159
+++ b/hw/arm/smmuv3.c
160
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
161
SMMUTranslationStatus status;
162
SMMUState *bs = ARM_SMMU(s);
163
uint64_t page_mask, aligned_addr;
164
- IOMMUTLBEntry *cached_entry = NULL;
165
+ SMMUTLBEntry *cached_entry = NULL;
166
SMMUTransTableInfo *tt;
167
SMMUTransCfg *cfg = NULL;
168
IOMMUTLBEntry entry = {
169
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
170
171
cached_entry = smmu_iotlb_lookup(bs, cfg, aligned_addr);
172
if (cached_entry) {
173
- if ((flag & IOMMU_WO) && !(cached_entry->perm & IOMMU_WO)) {
174
+ if ((flag & IOMMU_WO) && !(cached_entry->entry.perm & IOMMU_WO)) {
175
status = SMMU_TRANS_ERROR;
176
if (event.record_trans_faults) {
177
event.type = SMMU_EVT_F_PERMISSION;
178
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
179
goto epilogue;
180
}
181
182
- cached_entry = g_new0(IOMMUTLBEntry, 1);
183
+ cached_entry = g_new0(SMMUTLBEntry, 1);
184
185
if (smmu_ptw(cfg, aligned_addr, flag, cached_entry, &ptw_info)) {
186
g_free(cached_entry);
187
@@ -XXX,XX +XXX,XX @@ epilogue:
188
switch (status) {
189
case SMMU_TRANS_SUCCESS:
190
entry.perm = flag;
191
- entry.translated_addr = cached_entry->translated_addr +
192
+ entry.translated_addr = cached_entry->entry.translated_addr +
193
(addr & page_mask);
194
- entry.addr_mask = cached_entry->addr_mask;
195
+ entry.addr_mask = cached_entry->entry.addr_mask;
196
trace_smmuv3_translate_success(mr->parent_obj.name, sid, addr,
197
entry.translated_addr, entry.perm);
198
break;
199
--
88
--
200
2.20.1
89
2.34.1
201
202
diff view generated by jsdifflib
New patch
1
In the helper_compute_fprf functions, we pass a dummy float_status
2
in to the is_signaling_nan() function. This is unnecessary, because
3
we have convenient access to the CPU env pointer here and that
4
is already set up with the correct values for the snan_bit_is_one
5
and no_signaling_nans config settings. is_signaling_nan() doesn't
6
ever update the fp_status with any exception flags, so there is
7
no reason not to use env->fp_status here.
1
8
9
Use env->fp_status instead of the dummy fp_status.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20241202131347.498124-34-peter.maydell@linaro.org
14
---
15
target/ppc/fpu_helper.c | 3 +--
16
1 file changed, 1 insertion(+), 2 deletions(-)
17
18
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/ppc/fpu_helper.c
21
+++ b/target/ppc/fpu_helper.c
22
@@ -XXX,XX +XXX,XX @@ void helper_compute_fprf_##tp(CPUPPCState *env, tp arg) \
23
} else if (tp##_is_infinity(arg)) { \
24
fprf = neg ? 0x09 << FPSCR_FPRF : 0x05 << FPSCR_FPRF; \
25
} else { \
26
- float_status dummy = { }; /* snan_bit_is_one = 0 */ \
27
- if (tp##_is_signaling_nan(arg, &dummy)) { \
28
+ if (tp##_is_signaling_nan(arg, &env->fp_status)) { \
29
fprf = 0x00 << FPSCR_FPRF; \
30
} else { \
31
fprf = 0x11 << FPSCR_FPRF; \
32
--
33
2.34.1
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Expose the RIL bit so that the guest driver uses range
3
Now that float_status has a bunch of fp parameters,
4
invalidation. Although RIL is a 3.2 features, We let
4
it is easier to copy an existing structure than create
5
the AIDR advertise SMMUv3.1 support as v3.x implementation
5
one from scratch. Begin by copying the structure that
6
is allowed to implement features from v3.(x+1).
6
corresponds to the FPSR and make only the adjustments
7
required for BFloat16 semantics.
7
8
8
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20200728150815.11446-12-eric.auger@redhat.com
12
Message-id: 20241203203949.483774-2-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
14
---
13
hw/arm/smmuv3-internal.h | 1 +
15
target/arm/tcg/vec_helper.c | 20 +++++++-------------
14
hw/arm/smmuv3.c | 1 +
16
1 file changed, 7 insertions(+), 13 deletions(-)
15
2 files changed, 2 insertions(+)
16
17
17
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
18
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/smmuv3-internal.h
20
--- a/target/arm/tcg/vec_helper.c
20
+++ b/hw/arm/smmuv3-internal.h
21
+++ b/target/arm/tcg/vec_helper.c
21
@@ -XXX,XX +XXX,XX @@ REG32(IDR1, 0x4)
22
@@ -XXX,XX +XXX,XX @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp)
22
REG32(IDR2, 0x8)
23
* no effect on AArch32 instructions.
23
REG32(IDR3, 0xc)
24
*/
24
FIELD(IDR3, HAD, 2, 1);
25
bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF;
25
+ FIELD(IDR3, RIL, 10, 1);
26
- *statusp = (float_status){
26
REG32(IDR4, 0x10)
27
- .tininess_before_rounding = float_tininess_before_rounding,
27
REG32(IDR5, 0x14)
28
- .float_rounding_mode = float_round_to_odd_inf,
28
FIELD(IDR5, OAS, 0, 3);
29
- .flush_to_zero = true,
29
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
30
- .flush_inputs_to_zero = true,
30
index XXXXXXX..XXXXXXX 100644
31
- .default_nan_mode = true,
31
--- a/hw/arm/smmuv3.c
32
- };
32
+++ b/hw/arm/smmuv3.c
33
+
33
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
34
+ *statusp = env->vfp.fp_status;
34
s->idr[1] = FIELD_DP32(s->idr[1], IDR1, EVENTQS, SMMU_EVENTQS);
35
+ set_default_nan_mode(true, statusp);
35
s->idr[1] = FIELD_DP32(s->idr[1], IDR1, CMDQS, SMMU_CMDQS);
36
36
37
if (ebf) {
37
+ s->idr[3] = FIELD_DP32(s->idr[3], IDR3, RIL, 1);
38
- float_status *fpst = &env->vfp.fp_status;
38
s->idr[3] = FIELD_DP32(s->idr[3], IDR3, HAD, 1);
39
- set_flush_to_zero(get_flush_to_zero(fpst), statusp);
39
40
- set_flush_inputs_to_zero(get_flush_inputs_to_zero(fpst), statusp);
40
/* 4K and 64K granule support */
41
- set_float_rounding_mode(get_float_rounding_mode(fpst), statusp);
42
-
43
/* EBF=1 needs to do a step with round-to-odd semantics */
44
*oddstatusp = *statusp;
45
set_float_rounding_mode(float_round_to_odd, oddstatusp);
46
+ } else {
47
+ set_flush_to_zero(true, statusp);
48
+ set_flush_inputs_to_zero(true, statusp);
49
+ set_float_rounding_mode(float_round_to_odd_inf, statusp);
50
}
51
-
52
return ebf;
53
}
54
41
--
55
--
42
2.20.1
56
2.34.1
43
57
44
58
diff view generated by jsdifflib
1
Convert the A32 coprocessor instructions to decodetree.
1
Currently we hardcode the default NaN value in parts64_default_nan()
2
using a compile-time ifdef ladder. This is awkward for two cases:
3
* for single-QEMU-binary we can't hard-code target-specifics like this
4
* for Arm FEAT_AFP the default NaN value depends on FPCR.AH
5
(specifically the sign bit is different)
2
6
3
Note that this corrects an underdecoding: for the 64-bit access case
7
Add a field to float_status to specify the default NaN value; fall
4
(MRRC/MCRR) we did not check that bits [24:21] were 0b0010, so we
8
back to the old ifdef behaviour if these are not set.
5
would incorrectly treat LDC/STC as MRRC/MCRR rather than UNDEFing
6
them.
7
9
8
The decodetree versions of these insns assume the coprocessor
10
The default NaN value is specified by setting a uint8_t to a
9
is in the range 0..7 or 14..15. This is architecturally sensible
11
pattern corresponding to the sign and upper fraction parts of
10
(as per the comments) and OK in practice for QEMU because the only
12
the NaN; the lower bits of the fraction are set from bit 0 of
11
uses of the ARMCPRegInfo infrastructure we have that aren't
13
the pattern.
12
for coprocessors 14 or 15 are the pxa2xx use of coprocessor 6.
13
We add an assertion to the define_one_arm_cp_reg_with_opaque()
14
function to catch any accidental future attempts to use it to
15
define coprocessor registers for invalid coprocessors.
16
14
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20200803111849.13368-4-peter.maydell@linaro.org
17
Message-id: 20241202131347.498124-35-peter.maydell@linaro.org
20
---
18
---
21
target/arm/a32.decode | 19 +++++++++++
19
include/fpu/softfloat-helpers.h | 11 +++++++
22
target/arm/helper.c | 29 +++++++++++++++++
20
include/fpu/softfloat-types.h | 10 ++++++
23
target/arm/translate.c | 74 +++++++++++++++++++++++++++++++++++-------
21
fpu/softfloat-specialize.c.inc | 55 ++++++++++++++++++++-------------
24
3 files changed, 111 insertions(+), 11 deletions(-)
22
3 files changed, 54 insertions(+), 22 deletions(-)
25
23
26
diff --git a/target/arm/a32.decode b/target/arm/a32.decode
24
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
27
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/a32.decode
26
--- a/include/fpu/softfloat-helpers.h
29
+++ b/target/arm/a32.decode
27
+++ b/include/fpu/softfloat-helpers.h
30
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
31
&bfi rd rn lsb msb
29
status->float_infzeronan_rule = rule;
32
&sat rd rn satimm imm sh
30
}
33
&pkh rd rn rm imm tb
31
34
+&mcr cp opc1 crn crm opc2 rt
32
+static inline void set_float_default_nan_pattern(uint8_t dnan_pattern,
35
+&mcrr cp opc1 crm rt rt2
33
+ float_status *status)
36
37
# Data-processing (register)
38
39
@@ -XXX,XX +XXX,XX @@ LDM_a32 ---- 100 b:1 i:1 u:1 w:1 1 rn:4 list:16 &ldst_block
40
B .... 1010 ........................ @branch
41
BL .... 1011 ........................ @branch
42
43
+# Coprocessor instructions
44
+
45
+# We decode MCR, MCR, MRRC and MCRR only, because for QEMU the
46
+# other coprocessor instructions always UNDEF.
47
+# The trans_ functions for these will ignore cp values 8..13 for v7 or
48
+# earlier, and 0..13 for v8 and later, because those areas of the
49
+# encoding space may be used for other things, such as VFP or Neon.
50
+
51
+@mcr ---- .... opc1:3 . crn:4 rt:4 cp:4 opc2:3 . crm:4 &mcr
52
+@mcrr ---- .... .... rt2:4 rt:4 cp:4 opc1:4 crm:4 &mcrr
53
+
54
+MCRR .... 1100 0100 .... .... .... .... .... @mcrr
55
+MRRC .... 1100 0101 .... .... .... .... .... @mcrr
56
+
57
+MCR .... 1110 ... 0 .... .... .... ... 1 .... @mcr
58
+MRC .... 1110 ... 1 .... .... .... ... 1 .... @mcr
59
+
60
# Supervisor call
61
62
SVC ---- 1111 imm:24 &i
63
diff --git a/target/arm/helper.c b/target/arm/helper.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/helper.c
66
+++ b/target/arm/helper.c
67
@@ -XXX,XX +XXX,XX @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
68
assert((r->state != ARM_CP_STATE_AA32) || (r->opc0 == 0));
69
/* AArch64 regs are all 64 bit so ARM_CP_64BIT is meaningless */
70
assert((r->state != ARM_CP_STATE_AA64) || !(r->type & ARM_CP_64BIT));
71
+ /*
72
+ * This API is only for Arm's system coprocessors (14 and 15) or
73
+ * (M-profile or v7A-and-earlier only) for implementation defined
74
+ * coprocessors in the range 0..7. Our decode assumes this, since
75
+ * 8..13 can be used for other insns including VFP and Neon. See
76
+ * valid_cp() in translate.c. Assert here that we haven't tried
77
+ * to use an invalid coprocessor number.
78
+ */
79
+ switch (r->state) {
80
+ case ARM_CP_STATE_BOTH:
81
+ /* 0 has a special meaning, but otherwise the same rules as AA32. */
82
+ if (r->cp == 0) {
83
+ break;
84
+ }
85
+ /* fall through */
86
+ case ARM_CP_STATE_AA32:
87
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8) &&
88
+ !arm_feature(&cpu->env, ARM_FEATURE_M)) {
89
+ assert(r->cp >= 14 && r->cp <= 15);
90
+ } else {
91
+ assert(r->cp < 8 || (r->cp >= 14 && r->cp <= 15));
92
+ }
93
+ break;
94
+ case ARM_CP_STATE_AA64:
95
+ assert(r->cp == 0 || r->cp == CP_REG_ARM64_SYSREG_CP);
96
+ break;
97
+ default:
98
+ g_assert_not_reached();
99
+ }
100
/* The AArch64 pseudocode CheckSystemAccess() specifies that op1
101
* encodes a minimum access level for the register. We roll this
102
* runtime check into our general permission check code, so check
103
diff --git a/target/arm/translate.c b/target/arm/translate.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/target/arm/translate.c
106
+++ b/target/arm/translate.c
107
@@ -XXX,XX +XXX,XX @@ static int t16_pop_list(DisasContext *s, int x)
108
#include "decode-t32.c.inc"
109
#include "decode-t16.c.inc"
110
111
+static bool valid_cp(DisasContext *s, int cp)
112
+{
34
+{
113
+ /*
35
+ status->default_nan_pattern = dnan_pattern;
114
+ * Return true if this coprocessor field indicates something
115
+ * that's really a possible coprocessor.
116
+ * For v7 and earlier, coprocessors 8..15 were reserved for Arm use,
117
+ * and of those only cp14 and cp15 were used for registers.
118
+ * cp10 and cp11 were used for VFP and Neon, whose decode is
119
+ * dealt with elsewhere. With the advent of fp16, cp9 is also
120
+ * now part of VFP.
121
+ * For v8A and later, the encoding has been tightened so that
122
+ * only cp14 and cp15 are valid, and other values aren't considered
123
+ * to be in the coprocessor-instruction space at all. v8M still
124
+ * permits coprocessors 0..7.
125
+ */
126
+ if (arm_dc_feature(s, ARM_FEATURE_V8) &&
127
+ !arm_dc_feature(s, ARM_FEATURE_M)) {
128
+ return cp >= 14;
129
+ }
130
+ return cp < 8 || cp >= 14;
131
+}
36
+}
132
+
37
+
133
+static bool trans_MCR(DisasContext *s, arg_MCR *a)
38
static inline void set_flush_to_zero(bool val, float_status *status)
39
{
40
status->flush_to_zero = val;
41
@@ -XXX,XX +XXX,XX @@ static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status
42
return status->float_infzeronan_rule;
43
}
44
45
+static inline uint8_t get_float_default_nan_pattern(float_status *status)
134
+{
46
+{
135
+ if (!valid_cp(s, a->cp)) {
47
+ return status->default_nan_pattern;
136
+ return false;
137
+ }
138
+ do_coproc_insn(s, a->cp, false, a->opc1, a->crn, a->crm, a->opc2,
139
+ false, a->rt, 0);
140
+ return true;
141
+}
48
+}
142
+
49
+
143
+static bool trans_MRC(DisasContext *s, arg_MRC *a)
50
static inline bool get_flush_to_zero(float_status *status)
144
+{
51
{
145
+ if (!valid_cp(s, a->cp)) {
52
return status->flush_to_zero;
146
+ return false;
53
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/include/fpu/softfloat-types.h
56
+++ b/include/fpu/softfloat-types.h
57
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
58
/* should denormalised inputs go to zero and set the input_denormal flag? */
59
bool flush_inputs_to_zero;
60
bool default_nan_mode;
61
+ /*
62
+ * The pattern to use for the default NaN. Here the high bit specifies
63
+ * the default NaN's sign bit, and bits 6..0 specify the high bits of the
64
+ * fractional part. The low bits of the fractional part are copies of bit 0.
65
+ * The exponent of the default NaN is (as for any NaN) always all 1s.
66
+ * Note that a value of 0 here is not a valid NaN. The target must set
67
+ * this to the correct non-zero value, or we will assert when trying to
68
+ * create a default NaN.
69
+ */
70
+ uint8_t default_nan_pattern;
71
/*
72
* The flags below are not used on all specializations and may
73
* constant fold away (see snan_bit_is_one()/no_signalling_nans() in
74
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
75
index XXXXXXX..XXXXXXX 100644
76
--- a/fpu/softfloat-specialize.c.inc
77
+++ b/fpu/softfloat-specialize.c.inc
78
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
79
{
80
bool sign = 0;
81
uint64_t frac;
82
+ uint8_t dnan_pattern = status->default_nan_pattern;
83
84
+ if (dnan_pattern == 0) {
85
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
86
- /* !snan_bit_is_one, set all bits */
87
- frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
88
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
89
+ /* Sign bit clear, all frac bits set */
90
+ dnan_pattern = 0b01111111;
91
+#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
92
|| defined(TARGET_MICROBLAZE)
93
- /* !snan_bit_is_one, set sign and msb */
94
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
95
- sign = 1;
96
+ /* Sign bit set, most significant frac bit set */
97
+ dnan_pattern = 0b11000000;
98
#elif defined(TARGET_HPPA)
99
- /* snan_bit_is_one, set msb-1. */
100
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
101
+ /* Sign bit clear, msb-1 frac bit set */
102
+ dnan_pattern = 0b00100000;
103
#elif defined(TARGET_HEXAGON)
104
- sign = 1;
105
- frac = ~0ULL;
106
+ /* Sign bit set, all frac bits set. */
107
+ dnan_pattern = 0b11111111;
108
#else
109
- /*
110
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
111
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
112
- * do not have floating-point.
113
- */
114
- if (snan_bit_is_one(status)) {
115
- /* set all bits other than msb */
116
- frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1;
117
- } else {
118
- /* set msb */
119
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
120
- }
121
+ /*
122
+ * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
123
+ * S390, SH4, TriCore, and Xtensa. Our other supported targets
124
+ * do not have floating-point.
125
+ */
126
+ if (snan_bit_is_one(status)) {
127
+ /* sign bit clear, set all frac bits other than msb */
128
+ dnan_pattern = 0b00111111;
129
+ } else {
130
+ /* sign bit clear, set frac msb */
131
+ dnan_pattern = 0b01000000;
132
+ }
133
#endif
147
+ }
134
+ }
148
+ do_coproc_insn(s, a->cp, false, a->opc1, a->crn, a->crm, a->opc2,
135
+ assert(dnan_pattern != 0);
149
+ true, a->rt, 0);
150
+ return true;
151
+}
152
+
136
+
153
+static bool trans_MCRR(DisasContext *s, arg_MCRR *a)
137
+ sign = dnan_pattern >> 7;
154
+{
138
+ /*
155
+ if (!valid_cp(s, a->cp)) {
139
+ * Place default_nan_pattern [6:0] into bits [62:56],
156
+ return false;
140
+ * and replecate bit [0] down into [55:0]
157
+ }
141
+ */
158
+ do_coproc_insn(s, a->cp, true, a->opc1, 0, a->crm, 0,
142
+ frac = deposit64(0, DECOMPOSED_BINARY_POINT - 7, 7, dnan_pattern);
159
+ false, a->rt, a->rt2);
143
+ frac = deposit64(frac, 0, DECOMPOSED_BINARY_POINT - 7, -(dnan_pattern & 1));
160
+ return true;
144
161
+}
145
*p = (FloatParts64) {
162
+
146
.cls = float_class_qnan,
163
+static bool trans_MRRC(DisasContext *s, arg_MRRC *a)
164
+{
165
+ if (!valid_cp(s, a->cp)) {
166
+ return false;
167
+ }
168
+ do_coproc_insn(s, a->cp, true, a->opc1, 0, a->crm, 0,
169
+ true, a->rt, a->rt2);
170
+ return true;
171
+}
172
+
173
/* Helpers to swap operands for reverse-subtract. */
174
static void gen_rsb(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
175
{
176
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
177
disas_xscale_insn(s, insn);
178
break;
179
}
180
-
181
- if ((cpnum & 0xe) == 10) {
182
- /* VFP, but failed disas_vfp. */
183
- goto illegal_op;
184
- }
185
-
186
- if (disas_coproc_insn(s, insn)) {
187
- /* Coprocessor. */
188
- goto illegal_op;
189
- }
190
- break;
191
+ /* fall through */
192
}
193
default:
194
illegal_op:
195
--
147
--
196
2.20.1
148
2.34.1
197
198
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for the tests/fp code.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-36-peter.maydell@linaro.org
6
---
7
tests/fp/fp-bench.c | 1 +
8
tests/fp/fp-test-log2.c | 1 +
9
tests/fp/fp-test.c | 1 +
10
3 files changed, 3 insertions(+)
11
12
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/fp/fp-bench.c
15
+++ b/tests/fp/fp-bench.c
16
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
17
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
18
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &soft_status);
19
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
20
+ set_float_default_nan_pattern(0b01000000, &soft_status);
21
22
f = bench_funcs[operation][precision];
23
g_assert(f);
24
diff --git a/tests/fp/fp-test-log2.c b/tests/fp/fp-test-log2.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/tests/fp/fp-test-log2.c
27
+++ b/tests/fp/fp-test-log2.c
28
@@ -XXX,XX +XXX,XX @@ int main(int ac, char **av)
29
int i;
30
31
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
32
+ set_float_default_nan_pattern(0b01000000, &qsf);
33
set_float_rounding_mode(float_round_nearest_even, &qsf);
34
35
test.d = 0.0;
36
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/fp/fp-test.c
39
+++ b/tests/fp/fp-test.c
40
@@ -XXX,XX +XXX,XX @@ void run_test(void)
41
*/
42
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
43
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &qsf);
44
+ set_float_default_nan_pattern(0b01000000, &qsf);
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
46
47
genCases_setLevel(test_level);
48
--
49
2.34.1
diff view generated by jsdifflib
1
The ARCH() macro was used a lot in the legacy decoder, but
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
there are now just two uses of it left. Since a macro which
2
parts64_default_nan().
3
expands out to a goto is liable to be confusing when reading
4
code, replace the last two uses with a simple open-coded
5
qeuivalent.
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: 20200803111849.13368-8-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-37-peter.maydell@linaro.org
10
---
7
---
11
target/arm/translate.c | 14 +++++++++-----
8
target/microblaze/cpu.c | 2 ++
12
1 file changed, 9 insertions(+), 5 deletions(-)
9
fpu/softfloat-specialize.c.inc | 3 +--
10
2 files changed, 3 insertions(+), 2 deletions(-)
13
11
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.c
14
--- a/target/microblaze/cpu.c
17
+++ b/target/arm/translate.c
15
+++ b/target/microblaze/cpu.c
18
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_reset_hold(Object *obj, ResetType type)
19
#define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
17
* this architecture.
20
#define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
18
*/
21
19
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
22
-#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
20
+ /* Default NaN: sign bit set, most significant frac bit set */
23
-
21
+ set_float_default_nan_pattern(0b11000000, &env->fp_status);
24
#include "translate.h"
25
22
26
#if defined(CONFIG_USER_ONLY)
23
#if defined(CONFIG_USER_ONLY)
27
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
24
/* start in user mode with interrupts enabled. */
28
{
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
29
TCGv_i32 tmp;
26
index XXXXXXX..XXXXXXX 100644
30
27
--- a/fpu/softfloat-specialize.c.inc
31
- /* For A32, ARCH(5) is checked near the start of the uncond block. */
28
+++ b/fpu/softfloat-specialize.c.inc
32
+ /* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
33
if (s->thumb && (a->imm & 2)) {
30
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
34
return false;
31
/* Sign bit clear, all frac bits set */
35
}
32
dnan_pattern = 0b01111111;
36
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
33
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
37
* choose to UNDEF. In ARMv5 and above the space is used
34
- || defined(TARGET_MICROBLAZE)
38
* for miscellaneous unconditional instructions.
35
+#elif defined(TARGET_I386) || defined(TARGET_X86_64)
39
*/
36
/* Sign bit set, most significant frac bit set */
40
- ARCH(5);
37
dnan_pattern = 0b11000000;
41
+ if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
38
#elif defined(TARGET_HPPA)
42
+ unallocated_encoding(s);
43
+ return;
44
+ }
45
46
/* Unconditional instructions. */
47
/* TODO: Perhaps merge these into one decodetree output file. */
48
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
49
goto illegal_op;
50
}
51
} else if ((insn & 0xf800e800) != 0xf000e800) {
52
- ARCH(6T2);
53
+ if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
54
+ unallocated_encoding(s);
55
+ return;
56
+ }
57
}
58
59
if (arm_dc_feature(s, ARM_FEATURE_M)) {
60
--
39
--
61
2.20.1
40
2.34.1
62
63
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
parts64_default_nan().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-38-peter.maydell@linaro.org
7
---
8
target/i386/tcg/fpu_helper.c | 4 ++++
9
fpu/softfloat-specialize.c.inc | 3 ---
10
2 files changed, 4 insertions(+), 3 deletions(-)
11
12
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/i386/tcg/fpu_helper.c
15
+++ b/target/i386/tcg/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
17
*/
18
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
19
set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
20
+ /* Default NaN: sign bit set, most significant frac bit set */
21
+ set_float_default_nan_pattern(0b11000000, &env->fp_status);
22
+ set_float_default_nan_pattern(0b11000000, &env->mmx_status);
23
+ set_float_default_nan_pattern(0b11000000, &env->sse_status);
24
}
25
26
static inline uint8_t save_exception_flags(CPUX86State *env)
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
index XXXXXXX..XXXXXXX 100644
29
--- a/fpu/softfloat-specialize.c.inc
30
+++ b/fpu/softfloat-specialize.c.inc
31
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
32
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
33
/* Sign bit clear, all frac bits set */
34
dnan_pattern = 0b01111111;
35
-#elif defined(TARGET_I386) || defined(TARGET_X86_64)
36
- /* Sign bit set, most significant frac bit set */
37
- dnan_pattern = 0b11000000;
38
#elif defined(TARGET_HPPA)
39
/* Sign bit clear, msb-1 frac bit set */
40
dnan_pattern = 0b00100000;
41
--
42
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
parts64_default_nan().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-39-peter.maydell@linaro.org
7
---
8
target/hppa/fpu_helper.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 ---
10
2 files changed, 2 insertions(+), 3 deletions(-)
11
12
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/hppa/fpu_helper.c
15
+++ b/target/hppa/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
17
set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
18
/* For inf * 0 + NaN, return the input NaN */
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ /* Default NaN: sign bit clear, msb-1 frac bit set */
21
+ set_float_default_nan_pattern(0b00100000, &env->fp_status);
22
}
23
24
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
30
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
31
/* Sign bit clear, all frac bits set */
32
dnan_pattern = 0b01111111;
33
-#elif defined(TARGET_HPPA)
34
- /* Sign bit clear, msb-1 frac bit set */
35
- dnan_pattern = 0b00100000;
36
#elif defined(TARGET_HEXAGON)
37
/* Sign bit set, all frac bits set. */
38
dnan_pattern = 0b11111111;
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for the alpha target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-40-peter.maydell@linaro.org
6
---
7
target/alpha/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/alpha/cpu.c
13
+++ b/target/alpha/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_initfn(Object *obj)
15
* operand in Fa. That is float_2nan_prop_ba.
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
18
+ /* Default NaN: sign bit clear, msb frac bit set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
#if defined(CONFIG_USER_ONLY)
21
env->flags = ENV_FLAG_PS_USER | ENV_FLAG_FEN;
22
cpu_alpha_store_fpcr(env, (uint64_t)(FPCR_INVD | FPCR_DZED | FPCR_OVFD
23
--
24
2.34.1
diff view generated by jsdifflib
1
Architecturally, Neon FP16 operations use the "standard FPSCR" like
1
Set the default NaN pattern explicitly for the arm target.
2
all other Neon operations. However, this is defined in the Arm ARM
2
This includes setting it for the old linux-user nwfpe emulation.
3
pseudocode as "a fixed value, except that FZ16 (and AHP) follow the
3
For nwfpe, our default doesn't match the real kernel, but we
4
FPSCR bits". In QEMU, the softfloat float_status doesn't include
4
avoid making a behaviour change in this commit.
5
separate flush-to-zero for FP16 operations, so we must keep separate
6
fp_status for "Neon non-FP16" and "Neon fp16" operations, in the
7
same way we do already for the non-Neon "fp_status" vs "fp_status_f16".
8
9
Add the extra float_status field to the CPU state structure,
10
ensure it is correctly initialized and updated on FPSCR writes,
11
and make fpstatus_ptr(FPST_STD_F16) return a pointer to it.
12
5
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 20241202131347.498124-41-peter.maydell@linaro.org
16
Message-id: 20200806104453.30393-4-peter.maydell@linaro.org
17
---
9
---
18
target/arm/cpu.h | 9 ++++++++-
10
linux-user/arm/nwfpe/fpa11.c | 5 +++++
19
target/arm/translate.h | 3 ++-
11
target/arm/cpu.c | 2 ++
20
target/arm/cpu.c | 3 +++
12
2 files changed, 7 insertions(+)
21
target/arm/vfp_helper.c | 5 +++++
22
4 files changed, 18 insertions(+), 2 deletions(-)
23
13
24
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
25
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.h
16
--- a/linux-user/arm/nwfpe/fpa11.c
27
+++ b/target/arm/cpu.h
17
+++ b/linux-user/arm/nwfpe/fpa11.c
28
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
18
@@ -XXX,XX +XXX,XX @@ void resetFPA11(void)
29
* fp_status: is the "normal" fp status.
19
* this late date.
30
* fp_status_fp16: used for half-precision calculations
20
*/
31
* standard_fp_status : the ARM "Standard FPSCR Value"
21
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &fpa11->fp_status);
32
+ * standard_fp_status_fp16 : used for half-precision
22
+ /*
33
+ * calculations with the ARM "Standard FPSCR Value"
23
+ * Use the same default NaN value as Arm VFP. This doesn't match
34
*
24
+ * the Linux kernel's nwfpe emulation, which uses an all-1s value.
35
* Half-precision operations are governed by a separate
25
+ */
36
* flush-to-zero control bit in FPSCR:FZ16. We pass a separate
26
+ set_float_default_nan_pattern(0b01000000, &fpa11->fp_status);
37
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
27
}
38
* Neon) which the architecture defines as controlled by the
28
39
* standard FPSCR value rather than the FPSCR.
29
void SetRoundingMode(const unsigned int opcode)
40
*
41
+ * The "standard FPSCR but for fp16 ops" is needed because
42
+ * the "standard FPSCR" tracks the FPSCR.FZ16 bit rather than
43
+ * using a fixed value for it.
44
+ *
45
* To avoid having to transfer exception bits around, we simply
46
* say that the FPSCR cumulative exception flags are the logical
47
- * OR of the flags in the three fp statuses. This relies on the
48
+ * OR of the flags in the four fp statuses. This relies on the
49
* only thing which needs to read the exception flags being
50
* an explicit FPSCR read.
51
*/
52
float_status fp_status;
53
float_status fp_status_f16;
54
float_status standard_fp_status;
55
+ float_status standard_fp_status_f16;
56
57
/* ZCR_EL[1-3] */
58
uint64_t zcr_el[4];
59
diff --git a/target/arm/translate.h b/target/arm/translate.h
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/translate.h
62
+++ b/target/arm/translate.h
63
@@ -XXX,XX +XXX,XX @@ static inline TCGv_ptr fpstatus_ptr(ARMFPStatusFlavour flavour)
64
offset = offsetof(CPUARMState, vfp.standard_fp_status);
65
break;
66
case FPST_STD_F16:
67
- /* Not yet used or implemented: fall through to assert */
68
+ offset = offsetof(CPUARMState, vfp.standard_fp_status_f16);
69
+ break;
70
default:
71
g_assert_not_reached();
72
}
73
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
74
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
75
--- a/target/arm/cpu.c
32
--- a/target/arm/cpu.c
76
+++ b/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
77
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
34
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
78
set_flush_to_zero(1, &env->vfp.standard_fp_status);
35
* the pseudocode function the arguments are in the order c, a, b.
79
set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
36
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
80
set_default_nan_mode(1, &env->vfp.standard_fp_status);
37
* and the input NaN if it is signalling
81
+ set_default_nan_mode(1, &env->vfp.standard_fp_status_f16);
38
+ * * Default NaN has sign bit clear, msb frac bit set
82
set_float_detect_tininess(float_tininess_before_rounding,
39
*/
83
&env->vfp.fp_status);
40
static void arm_set_default_fp_behaviours(float_status *s)
84
set_float_detect_tininess(float_tininess_before_rounding,
41
{
85
&env->vfp.standard_fp_status);
42
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
86
set_float_detect_tininess(float_tininess_before_rounding,
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
87
&env->vfp.fp_status_f16);
44
set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
88
+ set_float_detect_tininess(float_tininess_before_rounding,
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
89
+ &env->vfp.standard_fp_status_f16);
46
+ set_float_default_nan_pattern(0b01000000, s);
90
#ifndef CONFIG_USER_ONLY
91
if (kvm_enabled()) {
92
kvm_arm_reset_vcpu(cpu);
93
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/vfp_helper.c
96
+++ b/target/arm/vfp_helper.c
97
@@ -XXX,XX +XXX,XX @@ static uint32_t vfp_get_fpscr_from_host(CPUARMState *env)
98
/* FZ16 does not generate an input denormal exception. */
99
i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
100
& ~float_flag_input_denormal);
101
+ i |= (get_float_exception_flags(&env->vfp.standard_fp_status_f16)
102
+ & ~float_flag_input_denormal);
103
return vfp_exceptbits_from_host(i);
104
}
47
}
105
48
106
@@ -XXX,XX +XXX,XX @@ static void vfp_set_fpscr_to_host(CPUARMState *env, uint32_t val)
49
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
107
if (changed & FPCR_FZ16) {
108
bool ftz_enabled = val & FPCR_FZ16;
109
set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
110
+ set_flush_to_zero(ftz_enabled, &env->vfp.standard_fp_status_f16);
111
set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
112
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.standard_fp_status_f16);
113
}
114
if (changed & FPCR_FZ) {
115
bool ftz_enabled = val & FPCR_FZ;
116
@@ -XXX,XX +XXX,XX @@ static void vfp_set_fpscr_to_host(CPUARMState *env, uint32_t val)
117
set_float_exception_flags(i, &env->vfp.fp_status);
118
set_float_exception_flags(0, &env->vfp.fp_status_f16);
119
set_float_exception_flags(0, &env->vfp.standard_fp_status);
120
+ set_float_exception_flags(0, &env->vfp.standard_fp_status_f16);
121
}
122
123
#else
124
--
50
--
125
2.20.1
51
2.34.1
126
127
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for loongarch.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-42-peter.maydell@linaro.org
6
---
7
target/loongarch/tcg/fpu_helper.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/loongarch/tcg/fpu_helper.c
13
+++ b/target/loongarch/tcg/fpu_helper.c
14
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
15
*/
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
17
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
18
+ /* Default NaN: sign bit clear, msb frac bit set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
}
21
22
int ieee_ex_to_loongarch(int xcpt)
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for m68k.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-43-peter.maydell@linaro.org
6
---
7
target/m68k/cpu.c | 2 ++
8
fpu/softfloat-specialize.c.inc | 2 +-
9
2 files changed, 3 insertions(+), 1 deletion(-)
10
11
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/m68k/cpu.c
14
+++ b/target/m68k/cpu.c
15
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
16
* preceding paragraph for nonsignaling NaNs.
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
+ /* Default NaN: sign bit clear, all frac bits set */
20
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
21
22
nan = floatx80_default_nan(&env->fp_status);
23
for (i = 0; i < 8; i++) {
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
29
uint8_t dnan_pattern = status->default_nan_pattern;
30
31
if (dnan_pattern == 0) {
32
-#if defined(TARGET_SPARC) || defined(TARGET_M68K)
33
+#if defined(TARGET_SPARC)
34
/* Sign bit clear, all frac bits set */
35
dnan_pattern = 0b01111111;
36
#elif defined(TARGET_HEXAGON)
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for MIPS. Note that this
2
is our only target which currently changes the default NaN
3
at runtime (which it was previously doing indirectly when it
4
changed the snan_bit_is_one setting).
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241202131347.498124-44-peter.maydell@linaro.org
9
---
10
target/mips/fpu_helper.h | 7 +++++++
11
target/mips/msa.c | 3 +++
12
2 files changed, 10 insertions(+)
13
14
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/mips/fpu_helper.h
17
+++ b/target/mips/fpu_helper.h
18
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
19
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
20
nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
21
set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
22
+ /*
23
+ * With nan2008, the default NaN value has the sign bit clear and the
24
+ * frac msb set; with the older mode, the sign bit is clear, and all
25
+ * frac bits except the msb are set.
26
+ */
27
+ set_float_default_nan_pattern(nan2008 ? 0b01000000 : 0b00111111,
28
+ &env->active_fpu.fp_status);
29
30
}
31
32
diff --git a/target/mips/msa.c b/target/mips/msa.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/mips/msa.c
35
+++ b/target/mips/msa.c
36
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
37
/* Inf * 0 + NaN returns the input NaN */
38
set_float_infzeronan_rule(float_infzeronan_dnan_never,
39
&env->active_tc.msa_fp_status);
40
+ /* Default NaN: sign bit clear, frac msb set */
41
+ set_float_default_nan_pattern(0b01000000,
42
+ &env->active_tc.msa_fp_status);
43
}
44
--
45
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for openrisc.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-45-peter.maydell@linaro.org
6
---
7
target/openrisc/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/openrisc/cpu.c
13
+++ b/target/openrisc/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_reset_hold(Object *obj, ResetType type)
15
*/
16
set_float_2nan_prop_rule(float_2nan_prop_x87, &cpu->env.fp_status);
17
18
+ /* Default NaN: sign bit clear, frac msb set */
19
+ set_float_default_nan_pattern(0b01000000, &cpu->env.fp_status);
20
21
#ifndef CONFIG_USER_ONLY
22
cpu->env.picmr = 0x00000000;
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for ppc.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-46-peter.maydell@linaro.org
6
---
7
target/ppc/cpu_init.c | 4 ++++
8
1 file changed, 4 insertions(+)
9
10
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/ppc/cpu_init.c
13
+++ b/target/ppc/cpu_init.c
14
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
15
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
17
18
+ /* Default NaN: sign bit clear, set frac msb */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
+ set_float_default_nan_pattern(0b01000000, &env->vec_status);
21
+
22
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
23
ppc_spr_t *spr = &env->spr_cb[i];
24
25
--
26
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for sh4. Note that sh4
2
is one of the only three targets (the others being HPPA and
3
sometimes MIPS) that has snan_bit_is_one set.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241202131347.498124-47-peter.maydell@linaro.org
8
---
9
target/sh4/cpu.c | 2 ++
10
1 file changed, 2 insertions(+)
11
12
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sh4/cpu.c
15
+++ b/target/sh4/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
17
set_flush_to_zero(1, &env->fp_status);
18
#endif
19
set_default_nan_mode(1, &env->fp_status);
20
+ /* sign bit clear, set all frac bits other than msb */
21
+ set_float_default_nan_pattern(0b00111111, &env->fp_status);
22
}
23
24
static void superh_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
25
--
26
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for rx.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-48-peter.maydell@linaro.org
6
---
7
target/rx/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/rx/cpu.c
13
+++ b/target/rx/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_reset_hold(Object *obj, ResetType type)
15
* then prefer dest over source", which is float_2nan_prop_s_ab.
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
18
+ /* Default NaN value: sign bit clear, set frac msb */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
}
21
22
static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for s390x.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-49-peter.maydell@linaro.org
6
---
7
target/s390x/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/s390x/cpu.c
13
+++ b/target/s390x/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
15
set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
16
set_float_infzeronan_rule(float_infzeronan_dnan_always,
17
&env->fpu_status);
18
+ /* Default NaN value: sign bit clear, frac msb set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fpu_status);
20
/* fall through */
21
case RESET_TYPE_S390_CPU_NORMAL:
22
env->psw.mask &= ~PSW_MASK_RI;
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for SPARC, and remove
2
the ifdef from parts64_default_nan.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-50-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 5 +----
10
2 files changed, 3 insertions(+), 4 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
18
/* For inf * 0 + NaN, return the input NaN */
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ /* Default NaN value: sign bit clear, all frac bits set */
21
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
22
23
cpu_exec_realizefn(cs, &local_err);
24
if (local_err != NULL) {
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
30
uint8_t dnan_pattern = status->default_nan_pattern;
31
32
if (dnan_pattern == 0) {
33
-#if defined(TARGET_SPARC)
34
- /* Sign bit clear, all frac bits set */
35
- dnan_pattern = 0b01111111;
36
-#elif defined(TARGET_HEXAGON)
37
+#if defined(TARGET_HEXAGON)
38
/* Sign bit set, all frac bits set. */
39
dnan_pattern = 0b11111111;
40
#else
41
--
42
2.34.1
diff view generated by jsdifflib
1
In arm_tr_init_disas_context() we have a FIXME comment that suggests
1
Set the default NaN pattern explicitly for xtensa.
2
"cpu_M0 can probably be the same as cpu_V0". This isn't in fact
3
possible: cpu_V0 is used as a temporary inside gen_iwmmxt_shift(),
4
and that function is called in various places where cpu_M0 contains a
5
live value (i.e. between gen_op_iwmmxt_movq_M0_wRn() and
6
gen_op_iwmmxt_movq_wRn_M0() calls). Remove the comment.
7
8
We also have a comment on the declarations of cpu_V0/V1/M0 which
9
claims they're "for efficiency". This isn't true with modern TCG, so
10
replace this comment with one which notes that they're only used with
11
the iwmmxt decode.
12
2
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20200803132815.3861-1-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-51-peter.maydell@linaro.org
16
---
6
---
17
target/arm/translate.c | 4 ++--
7
target/xtensa/cpu.c | 2 ++
18
1 file changed, 2 insertions(+), 2 deletions(-)
8
1 file changed, 2 insertions(+)
19
9
20
diff --git a/target/arm/translate.c b/target/arm/translate.c
10
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
21
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/translate.c
12
--- a/target/xtensa/cpu.c
23
+++ b/target/arm/translate.c
13
+++ b/target/xtensa/cpu.c
24
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
25
#define IS_USER(s) (s->user)
15
/* For inf * 0 + NaN, return the input NaN */
26
#endif
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
27
17
set_no_signaling_nans(!dfpu, &env->fp_status);
28
-/* We reuse the same 64-bit temporaries for efficiency. */
18
+ /* Default NaN value: sign bit clear, set frac msb */
29
+/* These are TCG temporaries used only by the legacy iwMMXt decoder */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
30
static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
20
xtensa_use_first_nan(env, !dfpu);
31
+/* These are TCG globals which alias CPUARMState fields */
32
static TCGv_i32 cpu_R[16];
33
TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
34
TCGv_i64 cpu_exclusive_addr;
35
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
36
37
cpu_V0 = tcg_temp_new_i64();
38
cpu_V1 = tcg_temp_new_i64();
39
- /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
40
cpu_M0 = tcg_temp_new_i64();
41
}
21
}
42
22
43
--
23
--
44
2.20.1
24
2.34.1
45
46
diff view generated by jsdifflib
1
At the moment we check for XScale/iwMMXt insns inside
1
Set the default NaN pattern explicitly for hexagon.
2
disas_coproc_insn(): for CPUs with ARM_FEATURE_XSCALE all copro insns
2
Remove the ifdef from parts64_default_nan(); the only
3
with cp 0 or 1 are handled specially. This works, but is an odd
3
remaining unconverted targets all use the default case.
4
place for this check, because disas_coproc_insn() is called from both
5
the Arm and Thumb decoders but the XScale case never applies for
6
Thumb (all the XScale CPUs were ARMv5, which has only Thumb1, not
7
Thumb2 with the 32-bit coprocessor insn encodings). It also makes it
8
awkward to convert the real copro access insns to decodetree.
9
10
Move the identification of XScale out to its own function
11
which is only called from disas_arm_insn().
12
4
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20200803111849.13368-2-peter.maydell@linaro.org
7
Message-id: 20241202131347.498124-52-peter.maydell@linaro.org
16
---
8
---
17
target/arm/translate.c | 44 ++++++++++++++++++++++++++++--------------
9
target/hexagon/cpu.c | 2 ++
18
1 file changed, 29 insertions(+), 15 deletions(-)
10
fpu/softfloat-specialize.c.inc | 5 -----
11
2 files changed, 2 insertions(+), 5 deletions(-)
19
12
20
diff --git a/target/arm/translate.c b/target/arm/translate.c
13
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
21
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/translate.c
15
--- a/target/hexagon/cpu.c
23
+++ b/target/arm/translate.c
16
+++ b/target/hexagon/cpu.c
24
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
17
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
25
18
26
cpnum = (insn >> 8) & 0xf;
19
set_default_nan_mode(1, &env->fp_status);
27
20
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
28
- /* First check for coprocessor space used for XScale/iwMMXt insns */
21
+ /* Default NaN value: sign bit set, all frac bits set */
29
- if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
22
+ set_float_default_nan_pattern(0b11111111, &env->fp_status);
30
- if (extract32(s->c15_cpar, cpnum, 1) == 0) {
31
- return 1;
32
- }
33
- if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
34
- return disas_iwmmxt_insn(s, insn);
35
- } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
36
- return disas_dsp_insn(s, insn);
37
- }
38
- return 1;
39
- }
40
-
41
- /* Otherwise treat as a generic register access */
42
is64 = (insn & (1 << 25)) == 0;
43
if (!is64 && ((insn & (1 << 4)) == 0)) {
44
/* cdp */
45
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
46
return 1;
47
}
23
}
48
24
49
+/* Decode XScale DSP or iWMMXt insn (in the copro space, cp=0 or 1) */
25
static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
50
+static void disas_xscale_insn(DisasContext *s, uint32_t insn)
26
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
51
+{
27
index XXXXXXX..XXXXXXX 100644
52
+ int cpnum = (insn >> 8) & 0xf;
28
--- a/fpu/softfloat-specialize.c.inc
53
+
29
+++ b/fpu/softfloat-specialize.c.inc
54
+ if (extract32(s->c15_cpar, cpnum, 1) == 0) {
30
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
55
+ unallocated_encoding(s);
31
uint8_t dnan_pattern = status->default_nan_pattern;
56
+ } else if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
32
57
+ if (disas_iwmmxt_insn(s, insn)) {
33
if (dnan_pattern == 0) {
58
+ unallocated_encoding(s);
34
-#if defined(TARGET_HEXAGON)
59
+ }
35
- /* Sign bit set, all frac bits set. */
60
+ } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
36
- dnan_pattern = 0b11111111;
61
+ if (disas_dsp_insn(s, insn)) {
37
-#else
62
+ unallocated_encoding(s);
38
/*
63
+ }
39
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
64
+ }
40
* S390, SH4, TriCore, and Xtensa. Our other supported targets
65
+}
41
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
66
42
/* sign bit clear, set frac msb */
67
/* Store a 64-bit value to a register pair. Clobbers val. */
43
dnan_pattern = 0b01000000;
68
static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
69
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
70
case 0xc:
71
case 0xd:
72
case 0xe:
73
- if (((insn >> 8) & 0xe) == 10) {
74
+ {
75
+ /* First check for coprocessor space used for XScale/iwMMXt insns */
76
+ int cpnum = (insn >> 8) & 0xf;
77
+
78
+ if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
79
+ disas_xscale_insn(s, insn);
80
+ break;
81
+ }
82
+
83
+ if ((cpnum & 0xe) == 10) {
84
/* VFP, but failed disas_vfp. */
85
goto illegal_op;
86
}
44
}
87
+
45
-#endif
88
if (disas_coproc_insn(s, insn)) {
46
}
89
/* Coprocessor. */
47
assert(dnan_pattern != 0);
90
goto illegal_op;
48
91
}
92
break;
93
+ }
94
default:
95
illegal_op:
96
unallocated_encoding(s);
97
--
49
--
98
2.20.1
50
2.34.1
99
100
diff view generated by jsdifflib
1
As part of the Neon decodetree conversion we removed all
1
Set the default NaN pattern explicitly for riscv.
2
the uses of the VFP_DREG macros, but forgot to remove the
3
macro definitions. Do so now.
4
2
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Message-id: 20241202131347.498124-53-peter.maydell@linaro.org
8
Message-id: 20200803124848.18295-1-peter.maydell@linaro.org
9
---
6
---
10
target/arm/translate.c | 15 ---------------
7
target/riscv/cpu.c | 2 ++
11
1 file changed, 15 deletions(-)
8
1 file changed, 2 insertions(+)
12
9
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
10
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
12
--- a/target/riscv/cpu.c
16
+++ b/target/arm/translate.c
13
+++ b/target/riscv/cpu.c
17
@@ -XXX,XX +XXX,XX @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn)
14
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
18
return 1;
15
cs->exception_index = RISCV_EXCP_NONE;
19
}
16
env->load_res = -1;
20
17
set_default_nan_mode(1, &env->fp_status);
21
-#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
18
+ /* Default NaN value: sign bit clear, frac msb set */
22
-#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
23
- if (dc_isar_feature(aa32_simd_r32, s)) { \
20
env->vill = true;
24
- reg = (((insn) >> (bigbit)) & 0x0f) \
21
25
- | (((insn) >> ((smallbit) - 4)) & 0x10); \
26
- } else { \
27
- if (insn & (1 << (smallbit))) \
28
- return 1; \
29
- reg = ((insn) >> (bigbit)) & 0x0f; \
30
- }} while (0)
31
-
32
-#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
33
-#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
34
-#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
35
-
36
static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
37
{
38
#ifndef CONFIG_USER_ONLY
22
#ifndef CONFIG_USER_ONLY
39
--
23
--
40
2.20.1
24
2.34.1
41
42
diff view generated by jsdifflib
1
The only thing left in the "legacy decoder" is the handling
1
Set the default NaN pattern explicitly for tricore.
2
of disas_xscale_insn(), and we can simplify the code.
3
2
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200803111849.13368-5-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-54-peter.maydell@linaro.org
7
---
6
---
8
target/arm/translate.c | 26 +++++++++-----------------
7
target/tricore/helper.c | 2 ++
9
1 file changed, 9 insertions(+), 17 deletions(-)
8
1 file changed, 2 insertions(+)
10
9
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
10
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
12
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
12
--- a/target/tricore/helper.c
14
+++ b/target/arm/translate.c
13
+++ b/target/tricore/helper.c
15
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
14
@@ -XXX,XX +XXX,XX @@ void fpu_set_state(CPUTriCoreState *env)
16
return;
15
set_flush_to_zero(1, &env->fp_status);
17
}
16
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
18
/* fall back to legacy decoder */
17
set_default_nan_mode(1, &env->fp_status);
19
-
18
+ /* Default NaN pattern: sign bit clear, frac msb set */
20
- switch ((insn >> 24) & 0xf) {
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
21
- case 0xc:
22
- case 0xd:
23
- case 0xe:
24
- {
25
- /* First check for coprocessor space used for XScale/iwMMXt insns */
26
- int cpnum = (insn >> 8) & 0xf;
27
-
28
- if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
29
+ /* TODO: convert xscale/iwmmxt decoder to decodetree ?? */
30
+ if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
31
+ if (((insn & 0x0c000e00) == 0x0c000000)
32
+ && ((insn & 0x03000000) != 0x03000000)) {
33
+ /* Coprocessor insn, coprocessor 0 or 1 */
34
disas_xscale_insn(s, insn);
35
- break;
36
+ return;
37
}
38
- /* fall through */
39
- }
40
- default:
41
- illegal_op:
42
- unallocated_encoding(s);
43
- break;
44
}
45
+
46
+illegal_op:
47
+ unallocated_encoding(s);
48
}
20
}
49
21
50
static bool thumb_insn_is_16bit(DisasContext *s, uint32_t pc, uint32_t insn)
22
uint32_t psw_read(CPUTriCoreState *env)
51
--
23
--
52
2.20.1
24
2.34.1
53
54
diff view generated by jsdifflib
1
In commit 962fcbf2efe57231a9f5df we converted the uses of the
1
Now that all our targets have bene converted to explicitly specify
2
ARM_FEATURE_CRC bit to use the aa32_crc32 isar_feature test
2
their pattern for the default NaN value we can remove the remaining
3
instead. However we forgot to remove the now-unused definition
3
fallback code in parts64_default_nan().
4
of the feature name in the enum. Delete it now.
5
4
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20241202131347.498124-55-peter.maydell@linaro.org
9
Message-id: 20200805210848.6688-1-peter.maydell@linaro.org
10
---
8
---
11
target/arm/cpu.h | 1 -
9
fpu/softfloat-specialize.c.inc | 14 --------------
12
1 file changed, 1 deletion(-)
10
1 file changed, 14 deletions(-)
13
11
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
14
--- a/fpu/softfloat-specialize.c.inc
17
+++ b/target/arm/cpu.h
15
+++ b/fpu/softfloat-specialize.c.inc
18
@@ -XXX,XX +XXX,XX @@ enum arm_features {
16
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
19
ARM_FEATURE_V8,
17
uint64_t frac;
20
ARM_FEATURE_AARCH64, /* supports 64 bit mode */
18
uint8_t dnan_pattern = status->default_nan_pattern;
21
ARM_FEATURE_CBAR, /* has cp15 CBAR */
19
22
- ARM_FEATURE_CRC, /* ARMv8 CRC instructions */
20
- if (dnan_pattern == 0) {
23
ARM_FEATURE_CBAR_RO, /* has cp15 CBAR and it is read-only */
21
- /*
24
ARM_FEATURE_EL2, /* has EL2 Virtualization support */
22
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
25
ARM_FEATURE_EL3, /* has EL3 Secure monitor support */
23
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
24
- * do not have floating-point.
25
- */
26
- if (snan_bit_is_one(status)) {
27
- /* sign bit clear, set all frac bits other than msb */
28
- dnan_pattern = 0b00111111;
29
- } else {
30
- /* sign bit clear, set frac msb */
31
- dnan_pattern = 0b01000000;
32
- }
33
- }
34
assert(dnan_pattern != 0);
35
36
sign = dnan_pattern >> 7;
26
--
37
--
27
2.20.1
38
2.34.1
28
29
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Let's introduce an helper for S1 IOVA range invalidation.
3
Inline pickNaNMulAdd into its only caller. This makes
4
This will be used for NH_VA and NH_VAA commands. It decodes
4
one assert redundant with the immediately preceding IF.
5
the same fields, trace, calls the UNMAP notifiers and
6
invalidate the corresponding IOTLB entries.
7
5
8
At the moment, we do not support 3.2 range invalidation yet.
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
So it reduces to a single IOVA invalidation.
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
8
Message-id: 20241203203949.483774-3-richard.henderson@linaro.org
11
Note the leaf bit now is also decoded for the CMD_TLBI_NH_VAA
9
[PMM: keep comment from old code in new location]
12
command. At the moment it is only used for tracing.
13
14
Signed-off-by: Eric Auger <eric.auger@redhat.com>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Message-id: 20200728150815.11446-7-eric.auger@redhat.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
11
---
19
hw/arm/smmuv3.c | 36 +++++++++++++++++-------------------
12
fpu/softfloat-parts.c.inc | 41 +++++++++++++++++++++++++-
20
hw/arm/trace-events | 3 +--
13
fpu/softfloat-specialize.c.inc | 54 ----------------------------------
21
2 files changed, 18 insertions(+), 21 deletions(-)
14
2 files changed, 40 insertions(+), 55 deletions(-)
22
15
23
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
24
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/smmuv3.c
18
--- a/fpu/softfloat-parts.c.inc
26
+++ b/hw/arm/smmuv3.c
19
+++ b/fpu/softfloat-parts.c.inc
27
@@ -XXX,XX +XXX,XX @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova)
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
21
}
22
23
if (s->default_nan_mode) {
24
+ /*
25
+ * We guarantee not to require the target to tell us how to
26
+ * pick a NaN if we're always returning the default NaN.
27
+ * But if we're not in default-NaN mode then the target must
28
+ * specify.
29
+ */
30
which = 3;
31
+ } else if (infzero) {
32
+ /*
33
+ * Inf * 0 + NaN -- some implementations return the
34
+ * default NaN here, and some return the input NaN.
35
+ */
36
+ switch (s->float_infzeronan_rule) {
37
+ case float_infzeronan_dnan_never:
38
+ which = 2;
39
+ break;
40
+ case float_infzeronan_dnan_always:
41
+ which = 3;
42
+ break;
43
+ case float_infzeronan_dnan_if_qnan:
44
+ which = is_qnan(c->cls) ? 3 : 2;
45
+ break;
46
+ default:
47
+ g_assert_not_reached();
48
+ }
49
} else {
50
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
51
+ FloatClass cls[3] = { a->cls, b->cls, c->cls };
52
+ Float3NaNPropRule rule = s->float_3nan_prop_rule;
53
+
54
+ assert(rule != float_3nan_prop_none);
55
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
56
+ /* We have at least one SNaN input and should prefer it */
57
+ do {
58
+ which = rule & R_3NAN_1ST_MASK;
59
+ rule >>= R_3NAN_1ST_LENGTH;
60
+ } while (!is_snan(cls[which]));
61
+ } else {
62
+ do {
63
+ which = rule & R_3NAN_1ST_MASK;
64
+ rule >>= R_3NAN_1ST_LENGTH;
65
+ } while (!is_nan(cls[which]));
66
+ }
67
}
68
69
if (which == 3) {
70
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
71
index XXXXXXX..XXXXXXX 100644
72
--- a/fpu/softfloat-specialize.c.inc
73
+++ b/fpu/softfloat-specialize.c.inc
74
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
28
}
75
}
29
}
76
}
30
77
31
+static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
78
-/*----------------------------------------------------------------------------
32
+{
79
-| Select which NaN to propagate for a three-input operation.
33
+ dma_addr_t addr = CMD_ADDR(cmd);
80
-| For the moment we assume that no CPU needs the 'larger significand'
34
+ uint8_t type = CMD_TYPE(cmd);
81
-| information.
35
+ uint16_t vmid = CMD_VMID(cmd);
82
-| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
36
+ bool leaf = CMD_LEAF(cmd);
83
-*----------------------------------------------------------------------------*/
37
+ int asid = -1;
84
-static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
38
+
85
- bool infzero, bool have_snan, float_status *status)
39
+ if (type == SMMU_CMD_TLBI_NH_VA) {
86
-{
40
+ asid = CMD_ASID(cmd);
87
- FloatClass cls[3] = { a_cls, b_cls, c_cls };
41
+ }
88
- Float3NaNPropRule rule = status->float_3nan_prop_rule;
42
+ trace_smmuv3_s1_range_inval(vmid, asid, addr, leaf);
89
- int which;
43
+ smmuv3_inv_notifiers_iova(s, asid, addr);
44
+ smmu_iotlb_inv_iova(s, asid, addr);
45
+}
46
+
47
static int smmuv3_cmdq_consume(SMMUv3State *s)
48
{
49
SMMUState *bs = ARM_SMMU(s);
50
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
51
smmu_iotlb_inv_all(bs);
52
break;
53
case SMMU_CMD_TLBI_NH_VAA:
54
- {
55
- dma_addr_t addr = CMD_ADDR(&cmd);
56
- uint16_t vmid = CMD_VMID(&cmd);
57
-
90
-
58
- trace_smmuv3_cmdq_tlbi_nh_vaa(vmid, addr);
91
- /*
59
- smmuv3_inv_notifiers_iova(bs, -1, addr);
92
- * We guarantee not to require the target to tell us how to
60
- smmu_iotlb_inv_iova(bs, -1, addr);
93
- * pick a NaN if we're always returning the default NaN.
61
- break;
94
- * But if we're not in default-NaN mode then the target must
95
- * specify.
96
- */
97
- assert(!status->default_nan_mode);
98
-
99
- if (infzero) {
100
- /*
101
- * Inf * 0 + NaN -- some implementations return the default NaN here,
102
- * and some return the input NaN.
103
- */
104
- switch (status->float_infzeronan_rule) {
105
- case float_infzeronan_dnan_never:
106
- return 2;
107
- case float_infzeronan_dnan_always:
108
- return 3;
109
- case float_infzeronan_dnan_if_qnan:
110
- return is_qnan(c_cls) ? 3 : 2;
111
- default:
112
- g_assert_not_reached();
62
- }
113
- }
63
case SMMU_CMD_TLBI_NH_VA:
114
- }
64
- {
65
- uint16_t asid = CMD_ASID(&cmd);
66
- uint16_t vmid = CMD_VMID(&cmd);
67
- dma_addr_t addr = CMD_ADDR(&cmd);
68
- bool leaf = CMD_LEAF(&cmd);
69
-
115
-
70
- trace_smmuv3_cmdq_tlbi_nh_va(vmid, asid, addr, leaf);
116
- assert(rule != float_3nan_prop_none);
71
- smmuv3_inv_notifiers_iova(bs, asid, addr);
117
- if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
72
- smmu_iotlb_inv_iova(bs, asid, addr);
118
- /* We have at least one SNaN input and should prefer it */
73
+ smmuv3_s1_range_inval(bs, &cmd);
119
- do {
74
break;
120
- which = rule & R_3NAN_1ST_MASK;
75
- }
121
- rule >>= R_3NAN_1ST_LENGTH;
76
case SMMU_CMD_TLBI_EL3_ALL:
122
- } while (!is_snan(cls[which]));
77
case SMMU_CMD_TLBI_EL3_VA:
123
- } else {
78
case SMMU_CMD_TLBI_EL2_ALL:
124
- do {
79
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
125
- which = rule & R_3NAN_1ST_MASK;
80
index XXXXXXX..XXXXXXX 100644
126
- rule >>= R_3NAN_1ST_LENGTH;
81
--- a/hw/arm/trace-events
127
- } while (!is_nan(cls[which]));
82
+++ b/hw/arm/trace-events
128
- }
83
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%d - end=0x%d"
129
- return which;
84
smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d"
130
-}
85
smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)"
131
-
86
smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)"
132
/*----------------------------------------------------------------------------
87
-smmuv3_cmdq_tlbi_nh_va(int vmid, int asid, uint64_t addr, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" leaf=%d"
133
| Returns 1 if the double-precision floating-point value `a' is a quiet
88
-smmuv3_cmdq_tlbi_nh_vaa(int vmid, uint64_t addr) "vmid =%d addr=0x%"PRIx64
134
| NaN; otherwise returns 0.
89
+smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" leaf=%d"
90
smmuv3_cmdq_tlbi_nh(void) ""
91
smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d"
92
smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d"
93
--
135
--
94
2.20.1
136
2.34.1
95
137
96
138
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add two helpers: one to lookup for a given IOTLB entry and
3
Remove "3" as a special case for which and simply
4
one to insert a new entry. We also move the tracing there.
4
branch to return the desired value.
5
5
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20200728150815.11446-3-eric.auger@redhat.com
8
Message-id: 20241203203949.483774-4-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
include/hw/arm/smmu-common.h | 2 ++
11
fpu/softfloat-parts.c.inc | 20 ++++++++++----------
12
hw/arm/smmu-common.c | 36 ++++++++++++++++++++++++++++++++++++
12
1 file changed, 10 insertions(+), 10 deletions(-)
13
hw/arm/smmuv3.c | 26 ++------------------------
14
hw/arm/trace-events | 5 +++--
15
4 files changed, 43 insertions(+), 26 deletions(-)
16
13
17
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/smmu-common.h
16
--- a/fpu/softfloat-parts.c.inc
20
+++ b/include/hw/arm/smmu-common.h
17
+++ b/fpu/softfloat-parts.c.inc
21
@@ -XXX,XX +XXX,XX @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid);
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
22
19
* But if we're not in default-NaN mode then the target must
23
#define SMMU_IOTLB_MAX_SIZE 256
20
* specify.
24
21
*/
25
+IOMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, hwaddr iova);
22
- which = 3;
26
+void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, IOMMUTLBEntry *entry);
23
+ goto default_nan;
27
void smmu_iotlb_inv_all(SMMUState *s);
24
} else if (infzero) {
28
void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
25
/*
29
void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova);
26
* Inf * 0 + NaN -- some implementations return the
30
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
27
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
31
index XXXXXXX..XXXXXXX 100644
28
*/
32
--- a/hw/arm/smmu-common.c
29
switch (s->float_infzeronan_rule) {
33
+++ b/hw/arm/smmu-common.c
30
case float_infzeronan_dnan_never:
34
@@ -XXX,XX +XXX,XX @@
31
- which = 2;
35
32
break;
36
/* IOTLB Management */
33
case float_infzeronan_dnan_always:
37
34
- which = 3;
38
+IOMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
35
- break;
39
+ hwaddr iova)
36
+ goto default_nan;
40
+{
37
case float_infzeronan_dnan_if_qnan:
41
+ SMMUIOTLBKey key = {.asid = cfg->asid, .iova = iova};
38
- which = is_qnan(c->cls) ? 3 : 2;
42
+ IOMMUTLBEntry *entry = g_hash_table_lookup(bs->iotlb, &key);
39
+ if (is_qnan(c->cls)) {
43
+
40
+ goto default_nan;
44
+ if (entry) {
41
+ }
45
+ cfg->iotlb_hits++;
42
break;
46
+ trace_smmu_iotlb_lookup_hit(cfg->asid, iova,
43
default:
47
+ cfg->iotlb_hits, cfg->iotlb_misses,
44
g_assert_not_reached();
48
+ 100 * cfg->iotlb_hits /
45
}
49
+ (cfg->iotlb_hits + cfg->iotlb_misses));
46
+ which = 2;
50
+ } else {
47
} else {
51
+ cfg->iotlb_misses++;
48
FloatClass cls[3] = { a->cls, b->cls, c->cls };
52
+ trace_smmu_iotlb_lookup_miss(cfg->asid, iova,
49
Float3NaNPropRule rule = s->float_3nan_prop_rule;
53
+ cfg->iotlb_hits, cfg->iotlb_misses,
50
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
54
+ 100 * cfg->iotlb_hits /
51
}
55
+ (cfg->iotlb_hits + cfg->iotlb_misses));
56
+ }
57
+ return entry;
58
+}
59
+
60
+void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, IOMMUTLBEntry *entry)
61
+{
62
+ SMMUIOTLBKey *key = g_new0(SMMUIOTLBKey, 1);
63
+
64
+ if (g_hash_table_size(bs->iotlb) >= SMMU_IOTLB_MAX_SIZE) {
65
+ smmu_iotlb_inv_all(bs);
66
+ }
67
+
68
+ key->asid = cfg->asid;
69
+ key->iova = entry->iova;
70
+ trace_smmu_iotlb_insert(cfg->asid, entry->iova);
71
+ g_hash_table_insert(bs->iotlb, key, entry);
72
+}
73
+
74
inline void smmu_iotlb_inv_all(SMMUState *s)
75
{
76
trace_smmu_iotlb_inv_all();
77
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/arm/smmuv3.c
80
+++ b/hw/arm/smmuv3.c
81
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
82
.addr_mask = ~(hwaddr)0,
83
.perm = IOMMU_NONE,
84
};
85
- SMMUIOTLBKey key, *new_key;
86
87
qemu_mutex_lock(&s->mutex);
88
89
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
90
page_mask = (1ULL << (tt->granule_sz)) - 1;
91
aligned_addr = addr & ~page_mask;
92
93
- key.asid = cfg->asid;
94
- key.iova = aligned_addr;
95
-
96
- cached_entry = g_hash_table_lookup(bs->iotlb, &key);
97
+ cached_entry = smmu_iotlb_lookup(bs, cfg, aligned_addr);
98
if (cached_entry) {
99
- cfg->iotlb_hits++;
100
- trace_smmu_iotlb_cache_hit(cfg->asid, aligned_addr,
101
- cfg->iotlb_hits, cfg->iotlb_misses,
102
- 100 * cfg->iotlb_hits /
103
- (cfg->iotlb_hits + cfg->iotlb_misses));
104
if ((flag & IOMMU_WO) && !(cached_entry->perm & IOMMU_WO)) {
105
status = SMMU_TRANS_ERROR;
106
if (event.record_trans_faults) {
107
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
108
goto epilogue;
109
}
52
}
110
53
111
- cfg->iotlb_misses++;
54
- if (which == 3) {
112
- trace_smmu_iotlb_cache_miss(cfg->asid, addr & ~page_mask,
55
- parts_default_nan(a, s);
113
- cfg->iotlb_hits, cfg->iotlb_misses,
56
- return a;
114
- 100 * cfg->iotlb_hits /
115
- (cfg->iotlb_hits + cfg->iotlb_misses));
116
-
117
- if (g_hash_table_size(bs->iotlb) >= SMMU_IOTLB_MAX_SIZE) {
118
- smmu_iotlb_inv_all(bs);
119
- }
57
- }
120
-
58
-
121
cached_entry = g_new0(IOMMUTLBEntry, 1);
59
switch (which) {
122
60
case 0:
123
if (smmu_ptw(cfg, aligned_addr, flag, cached_entry, &ptw_info)) {
61
break;
124
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
62
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
125
}
63
parts_silence_nan(a, s);
126
status = SMMU_TRANS_ERROR;
127
} else {
128
- new_key = g_new0(SMMUIOTLBKey, 1);
129
- new_key->asid = cfg->asid;
130
- new_key->iova = aligned_addr;
131
- g_hash_table_insert(bs->iotlb, new_key, cached_entry);
132
+ smmu_iotlb_insert(bs, cfg, cached_entry);
133
status = SMMU_TRANS_SUCCESS;
134
}
64
}
135
65
return a;
136
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
66
+
137
index XXXXXXX..XXXXXXX 100644
67
+ default_nan:
138
--- a/hw/arm/trace-events
68
+ parts_default_nan(a, s);
139
+++ b/hw/arm/trace-events
69
+ return a;
140
@@ -XXX,XX +XXX,XX @@ smmu_iotlb_inv_all(void) "IOTLB invalidate all"
70
}
141
smmu_iotlb_inv_asid(uint16_t asid) "IOTLB invalidate asid=%d"
71
142
smmu_iotlb_inv_iova(uint16_t asid, uint64_t addr) "IOTLB invalidate asid=%d addr=0x%"PRIx64
72
/*
143
smmu_inv_notifiers_mr(const char *name) "iommu mr=%s"
144
+smmu_iotlb_lookup_hit(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache HIT asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
145
+smmu_iotlb_lookup_miss(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache MISS asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
146
+smmu_iotlb_insert(uint16_t asid, uint64_t addr) "IOTLB ++ asid=%d addr=0x%"PRIx64
147
148
# smmuv3.c
149
smmuv3_read_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
150
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_tlbi_nh_va(int vmid, int asid, uint64_t addr, bool leaf) "vmid =%d a
151
smmuv3_cmdq_tlbi_nh_vaa(int vmid, uint64_t addr) "vmid =%d addr=0x%"PRIx64
152
smmuv3_cmdq_tlbi_nh(void) ""
153
smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d"
154
-smmu_iotlb_cache_hit(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache HIT asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
155
-smmu_iotlb_cache_miss(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache MISS asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
156
smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d"
157
smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
158
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
159
--
73
--
160
2.20.1
74
2.34.1
161
75
162
76
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
HAD is a mandatory features with SMMUv3.1 if S1P is set, which is
3
Assign the pointer return value to 'a' directly,
4
our case. Other 3.1 mandatory features come with S2P which we don't
4
rather than going through an intermediary index.
5
have.
6
5
7
So let's support HAD and advertise SMMUv3.1 support in AIDR.
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
HAD support allows the CD to disable hierarchical attributes, ie.
8
Message-id: 20241203203949.483774-5-richard.henderson@linaro.org
10
if the HAD0/1 bit is set, the APTable field of table descriptors
11
walked through TTB0/1 is ignored.
12
13
Signed-off-by: Eric Auger <eric.auger@redhat.com>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Message-id: 20200728150815.11446-11-eric.auger@redhat.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
10
---
18
hw/arm/smmuv3-internal.h | 2 ++
11
fpu/softfloat-parts.c.inc | 32 ++++++++++----------------------
19
include/hw/arm/smmu-common.h | 1 +
12
1 file changed, 10 insertions(+), 22 deletions(-)
20
hw/arm/smmu-common.c | 2 +-
21
hw/arm/smmuv3.c | 6 +++++-
22
hw/arm/trace-events | 2 +-
23
5 files changed, 10 insertions(+), 3 deletions(-)
24
13
25
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
26
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/smmuv3-internal.h
16
--- a/fpu/softfloat-parts.c.inc
28
+++ b/hw/arm/smmuv3-internal.h
17
+++ b/fpu/softfloat-parts.c.inc
29
@@ -XXX,XX +XXX,XX @@ REG32(IDR1, 0x4)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
30
19
FloatPartsN *c, float_status *s,
31
REG32(IDR2, 0x8)
20
int ab_mask, int abc_mask)
32
REG32(IDR3, 0xc)
21
{
33
+ FIELD(IDR3, HAD, 2, 1);
22
- int which;
34
REG32(IDR4, 0x10)
23
bool infzero = (ab_mask == float_cmask_infzero);
35
REG32(IDR5, 0x14)
24
bool have_snan = (abc_mask & float_cmask_snan);
36
FIELD(IDR5, OAS, 0, 3);
25
+ FloatPartsN *ret;
37
@@ -XXX,XX +XXX,XX @@ static inline int pa_range(STE *ste)
26
38
lo = (x)->word[(sel) * 2 + 2] & ~0xfULL; \
27
if (unlikely(have_snan)) {
39
hi | lo; \
28
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
40
})
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
41
+#define CD_HAD(x, sel) extract32((x)->word[(sel) * 2 + 2], 1, 1)
30
default:
42
31
g_assert_not_reached();
43
#define CD_TSZ(x, sel) extract32((x)->word[0], (16 * (sel)) + 0, 6)
44
#define CD_TG(x, sel) extract32((x)->word[0], (16 * (sel)) + 6, 2)
45
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/hw/arm/smmu-common.h
48
+++ b/include/hw/arm/smmu-common.h
49
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUTransTableInfo {
50
uint64_t ttb; /* TT base address */
51
uint8_t tsz; /* input range, ie. 2^(64 -tsz)*/
52
uint8_t granule_sz; /* granule page shift */
53
+ bool had; /* hierarchical attribute disable */
54
} SMMUTransTableInfo;
55
56
typedef struct SMMUTLBEntry {
57
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/arm/smmu-common.c
60
+++ b/hw/arm/smmu-common.c
61
@@ -XXX,XX +XXX,XX @@ static int smmu_ptw_64(SMMUTransCfg *cfg,
62
if (is_table_pte(pte, level)) {
63
ap = PTE_APTABLE(pte);
64
65
- if (is_permission_fault(ap, perm)) {
66
+ if (is_permission_fault(ap, perm) && !tt->had) {
67
info->type = SMMU_PTW_ERR_PERMISSION;
68
goto error;
69
}
70
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/hw/arm/smmuv3.c
73
+++ b/hw/arm/smmuv3.c
74
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
75
s->idr[1] = FIELD_DP32(s->idr[1], IDR1, EVENTQS, SMMU_EVENTQS);
76
s->idr[1] = FIELD_DP32(s->idr[1], IDR1, CMDQS, SMMU_CMDQS);
77
78
+ s->idr[3] = FIELD_DP32(s->idr[3], IDR3, HAD, 1);
79
+
80
/* 4K and 64K granule support */
81
s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1);
82
s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN64K, 1);
83
@@ -XXX,XX +XXX,XX @@ static void smmuv3_init_regs(SMMUv3State *s)
84
85
s->features = 0;
86
s->sid_split = 0;
87
+ s->aidr = 0x1;
88
}
89
90
static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
91
@@ -XXX,XX +XXX,XX @@ static int decode_cd(SMMUTransCfg *cfg, CD *cd, SMMUEventInfo *event)
92
if (tt->ttb & ~(MAKE_64BIT_MASK(0, cfg->oas))) {
93
goto bad_cd;
94
}
32
}
95
- trace_smmuv3_decode_cd_tt(i, tt->tsz, tt->ttb, tt->granule_sz);
33
- which = 2;
96
+ tt->had = CD_HAD(cd, i);
34
+ ret = c;
97
+ trace_smmuv3_decode_cd_tt(i, tt->tsz, tt->ttb, tt->granule_sz, tt->had);
35
} else {
36
- FloatClass cls[3] = { a->cls, b->cls, c->cls };
37
+ FloatPartsN *val[3] = { a, b, c };
38
Float3NaNPropRule rule = s->float_3nan_prop_rule;
39
40
assert(rule != float_3nan_prop_none);
41
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
42
/* We have at least one SNaN input and should prefer it */
43
do {
44
- which = rule & R_3NAN_1ST_MASK;
45
+ ret = val[rule & R_3NAN_1ST_MASK];
46
rule >>= R_3NAN_1ST_LENGTH;
47
- } while (!is_snan(cls[which]));
48
+ } while (!is_snan(ret->cls));
49
} else {
50
do {
51
- which = rule & R_3NAN_1ST_MASK;
52
+ ret = val[rule & R_3NAN_1ST_MASK];
53
rule >>= R_3NAN_1ST_LENGTH;
54
- } while (!is_nan(cls[which]));
55
+ } while (!is_nan(ret->cls));
56
}
98
}
57
}
99
58
100
event->record_trans_faults = CD_R(cd);
59
- switch (which) {
101
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
60
- case 0:
102
index XXXXXXX..XXXXXXX 100644
61
- break;
103
--- a/hw/arm/trace-events
62
- case 1:
104
+++ b/hw/arm/trace-events
63
- a = b;
105
@@ -XXX,XX +XXX,XX @@ smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is_write
64
- break;
106
smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=%d iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x"
65
- case 2:
107
smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64
66
- a = c;
108
smmuv3_decode_cd(uint32_t oas) "oas=%d"
67
- break;
109
-smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d"
68
- default:
110
+smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz, bool had) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d had:%d"
69
- g_assert_not_reached();
111
smmuv3_cmdq_cfgi_ste(int streamid) "streamid =%d"
70
+ if (is_snan(ret->cls)) {
112
smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%d - end=0x%d"
71
+ parts_silence_nan(ret, s);
113
smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d"
72
}
73
- if (is_snan(a->cls)) {
74
- parts_silence_nan(a, s);
75
- }
76
- return a;
77
+ return ret;
78
79
default_nan:
80
parts_default_nan(a, s);
114
--
81
--
115
2.20.1
82
2.34.1
116
83
117
84
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The SMMU IIDR register is at 0x018 offset.
3
While all indices into val[] should be in [0-2], the mask
4
applied is two bits. To help static analysis see there is
5
no possibility of read beyond the end of the array, pad the
6
array to 4 entries, with the final being (implicitly) NULL.
4
7
5
Fixes: 10a83cb9887 ("hw/arm/smmuv3: Skeleton")
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20241203203949.483774-6-richard.henderson@linaro.org
8
Message-id: 20200728150815.11446-9-eric.auger@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
12
---
11
hw/arm/smmuv3-internal.h | 2 +-
13
fpu/softfloat-parts.c.inc | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
13
15
14
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/smmuv3-internal.h
18
--- a/fpu/softfloat-parts.c.inc
17
+++ b/hw/arm/smmuv3-internal.h
19
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ REG32(IDR5, 0x14)
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
21
}
20
#define SMMU_IDR5_OAS 4
22
ret = c;
21
23
} else {
22
-REG32(IIDR, 0x1c)
24
- FloatPartsN *val[3] = { a, b, c };
23
+REG32(IIDR, 0x18)
25
+ FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
24
REG32(CR0, 0x20)
26
Float3NaNPropRule rule = s->float_3nan_prop_rule;
25
FIELD(CR0, SMMU_ENABLE, 0, 1)
27
26
FIELD(CR0, EVENTQEN, 2, 1)
28
assert(rule != float_3nan_prop_none);
27
--
29
--
28
2.20.1
30
2.34.1
29
31
30
32
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
At the moment each entry in the IOTLB corresponds to a page sized
3
This function is part of the public interface and
4
mapping (4K, 16K or 64K), even if the page belongs to a mapped
4
is not "specialized" to any target in any way.
5
block. In case of block mapping this unefficiently consumes IOTLB
6
entries.
7
5
8
Change the value of the entry so that it reflects the actual
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
mapping it belongs to (block or page start address and size).
10
11
Also the level/tg of the entry is encoded in the key. In subsequent
12
patches we will enable range invalidation. This latter is able
13
to provide the level/tg of the entry.
14
15
Encoding the level/tg directly in the key will allow to invalidate
16
using g_hash_table_remove() when num_pages equals to 1.
17
18
Signed-off-by: Eric Auger <eric.auger@redhat.com>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Message-id: 20200728150815.11446-6-eric.auger@redhat.com
8
Message-id: 20241203203949.483774-7-richard.henderson@linaro.org
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
10
---
23
hw/arm/smmu-internal.h | 7 ++++
11
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++++++++
24
include/hw/arm/smmu-common.h | 10 ++++--
12
fpu/softfloat-specialize.c.inc | 52 ----------------------------------
25
hw/arm/smmu-common.c | 67 ++++++++++++++++++++++++++----------
13
2 files changed, 52 insertions(+), 52 deletions(-)
26
hw/arm/smmuv3.c | 6 ++--
27
hw/arm/trace-events | 2 +-
28
5 files changed, 67 insertions(+), 25 deletions(-)
29
14
30
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
31
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/smmu-internal.h
17
--- a/fpu/softfloat.c
33
+++ b/hw/arm/smmu-internal.h
18
+++ b/fpu/softfloat.c
34
@@ -XXX,XX +XXX,XX @@ uint64_t iova_level_offset(uint64_t iova, int inputsize,
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
20
*zExpPtr = 1 - shiftCount;
35
}
21
}
36
22
37
#define SMMU_IOTLB_ASID(key) ((key).asid)
23
+/*----------------------------------------------------------------------------
24
+| Takes two extended double-precision floating-point values `a' and `b', one
25
+| of which is a NaN, and returns the appropriate NaN result. If either `a' or
26
+| `b' is a signaling NaN, the invalid exception is raised.
27
+*----------------------------------------------------------------------------*/
38
+
28
+
39
+typedef struct SMMUIOTLBPageInvInfo {
29
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
40
+ int asid;
30
+{
41
+ uint64_t iova;
31
+ bool aIsLargerSignificand;
42
+ uint64_t mask;
32
+ FloatClass a_cls, b_cls;
43
+} SMMUIOTLBPageInvInfo;
44
+
33
+
45
#endif
34
+ /* This is not complete, but is good enough for pickNaN. */
46
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
35
+ a_cls = (!floatx80_is_any_nan(a)
47
index XXXXXXX..XXXXXXX 100644
36
+ ? float_class_normal
48
--- a/include/hw/arm/smmu-common.h
37
+ : floatx80_is_signaling_nan(a, status)
49
+++ b/include/hw/arm/smmu-common.h
38
+ ? float_class_snan
50
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUPciBus {
39
+ : float_class_qnan);
51
typedef struct SMMUIOTLBKey {
40
+ b_cls = (!floatx80_is_any_nan(b)
52
uint64_t iova;
41
+ ? float_class_normal
53
uint16_t asid;
42
+ : floatx80_is_signaling_nan(b, status)
54
+ uint8_t tg;
43
+ ? float_class_snan
55
+ uint8_t level;
44
+ : float_class_qnan);
56
} SMMUIOTLBKey;
57
58
typedef struct SMMUState {
59
@@ -XXX,XX +XXX,XX @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid);
60
61
#define SMMU_IOTLB_MAX_SIZE 256
62
63
-SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, hwaddr iova);
64
+SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
65
+ SMMUTransTableInfo *tt, hwaddr iova);
66
void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *entry);
67
-SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova);
68
+SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova,
69
+ uint8_t tg, uint8_t level);
70
void smmu_iotlb_inv_all(SMMUState *s);
71
void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
72
-void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova);
73
+void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova);
74
75
/* Unmap the range of all the notifiers registered to any IOMMU mr */
76
void smmu_inv_notifiers_all(SMMUState *s);
77
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/arm/smmu-common.c
80
+++ b/hw/arm/smmu-common.c
81
@@ -XXX,XX +XXX,XX @@ static guint smmu_iotlb_key_hash(gconstpointer v)
82
83
/* Jenkins hash */
84
a = b = c = JHASH_INITVAL + sizeof(*key);
85
- a += key->asid;
86
+ a += key->asid + key->level + key->tg;
87
b += extract64(key->iova, 0, 32);
88
c += extract64(key->iova, 32, 32);
89
90
@@ -XXX,XX +XXX,XX @@ static guint smmu_iotlb_key_hash(gconstpointer v)
91
92
static gboolean smmu_iotlb_key_equal(gconstpointer v1, gconstpointer v2)
93
{
94
- const SMMUIOTLBKey *k1 = v1;
95
- const SMMUIOTLBKey *k2 = v2;
96
+ SMMUIOTLBKey *k1 = (SMMUIOTLBKey *)v1, *k2 = (SMMUIOTLBKey *)v2;
97
98
- return (k1->asid == k2->asid) && (k1->iova == k2->iova);
99
+ return (k1->asid == k2->asid) && (k1->iova == k2->iova) &&
100
+ (k1->level == k2->level) && (k1->tg == k2->tg);
101
}
102
103
-SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova)
104
+SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova,
105
+ uint8_t tg, uint8_t level)
106
{
107
- SMMUIOTLBKey key = {.asid = asid, .iova = iova};
108
+ SMMUIOTLBKey key = {.asid = asid, .iova = iova, .tg = tg, .level = level};
109
110
return key;
111
}
112
113
SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
114
- hwaddr iova)
115
+ SMMUTransTableInfo *tt, hwaddr iova)
116
{
117
- SMMUIOTLBKey key = smmu_get_iotlb_key(cfg->asid, iova);
118
- SMMUTLBEntry *entry = g_hash_table_lookup(bs->iotlb, &key);
119
+ uint8_t tg = (tt->granule_sz - 10) / 2;
120
+ uint8_t inputsize = 64 - tt->tsz;
121
+ uint8_t stride = tt->granule_sz - 3;
122
+ uint8_t level = 4 - (inputsize - 4) / stride;
123
+ SMMUTLBEntry *entry = NULL;
124
+
45
+
125
+ while (level <= 3) {
46
+ if (is_snan(a_cls) || is_snan(b_cls)) {
126
+ uint64_t subpage_size = 1ULL << level_shift(level, tt->granule_sz);
47
+ float_raise(float_flag_invalid, status);
127
+ uint64_t mask = subpage_size - 1;
48
+ }
128
+ SMMUIOTLBKey key;
129
+
49
+
130
+ key = smmu_get_iotlb_key(cfg->asid, iova & ~mask, tg, level);
50
+ if (status->default_nan_mode) {
131
+ entry = g_hash_table_lookup(bs->iotlb, &key);
51
+ return floatx80_default_nan(status);
132
+ if (entry) {
52
+ }
133
+ break;
53
+
54
+ if (a.low < b.low) {
55
+ aIsLargerSignificand = 0;
56
+ } else if (b.low < a.low) {
57
+ aIsLargerSignificand = 1;
58
+ } else {
59
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
60
+ }
61
+
62
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
63
+ if (is_snan(b_cls)) {
64
+ return floatx80_silence_nan(b, status);
134
+ }
65
+ }
135
+ level++;
66
+ return b;
67
+ } else {
68
+ if (is_snan(a_cls)) {
69
+ return floatx80_silence_nan(a, status);
70
+ }
71
+ return a;
136
+ }
72
+ }
137
138
if (entry) {
139
cfg->iotlb_hits++;
140
@@ -XXX,XX +XXX,XX @@ SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
141
void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *new)
142
{
143
SMMUIOTLBKey *key = g_new0(SMMUIOTLBKey, 1);
144
+ uint8_t tg = (new->granule - 10) / 2;
145
146
if (g_hash_table_size(bs->iotlb) >= SMMU_IOTLB_MAX_SIZE) {
147
smmu_iotlb_inv_all(bs);
148
}
149
150
- *key = smmu_get_iotlb_key(cfg->asid, new->entry.iova);
151
- trace_smmu_iotlb_insert(cfg->asid, new->entry.iova);
152
+ *key = smmu_get_iotlb_key(cfg->asid, new->entry.iova, tg, new->level);
153
+ trace_smmu_iotlb_insert(cfg->asid, new->entry.iova, tg, new->level);
154
g_hash_table_insert(bs->iotlb, key, new);
155
}
156
157
@@ -XXX,XX +XXX,XX @@ static gboolean smmu_hash_remove_by_asid(gpointer key, gpointer value,
158
return SMMU_IOTLB_ASID(*iotlb_key) == asid;
159
}
160
161
-inline void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova)
162
+static gboolean smmu_hash_remove_by_asid_iova(gpointer key, gpointer value,
163
+ gpointer user_data)
164
{
165
- SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova);
166
+ SMMUTLBEntry *iter = (SMMUTLBEntry *)value;
167
+ IOMMUTLBEntry *entry = &iter->entry;
168
+ SMMUIOTLBPageInvInfo *info = (SMMUIOTLBPageInvInfo *)user_data;
169
+ SMMUIOTLBKey iotlb_key = *(SMMUIOTLBKey *)key;
170
+
171
+ if (info->asid >= 0 && info->asid != SMMU_IOTLB_ASID(iotlb_key)) {
172
+ return false;
173
+ }
174
+ return (info->iova & ~entry->addr_mask) == entry->iova;
175
+}
73
+}
176
+
74
+
177
+inline void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova)
75
/*----------------------------------------------------------------------------
178
+{
76
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
179
+ SMMUIOTLBPageInvInfo info = {.asid = asid, .iova = iova};
77
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
180
78
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
181
trace_smmu_iotlb_inv_iova(asid, iova);
79
index XXXXXXX..XXXXXXX 100644
182
- g_hash_table_remove(s->iotlb, &key);
80
--- a/fpu/softfloat-specialize.c.inc
183
+ g_hash_table_foreach_remove(s->iotlb, smmu_hash_remove_by_asid_iova, &info);
81
+++ b/fpu/softfloat-specialize.c.inc
82
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
83
return a;
184
}
84
}
185
85
186
inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid)
86
-/*----------------------------------------------------------------------------
187
@@ -XXX,XX +XXX,XX @@ static int smmu_ptw_64(SMMUTransCfg *cfg,
87
-| Takes two extended double-precision floating-point values `a' and `b', one
188
baseaddr = extract64(tt->ttb, 0, 48);
88
-| of which is a NaN, and returns the appropriate NaN result. If either `a' or
189
baseaddr &= ~indexmask;
89
-| `b' is a signaling NaN, the invalid exception is raised.
190
90
-*----------------------------------------------------------------------------*/
191
- tlbe->entry.iova = iova;
192
- tlbe->entry.addr_mask = (1 << granule_sz) - 1;
193
-
91
-
194
while (level <= 3) {
92
-floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
195
uint64_t subpage_size = 1ULL << level_shift(level, granule_sz);
93
-{
196
uint64_t mask = subpage_size - 1;
94
- bool aIsLargerSignificand;
197
@@ -XXX,XX +XXX,XX @@ static int smmu_ptw_64(SMMUTransCfg *cfg,
95
- FloatClass a_cls, b_cls;
198
goto error;
96
-
199
}
97
- /* This is not complete, but is good enough for pickNaN. */
200
98
- a_cls = (!floatx80_is_any_nan(a)
201
- tlbe->entry.translated_addr = gpa + (iova & mask);
99
- ? float_class_normal
202
+ tlbe->entry.translated_addr = gpa;
100
- : floatx80_is_signaling_nan(a, status)
203
+ tlbe->entry.iova = iova & ~mask;
101
- ? float_class_snan
204
+ tlbe->entry.addr_mask = mask;
102
- : float_class_qnan);
205
tlbe->entry.perm = PTE_AP_TO_PERM(ap);
103
- b_cls = (!floatx80_is_any_nan(b)
206
tlbe->level = level;
104
- ? float_class_normal
207
tlbe->granule = granule_sz;
105
- : floatx80_is_signaling_nan(b, status)
208
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
106
- ? float_class_snan
209
index XXXXXXX..XXXXXXX 100644
107
- : float_class_qnan);
210
--- a/hw/arm/smmuv3.c
108
-
211
+++ b/hw/arm/smmuv3.c
109
- if (is_snan(a_cls) || is_snan(b_cls)) {
212
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
110
- float_raise(float_flag_invalid, status);
213
page_mask = (1ULL << (tt->granule_sz)) - 1;
111
- }
214
aligned_addr = addr & ~page_mask;
112
-
215
113
- if (status->default_nan_mode) {
216
- cached_entry = smmu_iotlb_lookup(bs, cfg, aligned_addr);
114
- return floatx80_default_nan(status);
217
+ cached_entry = smmu_iotlb_lookup(bs, cfg, tt, aligned_addr);
115
- }
218
if (cached_entry) {
116
-
219
if ((flag & IOMMU_WO) && !(cached_entry->entry.perm & IOMMU_WO)) {
117
- if (a.low < b.low) {
220
status = SMMU_TRANS_ERROR;
118
- aIsLargerSignificand = 0;
221
@@ -XXX,XX +XXX,XX @@ epilogue:
119
- } else if (b.low < a.low) {
222
case SMMU_TRANS_SUCCESS:
120
- aIsLargerSignificand = 1;
223
entry.perm = flag;
121
- } else {
224
entry.translated_addr = cached_entry->entry.translated_addr +
122
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
225
- (addr & page_mask);
123
- }
226
+ (addr & cached_entry->entry.addr_mask);
124
-
227
entry.addr_mask = cached_entry->entry.addr_mask;
125
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
228
trace_smmuv3_translate_success(mr->parent_obj.name, sid, addr,
126
- if (is_snan(b_cls)) {
229
entry.translated_addr, entry.perm);
127
- return floatx80_silence_nan(b, status);
230
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
128
- }
231
129
- return b;
232
trace_smmuv3_cmdq_tlbi_nh_vaa(vmid, addr);
130
- } else {
233
smmuv3_inv_notifiers_iova(bs, -1, addr);
131
- if (is_snan(a_cls)) {
234
- smmu_iotlb_inv_all(bs);
132
- return floatx80_silence_nan(a, status);
235
+ smmu_iotlb_inv_iova(bs, -1, addr);
133
- }
236
break;
134
- return a;
237
}
135
- }
238
case SMMU_CMD_TLBI_NH_VA:
136
-}
239
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
137
-
240
index XXXXXXX..XXXXXXX 100644
138
/*----------------------------------------------------------------------------
241
--- a/hw/arm/trace-events
139
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
242
+++ b/hw/arm/trace-events
140
| NaN; otherwise returns 0.
243
@@ -XXX,XX +XXX,XX @@ smmu_iotlb_inv_iova(uint16_t asid, uint64_t addr) "IOTLB invalidate asid=%d addr
244
smmu_inv_notifiers_mr(const char *name) "iommu mr=%s"
245
smmu_iotlb_lookup_hit(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache HIT asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
246
smmu_iotlb_lookup_miss(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache MISS asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
247
-smmu_iotlb_insert(uint16_t asid, uint64_t addr) "IOTLB ++ asid=%d addr=0x%"PRIx64
248
+smmu_iotlb_insert(uint16_t asid, uint64_t addr, uint8_t tg, uint8_t level) "IOTLB ++ asid=%d addr=0x%"PRIx64" tg=%d level=%d"
249
250
# smmuv3.c
251
smmuv3_read_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
252
--
141
--
253
2.20.1
142
2.34.1
254
255
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Unpacking and repacking the parts may be slightly more work
4
than we did before, but we get to reuse more code. For a
5
code path handling exceptional values, this is an improvement.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241203203949.483774-8-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
fpu/softfloat.c | 43 +++++--------------------------------------
13
1 file changed, 5 insertions(+), 38 deletions(-)
14
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/fpu/softfloat.c
18
+++ b/fpu/softfloat.c
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
20
21
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
22
{
23
- bool aIsLargerSignificand;
24
- FloatClass a_cls, b_cls;
25
+ FloatParts128 pa, pb, *pr;
26
27
- /* This is not complete, but is good enough for pickNaN. */
28
- a_cls = (!floatx80_is_any_nan(a)
29
- ? float_class_normal
30
- : floatx80_is_signaling_nan(a, status)
31
- ? float_class_snan
32
- : float_class_qnan);
33
- b_cls = (!floatx80_is_any_nan(b)
34
- ? float_class_normal
35
- : floatx80_is_signaling_nan(b, status)
36
- ? float_class_snan
37
- : float_class_qnan);
38
-
39
- if (is_snan(a_cls) || is_snan(b_cls)) {
40
- float_raise(float_flag_invalid, status);
41
- }
42
-
43
- if (status->default_nan_mode) {
44
+ if (!floatx80_unpack_canonical(&pa, a, status) ||
45
+ !floatx80_unpack_canonical(&pb, b, status)) {
46
return floatx80_default_nan(status);
47
}
48
49
- if (a.low < b.low) {
50
- aIsLargerSignificand = 0;
51
- } else if (b.low < a.low) {
52
- aIsLargerSignificand = 1;
53
- } else {
54
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
55
- }
56
-
57
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
58
- if (is_snan(b_cls)) {
59
- return floatx80_silence_nan(b, status);
60
- }
61
- return b;
62
- } else {
63
- if (is_snan(a_cls)) {
64
- return floatx80_silence_nan(a, status);
65
- }
66
- return a;
67
- }
68
+ pr = parts_pick_nan(&pa, &pb, status);
69
+ return floatx80_round_pack_canonical(pr, status);
70
}
71
72
/*----------------------------------------------------------------------------
73
--
74
2.34.1
diff view generated by jsdifflib
1
We currently have two versions of get_fpstatus_ptr(), which both take
1
From: Richard Henderson <richard.henderson@linaro.org>
2
an effectively boolean argument:
2
3
* the one for A64 takes "bool is_f16" to distinguish fp16 from other ops
3
Inline pickNaN into its only caller. This makes one assert
4
* the one for A32/T32 takes "int neon" to distinguish Neon from other ops
4
redundant with the immediately preceding IF.
5
5
6
This is confusing, and to implement ARMv8.2-FP16 the A32/T32 one will
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
need to make a four-way distinction between "non-Neon, FP16",
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
"non-Neon, single/double", "Neon, FP16" and "Neon, single/double".
8
Message-id: 20241203203949.483774-9-richard.henderson@linaro.org
9
The A64 version will then be a strict subset of the A32/T32 version.
10
11
To clean this all up, we want to go to a single implementation which
12
takes an enum argument with values FPST_FPCR, FPST_STD,
13
FPST_FPCR_F16, and FPST_STD_F16. We rename the function to
14
fpstatus_ptr() so that unconverted code gets a compilation error
15
rather than silently passing the wrong thing to the new function.
16
17
This commit implements that new API, and converts A64 to use it:
18
get_fpstatus_ptr(false) -> fpstatus_ptr(FPST_FPCR)
19
get_fpstatus_ptr(true) -> fpstatus_ptr(FPST_FPCR_F16)
20
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
24
Message-id: 20200806104453.30393-2-peter.maydell@linaro.org
25
---
10
---
26
target/arm/translate-a64.h | 1 -
11
fpu/softfloat-parts.c.inc | 82 +++++++++++++++++++++++++----
27
target/arm/translate.h | 51 ++++++++++++++++++++++
12
fpu/softfloat-specialize.c.inc | 96 ----------------------------------
28
target/arm/translate-a64.c | 89 +++++++++++++++-----------------------
13
2 files changed, 73 insertions(+), 105 deletions(-)
29
target/arm/translate-sve.c | 34 +++++++--------
14
30
4 files changed, 103 insertions(+), 72 deletions(-)
15
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
31
32
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
33
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate-a64.h
17
--- a/fpu/softfloat-parts.c.inc
35
+++ b/target/arm/translate-a64.h
18
+++ b/fpu/softfloat-parts.c.inc
36
@@ -XXX,XX +XXX,XX @@ TCGv_i64 cpu_reg_sp(DisasContext *s, int reg);
19
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
37
TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf);
20
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
38
TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf);
21
float_status *s)
39
void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v);
22
{
40
-TCGv_ptr get_fpstatus_ptr(bool);
23
+ int cmp, which;
41
bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
42
unsigned int imms, unsigned int immr);
43
bool sve_access_check(DisasContext *s);
44
diff --git a/target/arm/translate.h b/target/arm/translate.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/translate.h
47
+++ b/target/arm/translate.h
48
@@ -XXX,XX +XXX,XX @@ typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
49
typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
50
typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, MemOp);
51
52
+/*
53
+ * Enum for argument to fpstatus_ptr().
54
+ */
55
+typedef enum ARMFPStatusFlavour {
56
+ FPST_FPCR,
57
+ FPST_FPCR_F16,
58
+ FPST_STD,
59
+ FPST_STD_F16,
60
+} ARMFPStatusFlavour;
61
+
24
+
62
+/**
25
if (is_snan(a->cls) || is_snan(b->cls)) {
63
+ * fpstatus_ptr: return TCGv_ptr to the specified fp_status field
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
64
+ *
27
}
65
+ * We have multiple softfloat float_status fields in the Arm CPU state struct
28
66
+ * (see the comment in cpu.h for details). Return a TCGv_ptr which has
29
if (s->default_nan_mode) {
67
+ * been set up to point to the requested field in the CPU state struct.
30
parts_default_nan(a, s);
68
+ * The options are:
31
- } else {
69
+ *
32
- int cmp = frac_cmp(a, b);
70
+ * FPST_FPCR
33
- if (cmp == 0) {
71
+ * for non-FP16 operations controlled by the FPCR
34
- cmp = a->sign < b->sign;
72
+ * FPST_FPCR_F16
35
- }
73
+ * for operations controlled by the FPCR where FPCR.FZ16 is to be used
36
+ return a;
74
+ * FPST_STD
37
+ }
75
+ * for A32/T32 Neon operations using the "standard FPSCR value"
38
76
+ * FPST_STD_F16
39
- if (pickNaN(a->cls, b->cls, cmp > 0, s)) {
77
+ * as FPST_STD, but where FPCR.FZ16 is to be used
40
- a = b;
78
+ */
41
- }
79
+static inline TCGv_ptr fpstatus_ptr(ARMFPStatusFlavour flavour)
42
+ cmp = frac_cmp(a, b);
80
+{
43
+ if (cmp == 0) {
81
+ TCGv_ptr statusptr = tcg_temp_new_ptr();
44
+ cmp = a->sign < b->sign;
82
+ int offset;
45
+ }
83
+
46
+
84
+ switch (flavour) {
47
+ switch (s->float_2nan_prop_rule) {
85
+ case FPST_FPCR:
48
+ case float_2nan_prop_s_ab:
86
+ offset = offsetof(CPUARMState, vfp.fp_status);
49
if (is_snan(a->cls)) {
87
+ break;
50
- parts_silence_nan(a, s);
88
+ case FPST_FPCR_F16:
51
+ which = 0;
89
+ offset = offsetof(CPUARMState, vfp.fp_status_f16);
52
+ } else if (is_snan(b->cls)) {
90
+ break;
53
+ which = 1;
91
+ case FPST_STD:
54
+ } else if (is_qnan(a->cls)) {
92
+ offset = offsetof(CPUARMState, vfp.standard_fp_status);
55
+ which = 0;
93
+ break;
56
+ } else {
94
+ case FPST_STD_F16:
57
+ which = 1;
95
+ /* Not yet used or implemented: fall through to assert */
58
}
59
+ break;
60
+ case float_2nan_prop_s_ba:
61
+ if (is_snan(b->cls)) {
62
+ which = 1;
63
+ } else if (is_snan(a->cls)) {
64
+ which = 0;
65
+ } else if (is_qnan(b->cls)) {
66
+ which = 1;
67
+ } else {
68
+ which = 0;
69
+ }
70
+ break;
71
+ case float_2nan_prop_ab:
72
+ which = is_nan(a->cls) ? 0 : 1;
73
+ break;
74
+ case float_2nan_prop_ba:
75
+ which = is_nan(b->cls) ? 1 : 0;
76
+ break;
77
+ case float_2nan_prop_x87:
78
+ /*
79
+ * This implements x87 NaN propagation rules:
80
+ * SNaN + QNaN => return the QNaN
81
+ * two SNaNs => return the one with the larger significand, silenced
82
+ * two QNaNs => return the one with the larger significand
83
+ * SNaN and a non-NaN => return the SNaN, silenced
84
+ * QNaN and a non-NaN => return the QNaN
85
+ *
86
+ * If we get down to comparing significands and they are the same,
87
+ * return the NaN with the positive sign bit (if any).
88
+ */
89
+ if (is_snan(a->cls)) {
90
+ if (is_snan(b->cls)) {
91
+ which = cmp > 0 ? 0 : 1;
92
+ } else {
93
+ which = is_qnan(b->cls) ? 1 : 0;
94
+ }
95
+ } else if (is_qnan(a->cls)) {
96
+ if (is_snan(b->cls) || !is_qnan(b->cls)) {
97
+ which = 0;
98
+ } else {
99
+ which = cmp > 0 ? 0 : 1;
100
+ }
101
+ } else {
102
+ which = 1;
103
+ }
104
+ break;
96
+ default:
105
+ default:
97
+ g_assert_not_reached();
106
+ g_assert_not_reached();
98
+ }
107
+ }
99
+ tcg_gen_addi_ptr(statusptr, cpu_env, offset);
100
+ return statusptr;
101
+}
102
+
108
+
103
#endif /* TARGET_ARM_TRANSLATE_H */
109
+ if (which) {
104
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
110
+ a = b;
111
+ }
112
+ if (is_snan(a->cls)) {
113
+ parts_silence_nan(a, s);
114
}
115
return a;
116
}
117
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
105
index XXXXXXX..XXXXXXX 100644
118
index XXXXXXX..XXXXXXX 100644
106
--- a/target/arm/translate-a64.c
119
--- a/fpu/softfloat-specialize.c.inc
107
+++ b/target/arm/translate-a64.c
120
+++ b/fpu/softfloat-specialize.c.inc
108
@@ -XXX,XX +XXX,XX @@ static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
121
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
109
tcg_temp_free_i64(tmp);
122
}
110
}
123
}
111
124
112
-TCGv_ptr get_fpstatus_ptr(bool is_f16)
125
-/*----------------------------------------------------------------------------
126
-| Select which NaN to propagate for a two-input operation.
127
-| IEEE754 doesn't specify all the details of this, so the
128
-| algorithm is target-specific.
129
-| The routine is passed various bits of information about the
130
-| two NaNs and should return 0 to select NaN a and 1 for NaN b.
131
-| Note that signalling NaNs are always squashed to quiet NaNs
132
-| by the caller, by calling floatXX_silence_nan() before
133
-| returning them.
134
-|
135
-| aIsLargerSignificand is only valid if both a and b are NaNs
136
-| of some kind, and is true if a has the larger significand,
137
-| or if both a and b have the same significand but a is
138
-| positive but b is negative. It is only needed for the x87
139
-| tie-break rule.
140
-*----------------------------------------------------------------------------*/
141
-
142
-static int pickNaN(FloatClass a_cls, FloatClass b_cls,
143
- bool aIsLargerSignificand, float_status *status)
113
-{
144
-{
114
- TCGv_ptr statusptr = tcg_temp_new_ptr();
145
- /*
115
- int offset;
146
- * We guarantee not to require the target to tell us how to
147
- * pick a NaN if we're always returning the default NaN.
148
- * But if we're not in default-NaN mode then the target must
149
- * specify via set_float_2nan_prop_rule().
150
- */
151
- assert(!status->default_nan_mode);
116
-
152
-
117
- /* In A64 all instructions (both FP and Neon) use the FPCR; there
153
- switch (status->float_2nan_prop_rule) {
118
- * is no equivalent of the A32 Neon "standard FPSCR value".
154
- case float_2nan_prop_s_ab:
119
- * However half-precision operations operate under a different
155
- if (is_snan(a_cls)) {
120
- * FZ16 flag and use vfp.fp_status_f16 instead of vfp.fp_status.
156
- return 0;
121
- */
157
- } else if (is_snan(b_cls)) {
122
- if (is_f16) {
158
- return 1;
123
- offset = offsetof(CPUARMState, vfp.fp_status_f16);
159
- } else if (is_qnan(a_cls)) {
124
- } else {
160
- return 0;
125
- offset = offsetof(CPUARMState, vfp.fp_status);
161
- } else {
162
- return 1;
163
- }
164
- break;
165
- case float_2nan_prop_s_ba:
166
- if (is_snan(b_cls)) {
167
- return 1;
168
- } else if (is_snan(a_cls)) {
169
- return 0;
170
- } else if (is_qnan(b_cls)) {
171
- return 1;
172
- } else {
173
- return 0;
174
- }
175
- break;
176
- case float_2nan_prop_ab:
177
- if (is_nan(a_cls)) {
178
- return 0;
179
- } else {
180
- return 1;
181
- }
182
- break;
183
- case float_2nan_prop_ba:
184
- if (is_nan(b_cls)) {
185
- return 1;
186
- } else {
187
- return 0;
188
- }
189
- break;
190
- case float_2nan_prop_x87:
191
- /*
192
- * This implements x87 NaN propagation rules:
193
- * SNaN + QNaN => return the QNaN
194
- * two SNaNs => return the one with the larger significand, silenced
195
- * two QNaNs => return the one with the larger significand
196
- * SNaN and a non-NaN => return the SNaN, silenced
197
- * QNaN and a non-NaN => return the QNaN
198
- *
199
- * If we get down to comparing significands and they are the same,
200
- * return the NaN with the positive sign bit (if any).
201
- */
202
- if (is_snan(a_cls)) {
203
- if (is_snan(b_cls)) {
204
- return aIsLargerSignificand ? 0 : 1;
205
- }
206
- return is_qnan(b_cls) ? 1 : 0;
207
- } else if (is_qnan(a_cls)) {
208
- if (is_snan(b_cls) || !is_qnan(b_cls)) {
209
- return 0;
210
- } else {
211
- return aIsLargerSignificand ? 0 : 1;
212
- }
213
- } else {
214
- return 1;
215
- }
216
- default:
217
- g_assert_not_reached();
126
- }
218
- }
127
- tcg_gen_addi_ptr(statusptr, cpu_env, offset);
128
- return statusptr;
129
-}
219
-}
130
-
220
-
131
/* Expand a 2-operand AdvSIMD vector operation using an expander function. */
221
/*----------------------------------------------------------------------------
132
static void gen_gvec_fn2(DisasContext *s, bool is_q, int rd, int rn,
222
| Returns 1 if the double-precision floating-point value `a' is a quiet
133
GVecGen2Fn *gvec_fn, int vece)
223
| NaN; otherwise returns 0.
134
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn,
135
int rm, bool is_fp16, int data,
136
gen_helper_gvec_3_ptr *fn)
137
{
138
- TCGv_ptr fpst = get_fpstatus_ptr(is_fp16);
139
+ TCGv_ptr fpst = fpstatus_ptr(is_fp16 ? FPST_FPCR_F16 : FPST_FPCR);
140
tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
141
vec_full_reg_offset(s, rn),
142
vec_full_reg_offset(s, rm), fpst,
143
@@ -XXX,XX +XXX,XX @@ static void handle_fp_compare(DisasContext *s, int size,
144
bool cmp_with_zero, bool signal_all_nans)
145
{
146
TCGv_i64 tcg_flags = tcg_temp_new_i64();
147
- TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16);
148
+ TCGv_ptr fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
149
150
if (size == MO_64) {
151
TCGv_i64 tcg_vn, tcg_vm;
152
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
153
tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
154
break;
155
case 0x3: /* FSQRT */
156
- fpst = get_fpstatus_ptr(true);
157
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
158
gen_helper_sqrt_f16(tcg_res, tcg_op, fpst);
159
break;
160
case 0x8: /* FRINTN */
161
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
162
case 0xc: /* FRINTA */
163
{
164
TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
165
- fpst = get_fpstatus_ptr(true);
166
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
167
168
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
169
gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
170
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
171
break;
172
}
173
case 0xe: /* FRINTX */
174
- fpst = get_fpstatus_ptr(true);
175
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
176
gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, fpst);
177
break;
178
case 0xf: /* FRINTI */
179
- fpst = get_fpstatus_ptr(true);
180
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
181
gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
182
break;
183
default:
184
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
185
g_assert_not_reached();
186
}
187
188
- fpst = get_fpstatus_ptr(false);
189
+ fpst = fpstatus_ptr(FPST_FPCR);
190
if (rmode >= 0) {
191
TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
192
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
193
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
194
g_assert_not_reached();
195
}
196
197
- fpst = get_fpstatus_ptr(false);
198
+ fpst = fpstatus_ptr(FPST_FPCR);
199
if (rmode >= 0) {
200
TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
201
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
202
@@ -XXX,XX +XXX,XX @@ static void handle_fp_fcvt(DisasContext *s, int opcode,
203
/* Single to half */
204
TCGv_i32 tcg_rd = tcg_temp_new_i32();
205
TCGv_i32 ahp = get_ahp_flag();
206
- TCGv_ptr fpst = get_fpstatus_ptr(false);
207
+ TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR);
208
209
gen_helper_vfp_fcvt_f32_to_f16(tcg_rd, tcg_rn, fpst, ahp);
210
/* write_fp_sreg is OK here because top half of tcg_rd is zero */
211
@@ -XXX,XX +XXX,XX @@ static void handle_fp_fcvt(DisasContext *s, int opcode,
212
/* Double to single */
213
gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, cpu_env);
214
} else {
215
- TCGv_ptr fpst = get_fpstatus_ptr(false);
216
+ TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR);
217
TCGv_i32 ahp = get_ahp_flag();
218
/* Double to half */
219
gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, fpst, ahp);
220
@@ -XXX,XX +XXX,XX @@ static void handle_fp_fcvt(DisasContext *s, int opcode,
221
case 0x3:
222
{
223
TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
224
- TCGv_ptr tcg_fpst = get_fpstatus_ptr(false);
225
+ TCGv_ptr tcg_fpst = fpstatus_ptr(FPST_FPCR);
226
TCGv_i32 tcg_ahp = get_ahp_flag();
227
tcg_gen_ext16u_i32(tcg_rn, tcg_rn);
228
if (dtype == 0) {
229
@@ -XXX,XX +XXX,XX @@ static void handle_fp_2src_single(DisasContext *s, int opcode,
230
TCGv_ptr fpst;
231
232
tcg_res = tcg_temp_new_i32();
233
- fpst = get_fpstatus_ptr(false);
234
+ fpst = fpstatus_ptr(FPST_FPCR);
235
tcg_op1 = read_fp_sreg(s, rn);
236
tcg_op2 = read_fp_sreg(s, rm);
237
238
@@ -XXX,XX +XXX,XX @@ static void handle_fp_2src_double(DisasContext *s, int opcode,
239
TCGv_ptr fpst;
240
241
tcg_res = tcg_temp_new_i64();
242
- fpst = get_fpstatus_ptr(false);
243
+ fpst = fpstatus_ptr(FPST_FPCR);
244
tcg_op1 = read_fp_dreg(s, rn);
245
tcg_op2 = read_fp_dreg(s, rm);
246
247
@@ -XXX,XX +XXX,XX @@ static void handle_fp_2src_half(DisasContext *s, int opcode,
248
TCGv_ptr fpst;
249
250
tcg_res = tcg_temp_new_i32();
251
- fpst = get_fpstatus_ptr(true);
252
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
253
tcg_op1 = read_fp_hreg(s, rn);
254
tcg_op2 = read_fp_hreg(s, rm);
255
256
@@ -XXX,XX +XXX,XX @@ static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1,
257
{
258
TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
259
TCGv_i32 tcg_res = tcg_temp_new_i32();
260
- TCGv_ptr fpst = get_fpstatus_ptr(false);
261
+ TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR);
262
263
tcg_op1 = read_fp_sreg(s, rn);
264
tcg_op2 = read_fp_sreg(s, rm);
265
@@ -XXX,XX +XXX,XX @@ static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1,
266
{
267
TCGv_i64 tcg_op1, tcg_op2, tcg_op3;
268
TCGv_i64 tcg_res = tcg_temp_new_i64();
269
- TCGv_ptr fpst = get_fpstatus_ptr(false);
270
+ TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR);
271
272
tcg_op1 = read_fp_dreg(s, rn);
273
tcg_op2 = read_fp_dreg(s, rm);
274
@@ -XXX,XX +XXX,XX @@ static void handle_fp_3src_half(DisasContext *s, bool o0, bool o1,
275
{
276
TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
277
TCGv_i32 tcg_res = tcg_temp_new_i32();
278
- TCGv_ptr fpst = get_fpstatus_ptr(true);
279
+ TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR_F16);
280
281
tcg_op1 = read_fp_hreg(s, rn);
282
tcg_op2 = read_fp_hreg(s, rm);
283
@@ -XXX,XX +XXX,XX @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
284
TCGv_i32 tcg_shift, tcg_single;
285
TCGv_i64 tcg_double;
286
287
- tcg_fpstatus = get_fpstatus_ptr(type == 3);
288
+ tcg_fpstatus = fpstatus_ptr(type == 3 ? FPST_FPCR_F16 : FPST_FPCR);
289
290
tcg_shift = tcg_const_i32(64 - scale);
291
292
@@ -XXX,XX +XXX,XX @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
293
static void handle_fjcvtzs(DisasContext *s, int rd, int rn)
294
{
295
TCGv_i64 t = read_fp_dreg(s, rn);
296
- TCGv_ptr fpstatus = get_fpstatus_ptr(false);
297
+ TCGv_ptr fpstatus = fpstatus_ptr(FPST_FPCR);
298
299
gen_helper_fjcvtzs(t, t, fpstatus);
300
301
@@ -XXX,XX +XXX,XX @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
302
* Note that correct NaN propagation requires that we do these
303
* operations in exactly the order specified by the pseudocode.
304
*/
305
- TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16);
306
+ TCGv_ptr fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
307
int fpopcode = opcode | is_min << 4 | is_u << 5;
308
int vmap = (1 << elements) - 1;
309
TCGv_i32 tcg_res32 = do_reduction_op(s, fpopcode, rn, esize,
310
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
311
return;
312
}
313
314
- fpst = get_fpstatus_ptr(size == MO_16);
315
+ fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
316
break;
317
default:
318
unallocated_encoding(s);
319
@@ -XXX,XX +XXX,XX @@ static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn,
320
int elements, int is_signed,
321
int fracbits, int size)
322
{
323
- TCGv_ptr tcg_fpst = get_fpstatus_ptr(size == MO_16);
324
+ TCGv_ptr tcg_fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
325
TCGv_i32 tcg_shift = NULL;
326
327
MemOp mop = size | (is_signed ? MO_SIGN : 0);
328
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
329
assert(!(is_scalar && is_q));
330
331
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
332
- tcg_fpstatus = get_fpstatus_ptr(size == MO_16);
333
+ tcg_fpstatus = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
334
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
335
fracbits = (16 << size) - immhb;
336
tcg_shift = tcg_const_i32(fracbits);
337
@@ -XXX,XX +XXX,XX @@ static void handle_3same_float(DisasContext *s, int size, int elements,
338
int fpopcode, int rd, int rn, int rm)
339
{
340
int pass;
341
- TCGv_ptr fpst = get_fpstatus_ptr(false);
342
+ TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR);
343
344
for (pass = 0; pass < elements; pass++) {
345
if (size) {
346
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
347
return;
348
}
349
350
- fpst = get_fpstatus_ptr(true);
351
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
352
353
tcg_op1 = read_fp_hreg(s, rn);
354
tcg_op2 = read_fp_hreg(s, rm);
355
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
356
return;
357
}
358
359
- fpst = get_fpstatus_ptr(size == MO_16);
360
+ fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
361
362
if (is_double) {
363
TCGv_i64 tcg_op = tcg_temp_new_i64();
364
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_reciprocal(DisasContext *s, int opcode,
365
int size, int rn, int rd)
366
{
367
bool is_double = (size == 3);
368
- TCGv_ptr fpst = get_fpstatus_ptr(false);
369
+ TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR);
370
371
if (is_double) {
372
TCGv_i64 tcg_op = tcg_temp_new_i64();
373
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_narrow(DisasContext *s, bool scalar,
374
} else {
375
TCGv_i32 tcg_lo = tcg_temp_new_i32();
376
TCGv_i32 tcg_hi = tcg_temp_new_i32();
377
- TCGv_ptr fpst = get_fpstatus_ptr(false);
378
+ TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR);
379
TCGv_i32 ahp = get_ahp_flag();
380
381
tcg_gen_extr_i64_i32(tcg_lo, tcg_hi, tcg_op);
382
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
383
384
if (is_fcvt) {
385
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
386
- tcg_fpstatus = get_fpstatus_ptr(false);
387
+ tcg_fpstatus = fpstatus_ptr(FPST_FPCR);
388
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
389
} else {
390
tcg_rmode = NULL;
391
@@ -XXX,XX +XXX,XX @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
392
393
/* Floating point operations need fpst */
394
if (opcode >= 0x58) {
395
- fpst = get_fpstatus_ptr(false);
396
+ fpst = fpstatus_ptr(FPST_FPCR);
397
} else {
398
fpst = NULL;
399
}
400
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
401
break;
402
}
403
404
- fpst = get_fpstatus_ptr(true);
405
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
406
407
if (pairwise) {
408
int maxpass = is_q ? 8 : 4;
409
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
410
/* 16 -> 32 bit fp conversion */
411
int srcelt = is_q ? 4 : 0;
412
TCGv_i32 tcg_res[4];
413
- TCGv_ptr fpst = get_fpstatus_ptr(false);
414
+ TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR);
415
TCGv_i32 ahp = get_ahp_flag();
416
417
for (pass = 0; pass < 4; pass++) {
418
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
419
}
420
421
if (need_fpstatus || need_rmode) {
422
- tcg_fpstatus = get_fpstatus_ptr(false);
423
+ tcg_fpstatus = fpstatus_ptr(FPST_FPCR);
424
} else {
425
tcg_fpstatus = NULL;
426
}
427
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
428
}
429
430
if (need_rmode || need_fpst) {
431
- tcg_fpstatus = get_fpstatus_ptr(true);
432
+ tcg_fpstatus = fpstatus_ptr(FPST_FPCR_F16);
433
}
434
435
if (need_rmode) {
436
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
437
}
438
439
if (is_fp) {
440
- fpst = get_fpstatus_ptr(is_fp16);
441
+ fpst = fpstatus_ptr(is_fp16 ? FPST_FPCR_F16 : FPST_FPCR);
442
} else {
443
fpst = NULL;
444
}
445
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
446
index XXXXXXX..XXXXXXX 100644
447
--- a/target/arm/translate-sve.c
448
+++ b/target/arm/translate-sve.c
449
@@ -XXX,XX +XXX,XX @@ static bool trans_FMLA_zzxz(DisasContext *s, arg_FMLA_zzxz *a)
450
451
if (sve_access_check(s)) {
452
unsigned vsz = vec_full_reg_size(s);
453
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
454
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
455
tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, a->rd),
456
vec_full_reg_offset(s, a->rn),
457
vec_full_reg_offset(s, a->rm),
458
@@ -XXX,XX +XXX,XX @@ static bool trans_FMUL_zzx(DisasContext *s, arg_FMUL_zzx *a)
459
460
if (sve_access_check(s)) {
461
unsigned vsz = vec_full_reg_size(s);
462
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
463
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
464
tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
465
vec_full_reg_offset(s, a->rn),
466
vec_full_reg_offset(s, a->rm),
467
@@ -XXX,XX +XXX,XX @@ static void do_reduce(DisasContext *s, arg_rpr_esz *a,
468
469
tcg_gen_addi_ptr(t_zn, cpu_env, vec_full_reg_offset(s, a->rn));
470
tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, a->pg));
471
- status = get_fpstatus_ptr(a->esz == MO_16);
472
+ status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
473
474
fn(temp, t_zn, t_pg, status, t_desc);
475
tcg_temp_free_ptr(t_zn);
476
@@ -XXX,XX +XXX,XX @@ DO_VPZ(FMAXV, fmaxv)
477
static void do_zz_fp(DisasContext *s, arg_rr_esz *a, gen_helper_gvec_2_ptr *fn)
478
{
479
unsigned vsz = vec_full_reg_size(s);
480
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
481
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
482
483
tcg_gen_gvec_2_ptr(vec_full_reg_offset(s, a->rd),
484
vec_full_reg_offset(s, a->rn),
485
@@ -XXX,XX +XXX,XX @@ static void do_ppz_fp(DisasContext *s, arg_rpr_esz *a,
486
gen_helper_gvec_3_ptr *fn)
487
{
488
unsigned vsz = vec_full_reg_size(s);
489
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
490
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
491
492
tcg_gen_gvec_3_ptr(pred_full_reg_offset(s, a->rd),
493
vec_full_reg_offset(s, a->rn),
494
@@ -XXX,XX +XXX,XX @@ static bool trans_FTMAD(DisasContext *s, arg_FTMAD *a)
495
}
496
if (sve_access_check(s)) {
497
unsigned vsz = vec_full_reg_size(s);
498
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
499
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
500
tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
501
vec_full_reg_offset(s, a->rn),
502
vec_full_reg_offset(s, a->rm),
503
@@ -XXX,XX +XXX,XX @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a)
504
t_pg = tcg_temp_new_ptr();
505
tcg_gen_addi_ptr(t_rm, cpu_env, vec_full_reg_offset(s, a->rm));
506
tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, a->pg));
507
- t_fpst = get_fpstatus_ptr(a->esz == MO_16);
508
+ t_fpst = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
509
t_desc = tcg_const_i32(simd_desc(vsz, vsz, 0));
510
511
fns[a->esz - 1](t_val, t_val, t_rm, t_pg, t_fpst, t_desc);
512
@@ -XXX,XX +XXX,XX @@ static bool do_zzz_fp(DisasContext *s, arg_rrr_esz *a,
513
}
514
if (sve_access_check(s)) {
515
unsigned vsz = vec_full_reg_size(s);
516
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
517
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
518
tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
519
vec_full_reg_offset(s, a->rn),
520
vec_full_reg_offset(s, a->rm),
521
@@ -XXX,XX +XXX,XX @@ static bool do_zpzz_fp(DisasContext *s, arg_rprr_esz *a,
522
}
523
if (sve_access_check(s)) {
524
unsigned vsz = vec_full_reg_size(s);
525
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
526
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
527
tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, a->rd),
528
vec_full_reg_offset(s, a->rn),
529
vec_full_reg_offset(s, a->rm),
530
@@ -XXX,XX +XXX,XX @@ static void do_fp_scalar(DisasContext *s, int zd, int zn, int pg, bool is_fp16,
531
tcg_gen_addi_ptr(t_zn, cpu_env, vec_full_reg_offset(s, zn));
532
tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
533
534
- status = get_fpstatus_ptr(is_fp16);
535
+ status = fpstatus_ptr(is_fp16 ? FPST_FPCR_F16 : FPST_FPCR);
536
desc = tcg_const_i32(simd_desc(vsz, vsz, 0));
537
fn(t_zd, t_zn, t_pg, scalar, status, desc);
538
539
@@ -XXX,XX +XXX,XX @@ static bool do_fp_cmp(DisasContext *s, arg_rprr_esz *a,
540
}
541
if (sve_access_check(s)) {
542
unsigned vsz = vec_full_reg_size(s);
543
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
544
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
545
tcg_gen_gvec_4_ptr(pred_full_reg_offset(s, a->rd),
546
vec_full_reg_offset(s, a->rn),
547
vec_full_reg_offset(s, a->rm),
548
@@ -XXX,XX +XXX,XX @@ static bool trans_FCADD(DisasContext *s, arg_FCADD *a)
549
}
550
if (sve_access_check(s)) {
551
unsigned vsz = vec_full_reg_size(s);
552
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
553
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
554
tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, a->rd),
555
vec_full_reg_offset(s, a->rn),
556
vec_full_reg_offset(s, a->rm),
557
@@ -XXX,XX +XXX,XX @@ static bool do_fmla(DisasContext *s, arg_rprrr_esz *a,
558
}
559
if (sve_access_check(s)) {
560
unsigned vsz = vec_full_reg_size(s);
561
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
562
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
563
tcg_gen_gvec_5_ptr(vec_full_reg_offset(s, a->rd),
564
vec_full_reg_offset(s, a->rn),
565
vec_full_reg_offset(s, a->rm),
566
@@ -XXX,XX +XXX,XX @@ static bool trans_FCMLA_zpzzz(DisasContext *s, arg_FCMLA_zpzzz *a)
567
}
568
if (sve_access_check(s)) {
569
unsigned vsz = vec_full_reg_size(s);
570
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
571
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
572
tcg_gen_gvec_5_ptr(vec_full_reg_offset(s, a->rd),
573
vec_full_reg_offset(s, a->rn),
574
vec_full_reg_offset(s, a->rm),
575
@@ -XXX,XX +XXX,XX @@ static bool trans_FCMLA_zzxz(DisasContext *s, arg_FCMLA_zzxz *a)
576
tcg_debug_assert(a->rd == a->ra);
577
if (sve_access_check(s)) {
578
unsigned vsz = vec_full_reg_size(s);
579
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
580
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
581
tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
582
vec_full_reg_offset(s, a->rn),
583
vec_full_reg_offset(s, a->rm),
584
@@ -XXX,XX +XXX,XX @@ static bool do_zpz_ptr(DisasContext *s, int rd, int rn, int pg,
585
{
586
if (sve_access_check(s)) {
587
unsigned vsz = vec_full_reg_size(s);
588
- TCGv_ptr status = get_fpstatus_ptr(is_fp16);
589
+ TCGv_ptr status = fpstatus_ptr(is_fp16 ? FPST_FPCR_F16 : FPST_FPCR);
590
tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
591
vec_full_reg_offset(s, rn),
592
pred_full_reg_offset(s, pg),
593
@@ -XXX,XX +XXX,XX @@ static bool do_frint_mode(DisasContext *s, arg_rpr_esz *a, int mode)
594
if (sve_access_check(s)) {
595
unsigned vsz = vec_full_reg_size(s);
596
TCGv_i32 tmode = tcg_const_i32(mode);
597
- TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
598
+ TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
599
600
gen_helper_set_rmode(tmode, tmode, status);
601
602
--
224
--
603
2.20.1
225
2.34.1
604
226
605
227
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Remember if there was an SNaN, and use that to simplify
4
float_2nan_prop_s_{ab,ba} to only the snan component.
5
Then, fall through to the corresponding
6
float_2nan_prop_{ab,ba} case to handle any remaining
7
nans, which must be quiet.
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20241203203949.483774-10-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
fpu/softfloat-parts.c.inc | 32 ++++++++++++--------------------
15
1 file changed, 12 insertions(+), 20 deletions(-)
16
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
18
index XXXXXXX..XXXXXXX 100644
19
--- a/fpu/softfloat-parts.c.inc
20
+++ b/fpu/softfloat-parts.c.inc
21
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
22
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
23
float_status *s)
24
{
25
+ bool have_snan = false;
26
int cmp, which;
27
28
if (is_snan(a->cls) || is_snan(b->cls)) {
29
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
30
+ have_snan = true;
31
}
32
33
if (s->default_nan_mode) {
34
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
35
36
switch (s->float_2nan_prop_rule) {
37
case float_2nan_prop_s_ab:
38
- if (is_snan(a->cls)) {
39
- which = 0;
40
- } else if (is_snan(b->cls)) {
41
- which = 1;
42
- } else if (is_qnan(a->cls)) {
43
- which = 0;
44
- } else {
45
- which = 1;
46
+ if (have_snan) {
47
+ which = is_snan(a->cls) ? 0 : 1;
48
+ break;
49
}
50
- break;
51
- case float_2nan_prop_s_ba:
52
- if (is_snan(b->cls)) {
53
- which = 1;
54
- } else if (is_snan(a->cls)) {
55
- which = 0;
56
- } else if (is_qnan(b->cls)) {
57
- which = 1;
58
- } else {
59
- which = 0;
60
- }
61
- break;
62
+ /* fall through */
63
case float_2nan_prop_ab:
64
which = is_nan(a->cls) ? 0 : 1;
65
break;
66
+ case float_2nan_prop_s_ba:
67
+ if (have_snan) {
68
+ which = is_snan(b->cls) ? 1 : 0;
69
+ break;
70
+ }
71
+ /* fall through */
72
case float_2nan_prop_ba:
73
which = is_nan(b->cls) ? 1 : 0;
74
break;
75
--
76
2.34.1
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Page and block PTE decoding can share some code. Let's
3
Move the fractional comparison to the end of the
4
first handle table PTE and factorize some code shared by
4
float_2nan_prop_x87 case. This is not required for
5
page and block PTEs.
5
any other 2nan propagation rule. Reorganize the
6
x87 case itself to break out of the switch when the
7
fractional comparison is not required.
6
8
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20200728150815.11446-2-eric.auger@redhat.com
11
Message-id: 20241203203949.483774-11-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
hw/arm/smmu-common.c | 48 ++++++++++++++++----------------------------
14
fpu/softfloat-parts.c.inc | 19 +++++++++----------
13
1 file changed, 17 insertions(+), 31 deletions(-)
15
1 file changed, 9 insertions(+), 10 deletions(-)
14
16
15
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/smmu-common.c
19
--- a/fpu/softfloat-parts.c.inc
18
+++ b/hw/arm/smmu-common.c
20
+++ b/fpu/softfloat-parts.c.inc
19
@@ -XXX,XX +XXX,XX @@ static int smmu_ptw_64(SMMUTransCfg *cfg,
21
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
20
uint64_t subpage_size = 1ULL << level_shift(level, granule_sz);
22
return a;
21
uint64_t mask = subpage_size - 1;
23
}
22
uint32_t offset = iova_level_offset(iova, inputsize, level, granule_sz);
24
23
- uint64_t pte;
25
- cmp = frac_cmp(a, b);
24
+ uint64_t pte, gpa;
26
- if (cmp == 0) {
25
dma_addr_t pte_addr = baseaddr + offset * sizeof(pte);
27
- cmp = a->sign < b->sign;
26
uint8_t ap;
28
- }
27
29
-
28
@@ -XXX,XX +XXX,XX @@ static int smmu_ptw_64(SMMUTransCfg *cfg,
30
switch (s->float_2nan_prop_rule) {
29
if (is_invalid_pte(pte) || is_reserved_pte(pte, level)) {
31
case float_2nan_prop_s_ab:
30
trace_smmu_ptw_invalid_pte(stage, level, baseaddr,
32
if (have_snan) {
31
pte_addr, offset, pte);
33
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
32
- info->type = SMMU_PTW_ERR_TRANSLATION;
34
* return the NaN with the positive sign bit (if any).
33
- goto error;
35
*/
36
if (is_snan(a->cls)) {
37
- if (is_snan(b->cls)) {
38
- which = cmp > 0 ? 0 : 1;
39
- } else {
40
+ if (!is_snan(b->cls)) {
41
which = is_qnan(b->cls) ? 1 : 0;
42
+ break;
43
}
44
} else if (is_qnan(a->cls)) {
45
if (is_snan(b->cls) || !is_qnan(b->cls)) {
46
which = 0;
47
- } else {
48
- which = cmp > 0 ? 0 : 1;
49
+ break;
50
}
51
} else {
52
which = 1;
34
+ break;
53
+ break;
35
}
54
}
36
55
+ cmp = frac_cmp(a, b);
37
- if (is_page_pte(pte, level)) {
56
+ if (cmp == 0) {
38
- uint64_t gpa = get_page_pte_address(pte, granule_sz);
57
+ cmp = a->sign < b->sign;
39
+ if (is_table_pte(pte, level)) {
58
+ }
40
+ ap = PTE_APTABLE(pte);
59
+ which = cmp > 0 ? 0 : 1;
41
60
break;
42
- ap = PTE_AP(pte);
61
default:
43
if (is_permission_fault(ap, perm)) {
62
g_assert_not_reached();
44
info->type = SMMU_PTW_ERR_PERMISSION;
45
goto error;
46
}
47
-
48
- tlbe->translated_addr = gpa + (iova & mask);
49
- tlbe->perm = PTE_AP_TO_PERM(ap);
50
+ baseaddr = get_table_pte_address(pte, granule_sz);
51
+ level++;
52
+ continue;
53
+ } else if (is_page_pte(pte, level)) {
54
+ gpa = get_page_pte_address(pte, granule_sz);
55
trace_smmu_ptw_page_pte(stage, level, iova,
56
baseaddr, pte_addr, pte, gpa);
57
- return 0;
58
- }
59
- if (is_block_pte(pte, level)) {
60
+ } else {
61
uint64_t block_size;
62
- hwaddr gpa = get_block_pte_address(pte, level, granule_sz,
63
- &block_size);
64
-
65
- ap = PTE_AP(pte);
66
- if (is_permission_fault(ap, perm)) {
67
- info->type = SMMU_PTW_ERR_PERMISSION;
68
- goto error;
69
- }
70
71
+ gpa = get_block_pte_address(pte, level, granule_sz,
72
+ &block_size);
73
trace_smmu_ptw_block_pte(stage, level, baseaddr,
74
pte_addr, pte, iova, gpa,
75
block_size >> 20);
76
-
77
- tlbe->translated_addr = gpa + (iova & mask);
78
- tlbe->perm = PTE_AP_TO_PERM(ap);
79
- return 0;
80
}
81
-
82
- /* table pte */
83
- ap = PTE_APTABLE(pte);
84
-
85
+ ap = PTE_AP(pte);
86
if (is_permission_fault(ap, perm)) {
87
info->type = SMMU_PTW_ERR_PERMISSION;
88
goto error;
89
}
90
- baseaddr = get_table_pte_address(pte, granule_sz);
91
- level++;
92
- }
93
94
+ tlbe->translated_addr = gpa + (iova & mask);
95
+ tlbe->perm = PTE_AP_TO_PERM(ap);
96
+ return 0;
97
+ }
98
info->type = SMMU_PTW_ERR_TRANSLATION;
99
100
error:
101
--
63
--
102
2.20.1
64
2.34.1
103
104
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Introduce the smmu_get_iotlb_key() helper and the
3
Replace the "index" selecting between A and B with a result variable
4
SMMU_IOTLB_ASID() macro. Also move smmu_get_iotlb_key and
4
of the proper type. This improves clarity within the function.
5
smmu_iotlb_key_hash in the IOTLB related code section.
6
5
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20200728150815.11446-4-eric.auger@redhat.com
8
Message-id: 20241203203949.483774-12-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/arm/smmu-internal.h | 1 +
11
fpu/softfloat-parts.c.inc | 28 +++++++++++++---------------
13
include/hw/arm/smmu-common.h | 1 +
12
1 file changed, 13 insertions(+), 15 deletions(-)
14
hw/arm/smmu-common.c | 66 ++++++++++++++++++++----------------
15
3 files changed, 38 insertions(+), 30 deletions(-)
16
13
17
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/smmu-internal.h
16
--- a/fpu/softfloat-parts.c.inc
20
+++ b/hw/arm/smmu-internal.h
17
+++ b/fpu/softfloat-parts.c.inc
21
@@ -XXX,XX +XXX,XX @@ uint64_t iova_level_offset(uint64_t iova, int inputsize,
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
22
MAKE_64BIT_MASK(0, gsz - 3);
19
float_status *s)
20
{
21
bool have_snan = false;
22
- int cmp, which;
23
+ FloatPartsN *ret;
24
+ int cmp;
25
26
if (is_snan(a->cls) || is_snan(b->cls)) {
27
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
28
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
29
switch (s->float_2nan_prop_rule) {
30
case float_2nan_prop_s_ab:
31
if (have_snan) {
32
- which = is_snan(a->cls) ? 0 : 1;
33
+ ret = is_snan(a->cls) ? a : b;
34
break;
35
}
36
/* fall through */
37
case float_2nan_prop_ab:
38
- which = is_nan(a->cls) ? 0 : 1;
39
+ ret = is_nan(a->cls) ? a : b;
40
break;
41
case float_2nan_prop_s_ba:
42
if (have_snan) {
43
- which = is_snan(b->cls) ? 1 : 0;
44
+ ret = is_snan(b->cls) ? b : a;
45
break;
46
}
47
/* fall through */
48
case float_2nan_prop_ba:
49
- which = is_nan(b->cls) ? 1 : 0;
50
+ ret = is_nan(b->cls) ? b : a;
51
break;
52
case float_2nan_prop_x87:
53
/*
54
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
55
*/
56
if (is_snan(a->cls)) {
57
if (!is_snan(b->cls)) {
58
- which = is_qnan(b->cls) ? 1 : 0;
59
+ ret = is_qnan(b->cls) ? b : a;
60
break;
61
}
62
} else if (is_qnan(a->cls)) {
63
if (is_snan(b->cls) || !is_qnan(b->cls)) {
64
- which = 0;
65
+ ret = a;
66
break;
67
}
68
} else {
69
- which = 1;
70
+ ret = b;
71
break;
72
}
73
cmp = frac_cmp(a, b);
74
if (cmp == 0) {
75
cmp = a->sign < b->sign;
76
}
77
- which = cmp > 0 ? 0 : 1;
78
+ ret = cmp > 0 ? a : b;
79
break;
80
default:
81
g_assert_not_reached();
82
}
83
84
- if (which) {
85
- a = b;
86
+ if (is_snan(ret->cls)) {
87
+ parts_silence_nan(ret, s);
88
}
89
- if (is_snan(a->cls)) {
90
- parts_silence_nan(a, s);
91
- }
92
- return a;
93
+ return ret;
23
}
94
}
24
95
25
+#define SMMU_IOTLB_ASID(key) ((key).asid)
96
static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
26
#endif
27
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/arm/smmu-common.h
30
+++ b/include/hw/arm/smmu-common.h
31
@@ -XXX,XX +XXX,XX @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid);
32
33
IOMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, hwaddr iova);
34
void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, IOMMUTLBEntry *entry);
35
+SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova);
36
void smmu_iotlb_inv_all(SMMUState *s);
37
void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
38
void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova);
39
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/smmu-common.c
42
+++ b/hw/arm/smmu-common.c
43
@@ -XXX,XX +XXX,XX @@
44
45
/* IOTLB Management */
46
47
+static guint smmu_iotlb_key_hash(gconstpointer v)
48
+{
49
+ SMMUIOTLBKey *key = (SMMUIOTLBKey *)v;
50
+ uint32_t a, b, c;
51
+
52
+ /* Jenkins hash */
53
+ a = b = c = JHASH_INITVAL + sizeof(*key);
54
+ a += key->asid;
55
+ b += extract64(key->iova, 0, 32);
56
+ c += extract64(key->iova, 32, 32);
57
+
58
+ __jhash_mix(a, b, c);
59
+ __jhash_final(a, b, c);
60
+
61
+ return c;
62
+}
63
+
64
+static gboolean smmu_iotlb_key_equal(gconstpointer v1, gconstpointer v2)
65
+{
66
+ const SMMUIOTLBKey *k1 = v1;
67
+ const SMMUIOTLBKey *k2 = v2;
68
+
69
+ return (k1->asid == k2->asid) && (k1->iova == k2->iova);
70
+}
71
+
72
+SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova)
73
+{
74
+ SMMUIOTLBKey key = {.asid = asid, .iova = iova};
75
+
76
+ return key;
77
+}
78
+
79
IOMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
80
hwaddr iova)
81
{
82
- SMMUIOTLBKey key = {.asid = cfg->asid, .iova = iova};
83
+ SMMUIOTLBKey key = smmu_get_iotlb_key(cfg->asid, iova);
84
IOMMUTLBEntry *entry = g_hash_table_lookup(bs->iotlb, &key);
85
86
if (entry) {
87
@@ -XXX,XX +XXX,XX @@ void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, IOMMUTLBEntry *entry)
88
smmu_iotlb_inv_all(bs);
89
}
90
91
- key->asid = cfg->asid;
92
- key->iova = entry->iova;
93
+ *key = smmu_get_iotlb_key(cfg->asid, entry->iova);
94
trace_smmu_iotlb_insert(cfg->asid, entry->iova);
95
g_hash_table_insert(bs->iotlb, key, entry);
96
}
97
@@ -XXX,XX +XXX,XX @@ static gboolean smmu_hash_remove_by_asid(gpointer key, gpointer value,
98
uint16_t asid = *(uint16_t *)user_data;
99
SMMUIOTLBKey *iotlb_key = (SMMUIOTLBKey *)key;
100
101
- return iotlb_key->asid == asid;
102
+ return SMMU_IOTLB_ASID(*iotlb_key) == asid;
103
}
104
105
inline void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova)
106
{
107
- SMMUIOTLBKey key = {.asid = asid, .iova = iova};
108
+ SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova);
109
110
trace_smmu_iotlb_inv_iova(asid, iova);
111
g_hash_table_remove(s->iotlb, &key);
112
@@ -XXX,XX +XXX,XX @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid)
113
return NULL;
114
}
115
116
-static guint smmu_iotlb_key_hash(gconstpointer v)
117
-{
118
- SMMUIOTLBKey *key = (SMMUIOTLBKey *)v;
119
- uint32_t a, b, c;
120
-
121
- /* Jenkins hash */
122
- a = b = c = JHASH_INITVAL + sizeof(*key);
123
- a += key->asid;
124
- b += extract64(key->iova, 0, 32);
125
- c += extract64(key->iova, 32, 32);
126
-
127
- __jhash_mix(a, b, c);
128
- __jhash_final(a, b, c);
129
-
130
- return c;
131
-}
132
-
133
-static gboolean smmu_iotlb_key_equal(gconstpointer v1, gconstpointer v2)
134
-{
135
- const SMMUIOTLBKey *k1 = v1;
136
- const SMMUIOTLBKey *k2 = v2;
137
-
138
- return (k1->asid == k2->asid) && (k1->iova == k2->iova);
139
-}
140
-
141
/* Unmap the whole notifier's range */
142
static void smmu_unmap_notifier_range(IOMMUNotifier *n)
143
{
144
--
97
--
145
2.20.1
98
2.34.1
146
99
147
100
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
Add the support for AIDR register. It currently advertises
3
I'm migrating to Qualcomm's new open source email infrastructure, so
4
SMMU V3.0 spec.
4
update my email address, and update the mailmap to match.
5
5
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Signed-off-by: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
8
Message-id: 20200728150815.11446-10-eric.auger@redhat.com
8
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20241205114047.1125842-1-leif.lindholm@oss.qualcomm.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
hw/arm/smmuv3-internal.h | 1 +
14
MAINTAINERS | 2 +-
12
include/hw/arm/smmuv3.h | 1 +
15
.mailmap | 5 +++--
13
hw/arm/smmuv3.c | 3 +++
16
2 files changed, 4 insertions(+), 3 deletions(-)
14
3 files changed, 5 insertions(+)
15
17
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
18
diff --git a/MAINTAINERS b/MAINTAINERS
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/smmuv3-internal.h
20
--- a/MAINTAINERS
19
+++ b/hw/arm/smmuv3-internal.h
21
+++ b/MAINTAINERS
20
@@ -XXX,XX +XXX,XX @@ REG32(IDR5, 0x14)
22
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
21
#define SMMU_IDR5_OAS 4
23
SBSA-REF
22
24
M: Radoslaw Biernacki <rad@semihalf.com>
23
REG32(IIDR, 0x18)
25
M: Peter Maydell <peter.maydell@linaro.org>
24
+REG32(AIDR, 0x1c)
26
-R: Leif Lindholm <quic_llindhol@quicinc.com>
25
REG32(CR0, 0x20)
27
+R: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
26
FIELD(CR0, SMMU_ENABLE, 0, 1)
28
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
27
FIELD(CR0, EVENTQEN, 2, 1)
29
L: qemu-arm@nongnu.org
28
diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h
30
S: Maintained
31
diff --git a/.mailmap b/.mailmap
29
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/smmuv3.h
33
--- a/.mailmap
31
+++ b/include/hw/arm/smmuv3.h
34
+++ b/.mailmap
32
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUv3State {
35
@@ -XXX,XX +XXX,XX @@ Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
33
36
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
34
uint32_t idr[6];
37
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
35
uint32_t iidr;
38
Juan Quintela <quintela@trasno.org> <quintela@redhat.com>
36
+ uint32_t aidr;
39
-Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
37
uint32_t cr[3];
40
-Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
38
uint32_t cr0ack;
41
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <quic_llindhol@quicinc.com>
39
uint32_t statusr;
42
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif.lindholm@linaro.org>
40
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
43
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif@nuviainc.com>
41
index XXXXXXX..XXXXXXX 100644
44
Luc Michel <luc@lmichel.fr> <luc.michel@git.antfield.fr>
42
--- a/hw/arm/smmuv3.c
45
Luc Michel <luc@lmichel.fr> <luc.michel@greensocs.com>
43
+++ b/hw/arm/smmuv3.c
46
Luc Michel <luc@lmichel.fr> <lmichel@kalray.eu>
44
@@ -XXX,XX +XXX,XX @@ static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset,
45
case A_IIDR:
46
*data = s->iidr;
47
return MEMTX_OK;
48
+ case A_AIDR:
49
+ *data = s->aidr;
50
+ return MEMTX_OK;
51
case A_CR0:
52
*data = s->cr[0];
53
return MEMTX_OK;
54
--
47
--
55
2.20.1
48
2.34.1
56
49
57
50
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Vikram Garhwal <vikram.garhwal@bytedance.com>
2
2
3
Document the Xilinx Versal Virt board.
3
Previously, maintainer role was paused due to inactive email id. Commit id:
4
c009d715721861984c4987bcc78b7ee183e86d75.
4
5
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Signed-off-by: Vikram Garhwal <vikram.garhwal@bytedance.com>
6
Message-id: 20200803164749.301971-2-edgar.iglesias@gmail.com
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241204184205.12952-1-vikram.garhwal@bytedance.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
docs/system/arm/xlnx-versal-virt.rst | 176 +++++++++++++++++++++++++++
11
MAINTAINERS | 2 ++
11
docs/system/target-arm.rst | 1 +
12
1 file changed, 2 insertions(+)
12
MAINTAINERS | 3 +-
13
3 files changed, 179 insertions(+), 1 deletion(-)
14
create mode 100644 docs/system/arm/xlnx-versal-virt.rst
15
13
16
diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
17
new file mode 100644
18
index XXXXXXX..XXXXXXX
19
--- /dev/null
20
+++ b/docs/system/arm/xlnx-versal-virt.rst
21
@@ -XXX,XX +XXX,XX @@
22
+Xilinx Versal Virt (``xlnx-versal-virt``)
23
+=========================================
24
+
25
+Xilinx Versal is a family of heterogeneous multi-core SoCs
26
+(System on Chip) that combine traditional hardened CPUs and I/O
27
+peripherals in a Processing System (PS) with runtime programmable
28
+FPGA logic (PL) and an Artificial Intelligence Engine (AIE).
29
+
30
+More details here:
31
+https://www.xilinx.com/products/silicon-devices/acap/versal.html
32
+
33
+The family of Versal SoCs share a single architecture but come in
34
+different parts with different speed grades, amounts of PL and
35
+other differences.
36
+
37
+The Xilinx Versal Virt board in QEMU is a model of a virtual board
38
+(does not exist in reality) with a virtual Versal SoC without I/O
39
+limitations. Currently, we support the following cores and devices:
40
+
41
+Implemented CPU cores:
42
+
43
+- 2 ACPUs (ARM Cortex-A72)
44
+
45
+Implemented devices:
46
+
47
+- Interrupt controller (ARM GICv3)
48
+- 2 UARTs (ARM PL011)
49
+- An RTC (Versal built-in)
50
+- 2 GEMs (Cadence MACB Ethernet MACs)
51
+- 8 ADMA (Xilinx zDMA) channels
52
+- 2 SD Controllers
53
+- OCM (256KB of On Chip Memory)
54
+- DDR memory
55
+
56
+QEMU does not yet model any other devices, including the PL and the AI Engine.
57
+
58
+Other differences between the hardware and the QEMU model:
59
+
60
+- QEMU allows the amount of DDR memory provided to be specified with the
61
+ ``-m`` argument. If a DTB is provided on the command line then QEMU will
62
+ edit it to include suitable entries describing the Versal DDR memory ranges.
63
+
64
+- QEMU provides 8 virtio-mmio virtio transports; these start at
65
+ address ``0xa0000000`` and have IRQs from 111 and upwards.
66
+
67
+Running
68
+"""""""
69
+If the user provides an Operating System to be loaded, we expect users
70
+to use the ``-kernel`` command line option.
71
+
72
+Users can load firmware or boot-loaders with the ``-device loader`` options.
73
+
74
+When loading an OS, QEMU generates a DTB and selects an appropriate address
75
+where it gets loaded. This DTB will be passed to the kernel in register x0.
76
+
77
+If there's no ``-kernel`` option, we generate a DTB and place it at 0x1000
78
+for boot-loaders or firmware to pick it up.
79
+
80
+If users want to provide their own DTB, they can use the ``-dtb`` option.
81
+These DTBs will have their memory nodes modified to match QEMU's
82
+selected ram_size option before they get passed to the kernel or FW.
83
+
84
+When loading an OS, we turn on QEMU's PSCI implementation with SMC
85
+as the PSCI conduit. When there's no ``-kernel`` option, we assume the user
86
+provides EL3 firmware to handle PSCI.
87
+
88
+A few examples:
89
+
90
+Direct Linux boot of a generic ARM64 upstream Linux kernel:
91
+
92
+.. code-block:: bash
93
+
94
+ $ qemu-system-aarch64 -M xlnx-versal-virt -m 2G \
95
+ -serial mon:stdio -display none \
96
+ -kernel arch/arm64/boot/Image \
97
+ -nic user -nic user \
98
+ -device virtio-rng-device,bus=virtio-mmio-bus.0 \
99
+ -drive if=none,index=0,file=hd0.qcow2,id=hd0,snapshot \
100
+ -drive file=qemu_sd.qcow2,if=sd,index=0,snapshot \
101
+ -device virtio-blk-device,drive=hd0 -append root=/dev/vda
102
+
103
+Direct Linux boot of PetaLinux 2019.2:
104
+
105
+.. code-block:: bash
106
+
107
+ $ qemu-system-aarch64 -M xlnx-versal-virt -m 2G \
108
+ -serial mon:stdio -display none \
109
+ -kernel petalinux-v2019.2/Image \
110
+ -append "rdinit=/sbin/init console=ttyAMA0,115200n8 earlycon=pl011,mmio,0xFF000000,115200n8" \
111
+ -net nic,model=cadence_gem,netdev=net0 -netdev user,id=net0 \
112
+ -device virtio-rng-device,bus=virtio-mmio-bus.0,rng=rng0 \
113
+ -object rng-random,filename=/dev/urandom,id=rng0
114
+
115
+Boot PetaLinux 2019.2 via ARM Trusted Firmware (2018.3 because the 2019.2
116
+version of ATF tries to configure the CCI which we don't model) and U-boot:
117
+
118
+.. code-block:: bash
119
+
120
+ $ qemu-system-aarch64 -M xlnx-versal-virt -m 2G \
121
+ -serial stdio -display none \
122
+ -device loader,file=petalinux-v2018.3/bl31.elf,cpu-num=0 \
123
+ -device loader,file=petalinux-v2019.2/u-boot.elf \
124
+ -device loader,addr=0x20000000,file=petalinux-v2019.2/Image \
125
+ -nic user -nic user \
126
+ -device virtio-rng-device,bus=virtio-mmio-bus.0,rng=rng0 \
127
+ -object rng-random,filename=/dev/urandom,id=rng0
128
+
129
+Run the following at the U-Boot prompt:
130
+
131
+.. code-block:: bash
132
+
133
+ Versal>
134
+ fdt addr $fdtcontroladdr
135
+ fdt move $fdtcontroladdr 0x40000000
136
+ fdt set /timer clock-frequency <0x3dfd240>
137
+ setenv bootargs "rdinit=/sbin/init maxcpus=1 console=ttyAMA0,115200n8 earlycon=pl011,mmio,0xFF000000,115200n8"
138
+ booti 20000000 - 40000000
139
+ fdt addr $fdtcontroladdr
140
+
141
+Boot Linux as DOM0 on Xen via U-Boot:
142
+
143
+.. code-block:: bash
144
+
145
+ $ qemu-system-aarch64 -M xlnx-versal-virt -m 4G \
146
+ -serial stdio -display none \
147
+ -device loader,file=petalinux-v2019.2/u-boot.elf,cpu-num=0 \
148
+ -device loader,addr=0x30000000,file=linux/2018-04-24/xen \
149
+ -device loader,addr=0x40000000,file=petalinux-v2019.2/Image \
150
+ -nic user -nic user \
151
+ -device virtio-rng-device,bus=virtio-mmio-bus.0,rng=rng0 \
152
+ -object rng-random,filename=/dev/urandom,id=rng0
153
+
154
+Run the following at the U-Boot prompt:
155
+
156
+.. code-block:: bash
157
+
158
+ Versal>
159
+ fdt addr $fdtcontroladdr
160
+ fdt move $fdtcontroladdr 0x20000000
161
+ fdt set /timer clock-frequency <0x3dfd240>
162
+ fdt set /chosen xen,xen-bootargs "console=dtuart dtuart=/uart@ff000000 dom0_mem=640M bootscrub=0 maxcpus=1 timer_slop=0"
163
+ fdt set /chosen xen,dom0-bootargs "rdinit=/sbin/init clk_ignore_unused console=hvc0 maxcpus=1"
164
+ fdt mknode /chosen dom0
165
+ fdt set /chosen/dom0 compatible "xen,multiboot-module"
166
+ fdt set /chosen/dom0 reg <0x00000000 0x40000000 0x0 0x03100000>
167
+ booti 30000000 - 20000000
168
+
169
+Boot Linux as Dom0 on Xen via ARM Trusted Firmware and U-Boot:
170
+
171
+.. code-block:: bash
172
+
173
+ $ qemu-system-aarch64 -M xlnx-versal-virt -m 4G \
174
+ -serial stdio -display none \
175
+ -device loader,file=petalinux-v2018.3/bl31.elf,cpu-num=0 \
176
+ -device loader,file=petalinux-v2019.2/u-boot.elf \
177
+ -device loader,addr=0x30000000,file=linux/2018-04-24/xen \
178
+ -device loader,addr=0x40000000,file=petalinux-v2019.2/Image \
179
+ -nic user -nic user \
180
+ -device virtio-rng-device,bus=virtio-mmio-bus.0,rng=rng0 \
181
+ -object rng-random,filename=/dev/urandom,id=rng0
182
+
183
+Run the following at the U-Boot prompt:
184
+
185
+.. code-block:: bash
186
+
187
+ Versal>
188
+ fdt addr $fdtcontroladdr
189
+ fdt move $fdtcontroladdr 0x20000000
190
+ fdt set /timer clock-frequency <0x3dfd240>
191
+ fdt set /chosen xen,xen-bootargs "console=dtuart dtuart=/uart@ff000000 dom0_mem=640M bootscrub=0 maxcpus=1 timer_slop=0"
192
+ fdt set /chosen xen,dom0-bootargs "rdinit=/sbin/init clk_ignore_unused console=hvc0 maxcpus=1"
193
+ fdt mknode /chosen dom0
194
+ fdt set /chosen/dom0 compatible "xen,multiboot-module"
195
+ fdt set /chosen/dom0 reg <0x00000000 0x40000000 0x0 0x03100000>
196
+ booti 30000000 - 20000000
197
+
198
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
199
index XXXXXXX..XXXXXXX 100644
200
--- a/docs/system/target-arm.rst
201
+++ b/docs/system/target-arm.rst
202
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
203
arm/sx1
204
arm/stellaris
205
arm/virt
206
+ arm/xlnx-versal-virt
207
208
Arm CPU features
209
================
210
diff --git a/MAINTAINERS b/MAINTAINERS
14
diff --git a/MAINTAINERS b/MAINTAINERS
211
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
212
--- a/MAINTAINERS
16
--- a/MAINTAINERS
213
+++ b/MAINTAINERS
17
+++ b/MAINTAINERS
214
@@ -XXX,XX +XXX,XX @@ F: hw/misc/zynq*
18
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-sb16-test.c
215
F: include/hw/misc/zynq*
19
216
X: hw/ssi/xilinx_*
20
Xilinx CAN
217
21
M: Francisco Iglesias <francisco.iglesias@amd.com>
218
-Xilinx ZynqMP
22
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
219
+Xilinx ZynqMP and Versal
23
S: Maintained
220
M: Alistair Francis <alistair@alistair23.me>
24
F: hw/net/can/xlnx-*
221
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
25
F: include/hw/net/xlnx-*
222
M: Peter Maydell <peter.maydell@linaro.org>
26
@@ -XXX,XX +XXX,XX @@ F: include/hw/rx/
223
@@ -XXX,XX +XXX,XX @@ F: include/hw/*/xlnx*.h
27
CAN bus subsystem and hardware
224
F: include/hw/ssi/xilinx_spips.h
28
M: Pavel Pisa <pisa@cmp.felk.cvut.cz>
225
F: hw/display/dpcd.c
29
M: Francisco Iglesias <francisco.iglesias@amd.com>
226
F: include/hw/display/dpcd.h
30
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
227
+F: docs/system/arm/xlnx-versal-virt.rst
31
S: Maintained
228
32
W: https://canbus.pages.fel.cvut.cz/
229
ARM ACPI Subsystem
33
F: net/can/*
230
M: Shannon Zhao <shannon.zhaosl@gmail.com>
231
--
34
--
232
2.20.1
35
2.34.1
233
234
diff view generated by jsdifflib