1
The following changes since commit 11b8920ed2093848f79f93d106afe8a69a61a523:
1
First arm pullreq of the cycle; this is mostly my softfloat NaN
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 :-))
2
4
3
Merge tag 'pull-request-2024-11-04' of https://gitlab.com/thuth/qemu into staging (2024-11-04 17:37:59 +0000)
5
thanks
6
-- PMM
7
8
The following changes since commit 97f2796a3736ed37a1b85dc1c76a6c45b829dd17:
9
10
Open 10.0 development tree (2024-12-10 17:41:17 +0000)
4
11
5
are available in the Git repository at:
12
are available in the Git repository at:
6
13
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20241105
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20241211
8
15
9
for you to fetch changes up to 374cdc8efe4a039510cca47e8399d54a1aeb4f2d:
16
for you to fetch changes up to 1abe28d519239eea5cf9620bb13149423e5665f8:
10
17
11
target/arm: Enable FEAT_CMOW for -cpu max (2024-11-05 10:10:00 +0000)
18
MAINTAINERS: Add correct email address for Vikram Garhwal (2024-12-11 15:31:09 +0000)
12
19
13
----------------------------------------------------------------
20
----------------------------------------------------------------
14
target-arm queue:
21
target-arm queue:
15
* Fix MMU indexes for AArch32 Secure PL1&0 in a less complex and buggy way
22
* hw/net/lan9118: Extract PHY model, reuse with imx_fec, fix bugs
16
* Fix SVE SDOT/UDOT/USDOT (4-way, indexed)
23
* fpu: Make muladd NaN handling runtime-selected, not compile-time
17
* softfloat: set 2-operand NaN propagation rule at runtime
24
* fpu: Make default NaN pattern runtime-selected, not compile-time
18
* disas: Fix build against Capstone v6 (again)
25
* fpu: Minor NaN-related cleanups
19
* hw/rtc/ds1338: Trace send and receive operations
26
* MAINTAINERS: email address updates
20
* hw/timer/imx_gpt: Convert DPRINTF to trace events
21
* hw/watchdog/wdt_imx2: Remove redundant assignment
22
* hw/sensor/tmp105: Convert printf() to trace event, add tracing for read/write access
23
* hw/net/npcm_gmac: Change error log to trace event
24
* target/arm: Enable FEAT_CMOW for -cpu max
25
27
26
----------------------------------------------------------------
28
----------------------------------------------------------------
27
Bernhard Beschow (4):
29
Bernhard Beschow (5):
28
hw/rtc/ds1338: Trace send and receive operations
30
hw/net/lan9118: Extract lan9118_phy
29
hw/timer/imx_gpt: Convert DPRINTF to trace events
31
hw/net/lan9118_phy: Reuse in imx_fec and consolidate implementations
30
hw/watchdog/wdt_imx2: Remove redundant assignment
32
hw/net/lan9118_phy: Fix off-by-one error in MII_ANLPAR register
31
hw/sensor/tmp105: Convert printf() to trace event, add tracing for read/write access
33
hw/net/lan9118_phy: Reuse MII constants
34
hw/net/lan9118_phy: Add missing 100 mbps full duplex advertisement
32
35
33
Gustavo Romero (1):
36
Leif Lindholm (1):
34
target/arm: Enable FEAT_CMOW for -cpu max
37
MAINTAINERS: update email address for Leif Lindholm
35
38
36
Nabih Estefan (1):
39
Peter Maydell (54):
37
hw/net/npcm_gmac: Change error log to trace event
40
fpu: handle raising Invalid for infzero in pick_nan_muladd
41
fpu: Check for default_nan_mode before calling pickNaNMulAdd
42
softfloat: Allow runtime choice of inf * 0 + NaN result
43
tests/fp: Explicitly set inf-zero-nan rule
44
target/arm: Set FloatInfZeroNaNRule explicitly
45
target/s390: Set FloatInfZeroNaNRule explicitly
46
target/ppc: Set FloatInfZeroNaNRule explicitly
47
target/mips: Set FloatInfZeroNaNRule explicitly
48
target/sparc: Set FloatInfZeroNaNRule explicitly
49
target/xtensa: Set FloatInfZeroNaNRule explicitly
50
target/x86: Set FloatInfZeroNaNRule explicitly
51
target/loongarch: Set FloatInfZeroNaNRule explicitly
52
target/hppa: Set FloatInfZeroNaNRule explicitly
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
38
94
39
Peter Maydell (24):
95
Richard Henderson (11):
40
softfloat: Allow 2-operand NaN propagation rule to be set at runtime
96
target/arm: Copy entire float_status in is_ebf
41
tests/fp: Explicitly set 2-NaN propagation rule
97
softfloat: Inline pickNaNMulAdd
42
target/arm: Explicitly set 2-NaN propagation rule
98
softfloat: Use goto for default nan case in pick_nan_muladd
43
target/mips: Explicitly set 2-NaN propagation rule
99
softfloat: Remove which from parts_pick_nan_muladd
44
target/loongarch: Explicitly set 2-NaN propagation rule
100
softfloat: Pad array size in pick_nan_muladd
45
target/hppa: Explicitly set 2-NaN propagation rule
101
softfloat: Move propagateFloatx80NaN to softfloat.c
46
target/s390x: Explicitly set 2-NaN propagation rule
102
softfloat: Use parts_pick_nan in propagateFloatx80NaN
47
target/ppc: Explicitly set 2-NaN propagation rule
103
softfloat: Inline pickNaN
48
target/m68k: Explicitly set 2-NaN propagation rule
104
softfloat: Share code between parts_pick_nan cases
49
target/m68k: Initialize float_status fields in gdb set/get functions
105
softfloat: Sink frac_cmp in parts_pick_nan until needed
50
target/sparc: Move cpu_put_fsr(env, 0) call to reset
106
softfloat: Replace WHICH with RET in parts_pick_nan
51
target/sparc: Explicitly set 2-NaN propagation rule
52
target/xtensa: Factor out calls to set_use_first_nan()
53
target/xtensa: Explicitly set 2-NaN propagation rule
54
target/i386: Set 2-NaN propagation rule explicitly
55
target/alpha: Explicitly set 2-NaN propagation rule
56
target/microblaze: Move setting of float rounding mode to reset
57
target/microblaze: Explicitly set 2-NaN propagation rule
58
target/openrisc: Explicitly set 2-NaN propagation rule
59
target/rx: Explicitly set 2-NaN propagation rule
60
softfloat: Remove fallback rule from pickNaN()
61
Revert "target/arm: Fix usage of MMU indexes when EL3 is AArch32"
62
target/arm: Add new MMU indexes for AArch32 Secure PL1&0
63
target/arm: Fix SVE SDOT/UDOT/USDOT (4-way, indexed)
64
107
65
Richard Henderson (1):
108
Vikram Garhwal (1):
66
disas: Fix build against Capstone v6 (again)
109
MAINTAINERS: Add correct email address for Vikram Garhwal
67
110
68
docs/system/arm/emulation.rst | 1 +
111
MAINTAINERS | 4 +-
69
meson.build | 1 +
112
include/fpu/softfloat-helpers.h | 38 +++-
70
hw/sensor/trace.h | 1 +
113
include/fpu/softfloat-types.h | 89 +++++++-
71
include/disas/capstone.h | 1 +
114
include/hw/net/imx_fec.h | 9 +-
72
include/fpu/softfloat-helpers.h | 11 +++
115
include/hw/net/lan9118_phy.h | 37 ++++
73
include/fpu/softfloat-types.h | 38 ++++++++++
116
include/hw/net/mii.h | 6 +
74
target/arm/cpu-features.h | 5 ++
117
target/mips/fpu_helper.h | 20 ++
75
target/arm/cpu.h | 49 ++++++------
118
target/sparc/helper.h | 4 +-
76
target/arm/internals.h | 41 +++++-----
119
fpu/softfloat.c | 19 ++
77
target/arm/tcg/translate.h | 2 -
120
hw/net/imx_fec.c | 146 ++------------
78
target/i386/cpu.h | 3 +
121
hw/net/lan9118.c | 137 ++-----------
79
target/mips/fpu_helper.h | 22 ++++++
122
hw/net/lan9118_phy.c | 222 ++++++++++++++++++++
80
target/xtensa/cpu.h | 6 ++
123
linux-user/arm/nwfpe/fpa11.c | 5 +
81
hw/net/npcm_gmac.c | 5 +-
124
target/alpha/cpu.c | 2 +
82
hw/rtc/ds1338.c | 6 ++
125
target/arm/cpu.c | 10 +
83
hw/sensor/tmp105.c | 7 +-
126
target/arm/tcg/vec_helper.c | 20 +-
84
hw/timer/imx_gpt.c | 18 ++---
127
target/hexagon/cpu.c | 2 +
85
hw/watchdog/wdt_imx2.c | 1 -
128
target/hppa/fpu_helper.c | 12 ++
86
linux-user/arm/nwfpe/fpa11.c | 18 +++++
129
target/i386/tcg/fpu_helper.c | 12 ++
87
target/alpha/cpu.c | 11 +++
130
target/loongarch/tcg/fpu_helper.c | 14 +-
88
target/arm/cpu.c | 25 ++++--
131
target/m68k/cpu.c | 14 +-
89
target/arm/helper.c | 73 ++++++++++++------
132
target/m68k/fpu_helper.c | 6 +-
90
target/arm/ptw.c | 10 +--
133
target/m68k/helper.c | 6 +-
91
target/arm/tcg/cpu64.c | 1 +
134
target/microblaze/cpu.c | 2 +
92
target/arm/tcg/hflags.c | 4 -
135
target/mips/msa.c | 10 +
93
target/arm/tcg/op_helper.c | 14 +++-
136
target/openrisc/cpu.c | 2 +
94
target/arm/tcg/translate-a64.c | 2 +-
137
target/ppc/cpu_init.c | 19 ++
95
target/arm/tcg/translate.c | 12 +--
138
target/ppc/fpu_helper.c | 3 +-
96
target/arm/tcg/vec_helper.c | 9 ++-
139
target/riscv/cpu.c | 2 +
97
target/hppa/fpu_helper.c | 6 ++
140
target/rx/cpu.c | 2 +
98
target/i386/cpu.c | 4 +
141
target/s390x/cpu.c | 5 +
99
target/i386/tcg/fpu_helper.c | 40 ++++++++++
142
target/sh4/cpu.c | 2 +
100
target/loongarch/tcg/fpu_helper.c | 1 +
143
target/sparc/cpu.c | 6 +
101
target/m68k/cpu.c | 16 ++++
144
target/sparc/fop_helper.c | 8 +-
102
target/m68k/fpu_helper.c | 1 +
145
target/sparc/translate.c | 4 +-
103
target/m68k/helper.c | 4 +-
146
target/tricore/helper.c | 2 +
104
target/microblaze/cpu.c | 10 ++-
147
target/xtensa/cpu.c | 4 +
105
target/mips/cpu.c | 2 +-
148
target/xtensa/fpu_helper.c | 3 +-
106
target/mips/msa.c | 17 +++++
149
tests/fp/fp-bench.c | 7 +
107
target/openrisc/cpu.c | 6 ++
108
target/ppc/cpu_init.c | 8 ++
109
target/rx/cpu.c | 7 ++
110
target/s390x/cpu.c | 1 +
111
target/sparc/cpu.c | 10 ++-
112
target/sparc/fop_helper.c | 10 ++-
113
target/xtensa/cpu.c | 2 +-
114
target/xtensa/fpu_helper.c | 35 +++++----
115
tests/fp/fp-bench.c | 2 +
116
tests/fp/fp-test-log2.c | 1 +
150
tests/fp/fp-test-log2.c | 1 +
117
tests/fp/fp-test.c | 2 +
151
tests/fp/fp-test.c | 7 +
118
fpu/softfloat-specialize.c.inc | 156 ++++++++++++++------------------------
152
fpu/softfloat-parts.c.inc | 152 +++++++++++---
119
hw/net/trace-events | 1 +
153
fpu/softfloat-specialize.c.inc | 412 ++------------------------------------
120
hw/rtc/trace-events | 4 +
154
.mailmap | 5 +-
121
hw/sensor/trace-events | 6 ++
155
hw/net/Kconfig | 5 +
122
hw/timer/trace-events | 6 ++
156
hw/net/meson.build | 1 +
123
55 files changed, 516 insertions(+), 239 deletions(-)
157
hw/net/trace-events | 10 +-
124
create mode 100644 hw/sensor/trace.h
158
47 files changed, 778 insertions(+), 730 deletions(-)
125
create mode 100644 hw/sensor/trace-events
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
Our current usage of MMU indexes when EL3 is AArch32 is confused.
1
From: Bernhard Beschow <shentey@gmail.com>
2
Architecturally, when EL3 is AArch32, all Secure code runs under the
3
Secure PL1&0 translation regime:
4
* code at EL3, which might be Mon, or SVC, or any of the
5
other privileged modes (PL1)
6
* code at EL0 (Secure PL0)
7
2
8
This is different from when EL3 is AArch64, in which case EL3 is its
3
A very similar implementation of the same device exists in imx_fec. Prepare for
9
own translation regime, and EL1 and EL0 (whether AArch32 or AArch64)
4
a common implementation by extracting a device model into its own files.
10
have their own regime.
11
5
12
We claimed to be mapping Secure PL1 to our ARMMMUIdx_EL3, but didn't
6
Some migration state has been moved into the new device model which breaks
13
do anything special about Secure PL0, which meant it used the same
7
migration compatibility for the following machines:
14
ARMMMUIdx_EL10_0 that NonSecure PL0 does. This resulted in a bug
8
* smdkc210
15
where arm_sctlr() incorrectly picked the NonSecure SCTLR as the
9
* realview-*
16
controlling register when in Secure PL0, which meant we were
10
* vexpress-*
17
spuriously generating alignment faults because we were looking at the
11
* kzm
18
wrong SCTLR control bits.
12
* mps2-*
19
13
20
The use of ARMMMUIdx_EL3 for Secure PL1 also resulted in the bug that
14
While breaking migration ABI, fix the size of the MII registers to be 16 bit,
21
we wouldn't honour the PAN bit for Secure PL1, because there's no
15
as defined by IEEE 802.3u.
22
equivalent _PAN mmu index for it.
23
16
24
Fix this by adding two new MMU indexes:
17
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
25
* ARMMMUIdx_E30_0 is for Secure PL0
18
Tested-by: Guenter Roeck <linux@roeck-us.net>
26
* ARMMMUIdx_E30_3_PAN is for Secure PL1 when PAN is enabled
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
27
The existing ARMMMUIdx_E3 is used to mean "Secure PL1 without PAN"
20
Message-id: 20241102125724.532843-2-shentey@gmail.com
28
(and would be named ARMMMUIdx_E30_3 in an AArch32-centric scheme).
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
include/hw/net/lan9118_phy.h | 37 ++++++++
24
hw/net/lan9118.c | 137 +++++-----------------------
25
hw/net/lan9118_phy.c | 169 +++++++++++++++++++++++++++++++++++
26
hw/net/Kconfig | 4 +
27
hw/net/meson.build | 1 +
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
29
31
30
These extra two indexes bring us up to the maximum of 16 that the
32
diff --git a/include/hw/net/lan9118_phy.h b/include/hw/net/lan9118_phy.h
31
core code can currently support.
33
new file mode 100644
32
34
index XXXXXXX..XXXXXXX
33
This commit:
35
--- /dev/null
34
* adds the new MMU index handling to the various places
36
+++ b/include/hw/net/lan9118_phy.h
35
where we deal in MMU index values
37
@@ -XXX,XX +XXX,XX @@
36
* adds assertions that we aren't AArch32 EL3 in a couple of
38
+/*
37
places that currently use the E10 indexes, to document why
39
+ * SMSC LAN9118 PHY emulation
38
they don't also need to handle the E30 indexes
40
+ *
39
* documents in a comment why regime_has_2_ranges() doesn't need
41
+ * Copyright (c) 2009 CodeSourcery, LLC.
40
updating
42
+ * Written by Paul Brook
41
43
+ *
42
Notes for backporting: this commit depends on the preceding revert of
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
43
4c2c04746932; that revert and this commit should probably be
45
+ * See the COPYING file in the top-level directory.
44
backported to everywhere that we originally backported 4c2c04746932.
46
+ */
45
47
+
46
Cc: qemu-stable@nongnu.org
48
+#ifndef HW_NET_LAN9118_PHY_H
47
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2326
49
+#define HW_NET_LAN9118_PHY_H
48
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2588
50
+
49
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
51
+#include "qom/object.h"
50
Tested-by: Thomas Huth <thuth@redhat.com>
52
+#include "hw/sysbus.h"
51
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
53
+
52
Message-id: 20241101142845.1712482-3-peter.maydell@linaro.org
54
+#define TYPE_LAN9118_PHY "lan9118-phy"
53
---
55
+OBJECT_DECLARE_SIMPLE_TYPE(Lan9118PhyState, LAN9118_PHY)
54
target/arm/cpu.h | 31 ++++++++++++++++++-------------
56
+
55
target/arm/internals.h | 16 ++++++++++++++--
57
+typedef struct Lan9118PhyState {
56
target/arm/helper.c | 38 ++++++++++++++++++++++++++++++++++----
58
+ SysBusDevice parent_obj;
57
target/arm/ptw.c | 4 ++++
59
+
58
target/arm/tcg/op_helper.c | 14 +++++++++++++-
60
+ uint16_t status;
59
target/arm/tcg/translate.c | 3 +++
61
+ uint16_t control;
60
6 files changed, 86 insertions(+), 20 deletions(-)
62
+ uint16_t advertise;
61
63
+ uint16_t ints;
62
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
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
63
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
64
--- a/target/arm/cpu.h
77
--- a/hw/net/lan9118.c
65
+++ b/target/arm/cpu.h
78
+++ b/hw/net/lan9118.c
66
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
79
@@ -XXX,XX +XXX,XX @@
67
* + NonSecure PL1 & 0 stage 1
80
#include "net/net.h"
68
* + NonSecure PL1 & 0 stage 2
81
#include "net/eth.h"
69
* + NonSecure PL2
82
#include "hw/irq.h"
70
- * + Secure PL0
83
+#include "hw/net/lan9118_phy.h"
71
- * + Secure PL1
84
#include "hw/net/lan9118.h"
72
+ * + Secure PL1 & 0
85
#include "hw/ptimer.h"
73
* (reminder: for 32 bit EL3, Secure PL1 is *EL3*, not EL1.)
86
#include "hw/qdev-properties.h"
74
*
87
@@ -XXX,XX +XXX,XX @@ do { printf("lan9118: " fmt , ## __VA_ARGS__); } while (0)
75
* For QEMU, an mmu_idx is not quite the same as a translation regime because:
88
#define MAC_CR_RXEN 0x00000004
76
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
89
#define MAC_CR_RESERVED 0x7f404213
77
*
90
78
* This gives us the following list of cases:
91
-#define PHY_INT_ENERGYON 0x80
79
*
92
-#define PHY_INT_AUTONEG_COMPLETE 0x40
80
- * EL0 EL1&0 stage 1+2 (aka NS PL0)
93
-#define PHY_INT_FAULT 0x20
81
- * EL1 EL1&0 stage 1+2 (aka NS PL1)
94
-#define PHY_INT_DOWN 0x10
82
- * EL1 EL1&0 stage 1+2 +PAN
95
-#define PHY_INT_AUTONEG_LP 0x08
83
+ * EL0 EL1&0 stage 1+2 (aka NS PL0 PL1&0 stage 1+2)
96
-#define PHY_INT_PARFAULT 0x04
84
+ * EL1 EL1&0 stage 1+2 (aka NS PL1 PL1&0 stage 1+2)
97
-#define PHY_INT_AUTONEG_PAGE 0x02
85
+ * EL1 EL1&0 stage 1+2 +PAN (aka NS PL1 P1&0 stage 1+2 +PAN)
98
-
86
* EL0 EL2&0
99
#define GPT_TIMER_EN 0x20000000
87
* EL2 EL2&0
100
88
* EL2 EL2&0 +PAN
101
/*
89
* EL2 (aka NS PL2)
102
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
90
- * EL3 (aka S PL1)
103
uint32_t mac_mii_data;
91
+ * EL3 (aka AArch32 S PL1 PL1&0)
104
uint32_t mac_flow;
92
+ * AArch32 S PL0 PL1&0 (we call this EL30_0)
105
93
+ * AArch32 S PL1 PL1&0 +PAN (we call this EL30_3_PAN)
106
- uint32_t phy_status;
94
* Stage2 Secure
107
- uint32_t phy_control;
95
* Stage2 NonSecure
108
- uint32_t phy_advertise;
96
* plus one TLB per Physical address space: S, NS, Realm, Root
109
- uint32_t phy_int;
97
*
110
- uint32_t phy_int_mask;
98
- * for a total of 14 different mmu_idx.
111
+ Lan9118PhyState mii;
99
+ * for a total of 16 different mmu_idx.
112
+ IRQState mii_irq;
100
*
113
101
* R profile CPUs have an MPU, but can use the same set of MMU indexes
114
int32_t eeprom_writable;
102
* as A profile. They only need to distinguish EL0 and EL1 (and
115
uint8_t eeprom[128];
103
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
116
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
104
ARMMMUIdx_E20_2_PAN = 5 | ARM_MMU_IDX_A,
117
105
ARMMMUIdx_E2 = 6 | ARM_MMU_IDX_A,
118
static const VMStateDescription vmstate_lan9118 = {
106
ARMMMUIdx_E3 = 7 | ARM_MMU_IDX_A,
119
.name = "lan9118",
107
+ ARMMMUIdx_E30_0 = 8 | ARM_MMU_IDX_A,
120
- .version_id = 2,
108
+ ARMMMUIdx_E30_3_PAN = 9 | ARM_MMU_IDX_A,
121
- .minimum_version_id = 1,
109
122
+ .version_id = 3,
110
/*
123
+ .minimum_version_id = 3,
111
* Used for second stage of an S12 page table walk, or for descriptor
124
.fields = (const VMStateField[]) {
112
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdx {
125
VMSTATE_PTIMER(timer, lan9118_state),
113
* are in use simultaneously for SecureEL2: the security state for
126
VMSTATE_UINT32(irq_cfg, lan9118_state),
114
* the S2 ptw is selected by the NS bit from the S1 ptw.
127
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118 = {
115
*/
128
VMSTATE_UINT32(mac_mii_acc, lan9118_state),
116
- ARMMMUIdx_Stage2_S = 8 | ARM_MMU_IDX_A,
129
VMSTATE_UINT32(mac_mii_data, lan9118_state),
117
- ARMMMUIdx_Stage2 = 9 | ARM_MMU_IDX_A,
130
VMSTATE_UINT32(mac_flow, lan9118_state),
118
+ ARMMMUIdx_Stage2_S = 10 | ARM_MMU_IDX_A,
131
- VMSTATE_UINT32(phy_status, lan9118_state),
119
+ ARMMMUIdx_Stage2 = 11 | ARM_MMU_IDX_A,
132
- VMSTATE_UINT32(phy_control, lan9118_state),
120
133
- VMSTATE_UINT32(phy_advertise, lan9118_state),
121
/* TLBs with 1-1 mapping to the physical address spaces. */
134
- VMSTATE_UINT32(phy_int, lan9118_state),
122
- ARMMMUIdx_Phys_S = 10 | ARM_MMU_IDX_A,
135
- VMSTATE_UINT32(phy_int_mask, lan9118_state),
123
- ARMMMUIdx_Phys_NS = 11 | ARM_MMU_IDX_A,
136
VMSTATE_INT32(eeprom_writable, lan9118_state),
124
- ARMMMUIdx_Phys_Root = 12 | ARM_MMU_IDX_A,
137
VMSTATE_UINT8_ARRAY(eeprom, lan9118_state, 128),
125
- ARMMMUIdx_Phys_Realm = 13 | ARM_MMU_IDX_A,
138
VMSTATE_INT32(tx_fifo_size, lan9118_state),
126
+ ARMMMUIdx_Phys_S = 12 | ARM_MMU_IDX_A,
139
@@ -XXX,XX +XXX,XX @@ static void lan9118_reload_eeprom(lan9118_state *s)
127
+ ARMMMUIdx_Phys_NS = 13 | ARM_MMU_IDX_A,
140
lan9118_mac_changed(s);
128
+ ARMMMUIdx_Phys_Root = 14 | ARM_MMU_IDX_A,
141
}
129
+ ARMMMUIdx_Phys_Realm = 15 | ARM_MMU_IDX_A,
142
130
143
-static void phy_update_irq(lan9118_state *s)
131
/*
144
+static void lan9118_update_irq(void *opaque, int n, int level)
132
* These are not allocated TLBs and are used only for AT system
145
{
133
@@ -XXX,XX +XXX,XX @@ typedef enum ARMMMUIdxBit {
146
- if (s->phy_int & s->phy_int_mask) {
134
TO_CORE_BIT(E20_2),
147
+ lan9118_state *s = opaque;
135
TO_CORE_BIT(E20_2_PAN),
148
+
136
TO_CORE_BIT(E3),
149
+ if (level) {
137
+ TO_CORE_BIT(E30_0),
150
s->int_sts |= PHY_INT;
138
+ TO_CORE_BIT(E30_3_PAN),
151
} else {
139
TO_CORE_BIT(Stage2),
152
s->int_sts &= ~PHY_INT;
140
TO_CORE_BIT(Stage2_S),
153
@@ -XXX,XX +XXX,XX @@ static void phy_update_irq(lan9118_state *s)
141
154
lan9118_update(s);
142
diff --git a/target/arm/internals.h b/target/arm/internals.h
155
}
143
index XXXXXXX..XXXXXXX 100644
156
144
--- a/target/arm/internals.h
157
-static void phy_update_link(lan9118_state *s)
145
+++ b/target/arm/internals.h
158
-{
146
@@ -XXX,XX +XXX,XX @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
159
- /* Autonegotiation status mirrors link status. */
160
- if (qemu_get_queue(s->nic)->link_down) {
161
- s->phy_status &= ~0x0024;
162
- s->phy_int |= PHY_INT_DOWN;
163
- } else {
164
- s->phy_status |= 0x0024;
165
- s->phy_int |= PHY_INT_ENERGYON;
166
- s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
167
- }
168
- phy_update_irq(s);
169
-}
170
-
171
static void lan9118_set_link(NetClientState *nc)
172
{
173
- phy_update_link(qemu_get_nic_opaque(nc));
174
-}
175
-
176
-static void phy_reset(lan9118_state *s)
177
-{
178
- s->phy_status = 0x7809;
179
- s->phy_control = 0x3000;
180
- s->phy_advertise = 0x01e1;
181
- s->phy_int_mask = 0;
182
- s->phy_int = 0;
183
- phy_update_link(s);
184
+ lan9118_phy_update_link(&LAN9118(qemu_get_nic_opaque(nc))->mii,
185
+ nc->link_down);
186
}
187
188
static void lan9118_reset(DeviceState *d)
189
@@ -XXX,XX +XXX,XX @@ static void lan9118_reset(DeviceState *d)
190
s->read_word_n = 0;
191
s->write_word_n = 0;
192
193
- phy_reset(s);
194
-
195
s->eeprom_writable = 0;
196
lan9118_reload_eeprom(s);
197
}
198
@@ -XXX,XX +XXX,XX @@ static void do_tx_packet(lan9118_state *s)
199
uint32_t status;
200
201
/* FIXME: Honor TX disable, and allow queueing of packets. */
202
- if (s->phy_control & 0x4000) {
203
+ if (s->mii.control & 0x4000) {
204
/* This assumes the receive routine doesn't touch the VLANClient. */
205
qemu_receive_packet(qemu_get_queue(s->nic), s->txp->data, s->txp->len);
206
} else {
207
@@ -XXX,XX +XXX,XX @@ static void tx_fifo_push(lan9118_state *s, uint32_t val)
147
}
208
}
148
}
209
}
149
210
150
-/* Return true if this address translation regime has two ranges. */
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)
274
{
275
switch (reg) {
276
@@ -XXX,XX +XXX,XX @@ static void do_mac_write(lan9118_state *s, int reg, uint32_t val)
277
if (val & 2) {
278
DPRINTF("PHY write %d = 0x%04x\n",
279
(val >> 6) & 0x1f, s->mac_mii_data);
280
- do_phy_write(s, (val >> 6) & 0x1f, s->mac_mii_data);
281
+ lan9118_phy_write(&s->mii, (val >> 6) & 0x1f, s->mac_mii_data);
282
} else {
283
- s->mac_mii_data = do_phy_read(s, (val >> 6) & 0x1f);
284
+ s->mac_mii_data = lan9118_phy_read(&s->mii, (val >> 6) & 0x1f);
285
DPRINTF("PHY read %d = 0x%04x\n",
286
(val >> 6) & 0x1f, s->mac_mii_data);
287
}
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;
305
+ }
306
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
307
+
308
memory_region_init_io(&s->mmio, OBJECT(dev), mem_ops, s,
309
"lan9118-mmio", 0x100);
310
sysbus_init_mmio(sbd, &s->mmio);
311
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
312
new file mode 100644
313
index XXXXXXX..XXXXXXX
314
--- /dev/null
315
+++ b/hw/net/lan9118_phy.c
316
@@ -XXX,XX +XXX,XX @@
151
+/*
317
+/*
152
+ * Return true if this address translation regime has two ranges.
318
+ * SMSC LAN9118 PHY emulation
153
+ * Note that this will not return the correct answer for AArch32
319
+ *
154
+ * Secure PL1&0 (i.e. mmu indexes E3, E30_0, E30_3_PAN), but it is
320
+ * Copyright (c) 2009 CodeSourcery, LLC.
155
+ * never called from a context where EL3 can be AArch32. (The
321
+ * Written by Paul Brook
156
+ * correct return value for ARMMMUIdx_E3 would be different for
322
+ *
157
+ * that case, so we can't just make the function return the
323
+ * This code is licensed under the GNU GPL v2
158
+ * correct value anyway; we would need an extra "bool e3_is_aarch32"
324
+ *
159
+ * argument which all the current callsites would pass as 'false'.)
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.
160
+ */
327
+ */
161
static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
328
+
162
{
329
+#include "qemu/osdep.h"
163
switch (mmu_idx) {
330
+#include "hw/net/lan9118_phy.h"
164
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
331
+#include "hw/irq.h"
165
case ARMMMUIdx_Stage1_E1_PAN:
332
+#include "hw/resettable.h"
166
case ARMMMUIdx_E10_1_PAN:
333
+#include "migration/vmstate.h"
167
case ARMMMUIdx_E20_2_PAN:
334
+#include "qemu/log.h"
168
+ case ARMMMUIdx_E30_3_PAN:
335
+
169
return true;
336
+#define PHY_INT_ENERGYON (1 << 7)
170
default:
337
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
171
return false;
338
+#define PHY_INT_FAULT (1 << 5)
172
@@ -XXX,XX +XXX,XX @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
339
+#define PHY_INT_DOWN (1 << 4)
173
case ARMMMUIdx_E2:
340
+#define PHY_INT_AUTONEG_LP (1 << 3)
174
return 2;
341
+#define PHY_INT_PARFAULT (1 << 2)
175
case ARMMMUIdx_E3:
342
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
176
+ case ARMMMUIdx_E30_0:
343
+
177
+ case ARMMMUIdx_E30_3_PAN:
344
+static void lan9118_phy_update_irq(Lan9118PhyState *s)
178
return 3;
345
+{
179
case ARMMMUIdx_E10_0:
346
+ qemu_set_irq(s->irq, !!(s->ints & s->int_mask));
180
case ARMMMUIdx_Stage1_E0:
347
+}
181
- return arm_el_is_aa64(env, 3) || !arm_is_secure_below_el3(env) ? 1 : 3;
348
+
182
case ARMMMUIdx_Stage1_E1:
349
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
183
case ARMMMUIdx_Stage1_E1_PAN:
350
+{
184
case ARMMMUIdx_E10_1:
351
+ uint16_t val;
185
@@ -XXX,XX +XXX,XX @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
352
+
186
switch (mmu_idx) {
353
+ switch (reg) {
187
case ARMMMUIdx_E10_0:
354
+ case 0: /* Basic Control */
188
case ARMMMUIdx_E20_0:
355
+ return s->control;
189
+ case ARMMMUIdx_E30_0:
356
+ case 1: /* Basic Status */
190
case ARMMMUIdx_Stage1_E0:
357
+ return s->status;
191
case ARMMMUIdx_MUser:
358
+ case 2: /* ID1 */
192
case ARMMMUIdx_MSUser:
359
+ return 0x0007;
193
diff --git a/target/arm/helper.c b/target/arm/helper.c
360
+ case 3: /* ID2 */
194
index XXXXXXX..XXXXXXX 100644
361
+ return 0xc0d1;
195
--- a/target/arm/helper.c
362
+ case 4: /* Auto-neg advertisement */
196
+++ b/target/arm/helper.c
363
+ return s->advertise;
197
@@ -XXX,XX +XXX,XX @@ static int alle1_tlbmask(CPUARMState *env)
364
+ case 5: /* Auto-neg Link Partner Ability */
198
* Note that the 'ALL' scope must invalidate both stage 1 and
365
+ return 0x0f71;
199
* stage 2 translations, whereas most other scopes only invalidate
366
+ case 6: /* Auto-neg Expansion */
200
* stage 1 translations.
367
+ return 1;
201
+ *
368
+ /* TODO 17, 18, 27, 29, 30, 31 */
202
+ * For AArch32 this is only used for TLBIALLNSNH and VTTBR
369
+ case 29: /* Interrupt source. */
203
+ * writes, so only needs to apply to NS PL1&0, not S PL1&0.
370
+ val = s->ints;
204
*/
371
+ s->ints = 0;
205
return (ARMMMUIdxBit_E10_1 |
372
+ lan9118_phy_update_irq(s);
206
ARMMMUIdxBit_E10_1_PAN |
373
+ return val;
207
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
374
+ case 30: /* Interrupt mask */
208
/* stage 1 current state PL1: ATS1CPR, ATS1CPW, ATS1CPRP, ATS1CPWP */
375
+ return s->int_mask;
209
switch (el) {
376
+ default:
210
case 3:
377
+ qemu_log_mask(LOG_GUEST_ERROR,
211
- mmu_idx = ARMMMUIdx_E3;
378
+ "lan9118_phy_read: PHY read reg %d\n", reg);
212
+ if (ri->crm == 9 && arm_pan_enabled(env)) {
379
+ return 0;
213
+ mmu_idx = ARMMMUIdx_E30_3_PAN;
380
+ }
214
+ } else {
381
+}
215
+ mmu_idx = ARMMMUIdx_E3;
382
+
216
+ }
383
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
217
break;
384
+{
218
case 2:
385
+ switch (reg) {
219
g_assert(ss != ARMSS_Secure); /* ARMv8.4-SecEL2 is 64-bit only */
386
+ case 0: /* Basic Control */
220
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
387
+ if (val & 0x8000) {
221
/* stage 1 current state PL0: ATS1CUR, ATS1CUW */
388
+ lan9118_phy_reset(s);
222
switch (el) {
223
case 3:
224
- mmu_idx = ARMMMUIdx_E10_0;
225
+ mmu_idx = ARMMMUIdx_E30_0;
226
break;
227
case 2:
228
g_assert(ss != ARMSS_Secure); /* ARMv8.4-SecEL2 is 64-bit only */
229
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
230
uint64_t hcr = arm_hcr_el2_eff(env);
231
uint16_t mask;
232
233
+ assert(arm_feature(env, ARM_FEATURE_AARCH64));
234
+
235
if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
236
mask = ARMMMUIdxBit_E20_2 |
237
ARMMMUIdxBit_E20_2_PAN |
238
ARMMMUIdxBit_E20_0;
239
} else {
240
+ /* This is AArch64 only, so we don't need to touch the EL30_x TLBs */
241
mask = ARMMMUIdxBit_E10_1 |
242
ARMMMUIdxBit_E10_1_PAN |
243
ARMMMUIdxBit_E10_0;
244
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
245
uint64_t hcr = arm_hcr_el2_eff(env);
246
ARMMMUIdx mmu_idx;
247
248
+ assert(arm_feature(env, ARM_FEATURE_AARCH64));
249
+
250
/* Only the regime of the mmu_idx below is significant. */
251
if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
252
mmu_idx = ARMMMUIdx_E20_0;
253
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_interrupt(CPUState *cs)
254
255
uint64_t arm_sctlr(CPUARMState *env, int el)
256
{
257
- /* Only EL0 needs to be adjusted for EL1&0 or EL2&0. */
258
+ /* Only EL0 needs to be adjusted for EL1&0 or EL2&0 or EL3&0 */
259
if (el == 0) {
260
ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, 0);
261
- el = mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1;
262
+ switch (mmu_idx) {
263
+ case ARMMMUIdx_E20_0:
264
+ el = 2;
265
+ break;
266
+ case ARMMMUIdx_E30_0:
267
+ el = 3;
268
+ break;
269
+ default:
270
+ el = 1;
271
+ break;
389
+ break;
272
+ }
390
+ }
273
}
391
+ s->control = val & 0x7980;
274
return env->cp15.sctlr_el[el];
392
+ /* Complete autonegotiation immediately. */
275
}
393
+ if (val & 0x1000) {
276
@@ -XXX,XX +XXX,XX @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
394
+ s->status |= 0x0020;
277
switch (mmu_idx) {
278
case ARMMMUIdx_E10_0:
279
case ARMMMUIdx_E20_0:
280
+ case ARMMMUIdx_E30_0:
281
return 0;
282
case ARMMMUIdx_E10_1:
283
case ARMMMUIdx_E10_1_PAN:
284
@@ -XXX,XX +XXX,XX @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
285
case ARMMMUIdx_E20_2_PAN:
286
return 2;
287
case ARMMMUIdx_E3:
288
+ case ARMMMUIdx_E30_3_PAN:
289
return 3;
290
default:
291
g_assert_not_reached();
292
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
293
hcr = arm_hcr_el2_eff(env);
294
if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
295
idx = ARMMMUIdx_E20_0;
296
+ } else if (arm_is_secure_below_el3(env) &&
297
+ !arm_el_is_aa64(env, 3)) {
298
+ idx = ARMMMUIdx_E30_0;
299
} else {
300
idx = ARMMMUIdx_E10_0;
301
}
302
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
303
}
304
break;
305
case 3:
306
+ if (!arm_el_is_aa64(env, 3) && arm_pan_enabled(env)) {
307
+ return ARMMMUIdx_E30_3_PAN;
308
+ }
395
+ }
309
return ARMMMUIdx_E3;
310
default:
311
g_assert_not_reached();
312
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
313
index XXXXXXX..XXXXXXX 100644
314
--- a/target/arm/ptw.c
315
+++ b/target/arm/ptw.c
316
@@ -XXX,XX +XXX,XX @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
317
case ARMMMUIdx_E20_2_PAN:
318
case ARMMMUIdx_E2:
319
case ARMMMUIdx_E3:
320
+ case ARMMMUIdx_E30_0:
321
+ case ARMMMUIdx_E30_3_PAN:
322
break;
323
324
case ARMMMUIdx_Phys_S:
325
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, vaddr address,
326
ss = ARMSS_Secure;
327
break;
328
case ARMMMUIdx_E3:
329
+ case ARMMMUIdx_E30_0:
330
+ case ARMMMUIdx_E30_3_PAN:
331
if (arm_feature(env, ARM_FEATURE_AARCH64) &&
332
cpu_isar_feature(aa64_rme, env_archcpu(env))) {
333
ss = ARMSS_Root;
334
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
335
index XXXXXXX..XXXXXXX 100644
336
--- a/target/arm/tcg/op_helper.c
337
+++ b/target/arm/tcg/op_helper.c
338
@@ -XXX,XX +XXX,XX @@ void HELPER(tidcp_el0)(CPUARMState *env, uint32_t syndrome)
339
{
340
/* See arm_sctlr(), but we also need the sctlr el. */
341
ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, 0);
342
- int target_el = mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1;
343
+ int target_el;
344
+
345
+ switch (mmu_idx) {
346
+ case ARMMMUIdx_E20_0:
347
+ target_el = 2;
348
+ break;
396
+ break;
349
+ case ARMMMUIdx_E30_0:
397
+ case 4: /* Auto-neg advertisement */
350
+ target_el = 3;
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);
351
+ break;
404
+ break;
352
+ default:
405
+ default:
353
+ target_el = 1;
406
+ qemu_log_mask(LOG_GUEST_ERROR,
354
+ break;
407
+ "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
355
+ }
408
+ }
356
409
+}
357
/*
410
+
358
* The bit is not valid unless the target el is aa64, but since the
411
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
359
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
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
360
index XXXXXXX..XXXXXXX 100644
487
index XXXXXXX..XXXXXXX 100644
361
--- a/target/arm/tcg/translate.c
488
--- a/hw/net/Kconfig
362
+++ b/target/arm/tcg/translate.c
489
+++ b/hw/net/Kconfig
363
@@ -XXX,XX +XXX,XX @@ static inline int get_a32_user_mem_index(DisasContext *s)
490
@@ -XXX,XX +XXX,XX @@ config VMXNET3_PCI
364
*/
491
config SMC91C111
365
switch (s->mmu_idx) {
492
bool
366
case ARMMMUIdx_E3:
493
367
+ case ARMMMUIdx_E30_0:
494
+config LAN9118_PHY
368
+ case ARMMMUIdx_E30_3_PAN:
495
+ bool
369
+ return arm_to_core_mmu_idx(ARMMMUIdx_E30_0);
496
+
370
case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
497
config LAN9118
371
case ARMMMUIdx_E10_0:
498
bool
372
case ARMMMUIdx_E10_1:
499
+ select LAN9118_PHY
500
select PTIMER
501
502
config NE2000_ISA
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'))
373
--
515
--
374
2.34.1
516
2.34.1
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
imx_fec models the same PHY as lan9118_phy. The code is almost the same with
4
imx_fec having more logging and tracing. Merge these improvements into
5
lan9118_phy and reuse in imx_fec to fix the code duplication.
6
7
Some migration state how resides in the new device model which breaks migration
8
compatibility for the following machines:
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
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
include/hw/net/imx_fec.h | 9 ++-
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(-)
26
27
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/net/imx_fec.h
30
+++ b/include/hw/net/imx_fec.h
31
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC)
32
#define TYPE_IMX_ENET "imx.enet"
33
34
#include "hw/sysbus.h"
35
+#include "hw/net/lan9118_phy.h"
36
+#include "hw/irq.h"
37
#include "net/net.h"
38
39
#define ENET_EIR 1
40
@@ -XXX,XX +XXX,XX @@ struct IMXFECState {
41
uint32_t tx_descriptor[ENET_TX_RING_NUM];
42
uint32_t tx_ring_num;
43
44
- uint32_t phy_status;
45
- uint32_t phy_control;
46
- uint32_t phy_advertise;
47
- uint32_t phy_int;
48
- uint32_t phy_int_mask;
49
+ Lan9118PhyState mii;
50
+ IRQState mii_irq;
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)) {
259
+ return;
260
+ }
261
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
262
+
263
qemu_macaddr_default_if_unset(&s->conf.macaddr);
264
265
s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
266
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
267
index XXXXXXX..XXXXXXX 100644
268
--- a/hw/net/lan9118_phy.c
269
+++ b/hw/net/lan9118_phy.c
270
@@ -XXX,XX +XXX,XX @@
271
* Copyright (c) 2009 CodeSourcery, LLC.
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"
471
--
472
2.34.1
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
1
From: Bernhard Beschow <shentey@gmail.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
The same statement is executed unconditionally right before the if statement.
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.
4
6
5
Cc: Guenter Roeck <linux@roeck-us.net>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Tested-by: Guenter Roeck <linux@roeck-us.net>
9
Message-id: 20241103143330.123596-4-shentey@gmail.com
10
Message-id: 20241102125724.532843-6-shentey@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
hw/watchdog/wdt_imx2.c | 1 -
13
hw/net/lan9118_phy.c | 4 ++--
13
1 file changed, 1 deletion(-)
14
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
15
diff --git a/hw/watchdog/wdt_imx2.c b/hw/watchdog/wdt_imx2.c
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/watchdog/wdt_imx2.c
18
--- a/hw/net/lan9118_phy.c
18
+++ b/hw/watchdog/wdt_imx2.c
19
+++ b/hw/net/lan9118_phy.c
19
@@ -XXX,XX +XXX,XX @@ static void imx2_wdt_expired(void *opaque)
20
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
20
21
break;
21
/* Perform watchdog action if watchdog is enabled */
22
case MII_ANAR:
22
if (s->wcr & IMX2_WDT_WCR_WDE) {
23
s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
23
- s->wrsr = IMX2_WDT_WRSR_TOUT;
24
- MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
24
watchdog_perform_action();
25
- MII_ANAR_SELECT))
25
}
26
+ MII_ANAR_PAUSE | MII_ANAR_TXFD | MII_ANAR_10FD |
26
}
27
+ MII_ANAR_10 | MII_ANAR_SELECT))
28
| MII_ANAR_TX;
29
break;
30
case 30: /* Interrupt mask */
27
--
31
--
28
2.34.1
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
Now that all targets have been converted to explicitly set a NaN
1
IEEE 758 does not define a fixed rule for what NaN to return in
2
propagation rule, we can remove the set of target ifdefs (which now
2
the case of a fused multiply-add of inf * 0 + NaN. Different
3
list every target) and clean up the references to fallback behaviour
3
architectures thus do different things:
4
for float_2nan_prop_none.
4
* some return the default NaN
5
5
* some return the input NaN
6
The "default" case in the switch will catch any remaining places
6
* Arm returns the default NaN if the input NaN is quiet,
7
where status->float_2nan_prop_rule was not set by the target.
7
and the input NaN if it is signalling
8
9
We want to make this logic be runtime selected rather than
10
hardcoded into the binary, because:
11
* this will let us have multiple targets in one QEMU binary
12
* the Arm FEAT_AFP architectural feature includes letting
13
the guest select a NaN propagation rule at runtime
14
15
In this commit we add an enum for the propagation rule, the field in
16
float_status, and the corresponding getters and setters. We change
17
pickNaNMulAdd to honour this, but because all targets still leave
18
this field at its default 0 value, the fallback logic will pick the
19
rule type with the old ifdef ladder.
20
21
Note that four architectures both use the muladd softfloat functions
22
and did not have a branch of the ifdef ladder to specify their
23
behaviour (and so were ending up with the "default" case, probably
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.
8
29
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241025141254.2141506-22-peter.maydell@linaro.org
32
Message-id: 20241202131347.498124-4-peter.maydell@linaro.org
13
---
33
---
14
include/fpu/softfloat-types.h | 10 +++-------
34
include/fpu/softfloat-helpers.h | 11 ++++
15
fpu/softfloat-specialize.c.inc | 23 +++--------------------
35
include/fpu/softfloat-types.h | 23 +++++++++
16
2 files changed, 6 insertions(+), 27 deletions(-)
36
fpu/softfloat-specialize.c.inc | 91 ++++++++++++++++++++++-----------
17
37
3 files changed, 95 insertions(+), 30 deletions(-)
38
39
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/include/fpu/softfloat-helpers.h
42
+++ b/include/fpu/softfloat-helpers.h
43
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
44
status->float_2nan_prop_rule = rule;
45
}
46
47
+static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
+ float_status *status)
49
+{
50
+ status->float_infzeronan_rule = rule;
51
+}
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;
18
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
68
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
19
index XXXXXXX..XXXXXXX 100644
69
index XXXXXXX..XXXXXXX 100644
20
--- a/include/fpu/softfloat-types.h
70
--- a/include/fpu/softfloat-types.h
21
+++ b/include/fpu/softfloat-types.h
71
+++ b/include/fpu/softfloat-types.h
22
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
72
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
23
* If default_nan_mode is enabled then it is valid not to set a
73
float_2nan_prop_x87,
24
* NaN propagation rule, because the softfloat code guarantees
74
} Float2NaNPropRule;
25
* not to try to pick a NaN to propagate in default NaN mode.
75
26
- *
76
+/*
27
- * For transition, currently the 'none' rule will cause us to
77
+ * Rule for result of fused multiply-add 0 * Inf + NaN.
28
- * fall back to picking the propagation rule based on the existing
78
+ * This must be a NaN, but implementations differ on whether this
29
- * ifdef ladder. When all targets are converted it will be an error
79
+ * is the input NaN or the default NaN.
30
- * not to set the rule in float_status unless in default_nan_mode,
80
+ *
31
- * and we will assert if we need to handle an input NaN and no
81
+ * You don't need to set this if default_nan_mode is enabled.
32
- * rule was selected.
33
+ * When not in default-NaN mode, it is an error for the target
82
+ * When not in default-NaN mode, it is an error for the target
34
+ * not to set the rule in float_status, and we will assert if
83
+ * not to set the rule in float_status if it uses muladd, and we
35
+ * we need to handle an input NaN and no rule was selected.
84
+ * will assert if we need to handle an input NaN and no rule was
36
*/
85
+ * selected.
37
typedef enum __attribute__((__packed__)) {
86
+ */
38
/* No propagation rule specified */
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;
39
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
109
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
40
index XXXXXXX..XXXXXXX 100644
110
index XXXXXXX..XXXXXXX 100644
41
--- a/fpu/softfloat-specialize.c.inc
111
--- a/fpu/softfloat-specialize.c.inc
42
+++ b/fpu/softfloat-specialize.c.inc
112
+++ b/fpu/softfloat-specialize.c.inc
43
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
113
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
44
static int pickNaN(FloatClass a_cls, FloatClass b_cls,
114
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
45
bool aIsLargerSignificand, float_status *status)
115
bool infzero, float_status *status)
46
{
116
{
47
- Float2NaNPropRule rule = status->float_2nan_prop_rule;
117
+ FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
48
-
118
+
49
/*
119
/*
50
* We guarantee not to require the target to tell us how to
120
* We guarantee not to require the target to tell us how to
51
* pick a NaN if we're always returning the default NaN.
121
* 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
122
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
53
+ * specify via set_float_2nan_prop_rule().
123
* specify.
54
*/
124
*/
55
assert(!status->default_nan_mode);
125
assert(!status->default_nan_mode);
56
126
+
57
- if (rule == float_2nan_prop_none) {
127
+ if (rule == float_infzeronan_none) {
58
- /* target didn't set the rule: fall back to old ifdef choices */
128
+ /*
59
-#if defined(TARGET_AVR) || defined(TARGET_HEXAGON) \
129
+ * Temporarily fall back to ifdef ladder
60
- || defined(TARGET_RISCV) || defined(TARGET_SH4) \
130
+ */
61
- || defined(TARGET_TRICORE) || defined(TARGET_ARM) || defined(TARGET_MIPS) \
131
#if defined(TARGET_ARM)
62
- || defined(TARGET_LOONGARCH64) || defined(TARGET_HPPA) \
132
- /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
63
- || defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_M68K) \
133
- * the default NaN
64
- || defined(TARGET_SPARC) || defined(TARGET_XTENSA) \
134
- */
65
- || defined(TARGET_I386) || defined(TARGET_ALPHA) \
135
- if (infzero && is_qnan(c_cls)) {
66
- || defined(TARGET_MICROBLAZE) || defined(TARGET_OPENRISC) \
136
- return 3;
67
- || defined(TARGET_RX)
137
+ /*
68
- g_assert_not_reached();
138
+ * For ARM, the (inf,zero,qnan) case returns the default NaN,
69
-#else
139
+ * but (inf,zero,snan) returns the input NaN.
70
- rule = float_2nan_prop_x87;
140
+ */
71
-#endif
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();
188
+ }
189
+ }
190
+
191
+#if defined(TARGET_ARM)
192
+
193
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
194
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
195
*/
196
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
197
}
198
#elif defined(TARGET_MIPS)
199
if (snan_bit_is_one(status)) {
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
- */
229
-
230
/* Prefer sNaN over qNaN, in the c, a, b order. */
231
if (is_snan(c_cls)) {
232
return 2;
233
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
234
return 1;
235
}
236
#elif defined(TARGET_PPC)
237
- /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
238
- * to return an input NaN if we have one (ie c) rather than generating
239
- * a default NaN
240
- */
241
-
242
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
243
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
244
*/
245
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
246
return 1;
247
}
248
#elif defined(TARGET_S390X)
249
- if (infzero) {
250
- return 3;
72
- }
251
- }
73
-
252
-
74
- switch (rule) {
253
if (is_snan(a_cls)) {
75
+ switch (status->float_2nan_prop_rule) {
254
return 0;
76
case float_2nan_prop_s_ab:
255
} else if (is_snan(b_cls)) {
77
if (is_snan(a_cls)) {
78
return 0;
79
--
256
--
80
2.34.1
257
2.34.1
81
82
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
1
Set the 2-NaN propagation rule explicitly in env->fpu_status.
1
Set the FloatInfZeroNaNRule explicitly for s390, so we
2
can remove the ifdef from pickNaNMulAdd().
2
3
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241025141254.2141506-8-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-7-peter.maydell@linaro.org
8
---
7
---
9
target/s390x/cpu.c | 1 +
8
target/s390x/cpu.c | 2 ++
10
fpu/softfloat-specialize.c.inc | 5 ++---
9
fpu/softfloat-specialize.c.inc | 2 --
11
2 files changed, 3 insertions(+), 3 deletions(-)
10
2 files changed, 2 insertions(+), 2 deletions(-)
12
11
13
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/target/s390x/cpu.c
14
--- a/target/s390x/cpu.c
16
+++ b/target/s390x/cpu.c
15
+++ b/target/s390x/cpu.c
17
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
18
/* tininess for underflow is detected before rounding */
19
set_float_detect_tininess(float_tininess_before_rounding,
17
set_float_detect_tininess(float_tininess_before_rounding,
20
&env->fpu_status);
18
&env->fpu_status);
21
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, &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 */
22
/* fall through */
23
case RESET_TYPE_S390_CPU_NORMAL:
23
case RESET_TYPE_S390_CPU_NORMAL:
24
env->psw.mask &= ~PSW_MASK_RI;
24
env->psw.mask &= ~PSW_MASK_RI;
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
#if defined(TARGET_AVR) || defined(TARGET_HEXAGON) \
30
* a default NaN
31
|| defined(TARGET_RISCV) || defined(TARGET_SH4) \
31
*/
32
|| defined(TARGET_TRICORE) || defined(TARGET_ARM) || defined(TARGET_MIPS) \
32
rule = float_infzeronan_dnan_never;
33
- || defined(TARGET_LOONGARCH64) || defined(TARGET_HPPA)
34
+ || defined(TARGET_LOONGARCH64) || defined(TARGET_HPPA) \
35
+ || defined(TARGET_S390X)
36
g_assert_not_reached();
37
-#elif defined(TARGET_S390X)
33
-#elif defined(TARGET_S390X)
38
- rule = float_2nan_prop_s_ab;
34
- rule = float_infzeronan_dnan_always;
39
#elif defined(TARGET_PPC) || defined(TARGET_M68K)
35
#endif
40
/*
36
}
41
* PowerPC propagation rules:
37
42
--
38
--
43
2.34.1
39
2.34.1
44
45
diff view generated by jsdifflib
1
Set the 2-NaN propagation rule explicitly in env->fp_status
1
Set the FloatInfZeroNaNRule explicitly for the PPC target,
2
and env->vec_status.
2
so we can remove the ifdef from pickNaNMulAdd().
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241025141254.2141506-9-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-8-peter.maydell@linaro.org
7
---
7
---
8
target/ppc/cpu_init.c | 8 ++++++++
8
target/ppc/cpu_init.c | 7 +++++++
9
fpu/softfloat-specialize.c.inc | 10 ++--------
9
fpu/softfloat-specialize.c.inc | 7 +------
10
2 files changed, 10 insertions(+), 8 deletions(-)
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
14
--- a/target/ppc/cpu_init.c
15
+++ b/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)
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
/* tininess for underflow is detected before rounding */
17
*/
18
set_float_detect_tininess(float_tininess_before_rounding,
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
&env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
20
+ /*
21
+ * PowerPC propagation rules:
21
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
22
+ * 1. A if it sNaN or qNaN
22
+ * to return an input NaN if we have one (ie c) rather than generating
23
+ * 2. B if it sNaN or qNaN
23
+ * a default NaN
24
+ * A signaling NaN is always silenced before returning it.
25
+ */
24
+ */
26
+ set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
27
+ set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
26
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
28
27
29
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
28
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
30
ppc_spr_t *spr = &env->spr_cb[i];
29
ppc_spr_t *spr = &env->spr_cb[i];
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
32
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
33
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
34
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
|| defined(TARGET_RISCV) || defined(TARGET_SH4) \
35
*/
37
|| defined(TARGET_TRICORE) || defined(TARGET_ARM) || defined(TARGET_MIPS) \
36
rule = float_infzeronan_dnan_never;
38
|| defined(TARGET_LOONGARCH64) || defined(TARGET_HPPA) \
37
}
39
- || defined(TARGET_S390X)
38
-#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
40
+ || defined(TARGET_S390X) || defined(TARGET_PPC)
39
+#elif defined(TARGET_SPARC) || \
41
g_assert_not_reached();
40
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
42
-#elif defined(TARGET_PPC) || defined(TARGET_M68K)
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
*/
43
- /*
46
- /*
44
- * PowerPC propagation rules:
47
- * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
45
- * 1. A if it sNaN or qNaN
48
- * to return an input NaN if we have one (ie c) rather than generating
46
- * 2. B if it sNaN or qNaN
49
- * a default NaN
47
- * A signaling NaN is always silenced before returning it.
48
- */
50
- */
49
+#elif defined(TARGET_M68K)
51
rule = float_infzeronan_dnan_never;
50
/*
52
#endif
51
* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
53
}
52
* 3.4 FLOATING-POINT INSTRUCTION DETAILS
53
--
54
--
54
2.34.1
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
1
Set the NaN propagation rule explicitly in the float_status
1
Set the FloatInfZeroNaNRule explicitly for the SPARC target,
2
words we use.
2
so we can remove the ifdef from pickNaNMulAdd().
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241025141254.2141506-13-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-10-peter.maydell@linaro.org
8
---
7
---
9
target/sparc/cpu.c | 8 ++++++++
8
target/sparc/cpu.c | 2 ++
10
target/sparc/fop_helper.c | 10 ++++++++--
9
fpu/softfloat-specialize.c.inc | 3 +--
11
fpu/softfloat-specialize.c.inc | 6 ++----
10
2 files changed, 3 insertions(+), 2 deletions(-)
12
3 files changed, 18 insertions(+), 6 deletions(-)
13
11
14
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/target/sparc/cpu.c
14
--- a/target/sparc/cpu.c
17
+++ b/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
18
@@ -XXX,XX +XXX,XX @@
19
#include "hw/qdev-properties.h"
20
#include "qapi/visitor.h"
21
#include "tcg/tcg.h"
22
+#include "fpu/softfloat.h"
23
24
//#define DEBUG_FEATURES
25
26
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
27
env->version |= env->def.nwindows - 1;
17
* the CPU state struct so it won't get zeroed on reset.
28
#endif
18
*/
29
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
30
+ /*
20
+ /* For inf * 0 + NaN, return the input NaN */
31
+ * Prefer SNaN over QNaN, order B then A. It's OK to do this in realize
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
32
+ * rather than reset, because fp_status is after 'end_reset_fields' in
22
33
+ * the CPU state struct so it won't get zeroed on reset.
34
+ */
35
+ set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
36
+
37
cpu_exec_realizefn(cs, &local_err);
23
cpu_exec_realizefn(cs, &local_err);
38
if (local_err != NULL) {
24
if (local_err != NULL) {
39
error_propagate(errp, local_err);
40
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/sparc/fop_helper.c
43
+++ b/target/sparc/fop_helper.c
44
@@ -XXX,XX +XXX,XX @@ uint32_t helper_flcmps(float32 src1, float32 src2)
45
* Perform the comparison with a dummy fp environment.
46
*/
47
float_status discard = { };
48
- FloatRelation r = float32_compare_quiet(src1, src2, &discard);
49
+ FloatRelation r;
50
+
51
+ set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
52
+ r = float32_compare_quiet(src1, src2, &discard);
53
54
switch (r) {
55
case float_relation_equal:
56
@@ -XXX,XX +XXX,XX @@ uint32_t helper_flcmps(float32 src1, float32 src2)
57
uint32_t helper_flcmpd(float64 src1, float64 src2)
58
{
59
float_status discard = { };
60
- FloatRelation r = float64_compare_quiet(src1, src2, &discard);
61
+ FloatRelation r;
62
+
63
+ set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
64
+ r = float64_compare_quiet(src1, src2, &discard);
65
66
switch (r) {
67
case float_relation_equal:
68
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
69
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
70
--- a/fpu/softfloat-specialize.c.inc
27
--- a/fpu/softfloat-specialize.c.inc
71
+++ b/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
72
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
73
|| defined(TARGET_RISCV) || defined(TARGET_SH4) \
74
|| defined(TARGET_TRICORE) || defined(TARGET_ARM) || defined(TARGET_MIPS) \
75
|| defined(TARGET_LOONGARCH64) || defined(TARGET_HPPA) \
76
- || defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_M68K)
77
+ || defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_M68K) \
78
+ || defined(TARGET_SPARC)
79
g_assert_not_reached();
80
-#elif defined(TARGET_SPARC)
81
- /* Prefer SNaN over QNaN, order B then A. */
82
- rule = float_2nan_prop_s_ba;
83
#elif defined(TARGET_XTENSA)
84
/*
30
/*
85
* Xtensa has two NaN propagation modes.
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)
86
--
39
--
87
2.34.1
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
1
Set the 2-NaN propagation rule explicitly in env->fp_status.
1
Set the FloatInfZeroNaNRule explicitly for the HPPA target,
2
so we can remove the ifdef from pickNaNMulAdd().
2
3
3
Really we only need to do this at CPU reset (after reset has zeroed
4
As this is the last target to be converted to explicitly setting
4
out most of the CPU state struct, which typically includes fp_status
5
the rule, we can remove the fallback code in pickNaNMulAdd()
5
fields). However target/hppa does not currently implement CPU reset
6
entirely.
6
at all, so leave a TODO comment to note that this could be moved if
7
we ever do implement reset.
8
7
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20241025141254.2141506-7-peter.maydell@linaro.org
10
Message-id: 20241202131347.498124-14-peter.maydell@linaro.org
12
---
11
---
13
target/hppa/fpu_helper.c | 6 ++++++
12
target/hppa/fpu_helper.c | 2 ++
14
fpu/softfloat-specialize.c.inc | 4 ++--
13
fpu/softfloat-specialize.c.inc | 13 +------------
15
2 files changed, 8 insertions(+), 2 deletions(-)
14
2 files changed, 3 insertions(+), 12 deletions(-)
16
15
17
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
16
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/target/hppa/fpu_helper.c
18
--- a/target/hppa/fpu_helper.c
20
+++ b/target/hppa/fpu_helper.c
19
+++ b/target/hppa/fpu_helper.c
21
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
20
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
22
d = FIELD_EX32(shadow, FPSR, D);
21
* HPPA does note implement a CPU reset method at all...
23
set_flush_to_zero(d, &env->fp_status);
22
*/
24
set_flush_inputs_to_zero(d, &env->fp_status);
23
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
25
+
24
+ /* For inf * 0 + NaN, return the input NaN */
26
+ /*
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
27
+ * TODO: we only need to do this at CPU reset, but currently
28
+ * HPPA does note implement a CPU reset method at all...
29
+ */
30
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
31
}
26
}
32
27
33
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
28
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
34
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
35
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
36
--- a/fpu/softfloat-specialize.c.inc
31
--- a/fpu/softfloat-specialize.c.inc
37
+++ b/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
38
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
33
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
39
#if defined(TARGET_AVR) || defined(TARGET_HEXAGON) \
34
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
40
|| defined(TARGET_RISCV) || defined(TARGET_SH4) \
35
bool infzero, float_status *status)
41
|| defined(TARGET_TRICORE) || defined(TARGET_ARM) || defined(TARGET_MIPS) \
36
{
42
- || defined(TARGET_LOONGARCH64)
37
- FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
43
+ || defined(TARGET_LOONGARCH64) || defined(TARGET_HPPA)
38
-
44
g_assert_not_reached();
39
/*
45
-#elif defined(TARGET_HPPA) || defined(TARGET_S390X)
40
* We guarantee not to require the target to tell us how to
46
+#elif defined(TARGET_S390X)
41
* pick a NaN if we're always returning the default NaN.
47
rule = float_2nan_prop_s_ab;
42
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
48
#elif defined(TARGET_PPC) || defined(TARGET_M68K)
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) {
49
/*
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:
50
--
65
--
51
2.34.1
66
2.34.1
diff view generated by jsdifflib
New patch
1
The new implementation of pickNaNMulAdd() will find it convenient
2
to know whether at least one of the three arguments to the muladd
3
was a signaling NaN. We already calculate that in the caller,
4
so pass it in as a new bool have_snan.
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-15-peter.maydell@linaro.org
9
---
10
fpu/softfloat-parts.c.inc | 5 +++--
11
fpu/softfloat-specialize.c.inc | 2 +-
12
2 files changed, 4 insertions(+), 3 deletions(-)
13
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
16
--- a/fpu/softfloat-parts.c.inc
17
+++ b/fpu/softfloat-parts.c.inc
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);
27
}
28
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
30
if (s->default_nan_mode) {
31
which = 3;
32
} else {
33
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
34
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
35
}
36
37
if (which == 3) {
38
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
39
index XXXXXXX..XXXXXXX 100644
40
--- a/fpu/softfloat-specialize.c.inc
41
+++ b/fpu/softfloat-specialize.c.inc
42
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
43
| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
44
*----------------------------------------------------------------------------*/
45
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
46
- bool infzero, float_status *status)
47
+ bool infzero, bool have_snan, float_status *status)
48
{
49
/*
50
* We guarantee not to require the target to tell us how to
51
--
52
2.34.1
diff view generated by jsdifflib
1
IEEE 758 does not define a fixed rule for which NaN to pick as the
1
IEEE 758 does not define a fixed rule for which NaN to pick as the
2
result if both operands of a 2-operand operation are NaNs. As a
2
result if both operands of a 3-operand fused multiply-add operation
3
result different architectures have ended up with different rules for
3
are NaNs. As a result different architectures have ended up with
4
propagating NaNs.
4
different rules for propagating NaNs.
5
5
6
QEMU currently hardcodes the NaN propagation logic into the binary
6
QEMU currently hardcodes the NaN propagation logic into the binary
7
because pickNaN() has an ifdef ladder for different targets. We want
7
because pickNaNMulAdd() has an ifdef ladder for different targets.
8
to make the propagation rule instead be selectable at runtime,
8
We want to make the propagation rule instead be selectable at
9
because:
9
runtime, because:
10
* this will let us have multiple targets in one QEMU binary
10
* this will let us have multiple targets in one QEMU binary
11
* the Arm FEAT_AFP architectural feature includes letting
11
* the Arm FEAT_AFP architectural feature includes letting
12
the guest select a NaN propagation rule at runtime
12
the guest select a NaN propagation rule at runtime
13
* x86 specifies different propagation rules for x87 FPU ops
14
and for SSE ops, and specifying the rule in the float_status
15
would let us emulate this, instead of wrongly using the
16
x87 rules everywhere
17
13
18
In this commit we add an enum for the propagation rule, the field in
14
In this commit we add an enum for the propagation rule, the field in
19
float_status, and the corresponding getters and setters. We change
15
float_status, and the corresponding getters and setters. We change
20
pickNaN to honour this, but because all targets still leave this
16
pickNaNMulAdd to honour this, but because all targets still leave
21
field at its default 0 value, the fallback logic will pick the rule
17
this field at its default 0 value, the fallback logic will pick the
22
type with the old ifdef ladder.
18
rule type with the old ifdef ladder.
23
19
24
It's valid not to set a propagation rule if default_nan_mode is
20
It's valid not to set a propagation rule if default_nan_mode is
25
enabled, because in that case there's no need to pick a NaN; all the
21
enabled, because in that case there's no need to pick a NaN; all the
26
callers of pickNaN() catch this case and skip calling it. So we can
22
callers of pickNaNMulAdd() catch this case and skip calling it.
27
already assert that we don't get into the "no rule defined" codepath
28
for our four targets which always set default_nan_mode: Hexagon,
29
RiscV, SH4 and Tricore, and for the one target which does not have FP
30
at all: avr. These targets will not need to be updated to call
31
set_float_2nan_prop_rule().
32
23
33
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
35
Message-id: 20241025141254.2141506-2-peter.maydell@linaro.org
26
Message-id: 20241202131347.498124-16-peter.maydell@linaro.org
36
---
27
---
37
include/fpu/softfloat-helpers.h | 11 ++
28
include/fpu/softfloat-helpers.h | 11 +++
38
include/fpu/softfloat-types.h | 42 ++++++
29
include/fpu/softfloat-types.h | 55 +++++++++++
39
fpu/softfloat-specialize.c.inc | 229 ++++++++++++++++++--------------
30
fpu/softfloat-specialize.c.inc | 167 ++++++++------------------------
40
3 files changed, 185 insertions(+), 97 deletions(-)
31
3 files changed, 107 insertions(+), 126 deletions(-)
41
32
42
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
33
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
43
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
44
--- a/include/fpu/softfloat-helpers.h
35
--- a/include/fpu/softfloat-helpers.h
45
+++ b/include/fpu/softfloat-helpers.h
36
+++ b/include/fpu/softfloat-helpers.h
46
@@ -XXX,XX +XXX,XX @@ static inline void set_floatx80_rounding_precision(FloatX80RoundPrec val,
37
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
47
status->floatx80_rounding_precision = val;
38
status->float_2nan_prop_rule = rule;
48
}
39
}
49
40
50
+static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
41
+static inline void set_float_3nan_prop_rule(Float3NaNPropRule rule,
51
+ float_status *status)
42
+ float_status *status)
52
+{
43
+{
53
+ status->float_2nan_prop_rule = rule;
44
+ status->float_3nan_prop_rule = rule;
54
+}
45
+}
55
+
46
+
56
static inline void set_flush_to_zero(bool val, float_status *status)
47
static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
float_status *status)
57
{
49
{
58
status->flush_to_zero = val;
50
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
59
@@ -XXX,XX +XXX,XX @@ get_floatx80_rounding_precision(float_status *status)
51
return status->float_2nan_prop_rule;
60
return status->floatx80_rounding_precision;
61
}
52
}
62
53
63
+static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
54
+static inline Float3NaNPropRule get_float_3nan_prop_rule(float_status *status)
64
+{
55
+{
65
+ return status->float_2nan_prop_rule;
56
+ return status->float_3nan_prop_rule;
66
+}
57
+}
67
+
58
+
68
static inline bool get_flush_to_zero(float_status *status)
59
static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
69
{
60
{
70
return status->flush_to_zero;
61
return status->float_infzeronan_rule;
71
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
62
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
72
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
73
--- a/include/fpu/softfloat-types.h
64
--- a/include/fpu/softfloat-types.h
74
+++ b/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__)) {
75
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
76
floatx80_precision_s,
76
float_2nan_prop_x87,
77
} FloatX80RoundPrec;
77
} Float2NaNPropRule;
78
78
79
+/*
79
+/*
80
+ * 2-input NaN propagation rule. Individual architectures have
80
+ * 3-input NaN propagation rule, for fused multiply-add. Individual
81
+ * different rules for which input NaN is propagated to the output
81
+ * architectures have different rules for which input NaN is
82
+ * when there is more than one NaN on the input.
82
+ * propagated to the output when there is more than one NaN on the
83
+ * input.
83
+ *
84
+ *
84
+ * If default_nan_mode is enabled then it is valid not to set a
85
+ * If default_nan_mode is enabled then it is valid not to set a NaN
85
+ * NaN propagation rule, because the softfloat code guarantees
86
+ * propagation rule, because the softfloat code guarantees not to try
86
+ * not to try to pick a NaN to propagate in default NaN mode.
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.
87
+ *
91
+ *
88
+ * For transition, currently the 'none' rule will cause us to
92
+ * The naming scheme for Float3NaNPropRule values is:
89
+ * fall back to picking the propagation rule based on the existing
93
+ * float_3nan_prop_s_abc:
90
+ * ifdef ladder. When all targets are converted it will be an error
94
+ * = "Prefer SNaN over QNaN, then operand A over B over C"
91
+ * not to set the rule in float_status unless in default_nan_mode,
95
+ * float_3nan_prop_abc:
92
+ * and we will assert if we need to handle an input NaN and no
96
+ * = "Prefer A over B over C regardless of SNaN vs QNAN"
93
+ * rule was selected.
97
+ *
98
+ * For QEMU, the multiply-add operation is A * B + C.
94
+ */
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
+
95
+typedef enum __attribute__((__packed__)) {
113
+typedef enum __attribute__((__packed__)) {
96
+ /* No propagation rule specified */
114
+ float_3nan_prop_none = 0, /* No propagation rule specified */
97
+ float_2nan_prop_none = 0,
115
+ float_3nan_prop_abc = PROPRULE(0, 1, 2),
98
+ /* Prefer SNaN over QNaN, then operand A over B */
116
+ float_3nan_prop_acb = PROPRULE(0, 2, 1),
99
+ float_2nan_prop_s_ab,
117
+ float_3nan_prop_bac = PROPRULE(1, 0, 2),
100
+ /* Prefer SNaN over QNaN, then operand B over A */
118
+ float_3nan_prop_bca = PROPRULE(1, 2, 0),
101
+ float_2nan_prop_s_ba,
119
+ float_3nan_prop_cab = PROPRULE(2, 0, 1),
102
+ /* Prefer A over B regardless of SNaN vs QNaN */
120
+ float_3nan_prop_cba = PROPRULE(2, 1, 0),
103
+ float_2nan_prop_ab,
121
+ float_3nan_prop_s_abc = float_3nan_prop_abc | R_3NAN_SNAN_MASK,
104
+ /* Prefer B over A regardless of SNaN vs QNaN */
122
+ float_3nan_prop_s_acb = float_3nan_prop_acb | R_3NAN_SNAN_MASK,
105
+ float_2nan_prop_ba,
123
+ float_3nan_prop_s_bac = float_3nan_prop_bac | R_3NAN_SNAN_MASK,
106
+ /*
124
+ float_3nan_prop_s_bca = float_3nan_prop_bca | R_3NAN_SNAN_MASK,
107
+ * This implements x87 NaN propagation rules:
125
+ float_3nan_prop_s_cab = float_3nan_prop_cab | R_3NAN_SNAN_MASK,
108
+ * SNaN + QNaN => return the QNaN
126
+ float_3nan_prop_s_cba = float_3nan_prop_cba | R_3NAN_SNAN_MASK,
109
+ * two SNaNs => return the one with the larger significand, silenced
127
+} Float3NaNPropRule;
110
+ * two QNaNs => return the one with the larger significand
128
+
111
+ * SNaN and a non-NaN => return the SNaN, silenced
129
+#undef PROPRULE
112
+ * QNaN and a non-NaN => return the QNaN
113
+ *
114
+ * If we get down to comparing significands and they are the same,
115
+ * return the NaN with the positive sign bit (if any).
116
+ */
117
+ float_2nan_prop_x87,
118
+} Float2NaNPropRule;
119
+
130
+
120
/*
131
/*
121
* Floating Point Status. Individual architectures may maintain
132
* Rule for result of fused multiply-add 0 * Inf + NaN.
122
* several versions of float_status for different functions. The
133
* This must be a NaN, but implementations differ on whether this
123
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
134
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
124
uint16_t float_exception_flags;
125
FloatRoundMode float_rounding_mode;
135
FloatRoundMode float_rounding_mode;
126
FloatX80RoundPrec floatx80_rounding_precision;
136
FloatX80RoundPrec floatx80_rounding_precision;
127
+ Float2NaNPropRule float_2nan_prop_rule;
137
Float2NaNPropRule float_2nan_prop_rule;
138
+ Float3NaNPropRule float_3nan_prop_rule;
139
FloatInfZeroNaNRule float_infzeronan_rule;
128
bool tininess_before_rounding;
140
bool tininess_before_rounding;
129
/* should denormalised results go to zero and set the inexact flag? */
141
/* should denormalised results go to zero and set the inexact flag? */
130
bool flush_to_zero;
131
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
142
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
132
index XXXXXXX..XXXXXXX 100644
143
index XXXXXXX..XXXXXXX 100644
133
--- a/fpu/softfloat-specialize.c.inc
144
--- a/fpu/softfloat-specialize.c.inc
134
+++ b/fpu/softfloat-specialize.c.inc
145
+++ b/fpu/softfloat-specialize.c.inc
135
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
146
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
136
static int pickNaN(FloatClass a_cls, FloatClass b_cls,
147
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
137
bool aIsLargerSignificand, float_status *status)
148
bool infzero, bool have_snan, float_status *status)
138
{
149
{
139
-#if defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_HPPA) || \
150
+ FloatClass cls[3] = { a_cls, b_cls, c_cls };
140
- defined(TARGET_LOONGARCH64) || defined(TARGET_S390X)
151
+ Float3NaNPropRule rule = status->float_3nan_prop_rule;
141
- /* ARM mandated NaN propagation rules (see FPProcessNaNs()), take
152
+ int which;
142
- * the first of:
153
+
143
- * 1. A if it is signaling
154
/*
144
- * 2. B if it is signaling
155
* We guarantee not to require the target to tell us how to
145
- * 3. A (quiet)
156
* pick a NaN if we're always returning the default NaN.
146
- * 4. B (quiet)
157
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
147
- * A signaling NaN is always quietened before returning it.
158
}
159
}
160
161
+ if (rule == float_3nan_prop_none) {
162
#if defined(TARGET_ARM)
163
-
164
- /* This looks different from the ARM ARM pseudocode, because the ARM ARM
165
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
148
- */
166
- */
149
- /* According to MIPS specifications, if one of the two operands is
167
- if (is_snan(c_cls)) {
150
- * a sNaN, a new qNaN has to be generated. This is done in
168
- return 2;
151
- * floatXX_silence_nan(). For qNaN inputs the specifications
169
- } else if (is_snan(a_cls)) {
152
- * says: "When possible, this QNaN result is one of the operand QNaN
153
- * values." In practice it seems that most implementations choose
154
- * the first operand if both operands are qNaN. In short this gives
155
- * the following rules:
156
- * 1. A if it is signaling
157
- * 2. B if it is signaling
158
- * 3. A (quiet)
159
- * 4. B (quiet)
160
- * A signaling NaN is always silenced before returning it.
161
- */
162
- if (is_snan(a_cls)) {
163
- return 0;
170
- return 0;
164
- } else if (is_snan(b_cls)) {
171
- } else if (is_snan(b_cls)) {
165
- return 1;
172
- return 1;
173
- } else if (is_qnan(c_cls)) {
174
- return 2;
166
- } else if (is_qnan(a_cls)) {
175
- } else if (is_qnan(a_cls)) {
167
- return 0;
176
- return 0;
168
- } else {
177
- } else {
169
- return 1;
178
- return 1;
170
- }
179
- }
171
-#elif defined(TARGET_PPC) || defined(TARGET_M68K)
180
+ /*
172
- /* PowerPC propagation rules:
181
+ * This looks different from the ARM ARM pseudocode, because the ARM ARM
173
- * 1. A if it sNaN or qNaN
182
+ * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
174
- * 2. B if it sNaN or qNaN
183
+ */
175
- * A signaling NaN is always silenced before returning it.
184
+ rule = float_3nan_prop_s_cab;
176
- */
185
#elif defined(TARGET_MIPS)
177
- /* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
186
- if (snan_bit_is_one(status)) {
178
- * 3.4 FLOATING-POINT INSTRUCTION DETAILS
187
- /* Prefer sNaN over qNaN, in the a, b, c order. */
179
- * If either operand, but not both operands, of an operation is a
188
- if (is_snan(a_cls)) {
180
- * nonsignaling NaN, then that NaN is returned as the result. If both
189
- return 0;
181
- * operands are nonsignaling NaNs, then the destination operand
190
- } else if (is_snan(b_cls)) {
182
- * nonsignaling NaN is returned as the result.
191
- return 1;
183
- * If either operand to an operation is a signaling NaN (SNaN), then the
192
- } else if (is_snan(c_cls)) {
184
- * SNaN bit is set in the FPSR EXC byte. If the SNaN exception enable bit
193
- return 2;
185
- * is set in the FPCR ENABLE byte, then the exception is taken and the
194
- } else if (is_qnan(a_cls)) {
186
- * destination is not modified. If the SNaN exception enable bit is not
195
- return 0;
187
- * set, setting the SNaN bit in the operand to a one converts the SNaN to
196
- } else if (is_qnan(b_cls)) {
188
- * a nonsignaling NaN. The operation then continues as described in the
197
- return 1;
189
- * preceding paragraph for nonsignaling NaNs.
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;
203
}
204
- } else {
205
- /* Prefer sNaN over qNaN, in the c, a, b order. */
206
- if (is_snan(c_cls)) {
207
- return 2;
208
- } else if (is_snan(a_cls)) {
209
- return 0;
210
- } else if (is_snan(b_cls)) {
211
- return 1;
212
- } else if (is_qnan(c_cls)) {
213
- return 2;
214
- } else if (is_qnan(a_cls)) {
215
- return 0;
216
- } else {
217
- return 1;
218
- }
219
- }
220
#elif defined(TARGET_LOONGARCH64)
221
- /* Prefer sNaN over qNaN, in the c, a, b order. */
222
- if (is_snan(c_cls)) {
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
190
- */
239
- */
191
- if (is_nan(a_cls)) {
240
- if (is_nan(a_cls)) {
192
- return 0;
241
- return 0;
193
- } else {
242
- } else if (is_nan(c_cls)) {
194
- return 1;
243
- return 2;
195
- }
244
- } else {
196
-#elif defined(TARGET_SPARC)
245
- return 1;
197
- /* Prefer SNaN over QNaN, order B then A. */
246
- }
198
- if (is_snan(b_cls)) {
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)) {
199
- return 1;
272
- return 1;
200
- } else if (is_snan(a_cls)) {
273
- } else if (is_snan(a_cls)) {
201
- return 0;
274
- return 0;
275
- } else if (is_qnan(c_cls)) {
276
- return 2;
202
- } else if (is_qnan(b_cls)) {
277
- } else if (is_qnan(b_cls)) {
203
- return 1;
278
- return 1;
204
- } else {
279
- } else {
205
- return 0;
280
- return 0;
206
- }
281
- }
207
-#elif defined(TARGET_XTENSA)
282
+ rule = float_3nan_prop_s_cba;
208
+ Float2NaNPropRule rule = status->float_2nan_prop_rule;
283
#elif defined(TARGET_XTENSA)
209
+
284
- /*
210
/*
285
- * For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
211
- * Xtensa has two NaN propagation modes.
286
- * an input NaN if we have one (ie c).
212
- * Which one is active is controlled by float_status::use_first_nan.
287
- */
213
+ * We guarantee not to require the target to tell us how to
214
+ * pick a NaN if we're always returning the default NaN.
215
*/
216
- if (status->use_first_nan) {
288
- if (status->use_first_nan) {
217
+ assert(!status->default_nan_mode);
289
- if (is_nan(a_cls)) {
218
+
290
- return 0;
219
+ if (rule == float_2nan_prop_none) {
291
- } else if (is_nan(b_cls)) {
220
+ /* target didn't set the rule: fall back to old ifdef choices */
292
- return 1;
221
+#if defined(TARGET_AVR) || defined(TARGET_HEXAGON) \
222
+ || defined(TARGET_RISCV) || defined(TARGET_SH4) \
223
+ || defined(TARGET_TRICORE)
224
+ g_assert_not_reached();
225
+#elif defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_HPPA) || \
226
+ defined(TARGET_LOONGARCH64) || defined(TARGET_S390X)
227
+ /*
228
+ * ARM mandated NaN propagation rules (see FPProcessNaNs()), take
229
+ * the first of:
230
+ * 1. A if it is signaling
231
+ * 2. B if it is signaling
232
+ * 3. A (quiet)
233
+ * 4. B (quiet)
234
+ * A signaling NaN is always quietened before returning it.
235
+ */
236
+ /*
237
+ * According to MIPS specifications, if one of the two operands is
238
+ * a sNaN, a new qNaN has to be generated. This is done in
239
+ * floatXX_silence_nan(). For qNaN inputs the specifications
240
+ * says: "When possible, this QNaN result is one of the operand QNaN
241
+ * values." In practice it seems that most implementations choose
242
+ * the first operand if both operands are qNaN. In short this gives
243
+ * the following rules:
244
+ * 1. A if it is signaling
245
+ * 2. B if it is signaling
246
+ * 3. A (quiet)
247
+ * 4. B (quiet)
248
+ * A signaling NaN is always silenced before returning it.
249
+ */
250
+ rule = float_2nan_prop_s_ab;
251
+#elif defined(TARGET_PPC) || defined(TARGET_M68K)
252
+ /*
253
+ * PowerPC propagation rules:
254
+ * 1. A if it sNaN or qNaN
255
+ * 2. B if it sNaN or qNaN
256
+ * A signaling NaN is always silenced before returning it.
257
+ */
258
+ /*
259
+ * M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
260
+ * 3.4 FLOATING-POINT INSTRUCTION DETAILS
261
+ * If either operand, but not both operands, of an operation is a
262
+ * nonsignaling NaN, then that NaN is returned as the result. If both
263
+ * operands are nonsignaling NaNs, then the destination operand
264
+ * nonsignaling NaN is returned as the result.
265
+ * If either operand to an operation is a signaling NaN (SNaN), then the
266
+ * SNaN bit is set in the FPSR EXC byte. If the SNaN exception enable bit
267
+ * is set in the FPCR ENABLE byte, then the exception is taken and the
268
+ * destination is not modified. If the SNaN exception enable bit is not
269
+ * set, setting the SNaN bit in the operand to a one converts the SNaN to
270
+ * a nonsignaling NaN. The operation then continues as described in the
271
+ * preceding paragraph for nonsignaling NaNs.
272
+ */
273
+ rule = float_2nan_prop_ab;
274
+#elif defined(TARGET_SPARC)
275
+ /* Prefer SNaN over QNaN, order B then A. */
276
+ rule = float_2nan_prop_s_ba;
277
+#elif defined(TARGET_XTENSA)
278
+ /*
279
+ * Xtensa has two NaN propagation modes.
280
+ * Which one is active is controlled by float_status::use_first_nan.
281
+ */
282
+ if (status->use_first_nan) {
293
+ if (status->use_first_nan) {
283
+ rule = float_2nan_prop_ab;
294
+ rule = float_3nan_prop_abc;
284
+ } else {
295
} else {
285
+ rule = float_2nan_prop_ba;
296
- return 2;
286
+ }
297
+ rule = float_3nan_prop_cba;
287
+#else
298
}
288
+ rule = float_2nan_prop_x87;
299
- } else {
289
+#endif
300
- if (is_nan(c_cls)) {
301
- return 2;
302
- } else if (is_nan(b_cls)) {
303
- return 1;
304
- } else {
305
- return 0;
306
- }
307
- }
308
#else
309
- /* A default implementation: prefer a to b to c.
310
- * This is unlikely to actually match any real implementation.
311
- */
312
- if (is_nan(a_cls)) {
313
- return 0;
314
- } else if (is_nan(b_cls)) {
315
- return 1;
316
- } else {
317
- return 2;
318
- }
319
+ rule = float_3nan_prop_abc;
320
#endif
290
+ }
321
+ }
291
+
322
+
292
+ switch (rule) {
323
+ assert(rule != float_3nan_prop_none);
293
+ case float_2nan_prop_s_ab:
324
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
294
+ if (is_snan(a_cls)) {
325
+ /* We have at least one SNaN input and should prefer it */
295
+ return 0;
326
+ do {
296
+ } else if (is_snan(b_cls)) {
327
+ which = rule & R_3NAN_1ST_MASK;
297
+ return 1;
328
+ rule >>= R_3NAN_1ST_LENGTH;
298
+ } else if (is_qnan(a_cls)) {
329
+ } while (!is_snan(cls[which]));
299
+ return 0;
330
+ } else {
300
+ } else {
331
+ do {
301
+ return 1;
332
+ which = rule & R_3NAN_1ST_MASK;
302
+ }
333
+ rule >>= R_3NAN_1ST_LENGTH;
303
+ break;
334
+ } while (!is_nan(cls[which]));
304
+ case float_2nan_prop_s_ba:
335
+ }
305
+ if (is_snan(b_cls)) {
336
+ return which;
306
+ return 1;
307
+ } else if (is_snan(a_cls)) {
308
+ return 0;
309
+ } else if (is_qnan(b_cls)) {
310
+ return 1;
311
+ } else {
312
+ return 0;
313
+ }
314
+ break;
315
+ case float_2nan_prop_ab:
316
if (is_nan(a_cls)) {
317
return 0;
318
} else {
319
return 1;
320
}
321
- } else {
322
+ break;
323
+ case float_2nan_prop_ba:
324
if (is_nan(b_cls)) {
325
return 1;
326
} else {
327
return 0;
328
}
329
- }
330
-#else
331
- /* This implements x87 NaN propagation rules:
332
- * SNaN + QNaN => return the QNaN
333
- * two SNaNs => return the one with the larger significand, silenced
334
- * two QNaNs => return the one with the larger significand
335
- * SNaN and a non-NaN => return the SNaN, silenced
336
- * QNaN and a non-NaN => return the QNaN
337
- *
338
- * If we get down to comparing significands and they are the same,
339
- * return the NaN with the positive sign bit (if any).
340
- */
341
- if (is_snan(a_cls)) {
342
- if (is_snan(b_cls)) {
343
- return aIsLargerSignificand ? 0 : 1;
344
- }
345
- return is_qnan(b_cls) ? 1 : 0;
346
- } else if (is_qnan(a_cls)) {
347
- if (is_snan(b_cls) || !is_qnan(b_cls)) {
348
- return 0;
349
+ break;
350
+ case float_2nan_prop_x87:
351
+ /*
352
+ * This implements x87 NaN propagation rules:
353
+ * SNaN + QNaN => return the QNaN
354
+ * two SNaNs => return the one with the larger significand, silenced
355
+ * two QNaNs => return the one with the larger significand
356
+ * SNaN and a non-NaN => return the SNaN, silenced
357
+ * QNaN and a non-NaN => return the QNaN
358
+ *
359
+ * If we get down to comparing significands and they are the same,
360
+ * return the NaN with the positive sign bit (if any).
361
+ */
362
+ if (is_snan(a_cls)) {
363
+ if (is_snan(b_cls)) {
364
+ return aIsLargerSignificand ? 0 : 1;
365
+ }
366
+ return is_qnan(b_cls) ? 1 : 0;
367
+ } else if (is_qnan(a_cls)) {
368
+ if (is_snan(b_cls) || !is_qnan(b_cls)) {
369
+ return 0;
370
+ } else {
371
+ return aIsLargerSignificand ? 0 : 1;
372
+ }
373
} else {
374
- return aIsLargerSignificand ? 0 : 1;
375
+ return 1;
376
}
377
- } else {
378
- return 1;
379
+ default:
380
+ g_assert_not_reached();
381
}
382
-#endif
383
}
337
}
384
338
385
/*----------------------------------------------------------------------------
339
/*----------------------------------------------------------------------------
386
--
340
--
387
2.34.1
341
2.34.1
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
1
Set the 2-NaN propagation rule explicitly in the float_status word we
1
Set the Float3NaNPropRule explicitly for loongarch, and remove the
2
use.
2
ifdef from pickNaNMulAdd().
3
4
(There are a couple of places in fpu_helper.c where we create a
5
dummy float_status word with "float_status *s = { };", but these
6
are only used for calling float*_is_quiet_nan() so it doesn't
7
matter that we don't set a 2-NaN propagation rule there.)
8
3
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20241025141254.2141506-6-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-19-peter.maydell@linaro.org
12
---
7
---
13
target/loongarch/tcg/fpu_helper.c | 1 +
8
target/loongarch/tcg/fpu_helper.c | 1 +
14
fpu/softfloat-specialize.c.inc | 6 +++---
9
fpu/softfloat-specialize.c.inc | 2 --
15
2 files changed, 4 insertions(+), 3 deletions(-)
10
2 files changed, 1 insertion(+), 2 deletions(-)
16
11
17
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
12
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/target/loongarch/tcg/fpu_helper.c
14
--- a/target/loongarch/tcg/fpu_helper.c
20
+++ b/target/loongarch/tcg/fpu_helper.c
15
+++ b/target/loongarch/tcg/fpu_helper.c
21
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
16
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
22
set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3],
17
* case sets InvalidOp and returns the input value 'c'
23
&env->fp_status);
18
*/
24
set_flush_to_zero(0, &env->fp_status);
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
25
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
20
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
26
}
21
}
27
22
28
int ieee_ex_to_loongarch(int xcpt)
23
int ieee_ex_to_loongarch(int xcpt)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
26
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
28
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
34
/* target didn't set the rule: fall back to old ifdef choices */
29
} else {
35
#if defined(TARGET_AVR) || defined(TARGET_HEXAGON) \
30
rule = float_3nan_prop_s_cab;
36
|| defined(TARGET_RISCV) || defined(TARGET_SH4) \
31
}
37
- || defined(TARGET_TRICORE) || defined(TARGET_ARM) || defined(TARGET_MIPS)
32
-#elif defined(TARGET_LOONGARCH64)
38
+ || defined(TARGET_TRICORE) || defined(TARGET_ARM) || defined(TARGET_MIPS) \
33
- rule = float_3nan_prop_s_cab;
39
+ || defined(TARGET_LOONGARCH64)
34
#elif defined(TARGET_PPC)
40
g_assert_not_reached();
41
-#elif defined(TARGET_HPPA) || \
42
- defined(TARGET_LOONGARCH64) || defined(TARGET_S390X)
43
+#elif defined(TARGET_HPPA) || defined(TARGET_S390X)
44
rule = float_2nan_prop_s_ab;
45
#elif defined(TARGET_PPC) || defined(TARGET_M68K)
46
/*
35
/*
36
* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
47
--
37
--
48
2.34.1
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
1
Set the 2-NaN propagation rule explicitly in the float_status words
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
we use.
2
ifdef from pickNaNMulAdd().
3
4
For active_fpu.fp_status, we do this in a new fp_reset() function
5
which mirrors the existing msa_reset() function in doing "first call
6
restore to set the fp status parts that depend on CPU state, then set
7
the fp status parts that are constant".
8
3
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20241025141254.2141506-5-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-23-peter.maydell@linaro.org
12
---
7
---
13
target/mips/fpu_helper.h | 22 ++++++++++++++++++++++
8
target/mips/fpu_helper.h | 4 ++++
14
target/mips/cpu.c | 2 +-
9
target/mips/msa.c | 3 +++
15
target/mips/msa.c | 17 +++++++++++++++++
10
fpu/softfloat-specialize.c.inc | 8 +-------
16
fpu/softfloat-specialize.c.inc | 18 ++----------------
11
3 files changed, 8 insertions(+), 7 deletions(-)
17
4 files changed, 42 insertions(+), 17 deletions(-)
18
12
19
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/target/mips/fpu_helper.h
15
--- a/target/mips/fpu_helper.h
22
+++ b/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
23
@@ -XXX,XX +XXX,XX @@ static inline void restore_fp_status(CPUMIPSState *env)
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
24
restore_snan_bit_mode(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
+
25
}
32
}
26
33
27
+static inline void fp_reset(CPUMIPSState *env)
34
static inline void restore_fp_status(CPUMIPSState *env)
28
+{
29
+ restore_fp_status(env);
30
+
31
+ /*
32
+ * According to MIPS specifications, if one of the two operands is
33
+ * a sNaN, a new qNaN has to be generated. This is done in
34
+ * floatXX_silence_nan(). For qNaN inputs the specifications
35
+ * says: "When possible, this QNaN result is one of the operand QNaN
36
+ * values." In practice it seems that most implementations choose
37
+ * the first operand if both operands are qNaN. In short this gives
38
+ * the following rules:
39
+ * 1. A if it is signaling
40
+ * 2. B if it is signaling
41
+ * 3. A (quiet)
42
+ * 4. B (quiet)
43
+ * A signaling NaN is always silenced before returning it.
44
+ */
45
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab,
46
+ &env->active_fpu.fp_status);
47
+}
48
+
49
/* MSA */
50
51
enum CPUMIPSMSADataFormat {
52
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/mips/cpu.c
55
+++ b/target/mips/cpu.c
56
@@ -XXX,XX +XXX,XX @@ static void mips_cpu_reset_hold(Object *obj, ResetType type)
57
}
58
59
msa_reset(env);
60
+ fp_reset(env);
61
62
compute_hflags(env);
63
- restore_fp_status(env);
64
restore_pamask(env);
65
cs->exception_index = EXCP_NONE;
66
67
diff --git a/target/mips/msa.c b/target/mips/msa.c
35
diff --git a/target/mips/msa.c b/target/mips/msa.c
68
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
69
--- a/target/mips/msa.c
37
--- a/target/mips/msa.c
70
+++ b/target/mips/msa.c
38
+++ b/target/mips/msa.c
71
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
39
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
72
set_float_detect_tininess(float_tininess_after_rounding,
40
set_float_2nan_prop_rule(float_2nan_prop_s_ab,
73
&env->active_tc.msa_fp_status);
41
&env->active_tc.msa_fp_status);
74
42
75
+ /*
43
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab,
76
+ * According to MIPS specifications, if one of the two operands is
77
+ * a sNaN, a new qNaN has to be generated. This is done in
78
+ * floatXX_silence_nan(). For qNaN inputs the specifications
79
+ * says: "When possible, this QNaN result is one of the operand QNaN
80
+ * values." In practice it seems that most implementations choose
81
+ * the first operand if both operands are qNaN. In short this gives
82
+ * the following rules:
83
+ * 1. A if it is signaling
84
+ * 2. B if it is signaling
85
+ * 3. A (quiet)
86
+ * 4. B (quiet)
87
+ * A signaling NaN is always silenced before returning it.
88
+ */
89
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab,
90
+ &env->active_tc.msa_fp_status);
44
+ &env->active_tc.msa_fp_status);
91
+
45
+
92
/* clear float_status exception flags */
46
/* clear float_status exception flags */
93
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
47
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
94
48
95
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
49
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
96
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
97
--- a/fpu/softfloat-specialize.c.inc
51
--- a/fpu/softfloat-specialize.c.inc
98
+++ b/fpu/softfloat-specialize.c.inc
52
+++ b/fpu/softfloat-specialize.c.inc
99
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
53
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
100
/* target didn't set the rule: fall back to old ifdef choices */
54
}
101
#if defined(TARGET_AVR) || defined(TARGET_HEXAGON) \
55
102
|| defined(TARGET_RISCV) || defined(TARGET_SH4) \
56
if (rule == float_3nan_prop_none) {
103
- || defined(TARGET_TRICORE) || defined(TARGET_ARM)
57
-#if defined(TARGET_MIPS)
104
+ || defined(TARGET_TRICORE) || defined(TARGET_ARM) || defined(TARGET_MIPS)
58
- if (snan_bit_is_one(status)) {
105
g_assert_not_reached();
59
- rule = float_3nan_prop_s_abc;
106
-#elif defined(TARGET_MIPS) || defined(TARGET_HPPA) || \
60
- } else {
107
+#elif defined(TARGET_HPPA) || \
61
- rule = float_3nan_prop_s_cab;
108
defined(TARGET_LOONGARCH64) || defined(TARGET_S390X)
62
- }
109
- /*
63
-#elif defined(TARGET_XTENSA)
110
- * According to MIPS specifications, if one of the two operands is
64
+#if defined(TARGET_XTENSA)
111
- * a sNaN, a new qNaN has to be generated. This is done in
65
if (status->use_first_nan) {
112
- * floatXX_silence_nan(). For qNaN inputs the specifications
66
rule = float_3nan_prop_abc;
113
- * says: "When possible, this QNaN result is one of the operand QNaN
67
} else {
114
- * values." In practice it seems that most implementations choose
115
- * the first operand if both operands are qNaN. In short this gives
116
- * the following rules:
117
- * 1. A if it is signaling
118
- * 2. B if it is signaling
119
- * 3. A (quiet)
120
- * 4. B (quiet)
121
- * A signaling NaN is always silenced before returning it.
122
- */
123
rule = float_2nan_prop_s_ab;
124
#elif defined(TARGET_PPC) || defined(TARGET_M68K)
125
/*
126
--
68
--
127
2.34.1
69
2.34.1
128
129
diff view generated by jsdifflib
1
Set the NaN propagation rule explicitly in xtensa_use_first_nan().
1
Set the Float3NaNPropRule explicitly for xtensa, and remove the
2
2
ifdef from pickNaNMulAdd().
3
(When we convert the softfloat pickNaNMulAdd routine to also
4
select a NaN propagation rule at runtime, we will be able to
5
remove the use_first_nan flag because the propagation rules
6
will handle everything.)
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Max Filippov <jcmvbkbc@gmail.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241025141254.2141506-15-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-24-peter.maydell@linaro.org
13
---
7
---
14
target/xtensa/fpu_helper.c | 2 ++
8
target/xtensa/fpu_helper.c | 2 ++
15
fpu/softfloat-specialize.c.inc | 12 +-----------
9
fpu/softfloat-specialize.c.inc | 8 --------
16
2 files changed, 3 insertions(+), 11 deletions(-)
10
2 files changed, 2 insertions(+), 8 deletions(-)
17
11
18
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
12
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/target/xtensa/fpu_helper.c
14
--- a/target/xtensa/fpu_helper.c
21
+++ b/target/xtensa/fpu_helper.c
15
+++ b/target/xtensa/fpu_helper.c
22
@@ -XXX,XX +XXX,XX @@ static const struct {
16
@@ -XXX,XX +XXX,XX @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
23
void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
24
{
25
set_use_first_nan(use_first, &env->fp_status);
17
set_use_first_nan(use_first, &env->fp_status);
26
+ set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
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,
27
+ &env->fp_status);
21
+ &env->fp_status);
28
}
22
}
29
23
30
void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
24
void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
27
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
|| defined(TARGET_TRICORE) || defined(TARGET_ARM) || defined(TARGET_MIPS) \
30
}
37
|| defined(TARGET_LOONGARCH64) || defined(TARGET_HPPA) \
31
38
|| defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_M68K) \
32
if (rule == float_3nan_prop_none) {
39
- || defined(TARGET_SPARC)
33
-#if defined(TARGET_XTENSA)
40
+ || defined(TARGET_SPARC) || defined(TARGET_XTENSA)
41
g_assert_not_reached();
42
-#elif defined(TARGET_XTENSA)
43
- /*
44
- * Xtensa has two NaN propagation modes.
45
- * Which one is active is controlled by float_status::use_first_nan.
46
- */
47
- if (status->use_first_nan) {
34
- if (status->use_first_nan) {
48
- rule = float_2nan_prop_ab;
35
- rule = float_3nan_prop_abc;
49
- } else {
36
- } else {
50
- rule = float_2nan_prop_ba;
37
- rule = float_3nan_prop_cba;
51
- }
38
- }
52
#else
39
-#else
53
rule = float_2nan_prop_x87;
40
rule = float_3nan_prop_abc;
54
#endif
41
-#endif
42
}
43
44
assert(rule != float_3nan_prop_none);
55
--
45
--
56
2.34.1
46
2.34.1
57
58
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
New patch
1
The use_first_nan field in float_status was an xtensa-specific way to
2
select at runtime from two different NaN propagation rules. Now that
3
xtensa is using the target-agnostic NaN propagation rule selection
4
that we've just added, we can remove use_first_nan, because there is
5
no longer any code that reads it.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20241202131347.498124-27-peter.maydell@linaro.org
10
---
11
include/fpu/softfloat-helpers.h | 5 -----
12
include/fpu/softfloat-types.h | 1 -
13
target/xtensa/fpu_helper.c | 1 -
14
3 files changed, 7 deletions(-)
15
16
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/fpu/softfloat-helpers.h
19
+++ b/include/fpu/softfloat-helpers.h
20
@@ -XXX,XX +XXX,XX @@ static inline void set_snan_bit_is_one(bool val, float_status *status)
21
status->snan_bit_is_one = val;
22
}
23
24
-static inline void set_use_first_nan(bool val, float_status *status)
25
-{
26
- status->use_first_nan = val;
27
-}
28
-
29
static inline void set_no_signaling_nans(bool val, float_status *status)
30
{
31
status->no_signaling_nans = val;
32
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/fpu/softfloat-types.h
35
+++ b/include/fpu/softfloat-types.h
36
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
37
* softfloat-specialize.inc.c)
38
*/
39
bool snan_bit_is_one;
40
- bool use_first_nan;
41
bool no_signaling_nans;
42
/* should overflowed results subtract re_bias to its exponent? */
43
bool rebias_overflow;
44
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/xtensa/fpu_helper.c
47
+++ b/target/xtensa/fpu_helper.c
48
@@ -XXX,XX +XXX,XX @@ static const struct {
49
50
void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
51
{
52
- set_use_first_nan(use_first, &env->fp_status);
53
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
54
&env->fp_status);
55
set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
56
--
57
2.34.1
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
1
In cf_fpu_gdb_get_reg() and cf_fpu_gdb_set_reg() we use a temporary
1
In cf_fpu_gdb_get_reg() and cf_fpu_gdb_set_reg() we do the conversion
2
float_status variable to pass to floatx80_to_float64() and
2
from float64 to floatx80 using a scratch float_status, because we
3
float64_to_floatx80(), but we don't initialize it, meaning that those
3
don't want the conversion to affect the CPU's floating point exception
4
functions could access uninitialized data. Zero-init the structs.
4
status. Currently we use a zero-initialized float_status. This will
5
5
get steadily more awkward as we add config knobs to float_status
6
(We don't need to set a NaN-propagation rule here because we
6
that the target must initialize. Avoid having to add any of that
7
don't use these with a 2-argument fpu operation.)
7
configuration here by instead initializing our local float_status
8
from the env->fp_status.
8
9
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241025141254.2141506-11-peter.maydell@linaro.org
12
Message-id: 20241202131347.498124-32-peter.maydell@linaro.org
13
---
13
---
14
target/m68k/helper.c | 4 ++--
14
target/m68k/helper.c | 6 ++++--
15
1 file changed, 2 insertions(+), 2 deletions(-)
15
1 file changed, 4 insertions(+), 2 deletions(-)
16
16
17
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
17
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/m68k/helper.c
19
--- a/target/m68k/helper.c
20
+++ b/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)
21
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_get_reg(CPUState *cs, GByteArray *mem_buf, int n)
22
CPUM68KState *env = &cpu->env;
22
CPUM68KState *env = &cpu->env;
23
23
24
if (n < 8) {
24
if (n < 8) {
25
- float_status s;
25
- float_status s = {};
26
+ float_status s = {};
26
+ /* Use scratch float_status so any exceptions don't change CPU state */
27
+ float_status s = env->fp_status;
27
return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
28
return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
28
}
29
}
29
switch (n) {
30
switch (n) {
30
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n)
31
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n)
31
CPUM68KState *env = &cpu->env;
32
CPUM68KState *env = &cpu->env;
32
33
33
if (n < 8) {
34
if (n < 8) {
34
- float_status s;
35
- float_status s = {};
35
+ float_status s = {};
36
+ /* Use scratch float_status so any exceptions don't change CPU state */
37
+ float_status s = env->fp_status;
36
env->fregs[n].d = float64_to_floatx80(ldq_be_p(mem_buf), &s);
38
env->fregs[n].d = float64_to_floatx80(ldq_be_p(mem_buf), &s);
37
return 8;
39
return 8;
38
}
40
}
39
--
41
--
40
2.34.1
42
2.34.1
41
42
diff view generated by jsdifflib
1
This reverts commit 4c2c0474693229c1f533239bb983495c5427784d.
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
This commit tried to fix a problem with our usage of MMU indexes when
8
To do this we need to pass the CPU env pointer in to the helper.
4
EL3 is AArch32, using what it described as a "more complicated
5
approach" where we share the same MMU index values for Secure PL1&0
6
and NonSecure PL1&0. In theory this should work, but the change
7
didn't account for (at least) two things:
8
9
9
(1) The design change means we need to flush the TLBs at any point
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
where the CPU state flips from one to the other. We already flush
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
the TLB when SCR.NS is changed, but we don't flush the TLB when we
12
Message-id: 20241202131347.498124-33-peter.maydell@linaro.org
12
take an exception from NS PL1&0 into Mon or when we return from Mon
13
---
13
to NS PL1&0, and the commit didn't add any code to do that.
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(-)
14
18
15
(2) The ATS12NS* address translate instructions allow Mon code (which
19
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
16
is Secure) to do a stage 1+2 page table walk for NS. I thought this
17
was OK because do_ats_write() does a page table walk which doesn't
18
use the TLBs, so because it can pass both the MMU index and also an
19
ARMSecuritySpace argument we can tell the table walk that we want NS
20
stage1+2, not S. But that means that all the code within the ptw
21
that needs to find e.g. the regime EL cannot do so only with an
22
mmu_idx -- all these functions like regime_sctlr(), regime_el(), etc
23
would need to pass both an mmu_idx and the security_space, so they
24
can tell whether this is a translation regime controlled by EL1 or
25
EL3 (and so whether to look at SCTLR.S or SCTLR.NS, etc).
26
27
In particular, because regime_el() wasn't updated to look at the
28
ARMSecuritySpace it would return 1 even when the CPU was in Monitor
29
mode (and the controlling EL is 3). This meant that page table walks
30
in Monitor mode would look at the wrong SCTLR, TCR, etc and would
31
generally fault when they should not.
32
33
Rather than trying to make the complicated changes needed to rescue
34
the design of 4c2c04746932, we revert it in order to instead take the
35
route that that commit describes as "the most straightforward" fix,
36
where we add new MMU indexes EL30_0, EL30_3, EL30_3_PAN to correspond
37
to "Secure PL1&0 at PL0", "Secure PL1&0 at PL1", and "Secure PL1&0 at
38
PL1 with PAN".
39
40
This revert will re-expose the "spurious alignment faults in
41
Secure PL0" issue #2326; we'll fix it again in the next commit.
42
43
Cc: qemu-stable@nongnu.org
44
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
45
Tested-by: Thomas Huth <thuth@redhat.com>
46
Message-id: 20241101142845.1712482-2-peter.maydell@linaro.org
47
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
48
---
49
target/arm/cpu.h | 31 +++++++++++++------------------
50
target/arm/internals.h | 27 ++++-----------------------
51
target/arm/tcg/translate.h | 2 --
52
target/arm/helper.c | 34 +++++++++++-----------------------
53
target/arm/ptw.c | 6 +-----
54
target/arm/tcg/hflags.c | 4 ----
55
target/arm/tcg/translate-a64.c | 2 +-
56
target/arm/tcg/translate.c | 9 ++++-----
57
8 files changed, 34 insertions(+), 81 deletions(-)
58
59
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
60
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/cpu.h
21
--- a/target/sparc/helper.h
62
+++ b/target/arm/cpu.h
22
+++ b/target/sparc/helper.h
63
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
64
* + NonSecure PL1 & 0 stage 1
24
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
65
* + NonSecure PL1 & 0 stage 2
25
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128)
66
* + NonSecure PL2
26
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128)
67
- * + Secure PL1 & 0
27
-DEF_HELPER_FLAGS_2(flcmps, TCG_CALL_NO_RWG_SE, i32, f32, f32)
68
+ * + Secure PL0
28
-DEF_HELPER_FLAGS_2(flcmpd, TCG_CALL_NO_RWG_SE, i32, f64, f64)
69
+ * + Secure PL1
29
+DEF_HELPER_FLAGS_3(flcmps, TCG_CALL_NO_RWG_SE, i32, env, f32, f32)
70
* (reminder: for 32 bit EL3, Secure PL1 is *EL3*, not EL1.)
30
+DEF_HELPER_FLAGS_3(flcmpd, TCG_CALL_NO_RWG_SE, i32, env, f64, f64)
71
*
31
DEF_HELPER_2(raise_exception, noreturn, env, int)
72
* For QEMU, an mmu_idx is not quite the same as a translation regime because:
32
73
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
33
DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64)
74
* The only use of stage 2 translations is either as part of an s1+2
34
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
75
* lookup or when loading the descriptors during a stage 1 page table walk,
76
* and in both those cases we don't use the TLB.
77
- * 4. we want to be able to use the TLB for accesses done as part of a
78
+ * 4. we can also safely fold together the "32 bit EL3" and "64 bit EL3"
79
+ * translation regimes, because they map reasonably well to each other
80
+ * and they can't both be active at the same time.
81
+ * 5. we want to be able to use the TLB for accesses done as part of a
82
* stage1 page table walk, rather than having to walk the stage2 page
83
* table over and over.
84
- * 5. we need separate EL1/EL2 mmu_idx for handling the Privileged Access
85
+ * 6. we need separate EL1/EL2 mmu_idx for handling the Privileged Access
86
* Never (PAN) bit within PSTATE.
87
- * 6. we fold together most secure and non-secure regimes for A-profile,
88
+ * 7. we fold together most secure and non-secure regimes for A-profile,
89
* because there are no banked system registers for aarch64, so the
90
* process of switching between secure and non-secure is
91
* already heavyweight.
92
- * 7. we cannot fold together Stage 2 Secure and Stage 2 NonSecure,
93
+ * 8. we cannot fold together Stage 2 Secure and Stage 2 NonSecure,
94
* because both are in use simultaneously for Secure EL2.
95
*
96
* This gives us the following list of cases:
97
*
98
- * EL0 EL1&0 stage 1+2 (or AArch32 PL0 PL1&0 stage 1+2)
99
- * EL1 EL1&0 stage 1+2 (or AArch32 PL1 PL1&0 stage 1+2)
100
- * EL1 EL1&0 stage 1+2 +PAN (or AArch32 PL1 PL1&0 stage 1+2 +PAN)
101
+ * EL0 EL1&0 stage 1+2 (aka NS PL0)
102
+ * EL1 EL1&0 stage 1+2 (aka NS PL1)
103
+ * EL1 EL1&0 stage 1+2 +PAN
104
* EL0 EL2&0
105
* EL2 EL2&0
106
* EL2 EL2&0 +PAN
107
* EL2 (aka NS PL2)
108
- * EL3 (not used when EL3 is AArch32)
109
+ * EL3 (aka S PL1)
110
* Stage2 Secure
111
* Stage2 NonSecure
112
* plus one TLB per Physical address space: S, NS, Realm, Root
113
*
114
* for a total of 14 different mmu_idx.
115
*
116
- * Note that when EL3 is AArch32, the usage is potentially confusing
117
- * because the MMU indexes are named for their AArch64 use, so code
118
- * using the ARMMMUIdx_E10_1 might be at EL3, not EL1. This is because
119
- * Secure PL1 is always at EL3.
120
- *
121
* R profile CPUs have an MPU, but can use the same set of MMU indexes
122
* as A profile. They only need to distinguish EL0 and EL1 (and
123
* EL2 for cores like the Cortex-R52).
124
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 10, 1)
125
* This requires an SME trap from AArch32 mode when using NEON.
126
*/
127
FIELD(TBFLAG_A32, SME_TRAP_NONSTREAMING, 11, 1)
128
-/*
129
- * Indicates whether we are in the Secure PL1&0 translation regime
130
- */
131
-FIELD(TBFLAG_A32, S_PL1_0, 12, 1)
132
133
/*
134
* Bit usage when in AArch32 state, for M-profile only.
135
diff --git a/target/arm/internals.h b/target/arm/internals.h
136
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
137
--- a/target/arm/internals.h
36
--- a/target/sparc/fop_helper.c
138
+++ b/target/arm/internals.h
37
+++ b/target/sparc/fop_helper.c
139
@@ -XXX,XX +XXX,XX @@ FIELD(CNTHCTL, CNTPMASK, 19, 1)
38
@@ -XXX,XX +XXX,XX @@ uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
140
#define M_FAKE_FSR_NSC_EXEC 0xf /* NS executing in S&NSC memory */
39
return finish_fcmp(env, r, GETPC());
141
#define M_FAKE_FSR_SFAULT 0xe /* SecureFault INVTRAN, INVEP or AUVIOL */
142
143
-/**
144
- * arm_aa32_secure_pl1_0(): Return true if in Secure PL1&0 regime
145
- *
146
- * Return true if the CPU is in the Secure PL1&0 translation regime.
147
- * This requires that EL3 exists and is AArch32 and we are currently
148
- * Secure. If this is the case then the ARMMMUIdx_E10* apply and
149
- * mean we are in EL3, not EL1.
150
- */
151
-static inline bool arm_aa32_secure_pl1_0(CPUARMState *env)
152
-{
153
- return arm_feature(env, ARM_FEATURE_EL3) &&
154
- !arm_el_is_aa64(env, 3) && arm_is_secure(env);
155
-}
156
-
157
/**
158
* raise_exception: Raise the specified exception.
159
* Raise a guest exception with the specified value, syndrome register
160
@@ -XXX,XX +XXX,XX @@ static inline ARMMMUIdx core_to_aa64_mmu_idx(int mmu_idx)
161
return mmu_idx | ARM_MMU_IDX_A;
162
}
40
}
163
41
164
-/**
42
-uint32_t helper_flcmps(float32 src1, float32 src2)
165
- * Return the exception level we're running at if our current MMU index
43
+uint32_t helper_flcmps(CPUSPARCState *env, float32 src1, float32 src2)
166
- * is @mmu_idx. @s_pl1_0 should be true if this is the AArch32
44
{
167
- * Secure PL1&0 translation regime.
45
/*
168
- */
46
* FLCMP never raises an exception nor modifies any FSR fields.
169
-int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx, bool s_pl1_0);
47
* Perform the comparison with a dummy fp environment.
170
+int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx);
48
*/
171
49
- float_status discard = { };
172
/* Return the MMU index for a v7M CPU in the specified security state */
50
+ float_status discard = env->fp_status;
173
ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate);
51
FloatRelation r;
174
@@ -XXX,XX +XXX,XX @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
52
175
return 3;
53
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
176
case ARMMMUIdx_E10_0:
54
@@ -XXX,XX +XXX,XX @@ uint32_t helper_flcmps(float32 src1, float32 src2)
177
case ARMMMUIdx_Stage1_E0:
55
g_assert_not_reached();
178
- case ARMMMUIdx_E10_1:
56
}
179
- case ARMMMUIdx_E10_1_PAN:
57
180
+ return arm_el_is_aa64(env, 3) || !arm_is_secure_below_el3(env) ? 1 : 3;
58
-uint32_t helper_flcmpd(float64 src1, float64 src2)
181
case ARMMMUIdx_Stage1_E1:
59
+uint32_t helper_flcmpd(CPUSPARCState *env, float64 src1, float64 src2)
182
case ARMMMUIdx_Stage1_E1_PAN:
60
{
183
- return arm_el_is_aa64(env, 3) || !arm_is_secure_below_el3(env) ? 1 : 3;
61
- float_status discard = { };
184
+ case ARMMMUIdx_E10_1:
62
+ float_status discard = env->fp_status;
185
+ case ARMMMUIdx_E10_1_PAN:
63
FloatRelation r;
186
case ARMMMUIdx_MPrivNegPri:
64
187
case ARMMMUIdx_MUserNegPri:
65
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
188
case ARMMMUIdx_MPriv:
66
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
189
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
190
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
191
--- a/target/arm/tcg/translate.h
68
--- a/target/sparc/translate.c
192
+++ b/target/arm/tcg/translate.h
69
+++ b/target/sparc/translate.c
193
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
70
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a)
194
uint8_t gm_blocksize;
71
195
/* True if the current insn_start has been updated. */
72
src1 = gen_load_fpr_F(dc, a->rs1);
196
bool insn_start_updated;
73
src2 = gen_load_fpr_F(dc, a->rs2);
197
- /* True if this is the AArch32 Secure PL1&0 translation regime */
74
- gen_helper_flcmps(cpu_fcc[a->cc], src1, src2);
198
- bool s_pl1_0;
75
+ gen_helper_flcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
199
/* Bottom two bits of XScale c15_cpar coprocessor access control reg */
76
return advance_pc(dc);
200
int c15_cpar;
201
/* Offset from VNCR_EL2 when FEAT_NV2 redirects this reg to memory */
202
diff --git a/target/arm/helper.c b/target/arm/helper.c
203
index XXXXXXX..XXXXXXX 100644
204
--- a/target/arm/helper.c
205
+++ b/target/arm/helper.c
206
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
207
*/
208
format64 = arm_s1_regime_using_lpae_format(env, mmu_idx);
209
210
- if (arm_feature(env, ARM_FEATURE_EL2) && !arm_aa32_secure_pl1_0(env)) {
211
+ if (arm_feature(env, ARM_FEATURE_EL2)) {
212
if (mmu_idx == ARMMMUIdx_E10_0 ||
213
mmu_idx == ARMMMUIdx_E10_1 ||
214
mmu_idx == ARMMMUIdx_E10_1_PAN) {
215
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
216
case 0:
217
/* stage 1 current state PL1: ATS1CPR, ATS1CPW, ATS1CPRP, ATS1CPWP */
218
switch (el) {
219
+ case 3:
220
+ mmu_idx = ARMMMUIdx_E3;
221
+ break;
222
case 2:
223
g_assert(ss != ARMSS_Secure); /* ARMv8.4-SecEL2 is 64-bit only */
224
/* fall through */
225
case 1:
226
- case 3:
227
if (ri->crm == 9 && arm_pan_enabled(env)) {
228
mmu_idx = ARMMMUIdx_Stage1_E1_PAN;
229
} else {
230
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_interrupt(CPUState *cs)
231
232
uint64_t arm_sctlr(CPUARMState *env, int el)
233
{
234
- if (arm_aa32_secure_pl1_0(env)) {
235
- /* In Secure PL1&0 SCTLR_S is always controlling */
236
- el = 3;
237
- } else if (el == 0) {
238
- /* Only EL0 needs to be adjusted for EL1&0 or EL2&0. */
239
+ /* Only EL0 needs to be adjusted for EL1&0 or EL2&0. */
240
+ if (el == 0) {
241
ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, 0);
242
el = mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1;
243
}
244
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
245
return 0;
246
}
77
}
247
78
248
-/*
79
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
249
- * Return the exception level we're running at if this is our mmu_idx.
80
250
- * s_pl1_0 should be true if this is the AArch32 Secure PL1&0 translation
81
src1 = gen_load_fpr_D(dc, a->rs1);
251
- * regime.
82
src2 = gen_load_fpr_D(dc, a->rs2);
252
- */
83
- gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
253
-int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx, bool s_pl1_0)
84
+ gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
254
+/* Return the exception level we're running at if this is our mmu_idx */
85
return advance_pc(dc);
255
+int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
256
{
257
if (mmu_idx & ARM_MMU_IDX_M) {
258
return mmu_idx & ARM_MMU_IDX_M_PRIV;
259
@@ -XXX,XX +XXX,XX @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx, bool s_pl1_0)
260
return 0;
261
case ARMMMUIdx_E10_1:
262
case ARMMMUIdx_E10_1_PAN:
263
- return s_pl1_0 ? 3 : 1;
264
+ return 1;
265
case ARMMMUIdx_E2:
266
case ARMMMUIdx_E20_2:
267
case ARMMMUIdx_E20_2_PAN:
268
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
269
idx = ARMMMUIdx_E10_0;
270
}
271
break;
272
- case 3:
273
- /*
274
- * AArch64 EL3 has its own translation regime; AArch32 EL3
275
- * uses the Secure PL1&0 translation regime.
276
- */
277
- if (arm_el_is_aa64(env, 3)) {
278
- return ARMMMUIdx_E3;
279
- }
280
- /* fall through */
281
case 1:
282
if (arm_pan_enabled(env)) {
283
idx = ARMMMUIdx_E10_1_PAN;
284
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
285
idx = ARMMMUIdx_E2;
286
}
287
break;
288
+ case 3:
289
+ return ARMMMUIdx_E3;
290
default:
291
g_assert_not_reached();
292
}
293
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
294
index XXXXXXX..XXXXXXX 100644
295
--- a/target/arm/ptw.c
296
+++ b/target/arm/ptw.c
297
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, vaddr address,
298
case ARMMMUIdx_Stage1_E1:
299
case ARMMMUIdx_Stage1_E1_PAN:
300
case ARMMMUIdx_E2:
301
- if (arm_aa32_secure_pl1_0(env)) {
302
- ss = ARMSS_Secure;
303
- } else {
304
- ss = arm_security_space_below_el3(env);
305
- }
306
+ ss = arm_security_space_below_el3(env);
307
break;
308
case ARMMMUIdx_Stage2:
309
/*
310
diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c
311
index XXXXXXX..XXXXXXX 100644
312
--- a/target/arm/tcg/hflags.c
313
+++ b/target/arm/tcg/hflags.c
314
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
315
DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1);
316
}
317
318
- if (arm_aa32_secure_pl1_0(env)) {
319
- DP_TBFLAG_A32(flags, S_PL1_0, 1);
320
- }
321
-
322
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
323
}
86
}
324
87
325
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
326
index XXXXXXX..XXXXXXX 100644
327
--- a/target/arm/tcg/translate-a64.c
328
+++ b/target/arm/tcg/translate-a64.c
329
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
330
dc->tbii = EX_TBFLAG_A64(tb_flags, TBII);
331
dc->tbid = EX_TBFLAG_A64(tb_flags, TBID);
332
dc->tcma = EX_TBFLAG_A64(tb_flags, TCMA);
333
- dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx, false);
334
+ dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
335
#if !defined(CONFIG_USER_ONLY)
336
dc->user = (dc->current_el == 0);
337
#endif
338
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
339
index XXXXXXX..XXXXXXX 100644
340
--- a/target/arm/tcg/translate.c
341
+++ b/target/arm/tcg/translate.c
342
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
343
344
core_mmu_idx = EX_TBFLAG_ANY(tb_flags, MMUIDX);
345
dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
346
+ dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
347
+#if !defined(CONFIG_USER_ONLY)
348
+ dc->user = (dc->current_el == 0);
349
+#endif
350
dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
351
dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
352
dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
353
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
354
}
355
dc->sme_trap_nonstreaming =
356
EX_TBFLAG_A32(tb_flags, SME_TRAP_NONSTREAMING);
357
- dc->s_pl1_0 = EX_TBFLAG_A32(tb_flags, S_PL1_0);
358
}
359
- dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx, dc->s_pl1_0);
360
-#if !defined(CONFIG_USER_ONLY)
361
- dc->user = (dc->current_el == 0);
362
-#endif
363
dc->lse2 = false; /* applies only to aarch64 */
364
dc->cp_regs = cpu->cp_regs;
365
dc->features = env->features;
366
--
88
--
367
2.34.1
89
2.34.1
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
Our implementation of the indexed version of SVE SDOT/UDOT/USDOT got
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the calculation of the inner loop terminator wrong. Although we
3
correctly account for the element size when we calculate the
4
terminator for the first iteration:
5
intptr_t segend = MIN(16 / sizeof(TYPED), opr_sz_n);
6
we don't do that when we move it forward after the first inner loop
7
completes. The intention is that we process the vector in 128-bit
8
segments, which for a 64-bit element size should mean (1, 2), (3, 4),
9
(5, 6), etc. This bug meant that we would iterate (1, 2), (3, 4, 5,
10
6), (7, 8, 9, 10) etc and apply the wrong indexed element to some of
11
the operations, and also index off the end of the vector.
12
2
13
You don't see this bug if the vector length is small enough that we
3
Now that float_status has a bunch of fp parameters,
14
don't need to iterate the outer loop, i.e. if it is only 128 bits,
4
it is easier to copy an existing structure than create
15
or if it is the 64-bit special case from AA32/AA64 AdvSIMD. If the
5
one from scratch. Begin by copying the structure that
16
vector length is 256 bits then we calculate the right results for the
6
corresponds to the FPSR and make only the adjustments
17
elements in the vector but do index off the end of the vector. Vector
7
required for BFloat16 semantics.
18
lengths greater than 256 bits see wrong answers. The instructions
19
that produce 32-bit results behave correctly.
20
8
21
Fix the recalculation of 'segend' for subsequent iterations, and
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
22
restore a version of the comment that was lost in the refactor of
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
23
commit 7020ffd656a5 that explains why we only need to clamp segend to
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
opr_sz_n for the first iteration, not the later ones.
12
Message-id: 20241203203949.483774-2-richard.henderson@linaro.org
25
26
Cc: qemu-stable@nongnu.org
27
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2595
28
Fixes: 7020ffd656a5 ("target/arm: Macroize helper_gvec_{s,u}dot_idx_{b,h}")
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Message-id: 20241101185544.2130972-1-peter.maydell@linaro.org
32
---
14
---
33
target/arm/tcg/vec_helper.c | 9 ++++++++-
15
target/arm/tcg/vec_helper.c | 20 +++++++-------------
34
1 file changed, 8 insertions(+), 1 deletion(-)
16
1 file changed, 7 insertions(+), 13 deletions(-)
35
17
36
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
18
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
37
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/tcg/vec_helper.c
20
--- a/target/arm/tcg/vec_helper.c
39
+++ b/target/arm/tcg/vec_helper.c
21
+++ b/target/arm/tcg/vec_helper.c
40
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \
22
@@ -XXX,XX +XXX,XX @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp)
41
{ \
23
* no effect on AArch32 instructions.
42
intptr_t i = 0, opr_sz = simd_oprsz(desc); \
24
*/
43
intptr_t opr_sz_n = opr_sz / sizeof(TYPED); \
25
bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF;
44
+ /* \
26
- *statusp = (float_status){
45
+ * Special case: opr_sz == 8 from AA64/AA32 advsimd means the \
27
- .tininess_before_rounding = float_tininess_before_rounding,
46
+ * first iteration might not be a full 16 byte segment. But \
28
- .float_rounding_mode = float_round_to_odd_inf,
47
+ * for vector lengths beyond that this must be SVE and we know \
29
- .flush_to_zero = true,
48
+ * opr_sz is a multiple of 16, so we need not clamp segend \
30
- .flush_inputs_to_zero = true,
49
+ * to opr_sz_n when we advance it at the end of the loop. \
31
- .default_nan_mode = true,
50
+ */ \
32
- };
51
intptr_t segend = MIN(16 / sizeof(TYPED), opr_sz_n); \
33
+
52
intptr_t index = simd_data(desc); \
34
+ *statusp = env->vfp.fp_status;
53
TYPED *d = vd, *a = va; \
35
+ set_default_nan_mode(true, statusp);
54
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \
36
55
n[i * 4 + 2] * m2 + \
37
if (ebf) {
56
n[i * 4 + 3] * m3); \
38
- float_status *fpst = &env->vfp.fp_status;
57
} while (++i < segend); \
39
- set_flush_to_zero(get_flush_to_zero(fpst), statusp);
58
- segend = i + 4; \
40
- set_flush_inputs_to_zero(get_flush_inputs_to_zero(fpst), statusp);
59
+ segend = i + (16 / sizeof(TYPED)); \
41
- set_float_rounding_mode(get_float_rounding_mode(fpst), statusp);
60
} while (i < opr_sz_n); \
42
-
61
clear_tail(d, opr_sz, simd_maxsz(desc)); \
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;
62
}
53
}
54
63
--
55
--
64
2.34.1
56
2.34.1
57
58
diff view generated by jsdifflib
New patch
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)
1
6
7
Add a field to float_status to specify the default NaN value; fall
8
back to the old ifdef behaviour if these are not set.
9
10
The default NaN value is specified by setting a uint8_t to a
11
pattern corresponding to the sign and upper fraction parts of
12
the NaN; the lower bits of the fraction are set from bit 0 of
13
the pattern.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20241202131347.498124-35-peter.maydell@linaro.org
18
---
19
include/fpu/softfloat-helpers.h | 11 +++++++
20
include/fpu/softfloat-types.h | 10 ++++++
21
fpu/softfloat-specialize.c.inc | 55 ++++++++++++++++++++-------------
22
3 files changed, 54 insertions(+), 22 deletions(-)
23
24
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/fpu/softfloat-helpers.h
27
+++ b/include/fpu/softfloat-helpers.h
28
@@ -XXX,XX +XXX,XX @@ static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
29
status->float_infzeronan_rule = rule;
30
}
31
32
+static inline void set_float_default_nan_pattern(uint8_t dnan_pattern,
33
+ float_status *status)
34
+{
35
+ status->default_nan_pattern = dnan_pattern;
36
+}
37
+
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)
46
+{
47
+ return status->default_nan_pattern;
48
+}
49
+
50
static inline bool get_flush_to_zero(float_status *status)
51
{
52
return status->flush_to_zero;
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
134
+ }
135
+ assert(dnan_pattern != 0);
136
+
137
+ sign = dnan_pattern >> 7;
138
+ /*
139
+ * Place default_nan_pattern [6:0] into bits [62:56],
140
+ * and replecate bit [0] down into [55:0]
141
+ */
142
+ frac = deposit64(0, DECOMPOSED_BINARY_POINT - 7, 7, dnan_pattern);
143
+ frac = deposit64(frac, 0, DECOMPOSED_BINARY_POINT - 7, -(dnan_pattern & 1));
144
145
*p = (FloatParts64) {
146
.cls = float_class_qnan,
147
--
148
2.34.1
diff view generated by jsdifflib
1
Explicitly set a 2-NaN propagation rule in the softfloat tests. In
1
Set the default NaN pattern explicitly for the tests/fp code.
2
meson.build we put -DTARGET_ARM in fpcflags, and so we should select
3
here the Arm propagation rule of float_2nan_prop_s_ab.
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é <philmd@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241025141254.2141506-3-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-36-peter.maydell@linaro.org
9
---
6
---
10
tests/fp/fp-bench.c | 2 ++
7
tests/fp/fp-bench.c | 1 +
11
tests/fp/fp-test-log2.c | 1 +
8
tests/fp/fp-test-log2.c | 1 +
12
tests/fp/fp-test.c | 2 ++
9
tests/fp/fp-test.c | 1 +
13
3 files changed, 5 insertions(+)
10
3 files changed, 3 insertions(+)
14
11
15
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
12
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/fp/fp-bench.c
14
--- a/tests/fp/fp-bench.c
18
+++ b/tests/fp/fp-bench.c
15
+++ b/tests/fp/fp-bench.c
19
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
16
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
20
{
17
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
21
bench_func_t f;
18
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &soft_status);
22
19
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
23
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
20
+ set_float_default_nan_pattern(0b01000000, &soft_status);
24
+
21
25
f = bench_funcs[operation][precision];
22
f = bench_funcs[operation][precision];
26
g_assert(f);
23
g_assert(f);
27
f();
28
diff --git a/tests/fp/fp-test-log2.c b/tests/fp/fp-test-log2.c
24
diff --git a/tests/fp/fp-test-log2.c b/tests/fp/fp-test-log2.c
29
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
30
--- a/tests/fp/fp-test-log2.c
26
--- a/tests/fp/fp-test-log2.c
31
+++ b/tests/fp/fp-test-log2.c
27
+++ b/tests/fp/fp-test-log2.c
32
@@ -XXX,XX +XXX,XX @@ int main(int ac, char **av)
28
@@ -XXX,XX +XXX,XX @@ int main(int ac, char **av)
33
float_status qsf = {0};
34
int i;
29
int i;
35
30
36
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
31
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
32
+ set_float_default_nan_pattern(0b01000000, &qsf);
37
set_float_rounding_mode(float_round_nearest_even, &qsf);
33
set_float_rounding_mode(float_round_nearest_even, &qsf);
38
34
39
test.d = 0.0;
35
test.d = 0.0;
40
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
36
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
41
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
42
--- a/tests/fp/fp-test.c
38
--- a/tests/fp/fp-test.c
43
+++ b/tests/fp/fp-test.c
39
+++ b/tests/fp/fp-test.c
44
@@ -XXX,XX +XXX,XX @@ void run_test(void)
40
@@ -XXX,XX +XXX,XX @@ void run_test(void)
45
{
41
*/
46
unsigned int i;
42
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
47
43
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &qsf);
48
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
44
+ set_float_default_nan_pattern(0b01000000, &qsf);
49
+
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
46
50
genCases_setLevel(test_level);
47
genCases_setLevel(test_level);
51
verCases_maxErrorCount = n_max_errors;
52
53
--
48
--
54
2.34.1
49
2.34.1
55
56
diff view generated by jsdifflib
1
Although the floating point rounding mode for Microblaze is always
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
nearest-even, we cannot set it just once in the CPU initfn. This is
2
parts64_default_nan().
3
because env->fp_status is in the part of the CPU state struct that is
4
zeroed on reset.
5
6
Move the call to set_float_rounding_mode() into the reset fn.
7
8
(This had no guest-visible effects because it happens that the
9
float_round_nearest_even enum value is 0, so when the struct was
10
zeroed it didn't corrupt the setting.)
11
3
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20241025141254.2141506-18-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-37-peter.maydell@linaro.org
15
---
7
---
16
target/microblaze/cpu.c | 5 ++---
8
target/microblaze/cpu.c | 2 ++
17
1 file changed, 2 insertions(+), 3 deletions(-)
9
fpu/softfloat-specialize.c.inc | 3 +--
10
2 files changed, 3 insertions(+), 2 deletions(-)
18
11
19
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
12
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
20
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
21
--- a/target/microblaze/cpu.c
14
--- a/target/microblaze/cpu.c
22
+++ b/target/microblaze/cpu.c
15
+++ b/target/microblaze/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_reset_hold(Object *obj, ResetType type)
16
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_reset_hold(Object *obj, ResetType type)
24
17
* this architecture.
25
env->pc = cpu->cfg.base_vectors;
18
*/
26
19
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
27
+ set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
20
+ /* Default NaN: sign bit set, most significant frac bit set */
28
+
21
+ set_float_default_nan_pattern(0b11000000, &env->fp_status);
22
29
#if defined(CONFIG_USER_ONLY)
23
#if defined(CONFIG_USER_ONLY)
30
/* start in user mode with interrupts enabled. */
24
/* start in user mode with interrupts enabled. */
31
mb_cpu_write_msr(env, MSR_EE | MSR_IE | MSR_VM | MSR_UM);
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
26
index XXXXXXX..XXXXXXX 100644
33
static void mb_cpu_initfn(Object *obj)
27
--- a/fpu/softfloat-specialize.c.inc
34
{
28
+++ b/fpu/softfloat-specialize.c.inc
35
MicroBlazeCPU *cpu = MICROBLAZE_CPU(obj);
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
36
- CPUMBState *env = &cpu->env;
30
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
37
31
/* Sign bit clear, all frac bits set */
38
gdb_register_coprocessor(CPU(cpu), mb_cpu_gdb_read_stack_protect,
32
dnan_pattern = 0b01111111;
39
mb_cpu_gdb_write_stack_protect,
33
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
40
gdb_find_static_feature("microblaze-stack-protect.xml"),
34
- || defined(TARGET_MICROBLAZE)
41
0);
35
+#elif defined(TARGET_I386) || defined(TARGET_X86_64)
42
36
/* Sign bit set, most significant frac bit set */
43
- set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
37
dnan_pattern = 0b11000000;
44
-
38
#elif defined(TARGET_HPPA)
45
#ifndef CONFIG_USER_ONLY
46
/* Inbound IRQ and FIR lines */
47
qdev_init_gpio_in(DEVICE(cpu), microblaze_cpu_set_irq, 2);
48
--
39
--
49
2.34.1
40
2.34.1
diff view generated by jsdifflib
1
Set the NaN propagation rule explicitly for the float_status words
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
used in the x86 target.
2
parts64_default_nan().
3
4
This is a no-behaviour-change commit, so we retain the existing
5
behaviour of using the x87-style "prefer QNaN over SNaN, then prefer
6
the NaN with the larger significand" for MMX and SSE. This is
7
however not the documented hardware behaviour, so we leave a TODO
8
note about what we should be doing instead.
9
3
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241025141254.2141506-16-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-38-peter.maydell@linaro.org
13
---
7
---
14
target/i386/cpu.h | 3 +++
8
target/i386/tcg/fpu_helper.c | 4 ++++
15
target/i386/cpu.c | 4 ++++
9
fpu/softfloat-specialize.c.inc | 3 ---
16
target/i386/tcg/fpu_helper.c | 40 ++++++++++++++++++++++++++++++++++
10
2 files changed, 4 insertions(+), 3 deletions(-)
17
fpu/softfloat-specialize.c.inc | 3 ++-
18
4 files changed, 49 insertions(+), 1 deletion(-)
19
11
20
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/i386/cpu.h
23
+++ b/target/i386/cpu.h
24
@@ -XXX,XX +XXX,XX @@ static inline bool cpu_vmx_maybe_enabled(CPUX86State *env)
25
int get_pg_mode(CPUX86State *env);
26
27
/* fpu_helper.c */
28
+
29
+/* Set all non-runtime-variable float_status fields to x86 handling */
30
+void cpu_init_fp_statuses(CPUX86State *env);
31
void update_fp_status(CPUX86State *env);
32
void update_mxcsr_status(CPUX86State *env);
33
void update_mxcsr_from_sse_status(CPUX86State *env);
34
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/i386/cpu.c
37
+++ b/target/i386/cpu.c
38
@@ -XXX,XX +XXX,XX @@ static void x86_cpu_reset_hold(Object *obj, ResetType type)
39
40
memset(env, 0, offsetof(CPUX86State, end_reset_fields));
41
42
+ if (tcg_enabled()) {
43
+ cpu_init_fp_statuses(env);
44
+ }
45
+
46
env->old_exception = -1;
47
48
/* init to reset state */
49
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
12
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
50
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
51
--- a/target/i386/tcg/fpu_helper.c
14
--- a/target/i386/tcg/fpu_helper.c
52
+++ b/target/i386/tcg/fpu_helper.c
15
+++ b/target/i386/tcg/fpu_helper.c
53
@@ -XXX,XX +XXX,XX @@ static void fpu_set_exception(CPUX86State *env, int mask)
16
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
54
}
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);
55
}
24
}
56
25
57
+void cpu_init_fp_statuses(CPUX86State *env)
58
+{
59
+ /*
60
+ * Initialise the non-runtime-varying fields of the various
61
+ * float_status words to x86 behaviour. This must be called at
62
+ * CPU reset because the float_status words are in the
63
+ * "zeroed on reset" portion of the CPU state struct.
64
+ * Fields in float_status that vary under guest control are set
65
+ * via the codepath for setting that register, eg cpu_set_fpuc().
66
+ */
67
+ /*
68
+ * Use x87 NaN propagation rules:
69
+ * SNaN + QNaN => return the QNaN
70
+ * two SNaNs => return the one with the larger significand, silenced
71
+ * two QNaNs => return the one with the larger significand
72
+ * SNaN and a non-NaN => return the SNaN, silenced
73
+ * QNaN and a non-NaN => return the QNaN
74
+ *
75
+ * If we get down to comparing significands and they are the same,
76
+ * return the NaN with the positive sign bit (if any).
77
+ */
78
+ set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
79
+ /*
80
+ * TODO: These are incorrect: the x86 Software Developer's Manual vol 1
81
+ * section 4.8.3.5 "Operating on SNaNs and QNaNs" says that the
82
+ * "larger significand" behaviour is only used for x87 FPU operations.
83
+ * For SSE the required behaviour is to always return the first NaN,
84
+ * which is float_2nan_prop_ab.
85
+ *
86
+ * mmx_status is used only for the AMD 3DNow! instructions, which
87
+ * are documented in the "3DNow! Technology Manual" as not supporting
88
+ * NaNs or infinities as inputs. The result of passing two NaNs is
89
+ * documented as "undefined", so we can do what we choose.
90
+ * (Strictly there is some behaviour we don't implement correctly
91
+ * for these "unsupported" NaN and Inf values, like "NaN * 0 == 0".)
92
+ */
93
+ set_float_2nan_prop_rule(float_2nan_prop_x87, &env->mmx_status);
94
+ set_float_2nan_prop_rule(float_2nan_prop_x87, &env->sse_status);
95
+}
96
+
97
static inline uint8_t save_exception_flags(CPUX86State *env)
26
static inline uint8_t save_exception_flags(CPUX86State *env)
98
{
99
uint8_t old_flags = get_float_exception_flags(&env->fp_status);
100
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
101
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
102
--- a/fpu/softfloat-specialize.c.inc
29
--- a/fpu/softfloat-specialize.c.inc
103
+++ b/fpu/softfloat-specialize.c.inc
30
+++ b/fpu/softfloat-specialize.c.inc
104
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
31
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
105
|| defined(TARGET_TRICORE) || defined(TARGET_ARM) || defined(TARGET_MIPS) \
32
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
106
|| defined(TARGET_LOONGARCH64) || defined(TARGET_HPPA) \
33
/* Sign bit clear, all frac bits set */
107
|| defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_M68K) \
34
dnan_pattern = 0b01111111;
108
- || defined(TARGET_SPARC) || defined(TARGET_XTENSA)
35
-#elif defined(TARGET_I386) || defined(TARGET_X86_64)
109
+ || defined(TARGET_SPARC) || defined(TARGET_XTENSA) \
36
- /* Sign bit set, most significant frac bit set */
110
+ || defined(TARGET_I386)
37
- dnan_pattern = 0b11000000;
111
g_assert_not_reached();
38
#elif defined(TARGET_HPPA)
112
#else
39
/* Sign bit clear, msb-1 frac bit set */
113
rule = float_2nan_prop_x87;
40
dnan_pattern = 0b00100000;
114
--
41
--
115
2.34.1
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
1
Set the NaN propagation rule explicitly for the float_status word
1
Set the default NaN pattern explicitly for the alpha target.
2
used in this target.
3
4
This is a no-behaviour-change commit, so we retain the existing
5
behaviour of x87-style pick-largest-significand NaN propagation.
6
This is however not the architecturally correct handling, so we leave
7
a TODO note to that effect.
8
9
We also leave a TODO note pointing out that all this code in the cpu
10
initfn (including the existing setting up of env->flags and the FPCR)
11
should be in a currently non-existent CPU reset function.
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: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20241025141254.2141506-17-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-40-peter.maydell@linaro.org
17
---
6
---
18
target/alpha/cpu.c | 11 +++++++++++
7
target/alpha/cpu.c | 2 ++
19
fpu/softfloat-specialize.c.inc | 2 +-
8
1 file changed, 2 insertions(+)
20
2 files changed, 12 insertions(+), 1 deletion(-)
21
9
22
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
10
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
23
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
24
--- a/target/alpha/cpu.c
12
--- a/target/alpha/cpu.c
25
+++ b/target/alpha/cpu.c
13
+++ b/target/alpha/cpu.c
26
@@ -XXX,XX +XXX,XX @@
27
#include "qemu/qemu-print.h"
28
#include "cpu.h"
29
#include "exec/exec-all.h"
30
+#include "fpu/softfloat.h"
31
32
33
static void alpha_cpu_set_pc(CPUState *cs, vaddr value)
34
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_initfn(Object *obj)
14
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_initfn(Object *obj)
35
{
15
* operand in Fa. That is float_2nan_prop_ba.
36
CPUAlphaState *env = cpu_env(CPU(obj));
16
*/
37
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
38
+ /* TODO all this should be done in reset, not init */
18
+ /* Default NaN: sign bit clear, msb frac bit set */
39
+
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
40
env->lock_addr = -1;
41
+
42
+ /*
43
+ * TODO: this is incorrect. The Alpha Architecture Handbook version 4
44
+ * describes NaN propagation in section 4.7.10.4. We should prefer
45
+ * the operand in Fb (whether it is a QNaN or an SNaN), then the
46
+ * operand in Fa. That is float_2nan_prop_ba.
47
+ */
48
+ set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
49
#if defined(CONFIG_USER_ONLY)
20
#if defined(CONFIG_USER_ONLY)
50
env->flags = ENV_FLAG_PS_USER | ENV_FLAG_FEN;
21
env->flags = ENV_FLAG_PS_USER | ENV_FLAG_FEN;
51
cpu_alpha_store_fpcr(env, (uint64_t)(FPCR_INVD | FPCR_DZED | FPCR_OVFD
22
cpu_alpha_store_fpcr(env, (uint64_t)(FPCR_INVD | FPCR_DZED | FPCR_OVFD
52
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
53
index XXXXXXX..XXXXXXX 100644
54
--- a/fpu/softfloat-specialize.c.inc
55
+++ b/fpu/softfloat-specialize.c.inc
56
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
57
|| defined(TARGET_LOONGARCH64) || defined(TARGET_HPPA) \
58
|| defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_M68K) \
59
|| defined(TARGET_SPARC) || defined(TARGET_XTENSA) \
60
- || defined(TARGET_I386)
61
+ || defined(TARGET_I386) || defined(TARGET_ALPHA)
62
g_assert_not_reached();
63
#else
64
rule = float_2nan_prop_x87;
65
--
23
--
66
2.34.1
24
2.34.1
67
68
diff view generated by jsdifflib
1
Set the 2-NaN propagation rule explicitly in the float_status words
1
Set the default NaN pattern explicitly for the arm target.
2
we use. We wrap this plus the pre-existing setting of the
2
This includes setting it for the old linux-user nwfpe emulation.
3
tininess-before-rounding flag in a new function
3
For nwfpe, our default doesn't match the real kernel, but we
4
arm_set_default_fp_behaviours() to avoid repetition, since we have a
4
avoid making a behaviour change in this commit.
5
lot of float_status words at this point.
6
7
The situation with FPA11 emulation in linux-user is a little odd, and
8
arguably "correct" behaviour there would be to exactly match a real
9
Linux kernel's FPA11 emulation. However FPA11 emulation is
10
essentially dead at this point and so it seems better to continue
11
with QEMU's current behaviour and leave a comment describing the
12
situation.
13
5
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20241025141254.2141506-4-peter.maydell@linaro.org
8
Message-id: 20241202131347.498124-41-peter.maydell@linaro.org
17
---
9
---
18
linux-user/arm/nwfpe/fpa11.c | 18 ++++++++++++++++++
10
linux-user/arm/nwfpe/fpa11.c | 5 +++++
19
target/arm/cpu.c | 25 +++++++++++++++++--------
11
target/arm/cpu.c | 2 ++
20
fpu/softfloat-specialize.c.inc | 13 ++-----------
12
2 files changed, 7 insertions(+)
21
3 files changed, 37 insertions(+), 19 deletions(-)
22
13
23
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
14
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
24
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
25
--- a/linux-user/arm/nwfpe/fpa11.c
16
--- a/linux-user/arm/nwfpe/fpa11.c
26
+++ b/linux-user/arm/nwfpe/fpa11.c
17
+++ b/linux-user/arm/nwfpe/fpa11.c
27
@@ -XXX,XX +XXX,XX @@ void resetFPA11(void)
18
@@ -XXX,XX +XXX,XX @@ void resetFPA11(void)
28
#ifdef MAINTAIN_FPCR
19
* this late date.
29
fpa11->fpcr = MASK_RESET;
20
*/
30
#endif
21
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &fpa11->fp_status);
31
+
32
+ /*
22
+ /*
33
+ * Real FPA11 hardware does not handle NaNs, but always takes an
23
+ * Use the same default NaN value as Arm VFP. This doesn't match
34
+ * exception for them to be software-emulated (ARM7500FE datasheet
24
+ * the Linux kernel's nwfpe emulation, which uses an all-1s value.
35
+ * section 10.4). There is no documented architectural requirement
36
+ * for NaN propagation rules and it will depend on how the OS
37
+ * level software emulation opted to do it. We here use prop_s_ab
38
+ * which matches the later VFP hardware choice and how QEMU's
39
+ * fpa11 emulation has worked in the past. The real Linux kernel
40
+ * does something slightly different: arch/arm/nwfpe/softfloat-specialize
41
+ * propagateFloat64NaN() has the curious behaviour that it prefers
42
+ * the QNaN over the SNaN, but if both are QNaN it picks A and
43
+ * if both are SNaN it picks B. In theory we could add this as
44
+ * a NaN propagation rule, but in practice FPA11 emulation is so
45
+ * close to totally dead that it's not worth trying to match it at
46
+ * this late date.
47
+ */
25
+ */
48
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, &fpa11->fp_status);
26
+ set_float_default_nan_pattern(0b01000000, &fpa11->fp_status);
49
}
27
}
50
28
51
void SetRoundingMode(const unsigned int opcode)
29
void SetRoundingMode(const unsigned int opcode)
52
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
53
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/cpu.c
32
--- a/target/arm/cpu.c
55
+++ b/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
56
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
34
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
57
QLIST_INSERT_HEAD(&cpu->el_change_hooks, entry, node);
35
* the pseudocode function the arguments are in the order c, a, b.
36
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
37
* and the input NaN if it is signalling
38
+ * * Default NaN has sign bit clear, msb frac bit set
39
*/
40
static void arm_set_default_fp_behaviours(float_status *s)
41
{
42
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
44
set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
46
+ set_float_default_nan_pattern(0b01000000, s);
58
}
47
}
59
48
60
+/*
61
+ * Set the float_status behaviour to match the Arm defaults:
62
+ * * tininess-before-rounding
63
+ * * 2-input NaN propagation prefers SNaN over QNaN, and then
64
+ * operand A over operand B (see FPProcessNaNs() pseudocode)
65
+ */
66
+static void arm_set_default_fp_behaviours(float_status *s)
67
+{
68
+ set_float_detect_tininess(float_tininess_before_rounding, s);
69
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
70
+}
71
+
72
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
49
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
73
{
74
/* Reset a single ARMCPRegInfo register */
75
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset_hold(Object *obj, ResetType type)
76
set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
77
set_default_nan_mode(1, &env->vfp.standard_fp_status);
78
set_default_nan_mode(1, &env->vfp.standard_fp_status_f16);
79
- set_float_detect_tininess(float_tininess_before_rounding,
80
- &env->vfp.fp_status);
81
- set_float_detect_tininess(float_tininess_before_rounding,
82
- &env->vfp.standard_fp_status);
83
- set_float_detect_tininess(float_tininess_before_rounding,
84
- &env->vfp.fp_status_f16);
85
- set_float_detect_tininess(float_tininess_before_rounding,
86
- &env->vfp.standard_fp_status_f16);
87
+ arm_set_default_fp_behaviours(&env->vfp.fp_status);
88
+ arm_set_default_fp_behaviours(&env->vfp.standard_fp_status);
89
+ arm_set_default_fp_behaviours(&env->vfp.fp_status_f16);
90
+ arm_set_default_fp_behaviours(&env->vfp.standard_fp_status_f16);
91
+
92
#ifndef CONFIG_USER_ONLY
93
if (kvm_enabled()) {
94
kvm_arm_reset_vcpu(cpu);
95
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
96
index XXXXXXX..XXXXXXX 100644
97
--- a/fpu/softfloat-specialize.c.inc
98
+++ b/fpu/softfloat-specialize.c.inc
99
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
100
/* target didn't set the rule: fall back to old ifdef choices */
101
#if defined(TARGET_AVR) || defined(TARGET_HEXAGON) \
102
|| defined(TARGET_RISCV) || defined(TARGET_SH4) \
103
- || defined(TARGET_TRICORE)
104
+ || defined(TARGET_TRICORE) || defined(TARGET_ARM)
105
g_assert_not_reached();
106
-#elif defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_HPPA) || \
107
+#elif defined(TARGET_MIPS) || defined(TARGET_HPPA) || \
108
defined(TARGET_LOONGARCH64) || defined(TARGET_S390X)
109
- /*
110
- * ARM mandated NaN propagation rules (see FPProcessNaNs()), take
111
- * the first of:
112
- * 1. A if it is signaling
113
- * 2. B if it is signaling
114
- * 3. A (quiet)
115
- * 4. B (quiet)
116
- * A signaling NaN is always quietened before returning it.
117
- */
118
/*
119
* According to MIPS specifications, if one of the two operands is
120
* a sNaN, a new qNaN has to be generated. This is done in
121
--
50
--
122
2.34.1
51
2.34.1
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
1
Explicitly set the 2-NaN propagation rule on env->fp_status
1
Set the default NaN pattern explicitly for m68k.
2
and on the temporary fp_status that we use in frem (since
3
we pass that to a division operation function).
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: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Message-id: 20241202131347.498124-43-peter.maydell@linaro.org
8
---
6
---
9
target/m68k/cpu.c | 16 ++++++++++++++++
7
target/m68k/cpu.c | 2 ++
10
target/m68k/fpu_helper.c | 1 +
8
fpu/softfloat-specialize.c.inc | 2 +-
11
fpu/softfloat-specialize.c.inc | 19 +------------------
9
2 files changed, 3 insertions(+), 1 deletion(-)
12
3 files changed, 18 insertions(+), 18 deletions(-)
13
10
14
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
11
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/target/m68k/cpu.c
13
--- a/target/m68k/cpu.c
17
+++ b/target/m68k/cpu.c
14
+++ b/target/m68k/cpu.c
18
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
15
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
19
env->fregs[i].d = nan;
16
* preceding paragraph for nonsignaling NaNs.
20
}
17
*/
21
cpu_m68k_set_fpcr(env, 0);
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
22
+ /*
19
+ /* Default NaN: sign bit clear, all frac bits set */
23
+ * M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
20
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
24
+ * 3.4 FLOATING-POINT INSTRUCTION DETAILS
21
25
+ * If either operand, but not both operands, of an operation is a
22
nan = floatx80_default_nan(&env->fp_status);
26
+ * nonsignaling NaN, then that NaN is returned as the result. If both
23
for (i = 0; i < 8; i++) {
27
+ * operands are nonsignaling NaNs, then the destination operand
28
+ * nonsignaling NaN is returned as the result.
29
+ * If either operand to an operation is a signaling NaN (SNaN), then the
30
+ * SNaN bit is set in the FPSR EXC byte. If the SNaN exception enable bit
31
+ * is set in the FPCR ENABLE byte, then the exception is taken and the
32
+ * destination is not modified. If the SNaN exception enable bit is not
33
+ * set, setting the SNaN bit in the operand to a one converts the SNaN to
34
+ * a nonsignaling NaN. The operation then continues as described in the
35
+ * preceding paragraph for nonsignaling NaNs.
36
+ */
37
+ set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
38
env->fpsr = 0;
39
40
/* TODO: We should set PC from the interrupt vector. */
41
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/target/m68k/fpu_helper.c
44
+++ b/target/m68k/fpu_helper.c
45
@@ -XXX,XX +XXX,XX @@ void HELPER(frem)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
46
int sign;
47
48
/* Calculate quotient directly using round to nearest mode */
49
+ set_float_2nan_prop_rule(float_2nan_prop_ab, &fp_status);
50
set_float_rounding_mode(float_round_nearest_even, &fp_status);
51
set_floatx80_rounding_precision(
52
get_floatx80_rounding_precision(&env->fp_status), &fp_status);
53
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
54
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
55
--- a/fpu/softfloat-specialize.c.inc
26
--- a/fpu/softfloat-specialize.c.inc
56
+++ b/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
57
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
28
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
58
|| defined(TARGET_RISCV) || defined(TARGET_SH4) \
29
uint8_t dnan_pattern = status->default_nan_pattern;
59
|| defined(TARGET_TRICORE) || defined(TARGET_ARM) || defined(TARGET_MIPS) \
30
60
|| defined(TARGET_LOONGARCH64) || defined(TARGET_HPPA) \
31
if (dnan_pattern == 0) {
61
- || defined(TARGET_S390X) || defined(TARGET_PPC)
32
-#if defined(TARGET_SPARC) || defined(TARGET_M68K)
62
+ || defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_M68K)
33
+#if defined(TARGET_SPARC)
63
g_assert_not_reached();
34
/* Sign bit clear, all frac bits set */
64
-#elif defined(TARGET_M68K)
35
dnan_pattern = 0b01111111;
65
- /*
36
#elif defined(TARGET_HEXAGON)
66
- * M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
67
- * 3.4 FLOATING-POINT INSTRUCTION DETAILS
68
- * If either operand, but not both operands, of an operation is a
69
- * nonsignaling NaN, then that NaN is returned as the result. If both
70
- * operands are nonsignaling NaNs, then the destination operand
71
- * nonsignaling NaN is returned as the result.
72
- * If either operand to an operation is a signaling NaN (SNaN), then the
73
- * SNaN bit is set in the FPSR EXC byte. If the SNaN exception enable bit
74
- * is set in the FPCR ENABLE byte, then the exception is taken and the
75
- * destination is not modified. If the SNaN exception enable bit is not
76
- * set, setting the SNaN bit in the operand to a one converts the SNaN to
77
- * a nonsignaling NaN. The operation then continues as described in the
78
- * preceding paragraph for nonsignaling NaNs.
79
- */
80
- rule = float_2nan_prop_ab;
81
#elif defined(TARGET_SPARC)
82
/* Prefer SNaN over QNaN, order B then A. */
83
rule = float_2nan_prop_s_ba;
84
--
37
--
85
2.34.1
38
2.34.1
86
87
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
1
Set the NaN propagation rule explicitly for the float_status word
1
Set the default NaN pattern explicitly for openrisc.
2
used in the openrisc target.
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: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241025141254.2141506-20-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-45-peter.maydell@linaro.org
8
---
6
---
9
target/openrisc/cpu.c | 6 ++++++
7
target/openrisc/cpu.c | 2 ++
10
fpu/softfloat-specialize.c.inc | 2 +-
8
1 file changed, 2 insertions(+)
11
2 files changed, 7 insertions(+), 1 deletion(-)
12
9
13
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
10
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/target/openrisc/cpu.c
12
--- a/target/openrisc/cpu.c
16
+++ b/target/openrisc/cpu.c
13
+++ b/target/openrisc/cpu.c
17
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_reset_hold(Object *obj, ResetType type)
14
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_reset_hold(Object *obj, ResetType type)
18
15
*/
19
set_float_detect_tininess(float_tininess_before_rounding,
16
set_float_2nan_prop_rule(float_2nan_prop_x87, &cpu->env.fp_status);
20
&cpu->env.fp_status);
17
21
+ /*
18
+ /* Default NaN: sign bit clear, frac msb set */
22
+ * TODO: this is probably not the correct NaN propagation rule for
19
+ set_float_default_nan_pattern(0b01000000, &cpu->env.fp_status);
23
+ * this architecture.
24
+ */
25
+ set_float_2nan_prop_rule(float_2nan_prop_x87, &cpu->env.fp_status);
26
+
27
20
28
#ifndef CONFIG_USER_ONLY
21
#ifndef CONFIG_USER_ONLY
29
cpu->env.picmr = 0x00000000;
22
cpu->env.picmr = 0x00000000;
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 pickNaN(FloatClass a_cls, FloatClass b_cls,
35
|| defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_M68K) \
36
|| defined(TARGET_SPARC) || defined(TARGET_XTENSA) \
37
|| defined(TARGET_I386) || defined(TARGET_ALPHA) \
38
- || defined(TARGET_MICROBLAZE)
39
+ || defined(TARGET_MICROBLAZE) || defined(TARGET_OPENRISC)
40
g_assert_not_reached();
41
#else
42
rule = float_2nan_prop_x87;
43
--
23
--
44
2.34.1
24
2.34.1
45
46
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
1
Set the NaN propagation rule explicitly for the float_status word
1
Set the default NaN pattern explicitly for rx.
2
used in the rx target.
3
4
This not the architecturally correct behaviour, but since this is a
5
no-behaviour-change patch, we leave a TODO note to that effect.
6
2
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241025141254.2141506-21-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-48-peter.maydell@linaro.org
11
---
6
---
12
target/rx/cpu.c | 7 +++++++
7
target/rx/cpu.c | 2 ++
13
fpu/softfloat-specialize.c.inc | 3 ++-
8
1 file changed, 2 insertions(+)
14
2 files changed, 9 insertions(+), 1 deletion(-)
15
9
16
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
10
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
17
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
18
--- a/target/rx/cpu.c
12
--- a/target/rx/cpu.c
19
+++ b/target/rx/cpu.c
13
+++ b/target/rx/cpu.c
20
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_reset_hold(Object *obj, ResetType type)
14
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_reset_hold(Object *obj, ResetType type)
21
env->fpsw = 0;
15
* then prefer dest over source", which is float_2nan_prop_s_ab.
22
set_flush_to_zero(1, &env->fp_status);
16
*/
23
set_flush_inputs_to_zero(1, &env->fp_status);
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
24
+ /*
18
+ /* Default NaN value: sign bit clear, set frac msb */
25
+ * TODO: this is not the correct NaN propagation rule for this
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
26
+ * architecture. The "RX Family User's Manual: Software" table 1.6
27
+ * defines the propagation rules as "prefer SNaN over QNaN;
28
+ * then prefer dest over source", which is float_2nan_prop_s_ab.
29
+ */
30
+ set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
31
}
20
}
32
21
33
static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
22
static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
34
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
35
index XXXXXXX..XXXXXXX 100644
36
--- a/fpu/softfloat-specialize.c.inc
37
+++ b/fpu/softfloat-specialize.c.inc
38
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
39
|| defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_M68K) \
40
|| defined(TARGET_SPARC) || defined(TARGET_XTENSA) \
41
|| defined(TARGET_I386) || defined(TARGET_ALPHA) \
42
- || defined(TARGET_MICROBLAZE) || defined(TARGET_OPENRISC)
43
+ || defined(TARGET_MICROBLAZE) || defined(TARGET_OPENRISC) \
44
+ || defined(TARGET_RX)
45
g_assert_not_reached();
46
#else
47
rule = float_2nan_prop_x87;
48
--
23
--
49
2.34.1
24
2.34.1
50
51
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
1
Currently we call cpu_put_fsr(0) in sparc_cpu_realizefn(), which
1
Set the default NaN pattern explicitly for SPARC, and remove
2
initializes various fields in the CPU struct:
2
the ifdef from parts64_default_nan.
3
* fsr_cexc_ftt
4
* fcc[]
5
* fsr_qne
6
* fsr
7
It also sets the rounding mode in env->fp_status.
8
9
This is largely pointless, because when we later reset the CPU
10
this will zero out all the fields up until the "end_reset_fields"
11
label, which includes all of these (but not fp_status!)
12
13
Move the cpu_put_fsr(env, 0) call to reset, because that expresses
14
the logical requirement: we want to reset FSR to 0 on every reset.
15
This isn't a behaviour change because the fields are all zero anyway.
16
3
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
19
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20241025141254.2141506-12-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-50-peter.maydell@linaro.org
22
---
7
---
23
target/sparc/cpu.c | 2 +-
8
target/sparc/cpu.c | 2 ++
24
1 file changed, 1 insertion(+), 1 deletion(-)
9
fpu/softfloat-specialize.c.inc | 5 +----
10
2 files changed, 3 insertions(+), 4 deletions(-)
25
11
26
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
27
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
28
--- a/target/sparc/cpu.c
14
--- a/target/sparc/cpu.c
29
+++ b/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
30
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_reset_hold(Object *obj, ResetType type)
31
env->npc = env->pc + 4;
32
#endif
33
env->cache_control = 0;
34
+ cpu_put_fsr(env, 0);
35
}
36
37
#ifndef CONFIG_USER_ONLY
38
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
39
env->version |= env->def.maxtl << 8;
17
set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
40
env->version |= env->def.nwindows - 1;
18
/* For inf * 0 + NaN, return the input NaN */
41
#endif
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
42
- cpu_put_fsr(env, 0);
20
+ /* Default NaN value: sign bit clear, all frac bits set */
21
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
43
22
44
cpu_exec_realizefn(cs, &local_err);
23
cpu_exec_realizefn(cs, &local_err);
45
if (local_err != NULL) {
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
46
--
41
--
47
2.34.1
42
2.34.1
48
49
diff view generated by jsdifflib
1
In xtensa we currently call set_use_first_nan() in a lot of
1
Set the default NaN pattern explicitly for xtensa.
2
places where we want to switch the NaN-propagation handling.
3
We're about to change the softfloat API we use to do that,
4
so start by factoring all the calls out into a single
5
xtensa_use_first_nan() function.
6
7
The bulk of this change was done with
8
sed -i -e 's/set_use_first_nan(\([^,]*\),[^)]*)/xtensa_use_first_nan(env, \1)/' target/xtensa/fpu_helper.c
9
2
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Max Filippov <jcmvbkbc@gmail.com>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20241025141254.2141506-14-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-51-peter.maydell@linaro.org
14
---
6
---
15
target/xtensa/cpu.h | 6 ++++++
7
target/xtensa/cpu.c | 2 ++
16
target/xtensa/cpu.c | 2 +-
8
1 file changed, 2 insertions(+)
17
target/xtensa/fpu_helper.c | 33 +++++++++++++++++++--------------
18
3 files changed, 26 insertions(+), 15 deletions(-)
19
9
20
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/xtensa/cpu.h
23
+++ b/target/xtensa/cpu.h
24
@@ -XXX,XX +XXX,XX @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, vaddr *pc,
25
XtensaCPU *xtensa_cpu_create_with_clock(const char *cpu_type,
26
Clock *cpu_refclk);
27
28
+/*
29
+ * Set the NaN propagation rule for future FPU operations:
30
+ * use_first is true to pick the first NaN as the result if both
31
+ * inputs are NaNs, false to pick the second.
32
+ */
33
+void xtensa_use_first_nan(CPUXtensaState *env, bool use_first);
34
#endif
35
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
10
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
36
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
37
--- a/target/xtensa/cpu.c
12
--- a/target/xtensa/cpu.c
38
+++ b/target/xtensa/cpu.c
13
+++ b/target/xtensa/cpu.c
39
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
14
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
40
cs->halted = env->runstall;
15
/* For inf * 0 + NaN, return the input NaN */
41
#endif
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
42
set_no_signaling_nans(!dfpu, &env->fp_status);
17
set_no_signaling_nans(!dfpu, &env->fp_status);
43
- set_use_first_nan(!dfpu, &env->fp_status);
18
+ /* Default NaN value: sign bit clear, set frac msb */
44
+ xtensa_use_first_nan(env, !dfpu);
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
xtensa_use_first_nan(env, !dfpu);
45
}
21
}
46
47
static ObjectClass *xtensa_cpu_class_by_name(const char *cpu_model)
48
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/xtensa/fpu_helper.c
51
+++ b/target/xtensa/fpu_helper.c
52
@@ -XXX,XX +XXX,XX @@ static const struct {
53
{ XTENSA_FP_V, float_flag_invalid, },
54
};
55
56
+void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
57
+{
58
+ set_use_first_nan(use_first, &env->fp_status);
59
+}
60
+
61
void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
62
{
63
static const int rounding_mode[] = {
64
@@ -XXX,XX +XXX,XX @@ float32 HELPER(fpu2k_msub_s)(CPUXtensaState *env,
65
66
float64 HELPER(add_d)(CPUXtensaState *env, float64 a, float64 b)
67
{
68
- set_use_first_nan(true, &env->fp_status);
69
+ xtensa_use_first_nan(env, true);
70
return float64_add(a, b, &env->fp_status);
71
}
72
73
float32 HELPER(add_s)(CPUXtensaState *env, float32 a, float32 b)
74
{
75
- set_use_first_nan(env->config->use_first_nan, &env->fp_status);
76
+ xtensa_use_first_nan(env, env->config->use_first_nan);
77
return float32_add(a, b, &env->fp_status);
78
}
79
80
float64 HELPER(sub_d)(CPUXtensaState *env, float64 a, float64 b)
81
{
82
- set_use_first_nan(true, &env->fp_status);
83
+ xtensa_use_first_nan(env, true);
84
return float64_sub(a, b, &env->fp_status);
85
}
86
87
float32 HELPER(sub_s)(CPUXtensaState *env, float32 a, float32 b)
88
{
89
- set_use_first_nan(env->config->use_first_nan, &env->fp_status);
90
+ xtensa_use_first_nan(env, env->config->use_first_nan);
91
return float32_sub(a, b, &env->fp_status);
92
}
93
94
float64 HELPER(mul_d)(CPUXtensaState *env, float64 a, float64 b)
95
{
96
- set_use_first_nan(true, &env->fp_status);
97
+ xtensa_use_first_nan(env, true);
98
return float64_mul(a, b, &env->fp_status);
99
}
100
101
float32 HELPER(mul_s)(CPUXtensaState *env, float32 a, float32 b)
102
{
103
- set_use_first_nan(env->config->use_first_nan, &env->fp_status);
104
+ xtensa_use_first_nan(env, env->config->use_first_nan);
105
return float32_mul(a, b, &env->fp_status);
106
}
107
108
float64 HELPER(madd_d)(CPUXtensaState *env, float64 a, float64 b, float64 c)
109
{
110
- set_use_first_nan(env->config->use_first_nan, &env->fp_status);
111
+ xtensa_use_first_nan(env, env->config->use_first_nan);
112
return float64_muladd(b, c, a, 0, &env->fp_status);
113
}
114
115
float32 HELPER(madd_s)(CPUXtensaState *env, float32 a, float32 b, float32 c)
116
{
117
- set_use_first_nan(env->config->use_first_nan, &env->fp_status);
118
+ xtensa_use_first_nan(env, env->config->use_first_nan);
119
return float32_muladd(b, c, a, 0, &env->fp_status);
120
}
121
122
float64 HELPER(msub_d)(CPUXtensaState *env, float64 a, float64 b, float64 c)
123
{
124
- set_use_first_nan(env->config->use_first_nan, &env->fp_status);
125
+ xtensa_use_first_nan(env, env->config->use_first_nan);
126
return float64_muladd(b, c, a, float_muladd_negate_product,
127
&env->fp_status);
128
}
129
130
float32 HELPER(msub_s)(CPUXtensaState *env, float32 a, float32 b, float32 c)
131
{
132
- set_use_first_nan(env->config->use_first_nan, &env->fp_status);
133
+ xtensa_use_first_nan(env, env->config->use_first_nan);
134
return float32_muladd(b, c, a, float_muladd_negate_product,
135
&env->fp_status);
136
}
137
138
float64 HELPER(mkdadj_d)(CPUXtensaState *env, float64 a, float64 b)
139
{
140
- set_use_first_nan(true, &env->fp_status);
141
+ xtensa_use_first_nan(env, true);
142
return float64_div(b, a, &env->fp_status);
143
}
144
145
float32 HELPER(mkdadj_s)(CPUXtensaState *env, float32 a, float32 b)
146
{
147
- set_use_first_nan(env->config->use_first_nan, &env->fp_status);
148
+ xtensa_use_first_nan(env, env->config->use_first_nan);
149
return float32_div(b, a, &env->fp_status);
150
}
151
152
float64 HELPER(mksadj_d)(CPUXtensaState *env, float64 v)
153
{
154
- set_use_first_nan(true, &env->fp_status);
155
+ xtensa_use_first_nan(env, true);
156
return float64_sqrt(v, &env->fp_status);
157
}
158
159
float32 HELPER(mksadj_s)(CPUXtensaState *env, float32 v)
160
{
161
- set_use_first_nan(env->config->use_first_nan, &env->fp_status);
162
+ xtensa_use_first_nan(env, env->config->use_first_nan);
163
return float32_sqrt(v, &env->fp_status);
164
}
165
22
166
--
23
--
167
2.34.1
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for hexagon.
2
Remove the ifdef from parts64_default_nan(); the only
3
remaining unconverted targets all use the default case.
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-52-peter.maydell@linaro.org
8
---
9
target/hexagon/cpu.c | 2 ++
10
fpu/softfloat-specialize.c.inc | 5 -----
11
2 files changed, 2 insertions(+), 5 deletions(-)
12
13
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/hexagon/cpu.c
16
+++ b/target/hexagon/cpu.c
17
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
18
19
set_default_nan_mode(1, &env->fp_status);
20
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
21
+ /* Default NaN value: sign bit set, all frac bits set */
22
+ set_float_default_nan_pattern(0b11111111, &env->fp_status);
23
}
24
25
static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
26
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
27
index XXXXXXX..XXXXXXX 100644
28
--- a/fpu/softfloat-specialize.c.inc
29
+++ b/fpu/softfloat-specialize.c.inc
30
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
31
uint8_t dnan_pattern = status->default_nan_pattern;
32
33
if (dnan_pattern == 0) {
34
-#if defined(TARGET_HEXAGON)
35
- /* Sign bit set, all frac bits set. */
36
- dnan_pattern = 0b11111111;
37
-#else
38
/*
39
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
40
* S390, SH4, TriCore, and Xtensa. Our other supported targets
41
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
42
/* sign bit clear, set frac msb */
43
dnan_pattern = 0b01000000;
44
}
45
-#endif
46
}
47
assert(dnan_pattern != 0);
48
49
--
50
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for riscv.
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-53-peter.maydell@linaro.org
6
---
7
target/riscv/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/riscv/cpu.c
13
+++ b/target/riscv/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
15
cs->exception_index = RISCV_EXCP_NONE;
16
env->load_res = -1;
17
set_default_nan_mode(1, &env->fp_status);
18
+ /* Default NaN value: sign bit clear, frac msb set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
env->vill = true;
21
22
#ifndef CONFIG_USER_ONLY
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for tricore.
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-54-peter.maydell@linaro.org
6
---
7
target/tricore/helper.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/tricore/helper.c
13
+++ b/target/tricore/helper.c
14
@@ -XXX,XX +XXX,XX @@ void fpu_set_state(CPUTriCoreState *env)
15
set_flush_to_zero(1, &env->fp_status);
16
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
17
set_default_nan_mode(1, &env->fp_status);
18
+ /* Default NaN pattern: sign bit clear, frac msb set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
}
21
22
uint32_t psw_read(CPUTriCoreState *env)
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Now that all our targets have bene converted to explicitly specify
2
their pattern for the default NaN value we can remove the remaining
3
fallback code in parts64_default_nan().
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-55-peter.maydell@linaro.org
8
---
9
fpu/softfloat-specialize.c.inc | 14 --------------
10
1 file changed, 14 deletions(-)
11
12
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
13
index XXXXXXX..XXXXXXX 100644
14
--- a/fpu/softfloat-specialize.c.inc
15
+++ b/fpu/softfloat-specialize.c.inc
16
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
17
uint64_t frac;
18
uint8_t dnan_pattern = status->default_nan_pattern;
19
20
- if (dnan_pattern == 0) {
21
- /*
22
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
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;
37
--
38
2.34.1
diff view generated by jsdifflib
1
Set the NaN propagation rule explicitly for the float_status word
1
From: Richard Henderson <richard.henderson@linaro.org>
2
used in the microblaze target.
3
2
4
This is probably not the architecturally correct behaviour,
3
Inline pickNaNMulAdd into its only caller. This makes
5
but since this is a no-behaviour-change patch, we leave a
4
one assert redundant with the immediately preceding IF.
6
TODO note to that effect.
7
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-3-richard.henderson@linaro.org
9
[PMM: keep comment from old code in new location]
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20241025141254.2141506-19-peter.maydell@linaro.org
12
---
11
---
13
target/microblaze/cpu.c | 5 +++++
12
fpu/softfloat-parts.c.inc | 41 +++++++++++++++++++++++++-
14
fpu/softfloat-specialize.c.inc | 3 ++-
13
fpu/softfloat-specialize.c.inc | 54 ----------------------------------
15
2 files changed, 7 insertions(+), 1 deletion(-)
14
2 files changed, 40 insertions(+), 55 deletions(-)
16
15
17
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/target/microblaze/cpu.c
18
--- a/fpu/softfloat-parts.c.inc
20
+++ b/target/microblaze/cpu.c
19
+++ b/fpu/softfloat-parts.c.inc
21
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_reset_hold(Object *obj, ResetType type)
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
22
env->pc = cpu->cfg.base_vectors;
21
}
23
22
24
set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
23
if (s->default_nan_mode) {
25
+ /*
24
+ /*
26
+ * TODO: this is probably not the correct NaN propagation rule for
25
+ * We guarantee not to require the target to tell us how to
27
+ * this architecture.
26
+ * pick a NaN if we're always returning the default NaN.
28
+ */
27
+ * But if we're not in default-NaN mode then the target must
29
+ set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
28
+ * specify.
30
29
+ */
31
#if defined(CONFIG_USER_ONLY)
30
which = 3;
32
/* start in user mode with interrupts enabled. */
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) {
33
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
70
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
34
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
35
--- a/fpu/softfloat-specialize.c.inc
72
--- a/fpu/softfloat-specialize.c.inc
36
+++ b/fpu/softfloat-specialize.c.inc
73
+++ b/fpu/softfloat-specialize.c.inc
37
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
74
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
38
|| defined(TARGET_LOONGARCH64) || defined(TARGET_HPPA) \
75
}
39
|| defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_M68K) \
76
}
40
|| defined(TARGET_SPARC) || defined(TARGET_XTENSA) \
77
41
- || defined(TARGET_I386) || defined(TARGET_ALPHA)
78
-/*----------------------------------------------------------------------------
42
+ || defined(TARGET_I386) || defined(TARGET_ALPHA) \
79
-| Select which NaN to propagate for a three-input operation.
43
+ || defined(TARGET_MICROBLAZE)
80
-| For the moment we assume that no CPU needs the 'larger significand'
44
g_assert_not_reached();
81
-| information.
45
#else
82
-| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
46
rule = float_2nan_prop_x87;
83
-*----------------------------------------------------------------------------*/
84
-static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
85
- bool infzero, bool have_snan, float_status *status)
86
-{
87
- FloatClass cls[3] = { a_cls, b_cls, c_cls };
88
- Float3NaNPropRule rule = status->float_3nan_prop_rule;
89
- int which;
90
-
91
- /*
92
- * We guarantee not to require the target to tell us how to
93
- * pick a NaN if we're always returning the default NaN.
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();
113
- }
114
- }
115
-
116
- assert(rule != float_3nan_prop_none);
117
- if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
118
- /* We have at least one SNaN input and should prefer it */
119
- do {
120
- which = rule & R_3NAN_1ST_MASK;
121
- rule >>= R_3NAN_1ST_LENGTH;
122
- } while (!is_snan(cls[which]));
123
- } else {
124
- do {
125
- which = rule & R_3NAN_1ST_MASK;
126
- rule >>= R_3NAN_1ST_LENGTH;
127
- } while (!is_nan(cls[which]));
128
- }
129
- return which;
130
-}
131
-
132
/*----------------------------------------------------------------------------
133
| Returns 1 if the double-precision floating-point value `a' is a quiet
134
| NaN; otherwise returns 0.
47
--
135
--
48
2.34.1
136
2.34.1
49
137
50
138
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Remove "3" as a special case for which and simply
4
branch to return the desired value.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-4-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
fpu/softfloat-parts.c.inc | 20 ++++++++++----------
12
1 file changed, 10 insertions(+), 10 deletions(-)
13
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
16
--- a/fpu/softfloat-parts.c.inc
17
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
* But if we're not in default-NaN mode then the target must
20
* specify.
21
*/
22
- which = 3;
23
+ goto default_nan;
24
} else if (infzero) {
25
/*
26
* Inf * 0 + NaN -- some implementations return the
27
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
28
*/
29
switch (s->float_infzeronan_rule) {
30
case float_infzeronan_dnan_never:
31
- which = 2;
32
break;
33
case float_infzeronan_dnan_always:
34
- which = 3;
35
- break;
36
+ goto default_nan;
37
case float_infzeronan_dnan_if_qnan:
38
- which = is_qnan(c->cls) ? 3 : 2;
39
+ if (is_qnan(c->cls)) {
40
+ goto default_nan;
41
+ }
42
break;
43
default:
44
g_assert_not_reached();
45
}
46
+ which = 2;
47
} else {
48
FloatClass cls[3] = { a->cls, b->cls, c->cls };
49
Float3NaNPropRule rule = s->float_3nan_prop_rule;
50
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
51
}
52
}
53
54
- if (which == 3) {
55
- parts_default_nan(a, s);
56
- return a;
57
- }
58
-
59
switch (which) {
60
case 0:
61
break;
62
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
63
parts_silence_nan(a, s);
64
}
65
return a;
66
+
67
+ default_nan:
68
+ parts_default_nan(a, s);
69
+ return a;
70
}
71
72
/*
73
--
74
2.34.1
75
76
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Assign the pointer return value to 'a' directly,
4
rather than going through an intermediary index.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-5-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
fpu/softfloat-parts.c.inc | 32 ++++++++++----------------------
12
1 file changed, 10 insertions(+), 22 deletions(-)
13
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
16
--- a/fpu/softfloat-parts.c.inc
17
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
FloatPartsN *c, float_status *s,
20
int ab_mask, int abc_mask)
21
{
22
- int which;
23
bool infzero = (ab_mask == float_cmask_infzero);
24
bool have_snan = (abc_mask & float_cmask_snan);
25
+ FloatPartsN *ret;
26
27
if (unlikely(have_snan)) {
28
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
30
default:
31
g_assert_not_reached();
32
}
33
- which = 2;
34
+ ret = c;
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
}
57
}
58
59
- switch (which) {
60
- case 0:
61
- break;
62
- case 1:
63
- a = b;
64
- break;
65
- case 2:
66
- a = c;
67
- break;
68
- default:
69
- g_assert_not_reached();
70
+ if (is_snan(ret->cls)) {
71
+ parts_silence_nan(ret, s);
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);
81
--
82
2.34.1
83
84
diff view generated by jsdifflib
1
From: Nabih Estefan <nabihestefan@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Convert the LOG_GUEST_ERROR for the "tx descriptor is owned
3
While all indices into val[] should be in [0-2], the mask
4
by software" to a trace message. This condition is normal
4
applied is two bits. To help static analysis see there is
5
when there is there is nothing to transmit, and we would
5
no possibility of read beyond the end of the array, pad the
6
otherwise spam the logs with it in that situation.
6
array to 4 entries, with the final being (implicitly) NULL.
7
7
8
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Roque Arcudia Hernandez <roqueh@google.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20241014184847.1594056-1-roqueh@google.com
10
Message-id: 20241203203949.483774-6-richard.henderson@linaro.org
12
[PMM: tweaked commit message]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
12
---
15
hw/net/npcm_gmac.c | 5 ++---
13
fpu/softfloat-parts.c.inc | 2 +-
16
hw/net/trace-events | 1 +
14
1 file changed, 1 insertion(+), 1 deletion(-)
17
2 files changed, 3 insertions(+), 3 deletions(-)
18
15
19
diff --git a/hw/net/npcm_gmac.c b/hw/net/npcm_gmac.c
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/net/npcm_gmac.c
18
--- a/fpu/softfloat-parts.c.inc
22
+++ b/hw/net/npcm_gmac.c
19
+++ b/fpu/softfloat-parts.c.inc
23
@@ -XXX,XX +XXX,XX @@ static void gmac_try_send_next_packet(NPCMGMACState *gmac)
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
24
21
}
25
/* 1 = DMA Owned, 0 = Software Owned */
22
ret = c;
26
if (!(tx_desc.tdes0 & TX_DESC_TDES0_OWN)) {
23
} else {
27
- qemu_log_mask(LOG_GUEST_ERROR,
24
- FloatPartsN *val[3] = { a, b, c };
28
- "TX Descriptor @ 0x%x is owned by software\n",
25
+ FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
29
- desc_addr);
26
Float3NaNPropRule rule = s->float_3nan_prop_rule;
30
+ trace_npcm_gmac_tx_desc_owner(DEVICE(gmac)->canonical_path,
27
31
+ desc_addr);
28
assert(rule != float_3nan_prop_none);
32
gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_TU;
33
gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
34
NPCM_DMA_STATUS_TX_SUSPENDED_STATE);
35
diff --git a/hw/net/trace-events b/hw/net/trace-events
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/net/trace-events
38
+++ b/hw/net/trace-events
39
@@ -XXX,XX +XXX,XX @@ npcm_gmac_packet_received(const char* name, uint32_t len) "%s: Reception finishe
40
npcm_gmac_packet_sent(const char* name, uint16_t len) "%s: TX packet sent!, length: 0x%04" PRIX16
41
npcm_gmac_debug_desc_data(const char* name, void* addr, uint32_t des0, uint32_t des1, uint32_t des2, uint32_t des3)"%s: Address: %p Descriptor 0: 0x%04" PRIX32 " Descriptor 1: 0x%04" PRIX32 "Descriptor 2: 0x%04" PRIX32 " Descriptor 3: 0x%04" PRIX32
42
npcm_gmac_packet_tx_desc_data(const char* name, uint32_t tdes0, uint32_t tdes1) "%s: Tdes0: 0x%04" PRIX32 " Tdes1: 0x%04" PRIX32
43
+npcm_gmac_tx_desc_owner(const char* name, uint32_t desc_addr) "%s: TX Descriptor @0x%04" PRIX32 " is owned by software"
44
45
# npcm_pcs.c
46
npcm_pcs_reg_read(const char *name, uint16_t indirect_access_baes, uint64_t offset, uint16_t value) "%s: IND: 0x%02" PRIx16 " offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
47
--
29
--
48
2.34.1
30
2.34.1
49
31
50
32
diff view generated by jsdifflib
1
From: Gustavo Romero <gustavo.romero@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
FEAT_CMOW introduces support for controlling cache maintenance
3
This function is part of the public interface and
4
instructions executed in EL0/1 and is mandatory from Armv8.8.
4
is not "specialized" to any target in any way.
5
5
6
On real hardware, the main use for this feature is to prevent processes
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
from invalidating or flushing cache lines for addresses they only have
8
read permission, which can impact the performance of other processes.
9
10
QEMU implements all cache instructions as NOPs, and, according to rule
11
[1], which states that generating any Permission fault when a cache
12
instruction is implemented as a NOP is implementation-defined, no
13
Permission fault is generated for any cache instruction when it lacks
14
read and write permissions.
15
16
QEMU does not model any cache topology, so the PoU and PoC are before
17
any cache, and rules [2] apply. These rules state that generating any
18
MMU fault for cache instructions in this topology is also
19
implementation-defined. Therefore, for FEAT_CMOW, we do not generate any
20
MMU faults either, instead, we only advertise it in the feature
21
register.
22
23
[1] Rule R_HGLYG of section D8.14.3, Arm ARM K.a.
24
[2] Rules R_MZTNR and R_DNZYL of section D8.14.3, Arm ARM K.a.
25
26
Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
27
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Message-id: 20241104142606.941638-1-gustavo.romero@linaro.org
29
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-7-richard.henderson@linaro.org
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
---
10
---
32
docs/system/arm/emulation.rst | 1 +
11
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++++++++
33
target/arm/cpu-features.h | 5 +++++
12
fpu/softfloat-specialize.c.inc | 52 ----------------------------------
34
target/arm/cpu.h | 1 +
13
2 files changed, 52 insertions(+), 52 deletions(-)
35
target/arm/helper.c | 5 +++++
36
target/arm/tcg/cpu64.c | 1 +
37
5 files changed, 13 insertions(+)
38
14
39
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
40
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
41
--- a/docs/system/arm/emulation.rst
17
--- a/fpu/softfloat.c
42
+++ b/docs/system/arm/emulation.rst
18
+++ b/fpu/softfloat.c
43
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
44
- FEAT_BF16 (AArch64 BFloat16 instructions)
20
*zExpPtr = 1 - shiftCount;
45
- FEAT_BTI (Branch Target Identification)
46
- FEAT_CCIDX (Extended cache index)
47
+- FEAT_CMOW (Control for cache maintenance permission)
48
- FEAT_CRC32 (CRC32 instructions)
49
- FEAT_Crypto (Cryptographic Extension)
50
- FEAT_CSV2 (Cache speculation variant 2)
51
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/cpu-features.h
54
+++ b/target/arm/cpu-features.h
55
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id)
56
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, TIDCP1) != 0;
57
}
21
}
58
22
59
+static inline bool isar_feature_aa64_cmow(const ARMISARegisters *id)
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
+*----------------------------------------------------------------------------*/
28
+
29
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
60
+{
30
+{
61
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, CMOW) != 0;
31
+ bool aIsLargerSignificand;
32
+ FloatClass a_cls, b_cls;
33
+
34
+ /* This is not complete, but is good enough for pickNaN. */
35
+ a_cls = (!floatx80_is_any_nan(a)
36
+ ? float_class_normal
37
+ : floatx80_is_signaling_nan(a, status)
38
+ ? float_class_snan
39
+ : float_class_qnan);
40
+ b_cls = (!floatx80_is_any_nan(b)
41
+ ? float_class_normal
42
+ : floatx80_is_signaling_nan(b, status)
43
+ ? float_class_snan
44
+ : float_class_qnan);
45
+
46
+ if (is_snan(a_cls) || is_snan(b_cls)) {
47
+ float_raise(float_flag_invalid, status);
48
+ }
49
+
50
+ if (status->default_nan_mode) {
51
+ return floatx80_default_nan(status);
52
+ }
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);
65
+ }
66
+ return b;
67
+ } else {
68
+ if (is_snan(a_cls)) {
69
+ return floatx80_silence_nan(a, status);
70
+ }
71
+ return a;
72
+ }
62
+}
73
+}
63
+
74
+
64
static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id)
75
/*----------------------------------------------------------------------------
65
{
76
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
66
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) != 0;
77
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
67
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
78
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
68
index XXXXXXX..XXXXXXX 100644
79
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/cpu.h
80
--- a/fpu/softfloat-specialize.c.inc
70
+++ b/target/arm/cpu.h
81
+++ b/fpu/softfloat-specialize.c.inc
71
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
82
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
72
#define SCTLR_EnIB (1U << 30) /* v8.3, AArch64 only */
83
return a;
73
#define SCTLR_EnIA (1U << 31) /* v8.3, AArch64 only */
84
}
74
#define SCTLR_DSSBS_32 (1U << 31) /* v8.5, AArch32 only */
85
75
+#define SCTLR_CMOW (1ULL << 32) /* FEAT_CMOW */
86
-/*----------------------------------------------------------------------------
76
#define SCTLR_MSCEN (1ULL << 33) /* FEAT_MOPS */
87
-| Takes two extended double-precision floating-point values `a' and `b', one
77
#define SCTLR_BT0 (1ULL << 35) /* v8.5-BTI */
88
-| of which is a NaN, and returns the appropriate NaN result. If either `a' or
78
#define SCTLR_BT1 (1ULL << 36) /* v8.5-BTI */
89
-| `b' is a signaling NaN, the invalid exception is raised.
79
diff --git a/target/arm/helper.c b/target/arm/helper.c
90
-*----------------------------------------------------------------------------*/
80
index XXXXXXX..XXXXXXX 100644
91
-
81
--- a/target/arm/helper.c
92
-floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
82
+++ b/target/arm/helper.c
93
-{
83
@@ -XXX,XX +XXX,XX @@ static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri,
94
- bool aIsLargerSignificand;
84
if (cpu_isar_feature(aa64_nmi, cpu)) {
95
- FloatClass a_cls, b_cls;
85
valid_mask |= HCRX_TALLINT | HCRX_VINMI | HCRX_VFNMI;
96
-
86
}
97
- /* This is not complete, but is good enough for pickNaN. */
87
+ /* FEAT_CMOW adds CMOW */
98
- a_cls = (!floatx80_is_any_nan(a)
88
+
99
- ? float_class_normal
89
+ if (cpu_isar_feature(aa64_cmow, cpu)) {
100
- : floatx80_is_signaling_nan(a, status)
90
+ valid_mask |= HCRX_CMOW;
101
- ? float_class_snan
91
+ }
102
- : float_class_qnan);
92
103
- b_cls = (!floatx80_is_any_nan(b)
93
/* Clear RES0 bits. */
104
- ? float_class_normal
94
env->cp15.hcrx_el2 = value & valid_mask;
105
- : floatx80_is_signaling_nan(b, status)
95
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
106
- ? float_class_snan
96
index XXXXXXX..XXXXXXX 100644
107
- : float_class_qnan);
97
--- a/target/arm/tcg/cpu64.c
108
-
98
+++ b/target/arm/tcg/cpu64.c
109
- if (is_snan(a_cls) || is_snan(b_cls)) {
99
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
110
- float_raise(float_flag_invalid, status);
100
t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 2); /* FEAT_ETS2 */
111
- }
101
t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1); /* FEAT_HCX */
112
-
102
t = FIELD_DP64(t, ID_AA64MMFR1, TIDCP1, 1); /* FEAT_TIDCP1 */
113
- if (status->default_nan_mode) {
103
+ t = FIELD_DP64(t, ID_AA64MMFR1, CMOW, 1); /* FEAT_CMOW */
114
- return floatx80_default_nan(status);
104
cpu->isar.id_aa64mmfr1 = t;
115
- }
105
116
-
106
t = cpu->isar.id_aa64mmfr2;
117
- if (a.low < b.low) {
118
- aIsLargerSignificand = 0;
119
- } else if (b.low < a.low) {
120
- aIsLargerSignificand = 1;
121
- } else {
122
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
123
- }
124
-
125
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
126
- if (is_snan(b_cls)) {
127
- return floatx80_silence_nan(b, status);
128
- }
129
- return b;
130
- } else {
131
- if (is_snan(a_cls)) {
132
- return floatx80_silence_nan(a, status);
133
- }
134
- return a;
135
- }
136
-}
137
-
138
/*----------------------------------------------------------------------------
139
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
140
| NaN; otherwise returns 0.
107
--
141
--
108
2.34.1
142
2.34.1
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
From: Bernhard Beschow <shentey@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
printf() unconditionally prints to the console which disturbs `-serial stdio`.
3
Inline pickNaN into its only caller. This makes one assert
4
Fix that by converting into a trace event. While at it, add some tracing for
4
redundant with the immediately preceding IF.
5
read and write access.
5
6
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Fixes: 7e7c5e4c1ba5 "Nokia N800 machine support (ARM)."
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Message-id: 20241103143330.123596-5-shentey@gmail.com
8
Message-id: 20241203203949.483774-9-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
meson.build | 1 +
11
fpu/softfloat-parts.c.inc | 82 +++++++++++++++++++++++++----
14
hw/sensor/trace.h | 1 +
12
fpu/softfloat-specialize.c.inc | 96 ----------------------------------
15
hw/sensor/tmp105.c | 7 ++++++-
13
2 files changed, 73 insertions(+), 105 deletions(-)
16
hw/sensor/trace-events | 6 ++++++
14
17
4 files changed, 14 insertions(+), 1 deletion(-)
15
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
18
create mode 100644 hw/sensor/trace.h
19
create mode 100644 hw/sensor/trace-events
20
21
diff --git a/meson.build b/meson.build
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/meson.build
17
--- a/fpu/softfloat-parts.c.inc
24
+++ b/meson.build
18
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ if have_system
19
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
26
'hw/s390x',
20
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
27
'hw/scsi',
21
float_status *s)
28
'hw/sd',
22
{
29
+ 'hw/sensor',
23
+ int cmp, which;
30
'hw/sh4',
24
+
31
'hw/sparc',
25
if (is_snan(a->cls) || is_snan(b->cls)) {
32
'hw/sparc64',
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
33
diff --git a/hw/sensor/trace.h b/hw/sensor/trace.h
27
}
34
new file mode 100644
28
35
index XXXXXXX..XXXXXXX
29
if (s->default_nan_mode) {
36
--- /dev/null
30
parts_default_nan(a, s);
37
+++ b/hw/sensor/trace.h
31
- } else {
38
@@ -0,0 +1 @@
32
- int cmp = frac_cmp(a, b);
39
+#include "trace/trace-hw_sensor.h"
33
- if (cmp == 0) {
40
diff --git a/hw/sensor/tmp105.c b/hw/sensor/tmp105.c
34
- cmp = a->sign < b->sign;
35
- }
36
+ return a;
37
+ }
38
39
- if (pickNaN(a->cls, b->cls, cmp > 0, s)) {
40
- a = b;
41
- }
42
+ cmp = frac_cmp(a, b);
43
+ if (cmp == 0) {
44
+ cmp = a->sign < b->sign;
45
+ }
46
+
47
+ switch (s->float_2nan_prop_rule) {
48
+ case float_2nan_prop_s_ab:
49
if (is_snan(a->cls)) {
50
- parts_silence_nan(a, s);
51
+ which = 0;
52
+ } else if (is_snan(b->cls)) {
53
+ which = 1;
54
+ } else if (is_qnan(a->cls)) {
55
+ which = 0;
56
+ } else {
57
+ which = 1;
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;
105
+ default:
106
+ g_assert_not_reached();
107
+ }
108
+
109
+ if (which) {
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
41
index XXXXXXX..XXXXXXX 100644
118
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/sensor/tmp105.c
119
--- a/fpu/softfloat-specialize.c.inc
43
+++ b/hw/sensor/tmp105.c
120
+++ b/fpu/softfloat-specialize.c.inc
44
@@ -XXX,XX +XXX,XX @@
121
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
45
#include "qapi/visitor.h"
46
#include "qemu/module.h"
47
#include "hw/registerfields.h"
48
+#include "trace.h"
49
50
FIELD(CONFIG, SHUTDOWN_MODE, 0, 1)
51
FIELD(CONFIG, THERMOSTAT_MODE, 1, 1)
52
@@ -XXX,XX +XXX,XX @@ static void tmp105_read(TMP105State *s)
53
s->buf[s->len++] = ((uint16_t) s->limit[1]) >> 0;
54
break;
55
}
122
}
56
+
57
+ trace_tmp105_read(s->i2c.address, s->pointer);
58
}
123
}
59
124
60
static void tmp105_write(TMP105State *s)
125
-/*----------------------------------------------------------------------------
61
{
126
-| Select which NaN to propagate for a two-input operation.
62
+ trace_tmp105_write(s->i2c.address, s->pointer);
127
-| IEEE754 doesn't specify all the details of this, so the
63
+
128
-| algorithm is target-specific.
64
switch (s->pointer & 3) {
129
-| The routine is passed various bits of information about the
65
case TMP105_REG_TEMPERATURE:
130
-| two NaNs and should return 0 to select NaN a and 1 for NaN b.
66
break;
131
-| Note that signalling NaNs are always squashed to quiet NaNs
67
132
-| by the caller, by calling floatXX_silence_nan() before
68
case TMP105_REG_CONFIG:
133
-| returning them.
69
if (FIELD_EX8(s->buf[0] & ~s->config, CONFIG, SHUTDOWN_MODE)) {
134
-|
70
- printf("%s: TMP105 shutdown\n", __func__);
135
-| aIsLargerSignificand is only valid if both a and b are NaNs
71
+ trace_tmp105_write_shutdown(s->i2c.address);
136
-| of some kind, and is true if a has the larger significand,
72
}
137
-| or if both a and b have the same significand but a is
73
s->config = FIELD_DP8(s->buf[0], CONFIG, ONE_SHOT, 0);
138
-| positive but b is negative. It is only needed for the x87
74
s->faults = tmp105_faultq[FIELD_EX8(s->config, CONFIG, FAULT_QUEUE)];
139
-| tie-break rule.
75
diff --git a/hw/sensor/trace-events b/hw/sensor/trace-events
140
-*----------------------------------------------------------------------------*/
76
new file mode 100644
141
-
77
index XXXXXXX..XXXXXXX
142
-static int pickNaN(FloatClass a_cls, FloatClass b_cls,
78
--- /dev/null
143
- bool aIsLargerSignificand, float_status *status)
79
+++ b/hw/sensor/trace-events
144
-{
80
@@ -XXX,XX +XXX,XX @@
145
- /*
81
+# See docs/devel/tracing.rst for syntax documentation.
146
- * We guarantee not to require the target to tell us how to
82
+
147
- * pick a NaN if we're always returning the default NaN.
83
+# tmp105.c
148
- * But if we're not in default-NaN mode then the target must
84
+tmp105_read(uint8_t dev, uint8_t addr) "device: 0x%02x, addr: 0x%02x"
149
- * specify via set_float_2nan_prop_rule().
85
+tmp105_write(uint8_t dev, uint8_t addr) "device: 0x%02x, addr 0x%02x"
150
- */
86
+tmp105_write_shutdown(uint8_t dev) "device: 0x%02x"
151
- assert(!status->default_nan_mode);
152
-
153
- switch (status->float_2nan_prop_rule) {
154
- case float_2nan_prop_s_ab:
155
- if (is_snan(a_cls)) {
156
- return 0;
157
- } else if (is_snan(b_cls)) {
158
- return 1;
159
- } else if (is_qnan(a_cls)) {
160
- return 0;
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();
218
- }
219
-}
220
-
221
/*----------------------------------------------------------------------------
222
| Returns 1 if the double-precision floating-point value `a' is a quiet
223
| NaN; otherwise returns 0.
87
--
224
--
88
2.34.1
225
2.34.1
89
226
90
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: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Like 9971cbac2f3, which set CAPSTONE_AARCH64_COMPAT_HEADER,
3
Move the fractional comparison to the end of the
4
also set CAPSTONE_SYSTEMZ_COMPAT_HEADER. Fixes the build
4
float_2nan_prop_x87 case. This is not required for
5
against capstone v6-alpha.
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: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Gustavo Romero <gustavo.romero@linaro.org>
9
Message-id: 20241022013047.830273-1-richard.henderson@linaro.org
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20241203203949.483774-11-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
---
13
include/disas/capstone.h | 1 +
14
fpu/softfloat-parts.c.inc | 19 +++++++++----------
14
1 file changed, 1 insertion(+)
15
1 file changed, 9 insertions(+), 10 deletions(-)
15
16
16
diff --git a/include/disas/capstone.h b/include/disas/capstone.h
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/include/disas/capstone.h
19
--- a/fpu/softfloat-parts.c.inc
19
+++ b/include/disas/capstone.h
20
+++ b/fpu/softfloat-parts.c.inc
20
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
21
#ifdef CONFIG_CAPSTONE
22
return a;
22
23
}
23
#define CAPSTONE_AARCH64_COMPAT_HEADER
24
24
+#define CAPSTONE_SYSTEMZ_COMPAT_HEADER
25
- cmp = frac_cmp(a, b);
25
#include <capstone.h>
26
- if (cmp == 0) {
26
27
- cmp = a->sign < b->sign;
27
#else
28
- }
29
-
30
switch (s->float_2nan_prop_rule) {
31
case float_2nan_prop_s_ab:
32
if (have_snan) {
33
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
34
* return the NaN with the positive sign bit (if any).
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;
53
+ break;
54
}
55
+ cmp = frac_cmp(a, b);
56
+ if (cmp == 0) {
57
+ cmp = a->sign < b->sign;
58
+ }
59
+ which = cmp > 0 ? 0 : 1;
60
break;
61
default:
62
g_assert_not_reached();
28
--
63
--
29
2.34.1
64
2.34.1
diff view generated by jsdifflib
1
From: Bernhard Beschow <shentey@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Replace the "index" selecting between A and B with a result variable
4
of the proper type. This improves clarity within the function.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Message-id: 20241203203949.483774-12-richard.henderson@linaro.org
5
Message-id: 20241103143330.123596-3-shentey@gmail.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
hw/timer/imx_gpt.c | 18 +++++-------------
11
fpu/softfloat-parts.c.inc | 28 +++++++++++++---------------
9
hw/timer/trace-events | 6 ++++++
12
1 file changed, 13 insertions(+), 15 deletions(-)
10
2 files changed, 11 insertions(+), 13 deletions(-)
11
13
12
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/timer/imx_gpt.c
16
--- a/fpu/softfloat-parts.c.inc
15
+++ b/hw/timer/imx_gpt.c
17
+++ b/fpu/softfloat-parts.c.inc
16
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
17
#include "migration/vmstate.h"
19
float_status *s)
18
#include "qemu/module.h"
19
#include "qemu/log.h"
20
+#include "trace.h"
21
22
#ifndef DEBUG_IMX_GPT
23
#define DEBUG_IMX_GPT 0
24
#endif
25
26
-#define DPRINTF(fmt, args...) \
27
- do { \
28
- if (DEBUG_IMX_GPT) { \
29
- fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_GPT, \
30
- __func__, ##args); \
31
- } \
32
- } while (0)
33
-
34
static const char *imx_gpt_reg_name(uint32_t reg)
35
{
20
{
36
switch (reg) {
21
bool have_snan = false;
37
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_set_freq(IMXGPTState *s)
22
- int cmp, which;
38
s->freq = imx_ccm_get_clock_frequency(s->ccm,
23
+ FloatPartsN *ret;
39
s->clocks[clksrc]) / (1 + s->pr);
24
+ int cmp;
40
25
41
- DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, s->freq);
26
if (is_snan(a->cls) || is_snan(b->cls)) {
42
+ trace_imx_gpt_set_freq(clksrc, s->freq);
27
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
43
28
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
44
if (s->freq) {
29
switch (s->float_2nan_prop_rule) {
45
ptimer_set_freq(s->timer, s->freq);
30
case float_2nan_prop_s_ab:
46
@@ -XXX,XX +XXX,XX @@ static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size)
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;
47
break;
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();
48
}
82
}
49
83
50
- DPRINTF("(%s) = 0x%08x\n", imx_gpt_reg_name(offset >> 2), reg_value);
84
- if (which) {
51
+ trace_imx_gpt_read(imx_gpt_reg_name(offset >> 2), reg_value);
85
- a = b;
52
86
+ if (is_snan(ret->cls)) {
53
return reg_value;
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;
54
}
94
}
55
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
95
56
IMXGPTState *s = IMX_GPT(opaque);
96
static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
57
uint32_t oldreg;
58
59
- DPRINTF("(%s, value = 0x%08x)\n", imx_gpt_reg_name(offset >> 2),
60
- (uint32_t)value);
61
+ trace_imx_gpt_write(imx_gpt_reg_name(offset >> 2), (uint32_t)value);
62
63
switch (offset >> 2) {
64
case 0:
65
@@ -XXX,XX +XXX,XX @@ static void imx_gpt_timeout(void *opaque)
66
{
67
IMXGPTState *s = IMX_GPT(opaque);
68
69
- DPRINTF("\n");
70
+ trace_imx_gpt_timeout();
71
72
s->sr |= s->next_int;
73
s->next_int = 0;
74
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
75
index XXXXXXX..XXXXXXX 100644
76
--- a/hw/timer/trace-events
77
+++ b/hw/timer/trace-events
78
@@ -XXX,XX +XXX,XX @@ cmsdk_apb_dualtimer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK A
79
cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
80
cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset"
81
82
+# imx_gpt.c
83
+imx_gpt_set_freq(uint32_t clksrc, uint32_t freq) "Setting clksrc %u to %u Hz"
84
+imx_gpt_read(const char *name, uint64_t value) "%s -> 0x%08" PRIx64
85
+imx_gpt_write(const char *name, uint64_t value) "%s <- 0x%08" PRIx64
86
+imx_gpt_timeout(void) ""
87
+
88
# npcm7xx_timer.c
89
npcm7xx_timer_read(const char *id, uint64_t offset, uint64_t value) " %s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
90
npcm7xx_timer_write(const char *id, uint64_t offset, uint64_t value) "%s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
91
--
97
--
92
2.34.1
98
2.34.1
93
99
94
100
diff view generated by jsdifflib
1
From: Bernhard Beschow <shentey@gmail.com>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
I'm migrating to Qualcomm's new open source email infrastructure, so
4
update my email address, and update the mailmap to match.
5
6
Signed-off-by: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
8
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
3
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Message-id: 20241103143330.123596-2-shentey@gmail.com
11
Message-id: 20241205114047.1125842-1-leif.lindholm@oss.qualcomm.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
13
---
8
hw/rtc/ds1338.c | 6 ++++++
14
MAINTAINERS | 2 +-
9
hw/rtc/trace-events | 4 ++++
15
.mailmap | 5 +++--
10
2 files changed, 10 insertions(+)
16
2 files changed, 4 insertions(+), 3 deletions(-)
11
17
12
diff --git a/hw/rtc/ds1338.c b/hw/rtc/ds1338.c
18
diff --git a/MAINTAINERS b/MAINTAINERS
13
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/rtc/ds1338.c
20
--- a/MAINTAINERS
15
+++ b/hw/rtc/ds1338.c
21
+++ b/MAINTAINERS
16
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
17
#include "qemu/module.h"
23
SBSA-REF
18
#include "qom/object.h"
24
M: Radoslaw Biernacki <rad@semihalf.com>
19
#include "sysemu/rtc.h"
25
M: Peter Maydell <peter.maydell@linaro.org>
20
+#include "trace.h"
26
-R: Leif Lindholm <quic_llindhol@quicinc.com>
21
27
+R: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
22
/* Size of NVRAM including both the user-accessible area and the
28
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
23
* secondary register area.
29
L: qemu-arm@nongnu.org
24
@@ -XXX,XX +XXX,XX @@ static uint8_t ds1338_recv(I2CSlave *i2c)
30
S: Maintained
25
uint8_t res;
31
diff --git a/.mailmap b/.mailmap
26
27
res = s->nvram[s->ptr];
28
+
29
+ trace_ds1338_recv(s->ptr, res);
30
+
31
inc_regptr(s);
32
return res;
33
}
34
@@ -XXX,XX +XXX,XX @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
35
{
36
DS1338State *s = DS1338(i2c);
37
38
+ trace_ds1338_send(s->ptr, data);
39
+
40
if (s->addr_byte) {
41
s->ptr = data & (NVRAM_SIZE - 1);
42
s->addr_byte = false;
43
diff --git a/hw/rtc/trace-events b/hw/rtc/trace-events
44
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/rtc/trace-events
33
--- a/.mailmap
46
+++ b/hw/rtc/trace-events
34
+++ b/.mailmap
47
@@ -XXX,XX +XXX,XX @@ pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks"
35
@@ -XXX,XX +XXX,XX @@ Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
48
aspeed_rtc_read(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64
36
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
49
aspeed_rtc_write(uint64_t addr, uint64_t value) "addr 0x%02" PRIx64 " value 0x%08" PRIx64
37
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
50
38
Juan Quintela <quintela@trasno.org> <quintela@redhat.com>
51
+# ds1338.c
39
-Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
52
+ds1338_recv(uint32_t addr, uint8_t value) "[0x%" PRIx32 "] -> 0x%02" PRIx8
40
-Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
53
+ds1338_send(uint32_t addr, uint8_t value) "[0x%" PRIx32 "] <- 0x%02" PRIx8
41
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <quic_llindhol@quicinc.com>
54
+
42
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif.lindholm@linaro.org>
55
# m48t59.c
43
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif@nuviainc.com>
56
m48txx_nvram_io_read(uint64_t addr, uint64_t value) "io read addr:0x%04" PRIx64 " value:0x%02" PRIx64
44
Luc Michel <luc@lmichel.fr> <luc.michel@git.antfield.fr>
57
m48txx_nvram_io_write(uint64_t addr, uint64_t value) "io write addr:0x%04" PRIx64 " value:0x%02" PRIx64
45
Luc Michel <luc@lmichel.fr> <luc.michel@greensocs.com>
46
Luc Michel <luc@lmichel.fr> <lmichel@kalray.eu>
58
--
47
--
59
2.34.1
48
2.34.1
60
49
61
50
diff view generated by jsdifflib
New patch
1
From: Vikram Garhwal <vikram.garhwal@bytedance.com>
1
2
3
Previously, maintainer role was paused due to inactive email id. Commit id:
4
c009d715721861984c4987bcc78b7ee183e86d75.
5
6
Signed-off-by: Vikram Garhwal <vikram.garhwal@bytedance.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20241204184205.12952-1-vikram.garhwal@bytedance.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
MAINTAINERS | 2 ++
12
1 file changed, 2 insertions(+)
13
14
diff --git a/MAINTAINERS b/MAINTAINERS
15
index XXXXXXX..XXXXXXX 100644
16
--- a/MAINTAINERS
17
+++ b/MAINTAINERS
18
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-sb16-test.c
19
20
Xilinx CAN
21
M: Francisco Iglesias <francisco.iglesias@amd.com>
22
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
23
S: Maintained
24
F: hw/net/can/xlnx-*
25
F: include/hw/net/xlnx-*
26
@@ -XXX,XX +XXX,XX @@ F: include/hw/rx/
27
CAN bus subsystem and hardware
28
M: Pavel Pisa <pisa@cmp.felk.cvut.cz>
29
M: Francisco Iglesias <francisco.iglesias@amd.com>
30
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
31
S: Maintained
32
W: https://canbus.pages.fel.cvut.cz/
33
F: net/can/*
34
--
35
2.34.1
diff view generated by jsdifflib