1
The following changes since commit 4eac9dfbd72d346505642fb45ac3141c7eb2c516:
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-tcg-20240301' of https://gitlab.com/rth7680/qemu into staging (2024-03-05 09:45:22 +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-20240305
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 7558300c53057126514ee0fd5cf629c65ccc20e1:
16
for you to fetch changes up to 1abe28d519239eea5cf9620bb13149423e5665f8:
10
17
11
qemu-options.hx: Don't claim "-serial" has limit of 4 serial ports (2024-03-05 13:22:56 +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
* raspi: Implement Broadcom Serial Controller (BSC) for BCM2835 boards
22
* hw/net/lan9118: Extract PHY model, reuse with imx_fec, fix bugs
16
* hw/char/pl011: Add support for loopback
23
* fpu: Make muladd NaN handling runtime-selected, not compile-time
17
* STM32L4x5: Implement RCC clock control device
24
* fpu: Make default NaN pattern runtime-selected, not compile-time
18
* target/arm: Do memory type alignment checks
25
* fpu: Minor NaN-related cleanups
19
* atomic.h: Reword confusing comment for qatomic_cmpxchg
26
* MAINTAINERS: email address updates
20
* qemu-options.hx: Don't claim "-serial" has limit of 4 serial ports
21
27
22
----------------------------------------------------------------
28
----------------------------------------------------------------
23
Arnaud Minier (8):
29
Bernhard Beschow (5):
24
hw/misc/stm32l4x5_rcc: Implement STM32L4x5_RCC skeleton
30
hw/net/lan9118: Extract lan9118_phy
25
hw/misc/stm32l4x5_rcc: Add an internal clock multiplexer object
31
hw/net/lan9118_phy: Reuse in imx_fec and consolidate implementations
26
hw/misc/stm32l4x5_rcc: Add an internal PLL Clock object
32
hw/net/lan9118_phy: Fix off-by-one error in MII_ANLPAR register
27
hw/misc/stm32l4x5_rcc: Initialize PLLs and clock multiplexers
33
hw/net/lan9118_phy: Reuse MII constants
28
hw/misc/stm32l4x5_rcc: Handle Register Updates
34
hw/net/lan9118_phy: Add missing 100 mbps full duplex advertisement
29
hw/misc/stm32l4x5_rcc: Add write protections to CR register
30
hw/arm/stm32l4x5_soc.c: Use the RCC Sysclk
31
tests/qtest/stm32l4x5_rcc-test.c: Add tests for the STM32L4x5_RCC
32
35
33
Peter Maydell (1):
36
Leif Lindholm (1):
34
atomic.h: Reword confusing comment for qatomic_cmpxchg
37
MAINTAINERS: update email address for Leif Lindholm
35
38
36
Rayhan Faizel (3):
39
Peter Maydell (54):
37
hw/i2c: Implement Broadcom Serial Controller (BSC)
40
fpu: handle raising Invalid for infzero in pick_nan_muladd
38
hw/arm: Connect BSC to BCM2835 board as I2C0, I2C1 and I2C2
41
fpu: Check for default_nan_mode before calling pickNaNMulAdd
39
tests/qtest: Add testcase for BCM2835 BSC
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
40
94
41
Richard Henderson (6):
95
Richard Henderson (11):
42
target/arm: Support 32-byte alignment in pow2_align
96
target/arm: Copy entire float_status in is_ebf
43
exec/memattrs: Remove target_tlb_bit*
97
softfloat: Inline pickNaNMulAdd
44
accel/tcg: Add tlb_fill_flags to CPUTLBEntryFull
98
softfloat: Use goto for default nan case in pick_nan_muladd
45
accel/tcg: Add TLB_CHECK_ALIGNED
99
softfloat: Remove which from parts_pick_nan_muladd
46
target/arm: Do memory type alignment check when translation disabled
100
softfloat: Pad array size in pick_nan_muladd
47
target/arm: Do memory type alignment check when translation enabled
101
softfloat: Move propagateFloatx80NaN to softfloat.c
102
softfloat: Use parts_pick_nan in propagateFloatx80NaN
103
softfloat: Inline pickNaN
104
softfloat: Share code between parts_pick_nan cases
105
softfloat: Sink frac_cmp in parts_pick_nan until needed
106
softfloat: Replace WHICH with RET in parts_pick_nan
48
107
49
Steven Shen (1):
108
Vikram Garhwal (1):
50
qemu-options.hx: Don't claim "-serial" has limit of 4 serial ports
109
MAINTAINERS: Add correct email address for Vikram Garhwal
51
110
52
Tong Ho (1):
111
MAINTAINERS | 4 +-
53
hw/char/pl011: Add support for loopback
112
include/fpu/softfloat-helpers.h | 38 +++-
54
113
include/fpu/softfloat-types.h | 89 +++++++-
55
MAINTAINERS | 5 +-
114
include/hw/net/imx_fec.h | 9 +-
56
docs/system/arm/b-l475e-iot01a.rst | 2 +-
115
include/hw/net/lan9118_phy.h | 37 ++++
57
docs/system/arm/raspi.rst | 1 +
116
include/hw/net/mii.h | 6 +
58
include/exec/cpu-all.h | 4 +-
117
target/mips/fpu_helper.h | 20 ++
59
include/exec/memattrs.h | 12 -
118
target/sparc/helper.h | 4 +-
60
include/hw/arm/bcm2835_peripherals.h | 4 +-
119
fpu/softfloat.c | 19 ++
61
include/hw/arm/stm32l4x5_soc.h | 5 +-
120
hw/net/imx_fec.c | 146 ++------------
62
include/hw/core/cpu.h | 3 +
121
hw/net/lan9118.c | 137 ++-----------
63
include/hw/i2c/bcm2835_i2c.h | 80 ++
122
hw/net/lan9118_phy.c | 222 ++++++++++++++++++++
64
include/hw/misc/stm32l4x5_rcc.h | 239 +++++
123
linux-user/arm/nwfpe/fpa11.c | 5 +
65
include/hw/misc/stm32l4x5_rcc_internals.h | 1042 +++++++++++++++++++++
124
target/alpha/cpu.c | 2 +
66
include/qemu/atomic.h | 2 +-
125
target/arm/cpu.c | 10 +
67
accel/tcg/cputlb.c | 35 +-
126
target/arm/tcg/vec_helper.c | 20 +-
68
hw/arm/b-l475e-iot01a.c | 10 +-
127
target/hexagon/cpu.c | 2 +
69
hw/arm/bcm2835_peripherals.c | 45 +-
128
target/hppa/fpu_helper.c | 12 ++
70
hw/arm/stm32l4x5_soc.c | 45 +-
129
target/i386/tcg/fpu_helper.c | 12 ++
71
hw/char/pl011.c | 110 ++-
130
target/loongarch/tcg/fpu_helper.c | 14 +-
72
hw/i2c/bcm2835_i2c.c | 282 ++++++
131
target/m68k/cpu.c | 14 +-
73
hw/misc/stm32l4x5_rcc.c | 1457 +++++++++++++++++++++++++++++
132
target/m68k/fpu_helper.c | 6 +-
74
target/arm/ptw.c | 39 +
133
target/m68k/helper.c | 6 +-
75
target/arm/tcg/hflags.c | 34 +-
134
target/microblaze/cpu.c | 2 +
76
target/arm/tcg/translate.c | 8 +-
135
target/mips/msa.c | 10 +
77
target/sparc/mmu_helper.c | 2 +-
136
target/openrisc/cpu.c | 2 +
78
tests/qtest/bcm2835-i2c-test.c | 115 +++
137
target/ppc/cpu_init.c | 19 ++
79
tests/qtest/stm32l4x5_rcc-test.c | 189 ++++
138
target/ppc/fpu_helper.c | 3 +-
80
hw/arm/Kconfig | 2 +
139
target/riscv/cpu.c | 2 +
81
hw/i2c/Kconfig | 4 +
140
target/rx/cpu.c | 2 +
82
hw/i2c/meson.build | 1 +
141
target/s390x/cpu.c | 5 +
83
hw/misc/Kconfig | 3 +
142
target/sh4/cpu.c | 2 +
84
hw/misc/meson.build | 1 +
143
target/sparc/cpu.c | 6 +
85
hw/misc/trace-events | 14 +
144
target/sparc/fop_helper.c | 8 +-
86
qemu-options.hx | 2 +-
145
target/sparc/translate.c | 4 +-
87
tests/qtest/meson.build | 5 +-
146
target/tricore/helper.c | 2 +
88
33 files changed, 3718 insertions(+), 84 deletions(-)
147
target/xtensa/cpu.c | 4 +
89
create mode 100644 include/hw/i2c/bcm2835_i2c.h
148
target/xtensa/fpu_helper.c | 3 +-
90
create mode 100644 include/hw/misc/stm32l4x5_rcc.h
149
tests/fp/fp-bench.c | 7 +
91
create mode 100644 include/hw/misc/stm32l4x5_rcc_internals.h
150
tests/fp/fp-test-log2.c | 1 +
92
create mode 100644 hw/i2c/bcm2835_i2c.c
151
tests/fp/fp-test.c | 7 +
93
create mode 100644 hw/misc/stm32l4x5_rcc.c
152
fpu/softfloat-parts.c.inc | 152 +++++++++++---
94
create mode 100644 tests/qtest/bcm2835-i2c-test.c
153
fpu/softfloat-specialize.c.inc | 412 ++------------------------------------
95
create mode 100644 tests/qtest/stm32l4x5_rcc-test.c
154
.mailmap | 5 +-
155
hw/net/Kconfig | 5 +
156
hw/net/meson.build | 1 +
157
hw/net/trace-events | 10 +-
158
47 files changed, 778 insertions(+), 730 deletions(-)
159
create mode 100644 include/hw/net/lan9118_phy.h
160
create mode 100644 hw/net/lan9118_phy.c
diff view generated by jsdifflib
1
From: Rayhan Faizel <rayhan.faizel@gmail.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
A few deficiencies in the current device model need to be noted.
3
A very similar implementation of the same device exists in imx_fec. Prepare for
4
a common implementation by extracting a device model into its own files.
4
5
5
1. FIFOs are not used. All sends and receives are done directly.
6
Some migration state has been moved into the new device model which breaks
6
2. Repeated starts are not emulated. Repeated starts can be triggered in real
7
migration compatibility for the following machines:
7
hardware by sending a new read transfer request in the window time between
8
* smdkc210
8
transfer active set of write transfer request and done bit set of the same.
9
* realview-*
10
* vexpress-*
11
* kzm
12
* mps2-*
9
13
10
Signed-off-by: Rayhan Faizel <rayhan.faizel@gmail.com>
14
While breaking migration ABI, fix the size of the MII registers to be 16 bit,
15
as defined by IEEE 802.3u.
16
17
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
18
Tested-by: Guenter Roeck <linux@roeck-us.net>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20240224191038.2409945-2-rayhan.faizel@gmail.com
20
Message-id: 20241102125724.532843-2-shentey@gmail.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
22
---
15
docs/system/arm/raspi.rst | 1 +
23
include/hw/net/lan9118_phy.h | 37 ++++++++
16
include/hw/i2c/bcm2835_i2c.h | 80 ++++++++++
24
hw/net/lan9118.c | 137 +++++-----------------------
17
hw/i2c/bcm2835_i2c.c | 282 +++++++++++++++++++++++++++++++++++
25
hw/net/lan9118_phy.c | 169 +++++++++++++++++++++++++++++++++++
18
hw/i2c/Kconfig | 4 +
26
hw/net/Kconfig | 4 +
19
hw/i2c/meson.build | 1 +
27
hw/net/meson.build | 1 +
20
5 files changed, 368 insertions(+)
28
5 files changed, 233 insertions(+), 115 deletions(-)
21
create mode 100644 include/hw/i2c/bcm2835_i2c.h
29
create mode 100644 include/hw/net/lan9118_phy.h
22
create mode 100644 hw/i2c/bcm2835_i2c.c
30
create mode 100644 hw/net/lan9118_phy.c
23
31
24
diff --git a/docs/system/arm/raspi.rst b/docs/system/arm/raspi.rst
32
diff --git a/include/hw/net/lan9118_phy.h b/include/hw/net/lan9118_phy.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/docs/system/arm/raspi.rst
27
+++ b/docs/system/arm/raspi.rst
28
@@ -XXX,XX +XXX,XX @@ Implemented devices
29
* MailBox controller (MBOX)
30
* VideoCore firmware (property)
31
* Peripheral SPI controller (SPI)
32
+ * Broadcom Serial Controller (I2C)
33
34
Missing devices
35
---------------
36
diff --git a/include/hw/i2c/bcm2835_i2c.h b/include/hw/i2c/bcm2835_i2c.h
37
new file mode 100644
33
new file mode 100644
38
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
39
--- /dev/null
35
--- /dev/null
40
+++ b/include/hw/i2c/bcm2835_i2c.h
36
+++ b/include/hw/net/lan9118_phy.h
41
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
42
+/*
38
+/*
43
+ * Broadcom Serial Controller (BSC)
39
+ * SMSC LAN9118 PHY emulation
44
+ *
40
+ *
45
+ * Copyright (c) 2024 Rayhan Faizel <rayhan.faizel@gmail.com>
41
+ * Copyright (c) 2009 CodeSourcery, LLC.
42
+ * Written by Paul Brook
46
+ *
43
+ *
47
+ * SPDX-License-Identifier: MIT
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
48
+ *
45
+ * See the COPYING file in the top-level directory.
49
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
50
+ * of this software and associated documentation files (the "Software"), to deal
51
+ * in the Software without restriction, including without limitation the rights
52
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
53
+ * copies of the Software, and to permit persons to whom the Software is
54
+ * furnished to do so, subject to the following conditions:
55
+ *
56
+ * The above copyright notice and this permission notice shall be included in
57
+ * all copies or substantial portions of the Software.
58
+ *
59
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
60
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
61
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
62
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
64
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
65
+ * THE SOFTWARE.
66
+ */
46
+ */
67
+
47
+
48
+#ifndef HW_NET_LAN9118_PHY_H
49
+#define HW_NET_LAN9118_PHY_H
50
+
51
+#include "qom/object.h"
68
+#include "hw/sysbus.h"
52
+#include "hw/sysbus.h"
69
+#include "hw/i2c/i2c.h"
53
+
70
+#include "qom/object.h"
54
+#define TYPE_LAN9118_PHY "lan9118-phy"
71
+
55
+OBJECT_DECLARE_SIMPLE_TYPE(Lan9118PhyState, LAN9118_PHY)
72
+#define TYPE_BCM2835_I2C "bcm2835-i2c"
56
+
73
+OBJECT_DECLARE_SIMPLE_TYPE(BCM2835I2CState, BCM2835_I2C)
57
+typedef struct Lan9118PhyState {
74
+
75
+#define BCM2835_I2C_C 0x0 /* Control */
76
+#define BCM2835_I2C_S 0x4 /* Status */
77
+#define BCM2835_I2C_DLEN 0x8 /* Data Length */
78
+#define BCM2835_I2C_A 0xc /* Slave Address */
79
+#define BCM2835_I2C_FIFO 0x10 /* FIFO */
80
+#define BCM2835_I2C_DIV 0x14 /* Clock Divider */
81
+#define BCM2835_I2C_DEL 0x18 /* Data Delay */
82
+#define BCM2835_I2C_CLKT 0x20 /* Clock Stretch Timeout */
83
+
84
+#define BCM2835_I2C_C_I2CEN BIT(15) /* I2C enable */
85
+#define BCM2835_I2C_C_INTR BIT(10) /* Interrupt on RXR */
86
+#define BCM2835_I2C_C_INTT BIT(9) /* Interrupt on TXW */
87
+#define BCM2835_I2C_C_INTD BIT(8) /* Interrupt on DONE */
88
+#define BCM2835_I2C_C_ST BIT(7) /* Start transfer */
89
+#define BCM2835_I2C_C_CLEAR (BIT(5) | BIT(4)) /* Clear FIFO */
90
+#define BCM2835_I2C_C_READ BIT(0) /* I2C read mode */
91
+
92
+#define BCM2835_I2C_S_CLKT BIT(9) /* Clock stretch timeout */
93
+#define BCM2835_I2C_S_ERR BIT(8) /* Slave error */
94
+#define BCM2835_I2C_S_RXF BIT(7) /* RX FIFO full */
95
+#define BCM2835_I2C_S_TXE BIT(6) /* TX FIFO empty */
96
+#define BCM2835_I2C_S_RXD BIT(5) /* RX bytes available */
97
+#define BCM2835_I2C_S_TXD BIT(4) /* TX space available */
98
+#define BCM2835_I2C_S_RXR BIT(3) /* RX FIFO needs reading */
99
+#define BCM2835_I2C_S_TXW BIT(2) /* TX FIFO needs writing */
100
+#define BCM2835_I2C_S_DONE BIT(1) /* I2C Transfer complete */
101
+#define BCM2835_I2C_S_TA BIT(0) /* I2C Transfer active */
102
+
103
+struct BCM2835I2CState {
104
+ /* <private> */
105
+ SysBusDevice parent_obj;
58
+ SysBusDevice parent_obj;
106
+
59
+
107
+ /* <public> */
60
+ uint16_t status;
108
+ MemoryRegion iomem;
61
+ uint16_t control;
109
+ I2CBus *bus;
62
+ uint16_t advertise;
63
+ uint16_t ints;
64
+ uint16_t int_mask;
110
+ qemu_irq irq;
65
+ qemu_irq irq;
111
+
66
+ bool link_down;
112
+ uint32_t c;
67
+} Lan9118PhyState;
113
+ uint32_t s;
68
+
114
+ uint32_t dlen;
69
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down);
115
+ uint32_t a;
70
+void lan9118_phy_reset(Lan9118PhyState *s);
116
+ uint32_t div;
71
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg);
117
+ uint32_t del;
72
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val);
118
+ uint32_t clkt;
73
+
119
+
74
+#endif
120
+ uint32_t last_dlen;
75
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
121
+};
76
index XXXXXXX..XXXXXXX 100644
122
diff --git a/hw/i2c/bcm2835_i2c.c b/hw/i2c/bcm2835_i2c.c
77
--- a/hw/net/lan9118.c
78
+++ b/hw/net/lan9118.c
79
@@ -XXX,XX +XXX,XX @@
80
#include "net/net.h"
81
#include "net/eth.h"
82
#include "hw/irq.h"
83
+#include "hw/net/lan9118_phy.h"
84
#include "hw/net/lan9118.h"
85
#include "hw/ptimer.h"
86
#include "hw/qdev-properties.h"
87
@@ -XXX,XX +XXX,XX @@ do { printf("lan9118: " fmt , ## __VA_ARGS__); } while (0)
88
#define MAC_CR_RXEN 0x00000004
89
#define MAC_CR_RESERVED 0x7f404213
90
91
-#define PHY_INT_ENERGYON 0x80
92
-#define PHY_INT_AUTONEG_COMPLETE 0x40
93
-#define PHY_INT_FAULT 0x20
94
-#define PHY_INT_DOWN 0x10
95
-#define PHY_INT_AUTONEG_LP 0x08
96
-#define PHY_INT_PARFAULT 0x04
97
-#define PHY_INT_AUTONEG_PAGE 0x02
98
-
99
#define GPT_TIMER_EN 0x20000000
100
101
/*
102
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
103
uint32_t mac_mii_data;
104
uint32_t mac_flow;
105
106
- uint32_t phy_status;
107
- uint32_t phy_control;
108
- uint32_t phy_advertise;
109
- uint32_t phy_int;
110
- uint32_t phy_int_mask;
111
+ Lan9118PhyState mii;
112
+ IRQState mii_irq;
113
114
int32_t eeprom_writable;
115
uint8_t eeprom[128];
116
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
117
118
static const VMStateDescription vmstate_lan9118 = {
119
.name = "lan9118",
120
- .version_id = 2,
121
- .minimum_version_id = 1,
122
+ .version_id = 3,
123
+ .minimum_version_id = 3,
124
.fields = (const VMStateField[]) {
125
VMSTATE_PTIMER(timer, lan9118_state),
126
VMSTATE_UINT32(irq_cfg, lan9118_state),
127
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118 = {
128
VMSTATE_UINT32(mac_mii_acc, lan9118_state),
129
VMSTATE_UINT32(mac_mii_data, lan9118_state),
130
VMSTATE_UINT32(mac_flow, lan9118_state),
131
- VMSTATE_UINT32(phy_status, lan9118_state),
132
- VMSTATE_UINT32(phy_control, lan9118_state),
133
- VMSTATE_UINT32(phy_advertise, lan9118_state),
134
- VMSTATE_UINT32(phy_int, lan9118_state),
135
- VMSTATE_UINT32(phy_int_mask, lan9118_state),
136
VMSTATE_INT32(eeprom_writable, lan9118_state),
137
VMSTATE_UINT8_ARRAY(eeprom, lan9118_state, 128),
138
VMSTATE_INT32(tx_fifo_size, lan9118_state),
139
@@ -XXX,XX +XXX,XX @@ static void lan9118_reload_eeprom(lan9118_state *s)
140
lan9118_mac_changed(s);
141
}
142
143
-static void phy_update_irq(lan9118_state *s)
144
+static void lan9118_update_irq(void *opaque, int n, int level)
145
{
146
- if (s->phy_int & s->phy_int_mask) {
147
+ lan9118_state *s = opaque;
148
+
149
+ if (level) {
150
s->int_sts |= PHY_INT;
151
} else {
152
s->int_sts &= ~PHY_INT;
153
@@ -XXX,XX +XXX,XX @@ static void phy_update_irq(lan9118_state *s)
154
lan9118_update(s);
155
}
156
157
-static void phy_update_link(lan9118_state *s)
158
-{
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)
208
}
209
}
210
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
123
new file mode 100644
312
new file mode 100644
124
index XXXXXXX..XXXXXXX
313
index XXXXXXX..XXXXXXX
125
--- /dev/null
314
--- /dev/null
126
+++ b/hw/i2c/bcm2835_i2c.c
315
+++ b/hw/net/lan9118_phy.c
127
@@ -XXX,XX +XXX,XX @@
316
@@ -XXX,XX +XXX,XX @@
128
+/*
317
+/*
129
+ * Broadcom Serial Controller (BSC)
318
+ * SMSC LAN9118 PHY emulation
130
+ *
319
+ *
131
+ * Copyright (c) 2024 Rayhan Faizel <rayhan.faizel@gmail.com>
320
+ * Copyright (c) 2009 CodeSourcery, LLC.
321
+ * Written by Paul Brook
132
+ *
322
+ *
133
+ * SPDX-License-Identifier: MIT
323
+ * This code is licensed under the GNU GPL v2
134
+ *
324
+ *
135
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
325
+ * Contributions after 2012-01-13 are licensed under the terms of the
136
+ * of this software and associated documentation files (the "Software"), to deal
326
+ * GNU GPL, version 2 or (at your option) any later version.
137
+ * in the Software without restriction, including without limitation the rights
138
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
139
+ * copies of the Software, and to permit persons to whom the Software is
140
+ * furnished to do so, subject to the following conditions:
141
+ *
142
+ * The above copyright notice and this permission notice shall be included in
143
+ * all copies or substantial portions of the Software.
144
+ *
145
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
146
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
147
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
148
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
149
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
150
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
151
+ * THE SOFTWARE.
152
+ */
327
+ */
153
+
328
+
154
+#include "qemu/osdep.h"
329
+#include "qemu/osdep.h"
330
+#include "hw/net/lan9118_phy.h"
331
+#include "hw/irq.h"
332
+#include "hw/resettable.h"
333
+#include "migration/vmstate.h"
155
+#include "qemu/log.h"
334
+#include "qemu/log.h"
156
+#include "hw/i2c/bcm2835_i2c.h"
335
+
157
+#include "hw/irq.h"
336
+#define PHY_INT_ENERGYON (1 << 7)
158
+#include "migration/vmstate.h"
337
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
159
+
338
+#define PHY_INT_FAULT (1 << 5)
160
+static void bcm2835_i2c_update_interrupt(BCM2835I2CState *s)
339
+#define PHY_INT_DOWN (1 << 4)
161
+{
340
+#define PHY_INT_AUTONEG_LP (1 << 3)
162
+ int do_interrupt = 0;
341
+#define PHY_INT_PARFAULT (1 << 2)
163
+ /* Interrupt on RXR (Needs reading) */
342
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
164
+ if (s->c & BCM2835_I2C_C_INTR && s->s & BCM2835_I2C_S_RXR) {
343
+
165
+ do_interrupt = 1;
344
+static void lan9118_phy_update_irq(Lan9118PhyState *s)
345
+{
346
+ qemu_set_irq(s->irq, !!(s->ints & s->int_mask));
347
+}
348
+
349
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
350
+{
351
+ uint16_t val;
352
+
353
+ switch (reg) {
354
+ case 0: /* Basic Control */
355
+ return s->control;
356
+ case 1: /* Basic Status */
357
+ return s->status;
358
+ case 2: /* ID1 */
359
+ return 0x0007;
360
+ case 3: /* ID2 */
361
+ return 0xc0d1;
362
+ case 4: /* Auto-neg advertisement */
363
+ return s->advertise;
364
+ case 5: /* Auto-neg Link Partner Ability */
365
+ return 0x0f71;
366
+ case 6: /* Auto-neg Expansion */
367
+ return 1;
368
+ /* TODO 17, 18, 27, 29, 30, 31 */
369
+ case 29: /* Interrupt source. */
370
+ val = s->ints;
371
+ s->ints = 0;
372
+ lan9118_phy_update_irq(s);
373
+ return val;
374
+ case 30: /* Interrupt mask */
375
+ return s->int_mask;
376
+ default:
377
+ qemu_log_mask(LOG_GUEST_ERROR,
378
+ "lan9118_phy_read: PHY read reg %d\n", reg);
379
+ return 0;
166
+ }
380
+ }
167
+
381
+}
168
+ /* Interrupt on TXW (Needs writing) */
382
+
169
+ if (s->c & BCM2835_I2C_C_INTT && s->s & BCM2835_I2C_S_TXW) {
383
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
170
+ do_interrupt = 1;
384
+{
171
+ }
385
+ switch (reg) {
172
+
386
+ case 0: /* Basic Control */
173
+ /* Interrupt on DONE (Transfer complete) */
387
+ if (val & 0x8000) {
174
+ if (s->c & BCM2835_I2C_C_INTD && s->s & BCM2835_I2C_S_DONE) {
388
+ lan9118_phy_reset(s);
175
+ do_interrupt = 1;
389
+ break;
176
+ }
390
+ }
177
+ qemu_set_irq(s->irq, do_interrupt);
391
+ s->control = val & 0x7980;
178
+}
392
+ /* Complete autonegotiation immediately. */
179
+
393
+ if (val & 0x1000) {
180
+static void bcm2835_i2c_begin_transfer(BCM2835I2CState *s)
394
+ s->status |= 0x0020;
181
+{
395
+ }
182
+ int direction = s->c & BCM2835_I2C_C_READ;
183
+ if (i2c_start_transfer(s->bus, s->a, direction)) {
184
+ s->s |= BCM2835_I2C_S_ERR;
185
+ }
186
+ s->s |= BCM2835_I2C_S_TA;
187
+
188
+ if (direction) {
189
+ s->s |= BCM2835_I2C_S_RXR | BCM2835_I2C_S_RXD;
190
+ } else {
191
+ s->s |= BCM2835_I2C_S_TXW;
192
+ }
193
+}
194
+
195
+static void bcm2835_i2c_finish_transfer(BCM2835I2CState *s)
196
+{
197
+ /*
198
+ * STOP is sent when DLEN counts down to zero.
199
+ *
200
+ * https://github.com/torvalds/linux/blob/v6.7/drivers/i2c/busses/i2c-bcm2835.c#L223-L261
201
+ * It is possible to initiate repeated starts on real hardware.
202
+ * However, this requires sending another ST request before the bytes in
203
+ * TX FIFO are shifted out.
204
+ *
205
+ * This is not emulated currently.
206
+ */
207
+ i2c_end_transfer(s->bus);
208
+ s->s |= BCM2835_I2C_S_DONE;
209
+
210
+ /* Ensure RXD is cleared, otherwise the driver registers an error */
211
+ s->s &= ~(BCM2835_I2C_S_TA | BCM2835_I2C_S_RXR |
212
+ BCM2835_I2C_S_TXW | BCM2835_I2C_S_RXD);
213
+}
214
+
215
+static uint64_t bcm2835_i2c_read(void *opaque, hwaddr addr, unsigned size)
216
+{
217
+ BCM2835I2CState *s = opaque;
218
+ uint32_t readval = 0;
219
+
220
+ switch (addr) {
221
+ case BCM2835_I2C_C:
222
+ readval = s->c;
223
+ break;
396
+ break;
224
+ case BCM2835_I2C_S:
397
+ case 4: /* Auto-neg advertisement */
225
+ readval = s->s;
398
+ s->advertise = (val & 0x2d7f) | 0x80;
226
+ break;
399
+ break;
227
+ case BCM2835_I2C_DLEN:
400
+ /* TODO 17, 18, 27, 31 */
228
+ readval = s->dlen;
401
+ case 30: /* Interrupt mask */
229
+ break;
402
+ s->int_mask = val & 0xff;
230
+ case BCM2835_I2C_A:
403
+ lan9118_phy_update_irq(s);
231
+ readval = s->a;
232
+ break;
233
+ case BCM2835_I2C_FIFO:
234
+ /* We receive I2C messages directly instead of using FIFOs */
235
+ if (s->s & BCM2835_I2C_S_TA) {
236
+ readval = i2c_recv(s->bus);
237
+ s->dlen -= 1;
238
+
239
+ if (s->dlen == 0) {
240
+ bcm2835_i2c_finish_transfer(s);
241
+ }
242
+ }
243
+ bcm2835_i2c_update_interrupt(s);
244
+ break;
245
+ case BCM2835_I2C_DIV:
246
+ readval = s->div;
247
+ break;
248
+ case BCM2835_I2C_DEL:
249
+ readval = s->del;
250
+ break;
251
+ case BCM2835_I2C_CLKT:
252
+ readval = s->clkt;
253
+ break;
404
+ break;
254
+ default:
405
+ default:
255
+ qemu_log_mask(LOG_GUEST_ERROR,
406
+ qemu_log_mask(LOG_GUEST_ERROR,
256
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
407
+ "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
257
+ }
408
+ }
258
+
409
+}
259
+ return readval;
410
+
260
+}
411
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
261
+
412
+{
262
+static void bcm2835_i2c_write(void *opaque, hwaddr addr,
413
+ s->link_down = link_down;
263
+ uint64_t value, unsigned int size)
414
+
264
+{
415
+ /* Autonegotiation status mirrors link status. */
265
+ BCM2835I2CState *s = opaque;
416
+ if (link_down) {
266
+ uint32_t writeval = value;
417
+ s->status &= ~0x0024;
267
+
418
+ s->ints |= PHY_INT_DOWN;
268
+ switch (addr) {
419
+ } else {
269
+ case BCM2835_I2C_C:
420
+ s->status |= 0x0024;
270
+ /* ST is a one-shot operation; it must read back as 0 */
421
+ s->ints |= PHY_INT_ENERGYON;
271
+ s->c = writeval & ~BCM2835_I2C_C_ST;
422
+ s->ints |= PHY_INT_AUTONEG_COMPLETE;
272
+
273
+ /* Start transfer */
274
+ if (writeval & (BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN)) {
275
+ bcm2835_i2c_begin_transfer(s);
276
+ /*
277
+ * Handle special case where transfer starts with zero data length.
278
+ * Required for zero length i2c quick messages to work.
279
+ */
280
+ if (s->dlen == 0) {
281
+ bcm2835_i2c_finish_transfer(s);
282
+ }
283
+ }
284
+
285
+ bcm2835_i2c_update_interrupt(s);
286
+ break;
287
+ case BCM2835_I2C_S:
288
+ if (writeval & BCM2835_I2C_S_DONE && s->s & BCM2835_I2C_S_DONE) {
289
+ /* When DONE is cleared, DLEN should read last written value. */
290
+ s->dlen = s->last_dlen;
291
+ }
292
+
293
+ /* Clear DONE, CLKT and ERR by writing 1 */
294
+ s->s &= ~(writeval & (BCM2835_I2C_S_DONE |
295
+ BCM2835_I2C_S_ERR | BCM2835_I2C_S_CLKT));
296
+ break;
297
+ case BCM2835_I2C_DLEN:
298
+ s->dlen = writeval;
299
+ s->last_dlen = writeval;
300
+ break;
301
+ case BCM2835_I2C_A:
302
+ s->a = writeval;
303
+ break;
304
+ case BCM2835_I2C_FIFO:
305
+ /* We send I2C messages directly instead of using FIFOs */
306
+ if (s->s & BCM2835_I2C_S_TA) {
307
+ if (s->s & BCM2835_I2C_S_TXD) {
308
+ if (!i2c_send(s->bus, writeval & 0xff)) {
309
+ s->dlen -= 1;
310
+ } else {
311
+ s->s |= BCM2835_I2C_S_ERR;
312
+ }
313
+ }
314
+
315
+ if (s->dlen == 0) {
316
+ bcm2835_i2c_finish_transfer(s);
317
+ }
318
+ }
319
+ bcm2835_i2c_update_interrupt(s);
320
+ break;
321
+ case BCM2835_I2C_DIV:
322
+ s->div = writeval;
323
+ break;
324
+ case BCM2835_I2C_DEL:
325
+ s->del = writeval;
326
+ break;
327
+ case BCM2835_I2C_CLKT:
328
+ s->clkt = writeval;
329
+ break;
330
+ default:
331
+ qemu_log_mask(LOG_GUEST_ERROR,
332
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
333
+ }
423
+ }
334
+}
424
+ lan9118_phy_update_irq(s);
335
+
425
+}
336
+static const MemoryRegionOps bcm2835_i2c_ops = {
426
+
337
+ .read = bcm2835_i2c_read,
427
+void lan9118_phy_reset(Lan9118PhyState *s)
338
+ .write = bcm2835_i2c_write,
428
+{
339
+ .endianness = DEVICE_NATIVE_ENDIAN,
429
+ s->control = 0x3000;
340
+ .valid = {
430
+ s->status = 0x7809;
341
+ .min_access_size = 4,
431
+ s->advertise = 0x01e1;
342
+ .max_access_size = 4,
432
+ s->int_mask = 0;
343
+ },
433
+ s->ints = 0;
344
+};
434
+ lan9118_phy_update_link(s, s->link_down);
345
+
435
+}
346
+static void bcm2835_i2c_realize(DeviceState *dev, Error **errp)
436
+
347
+{
437
+static void lan9118_phy_reset_hold(Object *obj, ResetType type)
348
+ BCM2835I2CState *s = BCM2835_I2C(dev);
438
+{
349
+ s->bus = i2c_init_bus(dev, NULL);
439
+ Lan9118PhyState *s = LAN9118_PHY(obj);
350
+
440
+
351
+ memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_i2c_ops, s,
441
+ lan9118_phy_reset(s);
352
+ TYPE_BCM2835_I2C, 0x24);
442
+}
353
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
443
+
354
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
444
+static void lan9118_phy_init(Object *obj)
355
+}
445
+{
356
+
446
+ Lan9118PhyState *s = LAN9118_PHY(obj);
357
+static void bcm2835_i2c_reset(DeviceState *dev)
447
+
358
+{
448
+ qdev_init_gpio_out(DEVICE(s), &s->irq, 1);
359
+ BCM2835I2CState *s = BCM2835_I2C(dev);
449
+}
360
+
450
+
361
+ /* Reset values according to BCM2835 Peripheral Documentation */
451
+static const VMStateDescription vmstate_lan9118_phy = {
362
+ s->c = 0x0;
452
+ .name = "lan9118-phy",
363
+ s->s = BCM2835_I2C_S_TXD | BCM2835_I2C_S_TXE;
364
+ s->dlen = 0x0;
365
+ s->a = 0x0;
366
+ s->div = 0x5dc;
367
+ s->del = 0x00300030;
368
+ s->clkt = 0x40;
369
+}
370
+
371
+static const VMStateDescription vmstate_bcm2835_i2c = {
372
+ .name = TYPE_BCM2835_I2C,
373
+ .version_id = 1,
453
+ .version_id = 1,
374
+ .minimum_version_id = 1,
454
+ .minimum_version_id = 1,
375
+ .fields = (const VMStateField[]) {
455
+ .fields = (const VMStateField[]) {
376
+ VMSTATE_UINT32(c, BCM2835I2CState),
456
+ VMSTATE_UINT16(control, Lan9118PhyState),
377
+ VMSTATE_UINT32(s, BCM2835I2CState),
457
+ VMSTATE_UINT16(status, Lan9118PhyState),
378
+ VMSTATE_UINT32(dlen, BCM2835I2CState),
458
+ VMSTATE_UINT16(advertise, Lan9118PhyState),
379
+ VMSTATE_UINT32(a, BCM2835I2CState),
459
+ VMSTATE_UINT16(ints, Lan9118PhyState),
380
+ VMSTATE_UINT32(div, BCM2835I2CState),
460
+ VMSTATE_UINT16(int_mask, Lan9118PhyState),
381
+ VMSTATE_UINT32(del, BCM2835I2CState),
461
+ VMSTATE_BOOL(link_down, Lan9118PhyState),
382
+ VMSTATE_UINT32(clkt, BCM2835I2CState),
383
+ VMSTATE_UINT32(last_dlen, BCM2835I2CState),
384
+ VMSTATE_END_OF_LIST()
462
+ VMSTATE_END_OF_LIST()
385
+ }
463
+ }
386
+};
464
+};
387
+
465
+
388
+static void bcm2835_i2c_class_init(ObjectClass *klass, void *data)
466
+static void lan9118_phy_class_init(ObjectClass *klass, void *data)
389
+{
467
+{
468
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
390
+ DeviceClass *dc = DEVICE_CLASS(klass);
469
+ DeviceClass *dc = DEVICE_CLASS(klass);
391
+
470
+
392
+ dc->reset = bcm2835_i2c_reset;
471
+ rc->phases.hold = lan9118_phy_reset_hold;
393
+ dc->realize = bcm2835_i2c_realize;
472
+ dc->vmsd = &vmstate_lan9118_phy;
394
+ dc->vmsd = &vmstate_bcm2835_i2c;
473
+}
395
+}
474
+
396
+
475
+static const TypeInfo types[] = {
397
+static const TypeInfo bcm2835_i2c_info = {
476
+ {
398
+ .name = TYPE_BCM2835_I2C,
477
+ .name = TYPE_LAN9118_PHY,
399
+ .parent = TYPE_SYS_BUS_DEVICE,
478
+ .parent = TYPE_SYS_BUS_DEVICE,
400
+ .instance_size = sizeof(BCM2835I2CState),
479
+ .instance_size = sizeof(Lan9118PhyState),
401
+ .class_init = bcm2835_i2c_class_init,
480
+ .instance_init = lan9118_phy_init,
481
+ .class_init = lan9118_phy_class_init,
482
+ }
402
+};
483
+};
403
+
484
+
404
+static void bcm2835_i2c_register_types(void)
485
+DEFINE_TYPES(types)
405
+{
486
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
406
+ type_register_static(&bcm2835_i2c_info);
407
+}
408
+
409
+type_init(bcm2835_i2c_register_types)
410
diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig
411
index XXXXXXX..XXXXXXX 100644
487
index XXXXXXX..XXXXXXX 100644
412
--- a/hw/i2c/Kconfig
488
--- a/hw/net/Kconfig
413
+++ b/hw/i2c/Kconfig
489
+++ b/hw/net/Kconfig
414
@@ -XXX,XX +XXX,XX @@ config PCA954X
490
@@ -XXX,XX +XXX,XX @@ config VMXNET3_PCI
415
config PMBUS
491
config SMC91C111
416
bool
492
bool
417
select SMBUS
493
418
+
494
+config LAN9118_PHY
419
+config BCM2835_I2C
420
+ bool
495
+ bool
421
+ select I2C
496
+
422
diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build
497
config LAN9118
498
bool
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
423
index XXXXXXX..XXXXXXX 100644
504
index XXXXXXX..XXXXXXX 100644
424
--- a/hw/i2c/meson.build
505
--- a/hw/net/meson.build
425
+++ b/hw/i2c/meson.build
506
+++ b/hw/net/meson.build
426
@@ -XXX,XX +XXX,XX @@ i2c_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_i2c.c'))
507
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('vmxnet3.c'))
427
i2c_ss.add(when: 'CONFIG_PPC4XX', if_true: files('ppc4xx_i2c.c'))
508
428
i2c_ss.add(when: 'CONFIG_PCA954X', if_true: files('i2c_mux_pca954x.c'))
509
system_ss.add(when: 'CONFIG_SMC91C111', if_true: files('smc91c111.c'))
429
i2c_ss.add(when: 'CONFIG_PMBUS', if_true: files('pmbus_device.c'))
510
system_ss.add(when: 'CONFIG_LAN9118', if_true: files('lan9118.c'))
430
+i2c_ss.add(when: 'CONFIG_BCM2835_I2C', if_true: files('bcm2835_i2c.c'))
511
+system_ss.add(when: 'CONFIG_LAN9118_PHY', if_true: files('lan9118_phy.c'))
431
system_ss.add_all(when: 'CONFIG_I2C', if_true: i2c_ss)
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'))
432
--
515
--
433
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
1
From: Steven Shen <steven.shen@jaguarmicro.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Before v2.12, the implementation of serial ports was limited to
3
Turns 0x70 into 0xe0 (== 0x70 << 1) which adds the missing MII_ANLPAR_TX and
4
a value of MAX_SERIAL_PORTS = 4. We now dynamically allocate
4
fixes the MSB of selector field to be zero, as specified in the datasheet.
5
the data structures for serial ports, so this limit is no longer
6
present, but the documentation for the -serial options still reads:
7
5
8
"This option can be used several times to simulate up to 4 serial ports."
6
Fixes: 2a424990170b "LAN9118 emulation"
9
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
10
Update to "This option can be used several times to simulate
8
Tested-by: Guenter Roeck <linux@roeck-us.net>
11
multiple serial ports." to avoid misleading.
12
13
Signed-off-by: Steven Shen <steven.shen@jaguarmicro.com>
14
Message-id: 20240305013016.2268-1-steven.shen@jaguarmicro.com
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
[PMM: tweaked commit message]
10
Message-id: 20241102125724.532843-4-shentey@gmail.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
12
---
19
qemu-options.hx | 2 +-
13
hw/net/lan9118_phy.c | 2 +-
20
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
21
15
22
diff --git a/qemu-options.hx b/qemu-options.hx
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/qemu-options.hx
18
--- a/hw/net/lan9118_phy.c
25
+++ b/qemu-options.hx
19
+++ b/hw/net/lan9118_phy.c
26
@@ -XXX,XX +XXX,XX @@ SRST
20
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
27
default device is ``vc`` in graphical mode and ``stdio`` in non
21
val = s->advertise;
28
graphical mode.
22
break;
29
23
case 5: /* Auto-neg Link Partner Ability */
30
- This option can be used several times to simulate up to 4 serial
24
- val = 0x0f71;
31
+ This option can be used several times to simulate multiple serial
25
+ val = 0x0fe1;
32
ports.
26
break;
33
27
case 6: /* Auto-neg Expansion */
34
You can use ``-serial none`` to suppress the creation of default
28
val = 1;
35
--
29
--
36
2.34.1
30
2.34.1
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Prefer named constants over magic values for better readability.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
7
Tested-by: Guenter Roeck <linux@roeck-us.net>
8
Message-id: 20241102125724.532843-5-shentey@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/net/mii.h | 6 +++++
12
hw/net/lan9118_phy.c | 63 ++++++++++++++++++++++++++++----------------
13
2 files changed, 46 insertions(+), 23 deletions(-)
14
15
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/net/mii.h
18
+++ b/include/hw/net/mii.h
19
@@ -XXX,XX +XXX,XX @@
20
#define MII_BMSR_JABBER (1 << 1) /* Jabber detected */
21
#define MII_BMSR_EXTCAP (1 << 0) /* Ext-reg capability */
22
23
+#define MII_ANAR_RFAULT (1 << 13) /* Say we can detect faults */
24
#define MII_ANAR_PAUSE_ASYM (1 << 11) /* Try for asymmetric pause */
25
#define MII_ANAR_PAUSE (1 << 10) /* Try for pause */
26
#define MII_ANAR_TXFD (1 << 8)
27
@@ -XXX,XX +XXX,XX @@
28
#define MII_ANAR_10FD (1 << 6)
29
#define MII_ANAR_10 (1 << 5)
30
#define MII_ANAR_CSMACD (1 << 0)
31
+#define MII_ANAR_SELECT (0x001f) /* Selector bits */
32
33
#define MII_ANLPAR_ACK (1 << 14)
34
#define MII_ANLPAR_PAUSEASY (1 << 11) /* can pause asymmetrically */
35
@@ -XXX,XX +XXX,XX @@
36
#define RTL8201CP_PHYID1 0x0000
37
#define RTL8201CP_PHYID2 0x8201
38
39
+/* SMSC LAN9118 */
40
+#define SMSCLAN9118_PHYID1 0x0007
41
+#define SMSCLAN9118_PHYID2 0xc0d1
42
+
43
/* RealTek 8211E */
44
#define RTL8211E_PHYID1 0x001c
45
#define RTL8211E_PHYID2 0xc915
46
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/net/lan9118_phy.c
49
+++ b/hw/net/lan9118_phy.c
50
@@ -XXX,XX +XXX,XX @@
51
52
#include "qemu/osdep.h"
53
#include "hw/net/lan9118_phy.h"
54
+#include "hw/net/mii.h"
55
#include "hw/irq.h"
56
#include "hw/resettable.h"
57
#include "migration/vmstate.h"
58
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
59
uint16_t val;
60
61
switch (reg) {
62
- case 0: /* Basic Control */
63
+ case MII_BMCR:
64
val = s->control;
65
break;
66
- case 1: /* Basic Status */
67
+ case MII_BMSR:
68
val = s->status;
69
break;
70
- case 2: /* ID1 */
71
- val = 0x0007;
72
+ case MII_PHYID1:
73
+ val = SMSCLAN9118_PHYID1;
74
break;
75
- case 3: /* ID2 */
76
- val = 0xc0d1;
77
+ case MII_PHYID2:
78
+ val = SMSCLAN9118_PHYID2;
79
break;
80
- case 4: /* Auto-neg advertisement */
81
+ case MII_ANAR:
82
val = s->advertise;
83
break;
84
- case 5: /* Auto-neg Link Partner Ability */
85
- val = 0x0fe1;
86
+ case MII_ANLPAR:
87
+ val = MII_ANLPAR_PAUSEASY | MII_ANLPAR_PAUSE | MII_ANLPAR_T4 |
88
+ MII_ANLPAR_TXFD | MII_ANLPAR_TX | MII_ANLPAR_10FD |
89
+ MII_ANLPAR_10 | MII_ANLPAR_CSMACD;
90
break;
91
- case 6: /* Auto-neg Expansion */
92
- val = 1;
93
+ case MII_ANER:
94
+ val = MII_ANER_NWAY;
95
break;
96
case 29: /* Interrupt source. */
97
val = s->ints;
98
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
99
trace_lan9118_phy_write(val, reg);
100
101
switch (reg) {
102
- case 0: /* Basic Control */
103
- if (val & 0x8000) {
104
+ case MII_BMCR:
105
+ if (val & MII_BMCR_RESET) {
106
lan9118_phy_reset(s);
107
} else {
108
- s->control = val & 0x7980;
109
+ s->control = val & (MII_BMCR_LOOPBACK | MII_BMCR_SPEED100 |
110
+ MII_BMCR_AUTOEN | MII_BMCR_PDOWN | MII_BMCR_FD |
111
+ MII_BMCR_CTST);
112
/* Complete autonegotiation immediately. */
113
- if (val & 0x1000) {
114
- s->status |= 0x0020;
115
+ if (val & MII_BMCR_AUTOEN) {
116
+ s->status |= MII_BMSR_AN_COMP;
117
}
118
}
119
break;
120
- case 4: /* Auto-neg advertisement */
121
- s->advertise = (val & 0x2d7f) | 0x80;
122
+ case MII_ANAR:
123
+ s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
124
+ MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
125
+ MII_ANAR_SELECT))
126
+ | MII_ANAR_TX;
127
break;
128
case 30: /* Interrupt mask */
129
s->int_mask = val & 0xff;
130
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
131
/* Autonegotiation status mirrors link status. */
132
if (link_down) {
133
trace_lan9118_phy_update_link("down");
134
- s->status &= ~0x0024;
135
+ s->status &= ~(MII_BMSR_AN_COMP | MII_BMSR_LINK_ST);
136
s->ints |= PHY_INT_DOWN;
137
} else {
138
trace_lan9118_phy_update_link("up");
139
- s->status |= 0x0024;
140
+ s->status |= MII_BMSR_AN_COMP | MII_BMSR_LINK_ST;
141
s->ints |= PHY_INT_ENERGYON;
142
s->ints |= PHY_INT_AUTONEG_COMPLETE;
143
}
144
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_reset(Lan9118PhyState *s)
145
{
146
trace_lan9118_phy_reset();
147
148
- s->control = 0x3000;
149
- s->status = 0x7809;
150
- s->advertise = 0x01e1;
151
+ s->control = MII_BMCR_AUTOEN | MII_BMCR_SPEED100;
152
+ s->status = MII_BMSR_100TX_FD
153
+ | MII_BMSR_100TX_HD
154
+ | MII_BMSR_10T_FD
155
+ | MII_BMSR_10T_HD
156
+ | MII_BMSR_AUTONEG
157
+ | MII_BMSR_EXTCAP;
158
+ s->advertise = MII_ANAR_TXFD
159
+ | MII_ANAR_TX
160
+ | MII_ANAR_10FD
161
+ | MII_ANAR_10
162
+ | MII_ANAR_CSMACD;
163
s->int_mask = 0;
164
s->ints = 0;
165
lan9118_phy_update_link(s, s->link_down);
166
--
167
2.34.1
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
The real device advertises this mode and the device model already advertises
4
100 mbps half duplex and 10 mbps full+half duplex. So advertise this mode to
5
make the model more realistic.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
Message-id: 20241102125724.532843-6-shentey@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/net/lan9118_phy.c | 4 ++--
14
1 file changed, 2 insertions(+), 2 deletions(-)
15
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/lan9118_phy.c
19
+++ b/hw/net/lan9118_phy.c
20
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
21
break;
22
case MII_ANAR:
23
s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
24
- MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
25
- MII_ANAR_SELECT))
26
+ MII_ANAR_PAUSE | MII_ANAR_TXFD | MII_ANAR_10FD |
27
+ MII_ANAR_10 | MII_ANAR_SELECT))
28
| MII_ANAR_TX;
29
break;
30
case 30: /* Interrupt mask */
31
--
32
2.34.1
diff view generated by jsdifflib
New patch
1
For IEEE fused multiply-add, the (0 * inf) + NaN case should raise
2
Invalid for the multiplication of 0 by infinity. Currently we handle
3
this in the per-architecture ifdef ladder in pickNaNMulAdd().
4
However, since this isn't really architecture specific we can hoist
5
it up to the generic code.
1
6
7
For the cases where the infzero test in pickNaNMulAdd was
8
returning 2, we can delete the check entirely and allow the
9
code to fall into the normal pick-a-NaN handling, because this
10
will return 2 anyway (input 'c' being the only NaN in this case).
11
For the cases where infzero was returning 3 to indicate "return
12
the default NaN", we must retain that "return 3".
13
14
For Arm, this looks like it might be a behaviour change because we
15
used to set float_flag_invalid | float_flag_invalid_imz only if C is
16
a quiet NaN. However, it is not, because Arm target code never looks
17
at float_flag_invalid_imz, and for the (0 * inf) + SNaN case we
18
already raised float_flag_invalid via the "abc_mask &
19
float_cmask_snan" check in pick_nan_muladd.
20
21
For any target architecture using the "default implementation" at the
22
bottom of the ifdef, this is a behaviour change but will be fixing a
23
bug (where we failed to raise the Invalid exception for (0 * inf +
24
QNaN). The architectures using the default case are:
25
* hppa
26
* i386
27
* sh4
28
* tricore
29
30
The x86, Tricore and SH4 CPU architecture manuals are clear that this
31
should have raised Invalid; HPPA is a bit vaguer but still seems
32
clear enough.
33
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
36
Message-id: 20241202131347.498124-2-peter.maydell@linaro.org
37
---
38
fpu/softfloat-parts.c.inc | 13 +++++++------
39
fpu/softfloat-specialize.c.inc | 29 +----------------------------
40
2 files changed, 8 insertions(+), 34 deletions(-)
41
42
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
43
index XXXXXXX..XXXXXXX 100644
44
--- a/fpu/softfloat-parts.c.inc
45
+++ b/fpu/softfloat-parts.c.inc
46
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
47
int ab_mask, int abc_mask)
48
{
49
int which;
50
+ bool infzero = (ab_mask == float_cmask_infzero);
51
52
if (unlikely(abc_mask & float_cmask_snan)) {
53
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
54
}
55
56
- which = pickNaNMulAdd(a->cls, b->cls, c->cls,
57
- ab_mask == float_cmask_infzero, s);
58
+ if (infzero) {
59
+ /* This is (0 * inf) + NaN or (inf * 0) + NaN */
60
+ float_raise(float_flag_invalid | float_flag_invalid_imz, s);
61
+ }
62
+
63
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
64
65
if (s->default_nan_mode || which == 3) {
66
- /*
67
- * Note that this check is after pickNaNMulAdd so that function
68
- * has an opportunity to set the Invalid flag for infzero.
69
- */
70
parts_default_nan(a, s);
71
return a;
72
}
73
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
74
index XXXXXXX..XXXXXXX 100644
75
--- a/fpu/softfloat-specialize.c.inc
76
+++ b/fpu/softfloat-specialize.c.inc
77
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
78
* the default NaN
79
*/
80
if (infzero && is_qnan(c_cls)) {
81
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
82
return 3;
83
}
84
85
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
86
* case sets InvalidOp and returns the default NaN
87
*/
88
if (infzero) {
89
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
90
return 3;
91
}
92
/* Prefer sNaN over qNaN, in the a, b, c order. */
93
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
94
* For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
95
* case sets InvalidOp and returns the input value 'c'
96
*/
97
- if (infzero) {
98
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
99
- return 2;
100
- }
101
/* Prefer sNaN over qNaN, in the c, a, b order. */
102
if (is_snan(c_cls)) {
103
return 2;
104
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
105
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
106
* case sets InvalidOp and returns the input value 'c'
107
*/
108
- if (infzero) {
109
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
110
- return 2;
111
- }
112
+
113
/* Prefer sNaN over qNaN, in the c, a, b order. */
114
if (is_snan(c_cls)) {
115
return 2;
116
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
117
* to return an input NaN if we have one (ie c) rather than generating
118
* a default NaN
119
*/
120
- if (infzero) {
121
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
122
- return 2;
123
- }
124
125
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
126
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
127
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
128
return 1;
129
}
130
#elif defined(TARGET_RISCV)
131
- /* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
132
- if (infzero) {
133
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
134
- }
135
return 3; /* default NaN */
136
#elif defined(TARGET_S390X)
137
if (infzero) {
138
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
139
return 3;
140
}
141
142
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
143
return 2;
144
}
145
#elif defined(TARGET_SPARC)
146
- /* For (inf,0,nan) return c. */
147
- if (infzero) {
148
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
149
- return 2;
150
- }
151
/* Prefer SNaN over QNaN, order C, B, A. */
152
if (is_snan(c_cls)) {
153
return 2;
154
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
155
* For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
156
* an input NaN if we have one (ie c).
157
*/
158
- if (infzero) {
159
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
160
- return 2;
161
- }
162
if (status->use_first_nan) {
163
if (is_nan(a_cls)) {
164
return 0;
165
--
166
2.34.1
diff view generated by jsdifflib
New patch
1
If the target sets default_nan_mode then we're always going to return
2
the default NaN, and pickNaNMulAdd() no longer has any side effects.
3
For consistency with pickNaN(), check for default_nan_mode before
4
calling pickNaNMulAdd().
1
5
6
When we convert pickNaNMulAdd() to allow runtime selection of the NaN
7
propagation rule, this means we won't have to make the targets which
8
use default_nan_mode also set a propagation rule.
9
10
Since RiscV always uses default_nan_mode, this allows us to remove
11
its ifdef case from pickNaNMulAdd().
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20241202131347.498124-3-peter.maydell@linaro.org
16
---
17
fpu/softfloat-parts.c.inc | 8 ++++++--
18
fpu/softfloat-specialize.c.inc | 9 +++++++--
19
2 files changed, 13 insertions(+), 4 deletions(-)
20
21
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
22
index XXXXXXX..XXXXXXX 100644
23
--- a/fpu/softfloat-parts.c.inc
24
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
26
float_raise(float_flag_invalid | float_flag_invalid_imz, s);
27
}
28
29
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
30
+ if (s->default_nan_mode) {
31
+ which = 3;
32
+ } else {
33
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
34
+ }
35
36
- if (s->default_nan_mode || which == 3) {
37
+ if (which == 3) {
38
parts_default_nan(a, s);
39
return a;
40
}
41
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
42
index XXXXXXX..XXXXXXX 100644
43
--- a/fpu/softfloat-specialize.c.inc
44
+++ b/fpu/softfloat-specialize.c.inc
45
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
46
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
47
bool infzero, float_status *status)
48
{
49
+ /*
50
+ * We guarantee not to require the target to tell us how to
51
+ * pick a NaN if we're always returning the default NaN.
52
+ * But if we're not in default-NaN mode then the target must
53
+ * specify.
54
+ */
55
+ assert(!status->default_nan_mode);
56
#if defined(TARGET_ARM)
57
/* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
58
* the default NaN
59
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
60
} else {
61
return 1;
62
}
63
-#elif defined(TARGET_RISCV)
64
- return 3; /* default NaN */
65
#elif defined(TARGET_S390X)
66
if (infzero) {
67
return 3;
68
--
69
2.34.1
diff view generated by jsdifflib
1
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
1
IEEE 758 does not define a fixed rule for what NaN to return in
2
2
the case of a fused multiply-add of inf * 0 + NaN. Different
3
Add write protections for the fields in the CR register.
3
architectures thus do different things:
4
PLL configuration write protections (among others) have not
4
* some return the default NaN
5
been handled yet. This is planned in a future patch set.
5
* some return the input NaN
6
6
* Arm returns the default NaN if the input NaN is quiet,
7
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
7
and the input NaN if it is signalling
8
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
8
9
Message-id: 20240303140643.81957-7-arnaud.minier@telecom-paris.fr
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.
29
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
32
Message-id: 20241202131347.498124-4-peter.maydell@linaro.org
12
---
33
---
13
hw/misc/stm32l4x5_rcc.c | 166 ++++++++++++++++++++++++++++------------
34
include/fpu/softfloat-helpers.h | 11 ++++
14
1 file changed, 115 insertions(+), 51 deletions(-)
35
include/fpu/softfloat-types.h | 23 +++++++++
15
36
fpu/softfloat-specialize.c.inc | 91 ++++++++++++++++++++++-----------
16
diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c
37
3 files changed, 95 insertions(+), 30 deletions(-)
38
39
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
17
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/stm32l4x5_rcc.c
41
--- a/include/fpu/softfloat-helpers.h
19
+++ b/hw/misc/stm32l4x5_rcc.c
42
+++ b/include/fpu/softfloat-helpers.h
20
@@ -XXX,XX +XXX,XX @@ static void rcc_update_irq(Stm32l4x5RccState *s)
43
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
21
}
44
status->float_2nan_prop_rule = rule;
22
}
45
}
23
46
24
-static void rcc_update_cr_register(Stm32l4x5RccState *s)
47
+static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
25
+static void rcc_update_msi(Stm32l4x5RccState *s, uint32_t previous_value)
48
+ float_status *status)
26
+{
49
+{
27
+ uint32_t val;
50
+ status->float_infzeronan_rule = rule;
28
+
51
+}
29
+ static const uint32_t msirange[] = {
52
+
30
+ 100000, 200000, 400000, 800000, 1000000, 2000000,
53
static inline void set_flush_to_zero(bool val, float_status *status)
31
+ 4000000, 8000000, 16000000, 24000000, 32000000, 48000000
54
{
32
+ };
55
status->flush_to_zero = val;
33
+ /* MSIRANGE and MSIRGSEL */
56
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
34
+ val = extract32(s->cr, R_CR_MSIRGSEL_SHIFT, R_CR_MSIRGSEL_LENGTH);
57
return status->float_2nan_prop_rule;
35
+ if (val) {
58
}
36
+ /* MSIRGSEL is set, use the MSIRANGE field */
59
37
+ val = extract32(s->cr, R_CR_MSIRANGE_SHIFT, R_CR_MSIRANGE_LENGTH);
60
+static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
38
+ } else {
61
+{
39
+ /* MSIRGSEL is not set, use the MSISRANGE field */
62
+ return status->float_infzeronan_rule;
40
+ val = extract32(s->csr, R_CSR_MSISRANGE_SHIFT, R_CSR_MSISRANGE_LENGTH);
63
+}
64
+
65
static inline bool get_flush_to_zero(float_status *status)
66
{
67
return status->flush_to_zero;
68
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
69
index XXXXXXX..XXXXXXX 100644
70
--- a/include/fpu/softfloat-types.h
71
+++ b/include/fpu/softfloat-types.h
72
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
73
float_2nan_prop_x87,
74
} Float2NaNPropRule;
75
76
+/*
77
+ * Rule for result of fused multiply-add 0 * Inf + NaN.
78
+ * This must be a NaN, but implementations differ on whether this
79
+ * is the input NaN or the default NaN.
80
+ *
81
+ * You don't need to set this if default_nan_mode is enabled.
82
+ * When not in default-NaN mode, it is an error for the target
83
+ * not to set the rule in float_status if it uses muladd, and we
84
+ * will assert if we need to handle an input NaN and no rule was
85
+ * selected.
86
+ */
87
+typedef enum __attribute__((__packed__)) {
88
+ /* No propagation rule specified */
89
+ float_infzeronan_none = 0,
90
+ /* Result is never the default NaN (so always the input NaN) */
91
+ float_infzeronan_dnan_never,
92
+ /* Result is always the default NaN */
93
+ float_infzeronan_dnan_always,
94
+ /* Result is the default NaN if the input NaN is quiet */
95
+ float_infzeronan_dnan_if_qnan,
96
+} FloatInfZeroNaNRule;
97
+
98
/*
99
* Floating Point Status. Individual architectures may maintain
100
* several versions of float_status for different functions. The
101
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
102
FloatRoundMode float_rounding_mode;
103
FloatX80RoundPrec floatx80_rounding_precision;
104
Float2NaNPropRule float_2nan_prop_rule;
105
+ FloatInfZeroNaNRule float_infzeronan_rule;
106
bool tininess_before_rounding;
107
/* should denormalised results go to zero and set the inexact flag? */
108
bool flush_to_zero;
109
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
110
index XXXXXXX..XXXXXXX 100644
111
--- a/fpu/softfloat-specialize.c.inc
112
+++ b/fpu/softfloat-specialize.c.inc
113
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
114
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
115
bool infzero, float_status *status)
116
{
117
+ FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
118
+
119
/*
120
* We guarantee not to require the target to tell us how to
121
* pick a NaN if we're always returning the default NaN.
122
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
123
* specify.
124
*/
125
assert(!status->default_nan_mode);
126
+
127
+ if (rule == float_infzeronan_none) {
128
+ /*
129
+ * Temporarily fall back to ifdef ladder
130
+ */
131
#if defined(TARGET_ARM)
132
- /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
133
- * the default NaN
134
- */
135
- if (infzero && is_qnan(c_cls)) {
136
- return 3;
137
+ /*
138
+ * For ARM, the (inf,zero,qnan) case returns the default NaN,
139
+ * but (inf,zero,snan) returns the input NaN.
140
+ */
141
+ rule = float_infzeronan_dnan_if_qnan;
142
+#elif defined(TARGET_MIPS)
143
+ if (snan_bit_is_one(status)) {
144
+ /*
145
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
146
+ * case sets InvalidOp and returns the default NaN
147
+ */
148
+ rule = float_infzeronan_dnan_always;
149
+ } else {
150
+ /*
151
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
152
+ * case sets InvalidOp and returns the input value 'c'
153
+ */
154
+ rule = float_infzeronan_dnan_never;
155
+ }
156
+#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
157
+ defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
158
+ defined(TARGET_I386) || defined(TARGET_LOONGARCH)
159
+ /*
160
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
161
+ * case sets InvalidOp and returns the input value 'c'
162
+ */
163
+ /*
164
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
165
+ * to return an input NaN if we have one (ie c) rather than generating
166
+ * a default NaN
167
+ */
168
+ rule = float_infzeronan_dnan_never;
169
+#elif defined(TARGET_S390X)
170
+ rule = float_infzeronan_dnan_always;
171
+#endif
172
}
173
174
+ if (infzero) {
175
+ /*
176
+ * Inf * 0 + NaN -- some implementations return the default NaN here,
177
+ * and some return the input NaN.
178
+ */
179
+ switch (rule) {
180
+ case float_infzeronan_dnan_never:
181
+ return 2;
182
+ case float_infzeronan_dnan_always:
183
+ return 3;
184
+ case float_infzeronan_dnan_if_qnan:
185
+ return is_qnan(c_cls) ? 3 : 2;
186
+ default:
187
+ g_assert_not_reached();
188
+ }
41
+ }
189
+ }
42
+
190
+
43
+ if (val < ARRAY_SIZE(msirange)) {
191
+#if defined(TARGET_ARM)
44
+ clock_update_hz(s->msi_rc, msirange[val]);
192
+
45
+ } else {
193
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
46
+ /*
194
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
47
+ * There is a hardware write protection if the value is out of bound.
195
*/
48
+ * Restore the previous value.
196
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
49
+ */
197
}
50
+ s->cr = (s->cr & ~R_CSR_MSISRANGE_MASK) |
198
#elif defined(TARGET_MIPS)
51
+ (previous_value & R_CSR_MSISRANGE_MASK);
199
if (snan_bit_is_one(status)) {
52
+ }
200
- /*
53
+}
201
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
54
+
202
- * case sets InvalidOp and returns the default NaN
55
+/*
203
- */
56
+ * TODO: Add write-protection for all registers:
204
- if (infzero) {
57
+ * DONE: CR
205
- return 3;
58
+ */
206
- }
59
+
207
/* Prefer sNaN over qNaN, in the a, b, c order. */
60
+static void rcc_update_cr_register(Stm32l4x5RccState *s, uint32_t previous_value)
208
if (is_snan(a_cls)) {
61
{
209
return 0;
62
int val;
210
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
63
+ const RccClockMuxSource current_pll_src =
211
return 2;
64
+ CLOCK_MUX_INIT_INFO[RCC_CLOCK_MUX_PLL_INPUT].src_mapping[
65
+ s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT].src];
66
67
/* PLLSAI2ON and update PLLSAI2RDY */
68
val = FIELD_EX32(s->cr, CR, PLLSAI2ON);
69
@@ -XXX,XX +XXX,XX @@ static void rcc_update_cr_register(Stm32l4x5RccState *s)
70
s->cifr |= R_CIFR_PLLSAI1RDYF_MASK;
71
}
72
73
- /* PLLON and update PLLRDY */
74
+ /*
75
+ * PLLON and update PLLRDY
76
+ * PLLON cannot be reset if the PLL clock is used as the system clock.
77
+ */
78
val = FIELD_EX32(s->cr, CR, PLLON);
79
- pll_set_enable(&s->plls[RCC_PLL_PLL], val);
80
- s->cr = (s->cr & ~R_CR_PLLRDY_MASK) |
81
- (val << R_CR_PLLRDY_SHIFT);
82
- if (s->cier & R_CIER_PLLRDYIE_MASK) {
83
- s->cifr |= R_CIFR_PLLRDYF_MASK;
84
+ if (FIELD_EX32(s->cfgr, CFGR, SWS) != 0b11) {
85
+ pll_set_enable(&s->plls[RCC_PLL_PLL], val);
86
+ s->cr = (s->cr & ~R_CR_PLLRDY_MASK) |
87
+ (val << R_CR_PLLRDY_SHIFT);
88
+ if (s->cier & R_CIER_PLLRDYIE_MASK) {
89
+ s->cifr |= R_CIFR_PLLRDYF_MASK;
90
+ }
91
+ } else {
92
+ s->cr |= R_CR_PLLON_MASK;
93
}
94
95
/* CSSON: TODO */
96
/* HSEBYP: TODO */
97
98
- /* HSEON and update HSERDY */
99
+ /*
100
+ * HSEON and update HSERDY.
101
+ * HSEON cannot be reset if the HSE oscillator is used directly or
102
+ * indirectly as the system clock.
103
+ */
104
val = FIELD_EX32(s->cr, CR, HSEON);
105
- s->cr = (s->cr & ~R_CR_HSERDY_MASK) |
106
- (val << R_CR_HSERDY_SHIFT);
107
- if (val) {
108
- clock_update_hz(s->hse, s->hse_frequency);
109
- if (s->cier & R_CIER_HSERDYIE_MASK) {
110
- s->cifr |= R_CIFR_HSERDYF_MASK;
111
+ if (FIELD_EX32(s->cfgr, CFGR, SWS) != 0b10 &&
112
+ current_pll_src != RCC_CLOCK_MUX_SRC_HSE) {
113
+ s->cr = (s->cr & ~R_CR_HSERDY_MASK) |
114
+ (val << R_CR_HSERDY_SHIFT);
115
+ if (val) {
116
+ clock_update_hz(s->hse, s->hse_frequency);
117
+ if (s->cier & R_CIER_HSERDYIE_MASK) {
118
+ s->cifr |= R_CIFR_HSERDYF_MASK;
119
+ }
120
+ } else {
121
+ clock_update(s->hse, 0);
122
}
212
}
123
} else {
213
} else {
124
- clock_update(s->hse, 0);
214
- /*
125
+ s->cr |= R_CR_HSEON_MASK;
215
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
126
}
216
- * case sets InvalidOp and returns the input value 'c'
127
217
- */
128
/* HSIAFS: TODO*/
218
/* Prefer sNaN over qNaN, in the c, a, b order. */
129
/* HSIKERON: TODO*/
219
if (is_snan(c_cls)) {
130
220
return 2;
131
- /* HSION and update HSIRDY*/
221
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
132
- val = FIELD_EX32(s->cr, CR, HSION);
133
- s->cr = (s->cr & ~R_CR_HSIRDY_MASK) |
134
- (val << R_CR_HSIRDY_SHIFT);
135
- if (val) {
136
+ /*
137
+ * HSION and update HSIRDY
138
+ * HSION is set by hardware if the HSI16 is used directly
139
+ * or indirectly as system clock.
140
+ */
141
+ if (FIELD_EX32(s->cfgr, CFGR, SWS) == 0b01 ||
142
+ current_pll_src == RCC_CLOCK_MUX_SRC_HSI) {
143
+ s->cr |= (R_CR_HSION_MASK | R_CR_HSIRDY_MASK);
144
clock_update_hz(s->hsi16_rc, HSI_FRQ);
145
if (s->cier & R_CIER_HSIRDYIE_MASK) {
146
s->cifr |= R_CIFR_HSIRDYF_MASK;
147
}
222
}
148
} else {
223
}
149
- clock_update(s->hsi16_rc, 0);
224
#elif defined(TARGET_LOONGARCH64)
150
+ val = FIELD_EX32(s->cr, CR, HSION);
225
- /*
151
+ if (val) {
226
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
152
+ clock_update_hz(s->hsi16_rc, HSI_FRQ);
227
- * case sets InvalidOp and returns the input value 'c'
153
+ s->cr |= R_CR_HSIRDY_MASK;
228
- */
154
+ if (s->cier & R_CIER_HSIRDYIE_MASK) {
229
-
155
+ s->cifr |= R_CIFR_HSIRDYF_MASK;
230
/* Prefer sNaN over qNaN, in the c, a, b order. */
156
+ }
231
if (is_snan(c_cls)) {
157
+ } else {
232
return 2;
158
+ clock_update(s->hsi16_rc, 0);
233
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
159
+ s->cr &= ~R_CR_HSIRDY_MASK;
234
return 1;
160
+ }
235
}
161
}
236
#elif defined(TARGET_PPC)
162
237
- /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
163
- static const uint32_t msirange[] = {
238
- * to return an input NaN if we have one (ie c) rather than generating
164
- 100000, 200000, 400000, 800000, 1000000, 2000000,
239
- * a default NaN
165
- 4000000, 8000000, 16000000, 24000000, 32000000, 48000000
240
- */
166
- };
241
-
167
- /* MSIRANGE and MSIRGSEL */
242
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
168
- val = FIELD_EX32(s->cr, CR, MSIRGSEL);
243
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
169
- if (val) {
244
*/
170
- /* MSIRGSEL is set, use the MSIRANGE field */
245
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
171
- val = FIELD_EX32(s->cr, CR, MSIRANGE);
246
return 1;
172
+ /* MSIPLLEN: TODO */
247
}
173
+
248
#elif defined(TARGET_S390X)
174
+ /*
249
- if (infzero) {
175
+ * MSION and update MSIRDY
250
- return 3;
176
+ * Set by hardware when used directly or indirectly as system clock.
177
+ */
178
+ if (FIELD_EX32(s->cfgr, CFGR, SWS) == 0b00 ||
179
+ current_pll_src == RCC_CLOCK_MUX_SRC_MSI) {
180
+ s->cr |= (R_CR_MSION_MASK | R_CR_MSIRDY_MASK);
181
+ if (!(previous_value & R_CR_MSION_MASK) && (s->cier & R_CIER_MSIRDYIE_MASK)) {
182
+ s->cifr |= R_CIFR_MSIRDYF_MASK;
183
+ }
184
+ rcc_update_msi(s, previous_value);
185
} else {
186
- /* MSIRGSEL is not set, use the MSISRANGE field */
187
- val = FIELD_EX32(s->csr, CSR, MSISRANGE);
188
- }
251
- }
189
-
252
-
190
- if (val < ARRAY_SIZE(msirange)) {
253
if (is_snan(a_cls)) {
191
- clock_update_hz(s->msi_rc, msirange[val]);
254
return 0;
192
- } else {
255
} else if (is_snan(b_cls)) {
193
- clock_update_hz(s->msi_rc, MSI_DEFAULT_FRQ);
194
- /* TODO: there is a write protection if the value is out of bound,
195
- implement that instead of setting the default */
196
- }
197
-
198
- /* MSIPLLEN */
199
-
200
- /* MSION and update MSIRDY */
201
- val = FIELD_EX32(s->cr, CR, MSION);
202
- s->cr = (s->cr & ~R_CR_MSIRDY_MASK) |
203
- (val << R_CR_MSIRDY_SHIFT);
204
- if (s->cier & R_CIER_MSIRDYIE_MASK) {
205
- s->cifr |= R_CIFR_MSIRDYF_MASK;
206
+ val = FIELD_EX32(s->cr, CR, MSION);
207
+ if (val) {
208
+ s->cr |= R_CR_MSIRDY_MASK;
209
+ rcc_update_msi(s, previous_value);
210
+ if (s->cier & R_CIER_MSIRDYIE_MASK) {
211
+ s->cifr |= R_CIFR_MSIRDYF_MASK;
212
+ }
213
+ } else {
214
+ s->cr &= ~R_CR_MSIRDY_MASK;
215
+ clock_update(s->msi_rc, 0);
216
+ }
217
}
218
rcc_update_irq(s);
219
}
220
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_rcc_write(void *opaque, hwaddr addr,
221
uint64_t val64, unsigned int size)
222
{
223
Stm32l4x5RccState *s = opaque;
224
+ uint32_t previous_value = 0;
225
const uint32_t value = val64;
226
227
trace_stm32l4x5_rcc_write(addr, value);
228
229
switch (addr) {
230
case A_CR:
231
+ previous_value = s->cr;
232
s->cr = (s->cr & CR_READ_SET_MASK) |
233
(value & (CR_READ_SET_MASK | ~CR_READ_ONLY_MASK));
234
- rcc_update_cr_register(s);
235
+ rcc_update_cr_register(s, previous_value);
236
break;
237
case A_ICSCR:
238
s->icscr = value & ~ICSCR_READ_ONLY_MASK;
239
--
256
--
240
2.34.1
257
2.34.1
241
242
diff view generated by jsdifflib
New patch
1
Explicitly set a rule in the softfloat tests for the inf-zero-nan
2
muladd special case. In meson.build we put -DTARGET_ARM in fpcflags,
3
and so we should select here the Arm rule of
4
float_infzeronan_dnan_if_qnan.
1
5
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241202131347.498124-5-peter.maydell@linaro.org
9
---
10
tests/fp/fp-bench.c | 5 +++++
11
tests/fp/fp-test.c | 5 +++++
12
2 files changed, 10 insertions(+)
13
14
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/fp/fp-bench.c
17
+++ b/tests/fp/fp-bench.c
18
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
19
{
20
bench_func_t f;
21
22
+ /*
23
+ * These implementation-defined choices for various things IEEE
24
+ * doesn't specify match those used by the Arm architecture.
25
+ */
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
28
29
f = bench_funcs[operation][precision];
30
g_assert(f);
31
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/tests/fp/fp-test.c
34
+++ b/tests/fp/fp-test.c
35
@@ -XXX,XX +XXX,XX @@ void run_test(void)
36
{
37
unsigned int i;
38
39
+ /*
40
+ * These implementation-defined choices for various things IEEE
41
+ * doesn't specify match those used by the Arm architecture.
42
+ */
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
44
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
45
46
genCases_setLevel(test_level);
47
verCases_maxErrorCount = n_max_errors;
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the Arm target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-6-peter.maydell@linaro.org
7
---
8
target/arm/cpu.c | 3 +++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 4 insertions(+), 7 deletions(-)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
17
* * tininess-before-rounding
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
21
+ * and the input NaN if it is signalling
22
*/
23
static void arm_set_default_fp_behaviours(float_status *s)
24
{
25
set_float_detect_tininess(float_tininess_before_rounding, s);
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
28
}
29
30
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
/*
37
* Temporarily fall back to ifdef ladder
38
*/
39
-#if defined(TARGET_ARM)
40
- /*
41
- * For ARM, the (inf,zero,qnan) case returns the default NaN,
42
- * but (inf,zero,snan) returns the input NaN.
43
- */
44
- rule = float_infzeronan_dnan_if_qnan;
45
-#elif defined(TARGET_MIPS)
46
+#if defined(TARGET_MIPS)
47
if (snan_bit_is_one(status)) {
48
/*
49
* For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
50
--
51
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for s390, so we
2
can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-7-peter.maydell@linaro.org
7
---
8
target/s390x/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/s390x/cpu.c
15
+++ b/target/s390x/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
17
set_float_detect_tininess(float_tininess_before_rounding,
18
&env->fpu_status);
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
20
+ set_float_infzeronan_rule(float_infzeronan_dnan_always,
21
+ &env->fpu_status);
22
/* fall through */
23
case RESET_TYPE_S390_CPU_NORMAL:
24
env->psw.mask &= ~PSW_MASK_RI;
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
* a default NaN
31
*/
32
rule = float_infzeronan_dnan_never;
33
-#elif defined(TARGET_S390X)
34
- rule = float_infzeronan_dnan_always;
35
#endif
36
}
37
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the PPC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-8-peter.maydell@linaro.org
7
---
8
target/ppc/cpu_init.c | 7 +++++++
9
fpu/softfloat-specialize.c.inc | 7 +------
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
15
+++ b/target/ppc/cpu_init.c
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
21
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
22
+ * to return an input NaN if we have one (ie c) rather than generating
23
+ * a default NaN
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
27
28
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
29
ppc_spr_t *spr = &env->spr_cb[i];
30
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
index XXXXXXX..XXXXXXX 100644
32
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
*/
36
rule = float_infzeronan_dnan_never;
37
}
38
-#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
39
+#elif defined(TARGET_SPARC) || \
40
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
41
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
42
/*
43
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
44
* case sets InvalidOp and returns the input value 'c'
45
*/
46
- /*
47
- * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
48
- * to return an input NaN if we have one (ie c) rather than generating
49
- * a default NaN
50
- */
51
rule = float_infzeronan_dnan_never;
52
#endif
53
}
54
--
55
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the MIPS target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-9-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 9 +++++++++
9
target/mips/msa.c | 4 ++++
10
fpu/softfloat-specialize.c.inc | 16 +---------------
11
3 files changed, 14 insertions(+), 15 deletions(-)
12
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_flush_mode(CPUMIPSState *env)
18
static inline void restore_snan_bit_mode(CPUMIPSState *env)
19
{
20
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
21
+ FloatInfZeroNaNRule izn_rule;
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
set_snan_bit_is_one(!nan2008, &env->active_fpu.fp_status);
28
set_default_nan_mode(!nan2008, &env->active_fpu.fp_status);
29
+ /*
30
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
31
+ * case sets InvalidOp and returns the default NaN.
32
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
33
+ * case sets InvalidOp and returns the input value 'c'.
34
+ */
35
+ izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
36
+ set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
37
}
38
39
static inline void restore_fp_status(CPUMIPSState *env)
40
diff --git a/target/mips/msa.c b/target/mips/msa.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/mips/msa.c
43
+++ b/target/mips/msa.c
44
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
45
46
/* set proper signanling bit meaning ("1" means "quiet") */
47
set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
48
+
49
+ /* Inf * 0 + NaN returns the input NaN */
50
+ set_float_infzeronan_rule(float_infzeronan_dnan_never,
51
+ &env->active_tc.msa_fp_status);
52
}
53
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
54
index XXXXXXX..XXXXXXX 100644
55
--- a/fpu/softfloat-specialize.c.inc
56
+++ b/fpu/softfloat-specialize.c.inc
57
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
58
/*
59
* Temporarily fall back to ifdef ladder
60
*/
61
-#if defined(TARGET_MIPS)
62
- if (snan_bit_is_one(status)) {
63
- /*
64
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
65
- * case sets InvalidOp and returns the default NaN
66
- */
67
- rule = float_infzeronan_dnan_always;
68
- } else {
69
- /*
70
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
71
- * case sets InvalidOp and returns the input value 'c'
72
- */
73
- rule = float_infzeronan_dnan_never;
74
- }
75
-#elif defined(TARGET_SPARC) || \
76
+#if defined(TARGET_SPARC) || \
77
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
78
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
79
/*
80
--
81
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the SPARC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-10-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 +--
10
2 files changed, 3 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
23
cpu_exec_realizefn(cs, &local_err);
24
if (local_err != NULL) {
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_SPARC) || \
34
- defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
35
+#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
36
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
37
/*
38
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the xtensa target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-11-peter.maydell@linaro.org
7
---
8
target/xtensa/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 +-
10
2 files changed, 3 insertions(+), 1 deletion(-)
11
12
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/xtensa/cpu.c
15
+++ b/target/xtensa/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
17
reset_mmu(env);
18
cs->halted = env->runstall;
19
#endif
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
set_no_signaling_nans(!dfpu, &env->fp_status);
23
xtensa_use_first_nan(env, !dfpu);
24
}
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
34
+#if defined(TARGET_HPPA) || \
35
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
36
/*
37
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the x86 target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-12-peter.maydell@linaro.org
6
---
7
target/i386/tcg/fpu_helper.c | 7 +++++++
8
fpu/softfloat-specialize.c.inc | 2 +-
9
2 files changed, 8 insertions(+), 1 deletion(-)
10
11
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/i386/tcg/fpu_helper.c
14
+++ b/target/i386/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->mmx_status);
18
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->sse_status);
19
+ /*
20
+ * Only SSE has multiply-add instructions. In the SDM Section 14.5.2
21
+ * "Fused-Multiply-ADD (FMA) Numeric Behavior" the NaN handling is
22
+ * specified -- for 0 * inf + NaN the input NaN is selected, and if
23
+ * there are multiple input NaNs they are selected in the order a, b, c.
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
26
}
27
28
static inline uint8_t save_exception_flags(CPUX86State *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
34
* Temporarily fall back to ifdef ladder
35
*/
36
#if defined(TARGET_HPPA) || \
37
- defined(TARGET_I386) || defined(TARGET_LOONGARCH)
38
+ defined(TARGET_LOONGARCH)
39
/*
40
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
41
* case sets InvalidOp and returns the input value 'c'
42
--
43
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the loongarch target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-13-peter.maydell@linaro.org
6
---
7
target/loongarch/tcg/fpu_helper.c | 5 +++++
8
fpu/softfloat-specialize.c.inc | 7 +------
9
2 files changed, 6 insertions(+), 6 deletions(-)
10
11
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/loongarch/tcg/fpu_helper.c
14
+++ b/target/loongarch/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
16
&env->fp_status);
17
set_flush_to_zero(0, &env->fp_status);
18
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
19
+ /*
20
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
21
+ * case sets InvalidOp and returns the input value 'c'
22
+ */
23
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
}
25
26
int ieee_ex_to_loongarch(int xcpt)
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
index XXXXXXX..XXXXXXX 100644
29
--- a/fpu/softfloat-specialize.c.inc
30
+++ b/fpu/softfloat-specialize.c.inc
31
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
32
/*
33
* Temporarily fall back to ifdef ladder
34
*/
35
-#if defined(TARGET_HPPA) || \
36
- defined(TARGET_LOONGARCH)
37
- /*
38
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
- * case sets InvalidOp and returns the input value 'c'
40
- */
41
+#if defined(TARGET_HPPA)
42
rule = float_infzeronan_dnan_never;
43
#endif
44
}
45
--
46
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the HPPA target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
As this is the last target to be converted to explicitly setting
5
the rule, we can remove the fallback code in pickNaNMulAdd()
6
entirely.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241202131347.498124-14-peter.maydell@linaro.org
11
---
12
target/hppa/fpu_helper.c | 2 ++
13
fpu/softfloat-specialize.c.inc | 13 +------------
14
2 files changed, 3 insertions(+), 12 deletions(-)
15
16
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/hppa/fpu_helper.c
19
+++ b/target/hppa/fpu_helper.c
20
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
21
* HPPA does note implement a CPU reset method at all...
22
*/
23
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
24
+ /* For inf * 0 + NaN, return the input NaN */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
}
27
28
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
34
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
bool infzero, float_status *status)
36
{
37
- FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
38
-
39
/*
40
* We guarantee not to require the target to tell us how to
41
* pick a NaN if we're always returning the default NaN.
42
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
43
*/
44
assert(!status->default_nan_mode);
45
46
- if (rule == float_infzeronan_none) {
47
- /*
48
- * Temporarily fall back to ifdef ladder
49
- */
50
-#if defined(TARGET_HPPA)
51
- rule = float_infzeronan_dnan_never;
52
-#endif
53
- }
54
-
55
if (infzero) {
56
/*
57
* Inf * 0 + NaN -- some implementations return the default NaN here,
58
* and some return the input NaN.
59
*/
60
- switch (rule) {
61
+ switch (status->float_infzeronan_rule) {
62
case float_infzeronan_dnan_never:
63
return 2;
64
case float_infzeronan_dnan_always:
65
--
66
2.34.1
diff view generated by jsdifflib
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
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
1
IEEE 758 does not define a fixed rule for which NaN to pick as the
2
2
result if both operands of a 3-operand fused multiply-add operation
3
Instantiate the whole clock tree and using the Clock multiplexers and
3
are NaNs. As a result different architectures have ended up with
4
the PLLs defined in the previous commits. This allows to statically
4
different rules for propagating NaNs.
5
define the clock tree and easily follow the clock signal from one end to
5
6
another.
6
QEMU currently hardcodes the NaN propagation logic into the binary
7
7
because pickNaNMulAdd() has an ifdef ladder for different targets.
8
Also handle three-phase reset now that we have defined a known base
8
We want to make the propagation rule instead be selectable at
9
state for every object.
9
runtime, because:
10
(Reset handling based on hw/misc/zynq_sclr.c)
10
* this will let us have multiple targets in one QEMU binary
11
11
* the Arm FEAT_AFP architectural feature includes letting
12
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
12
the guest select a NaN propagation rule at runtime
13
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
13
14
Message-id: 20240303140643.81957-5-arnaud.minier@telecom-paris.fr
14
In this commit we add an enum for the propagation rule, the field in
15
float_status, and the corresponding getters and setters. We change
16
pickNaNMulAdd to honour this, but because all targets still leave
17
this field at its default 0 value, the fallback logic will pick the
18
rule type with the old ifdef ladder.
19
20
It's valid not to set a propagation rule if default_nan_mode is
21
enabled, because in that case there's no need to pick a NaN; all the
22
callers of pickNaNMulAdd() catch this case and skip calling it.
23
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Message-id: 20241202131347.498124-16-peter.maydell@linaro.org
17
---
27
---
18
include/hw/misc/stm32l4x5_rcc_internals.h | 705 ++++++++++++++++++++++
28
include/fpu/softfloat-helpers.h | 11 +++
19
hw/misc/stm32l4x5_rcc.c | 145 ++++-
29
include/fpu/softfloat-types.h | 55 +++++++++++
20
2 files changed, 833 insertions(+), 17 deletions(-)
30
fpu/softfloat-specialize.c.inc | 167 ++++++++------------------------
21
31
3 files changed, 107 insertions(+), 126 deletions(-)
22
diff --git a/include/hw/misc/stm32l4x5_rcc_internals.h b/include/hw/misc/stm32l4x5_rcc_internals.h
32
33
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
23
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/misc/stm32l4x5_rcc_internals.h
35
--- a/include/fpu/softfloat-helpers.h
25
+++ b/include/hw/misc/stm32l4x5_rcc_internals.h
36
+++ b/include/fpu/softfloat-helpers.h
26
@@ -XXX,XX +XXX,XX @@ typedef enum RccClockMuxSource {
37
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
27
RCC_CLOCK_MUX_SRC_NUMBER,
38
status->float_2nan_prop_rule = rule;
28
} RccClockMuxSource;
39
}
29
40
30
+/* PLL init info */
41
+static inline void set_float_3nan_prop_rule(Float3NaNPropRule rule,
31
+typedef struct PllInitInfo {
42
+ float_status *status)
32
+ const char *name;
33
+
34
+ const char *channel_name[RCC_NUM_CHANNEL_PLL_OUT];
35
+ bool channel_exists[RCC_NUM_CHANNEL_PLL_OUT];
36
+ uint32_t default_channel_divider[RCC_NUM_CHANNEL_PLL_OUT];
37
+
38
+ RccClockMuxSource src_mapping[RCC_NUM_CLOCK_MUX_SRC];
39
+} PllInitInfo;
40
+
41
+static const PllInitInfo PLL_INIT_INFO[] = {
42
+ [RCC_PLL_PLL] = {
43
+ .name = "pll",
44
+ .channel_name = {
45
+ "pllsai3clk",
46
+ "pll48m1clk",
47
+ "pllclk"
48
+ },
49
+ .channel_exists = {
50
+ true, true, true
51
+ },
52
+ /* From PLLCFGR register documentation */
53
+ .default_channel_divider = {
54
+ 7, 2, 2
55
+ }
56
+ },
57
+ [RCC_PLL_PLLSAI1] = {
58
+ .name = "pllsai1",
59
+ .channel_name = {
60
+ "pllsai1clk",
61
+ "pll48m2clk",
62
+ "plladc1clk"
63
+ },
64
+ .channel_exists = {
65
+ true, true, true
66
+ },
67
+ /* From PLLSAI1CFGR register documentation */
68
+ .default_channel_divider = {
69
+ 7, 2, 2
70
+ }
71
+ },
72
+ [RCC_PLL_PLLSAI2] = {
73
+ .name = "pllsai2",
74
+ .channel_name = {
75
+ "pllsai2clk",
76
+ NULL,
77
+ "plladc2clk"
78
+ },
79
+ .channel_exists = {
80
+ true, false, true
81
+ },
82
+ /* From PLLSAI2CFGR register documentation */
83
+ .default_channel_divider = {
84
+ 7, 0, 2
85
+ }
86
+ }
87
+};
88
+
89
+static inline void set_pll_init_info(RccPllState *pll,
90
+ RccPll id)
91
+{
43
+{
92
+ int i;
44
+ status->float_3nan_prop_rule = rule;
93
+
94
+ pll->id = id;
95
+ pll->vco_multiplier = 1;
96
+ for (i = 0; i < RCC_NUM_CHANNEL_PLL_OUT; i++) {
97
+ pll->channel_enabled[i] = false;
98
+ pll->channel_exists[i] = PLL_INIT_INFO[id].channel_exists[i];
99
+ pll->channel_divider[i] = PLL_INIT_INFO[id].default_channel_divider[i];
100
+ }
101
+}
45
+}
102
+
46
+
103
+/* Clock mux init info */
47
static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
104
+typedef struct ClockMuxInitInfo {
48
float_status *status)
105
+ const char *name;
49
{
106
+
50
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
107
+ uint32_t multiplier;
51
return status->float_2nan_prop_rule;
108
+ uint32_t divider;
52
}
109
+ bool enabled;
53
110
+ /* If this is true, the clock will not be exposed outside of the device */
54
+static inline Float3NaNPropRule get_float_3nan_prop_rule(float_status *status)
111
+ bool hidden;
112
+
113
+ RccClockMuxSource src_mapping[RCC_NUM_CLOCK_MUX_SRC];
114
+} ClockMuxInitInfo;
115
+
116
+#define FILL_DEFAULT_FACTOR \
117
+ .multiplier = 1, \
118
+ .divider = 1
119
+
120
+#define FILL_DEFAULT_INIT_ENABLED \
121
+ FILL_DEFAULT_FACTOR, \
122
+ .enabled = true
123
+
124
+#define FILL_DEFAULT_INIT_DISABLED \
125
+ FILL_DEFAULT_FACTOR, \
126
+ .enabled = false
127
+
128
+
129
+static const ClockMuxInitInfo CLOCK_MUX_INIT_INFO[] = {
130
+ [RCC_CLOCK_MUX_SYSCLK] = {
131
+ .name = "sysclk",
132
+ /* Same mapping as: CFGR_SW */
133
+ .src_mapping = {
134
+ RCC_CLOCK_MUX_SRC_MSI,
135
+ RCC_CLOCK_MUX_SRC_HSI,
136
+ RCC_CLOCK_MUX_SRC_HSE,
137
+ RCC_CLOCK_MUX_SRC_PLL,
138
+ },
139
+ .hidden = true,
140
+ FILL_DEFAULT_INIT_ENABLED,
141
+ },
142
+ [RCC_CLOCK_MUX_PLL_INPUT] = {
143
+ .name = "pll-input",
144
+ /* Same mapping as: PLLCFGR_PLLSRC */
145
+ .src_mapping = {
146
+ RCC_CLOCK_MUX_SRC_MSI,
147
+ RCC_CLOCK_MUX_SRC_HSI,
148
+ RCC_CLOCK_MUX_SRC_HSE,
149
+ },
150
+ .hidden = true,
151
+ FILL_DEFAULT_INIT_ENABLED,
152
+ },
153
+ [RCC_CLOCK_MUX_HCLK] = {
154
+ .name = "hclk",
155
+ .src_mapping = {
156
+ RCC_CLOCK_MUX_SRC_SYSCLK,
157
+ },
158
+ .hidden = true,
159
+ FILL_DEFAULT_INIT_ENABLED,
160
+ },
161
+ [RCC_CLOCK_MUX_PCLK1] = {
162
+ .name = "pclk1",
163
+ .src_mapping = {
164
+ RCC_CLOCK_MUX_SRC_HCLK,
165
+ },
166
+ .hidden = true,
167
+ FILL_DEFAULT_INIT_ENABLED,
168
+ },
169
+ [RCC_CLOCK_MUX_PCLK2] = {
170
+ .name = "pclk2",
171
+ .src_mapping = {
172
+ RCC_CLOCK_MUX_SRC_HCLK,
173
+ },
174
+ .hidden = true,
175
+ FILL_DEFAULT_INIT_ENABLED,
176
+ },
177
+ [RCC_CLOCK_MUX_HSE_OVER_32] = {
178
+ .name = "hse-divided-by-32",
179
+ .multiplier = 1,
180
+ .divider = 32,
181
+ .enabled = true,
182
+ .src_mapping = {
183
+ RCC_CLOCK_MUX_SRC_HSE,
184
+ },
185
+ .hidden = true,
186
+ },
187
+ [RCC_CLOCK_MUX_LCD_AND_RTC_COMMON] = {
188
+ .name = "lcd-and-rtc-common-mux",
189
+ /* Same mapping as: BDCR_RTCSEL */
190
+ .src_mapping = {
191
+ RCC_CLOCK_MUX_SRC_GND,
192
+ RCC_CLOCK_MUX_SRC_LSE,
193
+ RCC_CLOCK_MUX_SRC_LSI,
194
+ RCC_CLOCK_MUX_SRC_HSE_OVER_32,
195
+ },
196
+ .hidden = true,
197
+ FILL_DEFAULT_INIT_ENABLED,
198
+ },
199
+ /* From now on, muxes with a publicly available output */
200
+ [RCC_CLOCK_MUX_CORTEX_REFCLK] = {
201
+ .name = "cortex-refclk",
202
+ .multiplier = 1,
203
+ /* REFCLK is always HCLK/8 */
204
+ .divider = 8,
205
+ .enabled = true,
206
+ .src_mapping = {
207
+ RCC_CLOCK_MUX_SRC_HCLK,
208
+ }
209
+ },
210
+ [RCC_CLOCK_MUX_USART1] = {
211
+ .name = "usart1",
212
+ /* Same mapping as: CCIPR_USART1SEL */
213
+ .src_mapping = {
214
+ RCC_CLOCK_MUX_SRC_PCLK2,
215
+ RCC_CLOCK_MUX_SRC_SYSCLK,
216
+ RCC_CLOCK_MUX_SRC_HSI,
217
+ RCC_CLOCK_MUX_SRC_LSE,
218
+ },
219
+ FILL_DEFAULT_INIT_DISABLED,
220
+ },
221
+ [RCC_CLOCK_MUX_USART2] = {
222
+ .name = "usart2",
223
+ /* Same mapping as: CCIPR_USART2SEL */
224
+ .src_mapping = {
225
+ RCC_CLOCK_MUX_SRC_PCLK1,
226
+ RCC_CLOCK_MUX_SRC_SYSCLK,
227
+ RCC_CLOCK_MUX_SRC_HSI,
228
+ RCC_CLOCK_MUX_SRC_LSE,
229
+ },
230
+ FILL_DEFAULT_INIT_DISABLED,
231
+ },
232
+ [RCC_CLOCK_MUX_USART3] = {
233
+ .name = "usart3",
234
+ /* Same mapping as: CCIPR_USART3SEL */
235
+ .src_mapping = {
236
+ RCC_CLOCK_MUX_SRC_PCLK1,
237
+ RCC_CLOCK_MUX_SRC_SYSCLK,
238
+ RCC_CLOCK_MUX_SRC_HSI,
239
+ RCC_CLOCK_MUX_SRC_LSE,
240
+ },
241
+ FILL_DEFAULT_INIT_DISABLED,
242
+ },
243
+ [RCC_CLOCK_MUX_UART4] = {
244
+ .name = "uart4",
245
+ /* Same mapping as: CCIPR_UART4SEL */
246
+ .src_mapping = {
247
+ RCC_CLOCK_MUX_SRC_PCLK1,
248
+ RCC_CLOCK_MUX_SRC_SYSCLK,
249
+ RCC_CLOCK_MUX_SRC_HSI,
250
+ RCC_CLOCK_MUX_SRC_LSE,
251
+ },
252
+ FILL_DEFAULT_INIT_DISABLED,
253
+ },
254
+ [RCC_CLOCK_MUX_UART5] = {
255
+ .name = "uart5",
256
+ /* Same mapping as: CCIPR_UART5SEL */
257
+ .src_mapping = {
258
+ RCC_CLOCK_MUX_SRC_PCLK1,
259
+ RCC_CLOCK_MUX_SRC_SYSCLK,
260
+ RCC_CLOCK_MUX_SRC_HSI,
261
+ RCC_CLOCK_MUX_SRC_LSE,
262
+ },
263
+ FILL_DEFAULT_INIT_DISABLED,
264
+ },
265
+ [RCC_CLOCK_MUX_LPUART1] = {
266
+ .name = "lpuart1",
267
+ /* Same mapping as: CCIPR_LPUART1SEL */
268
+ .src_mapping = {
269
+ RCC_CLOCK_MUX_SRC_PCLK1,
270
+ RCC_CLOCK_MUX_SRC_SYSCLK,
271
+ RCC_CLOCK_MUX_SRC_HSI,
272
+ RCC_CLOCK_MUX_SRC_LSE,
273
+ },
274
+ FILL_DEFAULT_INIT_DISABLED,
275
+ },
276
+ [RCC_CLOCK_MUX_I2C1] = {
277
+ .name = "i2c1",
278
+ /* Same mapping as: CCIPR_I2C1SEL */
279
+ .src_mapping = {
280
+ RCC_CLOCK_MUX_SRC_PCLK1,
281
+ RCC_CLOCK_MUX_SRC_SYSCLK,
282
+ RCC_CLOCK_MUX_SRC_HSI,
283
+ },
284
+ FILL_DEFAULT_INIT_DISABLED,
285
+ },
286
+ [RCC_CLOCK_MUX_I2C2] = {
287
+ .name = "i2c2",
288
+ /* Same mapping as: CCIPR_I2C2SEL */
289
+ .src_mapping = {
290
+ RCC_CLOCK_MUX_SRC_PCLK1,
291
+ RCC_CLOCK_MUX_SRC_SYSCLK,
292
+ RCC_CLOCK_MUX_SRC_HSI,
293
+ },
294
+ FILL_DEFAULT_INIT_DISABLED,
295
+ },
296
+ [RCC_CLOCK_MUX_I2C3] = {
297
+ .name = "i2c3",
298
+ /* Same mapping as: CCIPR_I2C3SEL */
299
+ .src_mapping = {
300
+ RCC_CLOCK_MUX_SRC_PCLK1,
301
+ RCC_CLOCK_MUX_SRC_SYSCLK,
302
+ RCC_CLOCK_MUX_SRC_HSI,
303
+ },
304
+ FILL_DEFAULT_INIT_DISABLED,
305
+ },
306
+ [RCC_CLOCK_MUX_LPTIM1] = {
307
+ .name = "lptim1",
308
+ /* Same mapping as: CCIPR_LPTIM1SEL */
309
+ .src_mapping = {
310
+ RCC_CLOCK_MUX_SRC_PCLK1,
311
+ RCC_CLOCK_MUX_SRC_LSI,
312
+ RCC_CLOCK_MUX_SRC_HSI,
313
+ RCC_CLOCK_MUX_SRC_LSE,
314
+ },
315
+ FILL_DEFAULT_INIT_DISABLED,
316
+ },
317
+ [RCC_CLOCK_MUX_LPTIM2] = {
318
+ .name = "lptim2",
319
+ /* Same mapping as: CCIPR_LPTIM2SEL */
320
+ .src_mapping = {
321
+ RCC_CLOCK_MUX_SRC_PCLK1,
322
+ RCC_CLOCK_MUX_SRC_LSI,
323
+ RCC_CLOCK_MUX_SRC_HSI,
324
+ RCC_CLOCK_MUX_SRC_LSE,
325
+ },
326
+ FILL_DEFAULT_INIT_DISABLED,
327
+ },
328
+ [RCC_CLOCK_MUX_SWPMI1] = {
329
+ .name = "swpmi1",
330
+ /* Same mapping as: CCIPR_SWPMI1SEL */
331
+ .src_mapping = {
332
+ RCC_CLOCK_MUX_SRC_PCLK1,
333
+ RCC_CLOCK_MUX_SRC_HSI,
334
+ },
335
+ FILL_DEFAULT_INIT_DISABLED,
336
+ },
337
+ [RCC_CLOCK_MUX_MCO] = {
338
+ .name = "mco",
339
+ /* Same mapping as: CFGR_MCOSEL */
340
+ .src_mapping = {
341
+ RCC_CLOCK_MUX_SRC_SYSCLK,
342
+ RCC_CLOCK_MUX_SRC_MSI,
343
+ RCC_CLOCK_MUX_SRC_HSI,
344
+ RCC_CLOCK_MUX_SRC_HSE,
345
+ RCC_CLOCK_MUX_SRC_PLL,
346
+ RCC_CLOCK_MUX_SRC_LSI,
347
+ RCC_CLOCK_MUX_SRC_LSE,
348
+ },
349
+ FILL_DEFAULT_INIT_DISABLED,
350
+ },
351
+ [RCC_CLOCK_MUX_LSCO] = {
352
+ .name = "lsco",
353
+ /* Same mapping as: BDCR_LSCOSEL */
354
+ .src_mapping = {
355
+ RCC_CLOCK_MUX_SRC_LSI,
356
+ RCC_CLOCK_MUX_SRC_LSE,
357
+ },
358
+ FILL_DEFAULT_INIT_DISABLED,
359
+ },
360
+ [RCC_CLOCK_MUX_DFSDM1] = {
361
+ .name = "dfsdm1",
362
+ /* Same mapping as: CCIPR_DFSDM1SEL */
363
+ .src_mapping = {
364
+ RCC_CLOCK_MUX_SRC_PCLK2,
365
+ RCC_CLOCK_MUX_SRC_SYSCLK,
366
+ },
367
+ FILL_DEFAULT_INIT_DISABLED,
368
+ },
369
+ [RCC_CLOCK_MUX_ADC] = {
370
+ .name = "adc",
371
+ /* Same mapping as: CCIPR_ADCSEL */
372
+ .src_mapping = {
373
+ RCC_CLOCK_MUX_SRC_GND,
374
+ RCC_CLOCK_MUX_SRC_PLLADC1,
375
+ RCC_CLOCK_MUX_SRC_PLLADC2,
376
+ RCC_CLOCK_MUX_SRC_SYSCLK,
377
+ },
378
+ FILL_DEFAULT_INIT_DISABLED,
379
+ },
380
+ [RCC_CLOCK_MUX_CLK48] = {
381
+ .name = "clk48",
382
+ /* Same mapping as: CCIPR_CLK48SEL */
383
+ .src_mapping = {
384
+ RCC_CLOCK_MUX_SRC_GND,
385
+ RCC_CLOCK_MUX_SRC_PLL48M2,
386
+ RCC_CLOCK_MUX_SRC_PLL48M1,
387
+ RCC_CLOCK_MUX_SRC_MSI,
388
+ },
389
+ FILL_DEFAULT_INIT_DISABLED,
390
+ },
391
+ [RCC_CLOCK_MUX_SAI2] = {
392
+ .name = "sai2",
393
+ /* Same mapping as: CCIPR_SAI2SEL */
394
+ .src_mapping = {
395
+ RCC_CLOCK_MUX_SRC_PLLSAI1,
396
+ RCC_CLOCK_MUX_SRC_PLLSAI2,
397
+ RCC_CLOCK_MUX_SRC_PLLSAI3,
398
+ RCC_CLOCK_MUX_SRC_SAI2_EXTCLK,
399
+ },
400
+ FILL_DEFAULT_INIT_DISABLED,
401
+ },
402
+ [RCC_CLOCK_MUX_SAI1] = {
403
+ .name = "sai1",
404
+ /* Same mapping as: CCIPR_SAI1SEL */
405
+ .src_mapping = {
406
+ RCC_CLOCK_MUX_SRC_PLLSAI1,
407
+ RCC_CLOCK_MUX_SRC_PLLSAI2,
408
+ RCC_CLOCK_MUX_SRC_PLLSAI3,
409
+ RCC_CLOCK_MUX_SRC_SAI1_EXTCLK,
410
+ },
411
+ FILL_DEFAULT_INIT_DISABLED,
412
+ },
413
+ /* From now on, these muxes only have one valid source */
414
+ [RCC_CLOCK_MUX_TSC] = {
415
+ .name = "tsc",
416
+ .src_mapping = {
417
+ RCC_CLOCK_MUX_SRC_SYSCLK,
418
+ },
419
+ FILL_DEFAULT_INIT_DISABLED,
420
+ },
421
+ [RCC_CLOCK_MUX_CRC] = {
422
+ .name = "crc",
423
+ .src_mapping = {
424
+ RCC_CLOCK_MUX_SRC_SYSCLK,
425
+ },
426
+ FILL_DEFAULT_INIT_DISABLED,
427
+ },
428
+ [RCC_CLOCK_MUX_FLASH] = {
429
+ .name = "flash",
430
+ .src_mapping = {
431
+ RCC_CLOCK_MUX_SRC_SYSCLK,
432
+ },
433
+ FILL_DEFAULT_INIT_DISABLED,
434
+ },
435
+ [RCC_CLOCK_MUX_DMA2] = {
436
+ .name = "dma2",
437
+ .src_mapping = {
438
+ RCC_CLOCK_MUX_SRC_SYSCLK,
439
+ },
440
+ FILL_DEFAULT_INIT_DISABLED,
441
+ },
442
+ [RCC_CLOCK_MUX_DMA1] = {
443
+ .name = "dma1",
444
+ .src_mapping = {
445
+ RCC_CLOCK_MUX_SRC_SYSCLK,
446
+ },
447
+ FILL_DEFAULT_INIT_DISABLED,
448
+ },
449
+ [RCC_CLOCK_MUX_RNG] = {
450
+ .name = "rng",
451
+ .src_mapping = {
452
+ RCC_CLOCK_MUX_SRC_SYSCLK,
453
+ },
454
+ FILL_DEFAULT_INIT_DISABLED,
455
+ },
456
+ [RCC_CLOCK_MUX_AES] = {
457
+ .name = "aes",
458
+ .src_mapping = {
459
+ RCC_CLOCK_MUX_SRC_SYSCLK,
460
+ },
461
+ FILL_DEFAULT_INIT_DISABLED,
462
+ },
463
+ [RCC_CLOCK_MUX_OTGFS] = {
464
+ .name = "otgfs",
465
+ .src_mapping = {
466
+ RCC_CLOCK_MUX_SRC_SYSCLK,
467
+ },
468
+ FILL_DEFAULT_INIT_DISABLED,
469
+ },
470
+ [RCC_CLOCK_MUX_GPIOA] = {
471
+ .name = "gpioa",
472
+ .src_mapping = {
473
+ RCC_CLOCK_MUX_SRC_SYSCLK,
474
+ },
475
+ FILL_DEFAULT_INIT_DISABLED,
476
+ },
477
+ [RCC_CLOCK_MUX_GPIOB] = {
478
+ .name = "gpiob",
479
+ .src_mapping = {
480
+ RCC_CLOCK_MUX_SRC_SYSCLK,
481
+ },
482
+ FILL_DEFAULT_INIT_DISABLED,
483
+ },
484
+ [RCC_CLOCK_MUX_GPIOC] = {
485
+ .name = "gpioc",
486
+ .src_mapping = {
487
+ RCC_CLOCK_MUX_SRC_SYSCLK,
488
+ },
489
+ FILL_DEFAULT_INIT_DISABLED,
490
+ },
491
+ [RCC_CLOCK_MUX_GPIOD] = {
492
+ .name = "gpiod",
493
+ .src_mapping = {
494
+ RCC_CLOCK_MUX_SRC_SYSCLK,
495
+ },
496
+ FILL_DEFAULT_INIT_DISABLED,
497
+ },
498
+ [RCC_CLOCK_MUX_GPIOE] = {
499
+ .name = "gpioe",
500
+ .src_mapping = {
501
+ RCC_CLOCK_MUX_SRC_SYSCLK,
502
+ },
503
+ FILL_DEFAULT_INIT_DISABLED,
504
+ },
505
+ [RCC_CLOCK_MUX_GPIOF] = {
506
+ .name = "gpiof",
507
+ .src_mapping = {
508
+ RCC_CLOCK_MUX_SRC_SYSCLK,
509
+ },
510
+ FILL_DEFAULT_INIT_DISABLED,
511
+ },
512
+ [RCC_CLOCK_MUX_GPIOG] = {
513
+ .name = "gpiog",
514
+ .src_mapping = {
515
+ RCC_CLOCK_MUX_SRC_SYSCLK,
516
+ },
517
+ FILL_DEFAULT_INIT_DISABLED,
518
+ },
519
+ [RCC_CLOCK_MUX_GPIOH] = {
520
+ .name = "gpioh",
521
+ .src_mapping = {
522
+ RCC_CLOCK_MUX_SRC_SYSCLK,
523
+ },
524
+ FILL_DEFAULT_INIT_DISABLED,
525
+ },
526
+ [RCC_CLOCK_MUX_QSPI] = {
527
+ .name = "qspi",
528
+ .src_mapping = {
529
+ RCC_CLOCK_MUX_SRC_SYSCLK,
530
+ },
531
+ FILL_DEFAULT_INIT_DISABLED,
532
+ },
533
+ [RCC_CLOCK_MUX_FMC] = {
534
+ .name = "fmc",
535
+ .src_mapping = {
536
+ RCC_CLOCK_MUX_SRC_SYSCLK,
537
+ },
538
+ FILL_DEFAULT_INIT_DISABLED,
539
+ },
540
+ [RCC_CLOCK_MUX_OPAMP] = {
541
+ .name = "opamp",
542
+ .src_mapping = {
543
+ RCC_CLOCK_MUX_SRC_PCLK1,
544
+ },
545
+ FILL_DEFAULT_INIT_DISABLED,
546
+ },
547
+ [RCC_CLOCK_MUX_DAC1] = {
548
+ .name = "dac1",
549
+ .src_mapping = {
550
+ RCC_CLOCK_MUX_SRC_PCLK1,
551
+ },
552
+ FILL_DEFAULT_INIT_DISABLED,
553
+ },
554
+ [RCC_CLOCK_MUX_PWR] = {
555
+ .name = "pwr",
556
+ /*
557
+ * PWREN is in the APB1ENR1 register,
558
+ * but PWR uses SYSCLK according to the clock tree.
559
+ */
560
+ .src_mapping = {
561
+ RCC_CLOCK_MUX_SRC_SYSCLK,
562
+ },
563
+ FILL_DEFAULT_INIT_DISABLED,
564
+ },
565
+ [RCC_CLOCK_MUX_CAN1] = {
566
+ .name = "can1",
567
+ .src_mapping = {
568
+ RCC_CLOCK_MUX_SRC_PCLK1,
569
+ },
570
+ FILL_DEFAULT_INIT_DISABLED,
571
+ },
572
+ [RCC_CLOCK_MUX_SPI3] = {
573
+ .name = "spi3",
574
+ .src_mapping = {
575
+ RCC_CLOCK_MUX_SRC_PCLK1,
576
+ },
577
+ FILL_DEFAULT_INIT_DISABLED,
578
+ },
579
+ [RCC_CLOCK_MUX_SPI2] = {
580
+ .name = "spi2",
581
+ .src_mapping = {
582
+ RCC_CLOCK_MUX_SRC_PCLK1,
583
+ },
584
+ FILL_DEFAULT_INIT_DISABLED,
585
+ },
586
+ [RCC_CLOCK_MUX_WWDG] = {
587
+ .name = "wwdg",
588
+ .src_mapping = {
589
+ RCC_CLOCK_MUX_SRC_PCLK1,
590
+ },
591
+ FILL_DEFAULT_INIT_DISABLED,
592
+ },
593
+ [RCC_CLOCK_MUX_LCD] = {
594
+ .name = "lcd",
595
+ .src_mapping = {
596
+ RCC_CLOCK_MUX_SRC_LCD_AND_RTC_COMMON,
597
+ },
598
+ FILL_DEFAULT_INIT_DISABLED,
599
+ },
600
+ [RCC_CLOCK_MUX_TIM7] = {
601
+ .name = "tim7",
602
+ .src_mapping = {
603
+ RCC_CLOCK_MUX_SRC_PCLK1,
604
+ },
605
+ FILL_DEFAULT_INIT_DISABLED,
606
+ },
607
+ [RCC_CLOCK_MUX_TIM6] = {
608
+ .name = "tim6",
609
+ .src_mapping = {
610
+ RCC_CLOCK_MUX_SRC_PCLK1,
611
+ },
612
+ FILL_DEFAULT_INIT_DISABLED,
613
+ },
614
+ [RCC_CLOCK_MUX_TIM5] = {
615
+ .name = "tim5",
616
+ .src_mapping = {
617
+ RCC_CLOCK_MUX_SRC_PCLK1,
618
+ },
619
+ FILL_DEFAULT_INIT_DISABLED,
620
+ },
621
+ [RCC_CLOCK_MUX_TIM4] = {
622
+ .name = "tim4",
623
+ .src_mapping = {
624
+ RCC_CLOCK_MUX_SRC_PCLK1,
625
+ },
626
+ FILL_DEFAULT_INIT_DISABLED,
627
+ },
628
+ [RCC_CLOCK_MUX_TIM3] = {
629
+ .name = "tim3",
630
+ .src_mapping = {
631
+ RCC_CLOCK_MUX_SRC_PCLK1,
632
+ },
633
+ FILL_DEFAULT_INIT_DISABLED,
634
+ },
635
+ [RCC_CLOCK_MUX_TIM2] = {
636
+ .name = "tim2",
637
+ .src_mapping = {
638
+ RCC_CLOCK_MUX_SRC_PCLK1,
639
+ },
640
+ FILL_DEFAULT_INIT_DISABLED,
641
+ },
642
+ [RCC_CLOCK_MUX_TIM17] = {
643
+ .name = "tim17",
644
+ .src_mapping = {
645
+ RCC_CLOCK_MUX_SRC_PCLK2,
646
+ },
647
+ FILL_DEFAULT_INIT_DISABLED,
648
+ },
649
+ [RCC_CLOCK_MUX_TIM16] = {
650
+ .name = "tim16",
651
+ .src_mapping = {
652
+ RCC_CLOCK_MUX_SRC_PCLK2,
653
+ },
654
+ FILL_DEFAULT_INIT_DISABLED,
655
+ },
656
+ [RCC_CLOCK_MUX_TIM15] = {
657
+ .name = "tim15",
658
+ .src_mapping = {
659
+ RCC_CLOCK_MUX_SRC_PCLK2,
660
+ },
661
+ FILL_DEFAULT_INIT_DISABLED,
662
+ },
663
+ [RCC_CLOCK_MUX_TIM8] = {
664
+ .name = "tim8",
665
+ .src_mapping = {
666
+ RCC_CLOCK_MUX_SRC_PCLK2,
667
+ },
668
+ FILL_DEFAULT_INIT_DISABLED,
669
+ },
670
+ [RCC_CLOCK_MUX_SPI1] = {
671
+ .name = "spi1",
672
+ .src_mapping = {
673
+ RCC_CLOCK_MUX_SRC_PCLK2,
674
+ },
675
+ FILL_DEFAULT_INIT_DISABLED,
676
+ },
677
+ [RCC_CLOCK_MUX_TIM1] = {
678
+ .name = "tim1",
679
+ .src_mapping = {
680
+ RCC_CLOCK_MUX_SRC_PCLK2,
681
+ },
682
+ FILL_DEFAULT_INIT_DISABLED,
683
+ },
684
+ [RCC_CLOCK_MUX_SDMMC1] = {
685
+ .name = "sdmmc1",
686
+ .src_mapping = {
687
+ RCC_CLOCK_MUX_SRC_PCLK2,
688
+ },
689
+ FILL_DEFAULT_INIT_DISABLED,
690
+ },
691
+ [RCC_CLOCK_MUX_FW] = {
692
+ .name = "fw",
693
+ .src_mapping = {
694
+ RCC_CLOCK_MUX_SRC_PCLK2,
695
+ },
696
+ FILL_DEFAULT_INIT_DISABLED,
697
+ },
698
+ [RCC_CLOCK_MUX_SYSCFG] = {
699
+ .name = "syscfg",
700
+ .src_mapping = {
701
+ RCC_CLOCK_MUX_SRC_PCLK2,
702
+ },
703
+ FILL_DEFAULT_INIT_DISABLED,
704
+ },
705
+ [RCC_CLOCK_MUX_RTC] = {
706
+ .name = "rtc",
707
+ .src_mapping = {
708
+ RCC_CLOCK_MUX_SRC_LCD_AND_RTC_COMMON,
709
+ },
710
+ FILL_DEFAULT_INIT_DISABLED,
711
+ },
712
+ [RCC_CLOCK_MUX_CORTEX_FCLK] = {
713
+ .name = "cortex-fclk",
714
+ .src_mapping = {
715
+ RCC_CLOCK_MUX_SRC_HCLK,
716
+ },
717
+ FILL_DEFAULT_INIT_ENABLED,
718
+ },
719
+};
720
+
721
+static inline void set_clock_mux_init_info(RccClockMuxState *mux,
722
+ RccClockMux id)
723
+{
55
+{
724
+ mux->id = id;
56
+ return status->float_3nan_prop_rule;
725
+ mux->multiplier = CLOCK_MUX_INIT_INFO[id].multiplier;
726
+ mux->divider = CLOCK_MUX_INIT_INFO[id].divider;
727
+ mux->enabled = CLOCK_MUX_INIT_INFO[id].enabled;
728
+ /*
729
+ * Every peripheral has the first source of their source list as
730
+ * as their default source.
731
+ */
732
+ mux->src = 0;
733
+}
57
+}
734
+
58
+
735
#endif /* HW_STM32L4X5_RCC_INTERNALS_H */
59
static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
736
diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c
60
{
61
return status->float_infzeronan_rule;
62
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
737
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
738
--- a/hw/misc/stm32l4x5_rcc.c
64
--- a/include/fpu/softfloat-types.h
739
+++ b/hw/misc/stm32l4x5_rcc.c
65
+++ b/include/fpu/softfloat-types.h
740
@@ -XXX,XX +XXX,XX @@
66
@@ -XXX,XX +XXX,XX @@ this code that are retained.
741
#define LSE_FRQ 32768ULL
67
#ifndef SOFTFLOAT_TYPES_H
742
#define LSI_FRQ 32000ULL
68
#define SOFTFLOAT_TYPES_H
743
69
744
-static void clock_mux_update(RccClockMuxState *mux)
70
+#include "hw/registerfields.h"
71
+
72
/*
73
* Software IEC/IEEE floating-point types.
74
*/
75
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
76
float_2nan_prop_x87,
77
} Float2NaNPropRule;
78
745
+/*
79
+/*
746
+ * Function to simply acknowledge and propagate changes in a clock mux
80
+ * 3-input NaN propagation rule, for fused multiply-add. Individual
747
+ * frequency.
81
+ * architectures have different rules for which input NaN is
748
+ * `bypass_source` allows to bypass the period of the current source and just
82
+ * propagated to the output when there is more than one NaN on the
749
+ * consider it equal to 0. This is useful during the hold phase of reset.
83
+ * input.
84
+ *
85
+ * If default_nan_mode is enabled then it is valid not to set a NaN
86
+ * propagation rule, because the softfloat code guarantees not to try
87
+ * to pick a NaN to propagate in default NaN mode. When not in
88
+ * default-NaN mode, it is an error for the target not to set the rule
89
+ * in float_status if it uses a muladd, and we will assert if we need
90
+ * to handle an input NaN and no rule was selected.
91
+ *
92
+ * The naming scheme for Float3NaNPropRule values is:
93
+ * float_3nan_prop_s_abc:
94
+ * = "Prefer SNaN over QNaN, then operand A over B over C"
95
+ * float_3nan_prop_abc:
96
+ * = "Prefer A over B over C regardless of SNaN vs QNAN"
97
+ *
98
+ * For QEMU, the multiply-add operation is A * B + C.
750
+ */
99
+ */
751
+static void clock_mux_update(RccClockMuxState *mux, bool bypass_source)
100
+
101
+/*
102
+ * We set the Float3NaNPropRule enum values up so we can select the
103
+ * right value in pickNaNMulAdd in a data driven way.
104
+ */
105
+FIELD(3NAN, 1ST, 0, 2) /* which operand is most preferred ? */
106
+FIELD(3NAN, 2ND, 2, 2) /* which operand is next most preferred ? */
107
+FIELD(3NAN, 3RD, 4, 2) /* which operand is least preferred ? */
108
+FIELD(3NAN, SNAN, 6, 1) /* do we prefer SNaN over QNaN ? */
109
+
110
+#define PROPRULE(X, Y, Z) \
111
+ ((X << R_3NAN_1ST_SHIFT) | (Y << R_3NAN_2ND_SHIFT) | (Z << R_3NAN_3RD_SHIFT))
112
+
113
+typedef enum __attribute__((__packed__)) {
114
+ float_3nan_prop_none = 0, /* No propagation rule specified */
115
+ float_3nan_prop_abc = PROPRULE(0, 1, 2),
116
+ float_3nan_prop_acb = PROPRULE(0, 2, 1),
117
+ float_3nan_prop_bac = PROPRULE(1, 0, 2),
118
+ float_3nan_prop_bca = PROPRULE(1, 2, 0),
119
+ float_3nan_prop_cab = PROPRULE(2, 0, 1),
120
+ float_3nan_prop_cba = PROPRULE(2, 1, 0),
121
+ float_3nan_prop_s_abc = float_3nan_prop_abc | R_3NAN_SNAN_MASK,
122
+ float_3nan_prop_s_acb = float_3nan_prop_acb | R_3NAN_SNAN_MASK,
123
+ float_3nan_prop_s_bac = float_3nan_prop_bac | R_3NAN_SNAN_MASK,
124
+ float_3nan_prop_s_bca = float_3nan_prop_bca | R_3NAN_SNAN_MASK,
125
+ float_3nan_prop_s_cab = float_3nan_prop_cab | R_3NAN_SNAN_MASK,
126
+ float_3nan_prop_s_cba = float_3nan_prop_cba | R_3NAN_SNAN_MASK,
127
+} Float3NaNPropRule;
128
+
129
+#undef PROPRULE
130
+
131
/*
132
* Rule for result of fused multiply-add 0 * Inf + NaN.
133
* This must be a NaN, but implementations differ on whether this
134
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
135
FloatRoundMode float_rounding_mode;
136
FloatX80RoundPrec floatx80_rounding_precision;
137
Float2NaNPropRule float_2nan_prop_rule;
138
+ Float3NaNPropRule float_3nan_prop_rule;
139
FloatInfZeroNaNRule float_infzeronan_rule;
140
bool tininess_before_rounding;
141
/* should denormalised results go to zero and set the inexact flag? */
142
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
143
index XXXXXXX..XXXXXXX 100644
144
--- a/fpu/softfloat-specialize.c.inc
145
+++ b/fpu/softfloat-specialize.c.inc
146
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
147
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
148
bool infzero, bool have_snan, float_status *status)
752
{
149
{
753
uint64_t src_freq;
150
+ FloatClass cls[3] = { a_cls, b_cls, c_cls };
754
Clock *current_source = mux->srcs[mux->src];
151
+ Float3NaNPropRule rule = status->float_3nan_prop_rule;
755
@@ -XXX,XX +XXX,XX @@ static void clock_mux_update(RccClockMuxState *mux)
152
+ int which;
756
* the clock and the divider of the mux becomes the multiplier of the
153
+
757
* clock.
154
/*
758
*/
155
* We guarantee not to require the target to tell us how to
759
- if (mux->enabled && mux->divider) {
156
* pick a NaN if we're always returning the default NaN.
760
+ if (!bypass_source && mux->enabled && mux->divider) {
157
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
761
freq_multiplier = mux->divider;
762
}
763
764
@@ -XXX,XX +XXX,XX @@ static void clock_mux_src_update(void *opaque, ClockEvent event)
765
const uint32_t update_src = backref - s->backref;
766
/* Only update if the clock that was updated is the current source */
767
if (update_src == s->src) {
768
- clock_mux_update(s);
769
+ clock_mux_update(s, false);
770
}
771
}
772
773
@@ -XXX,XX +XXX,XX @@ static void clock_mux_init(Object *obj)
774
s->out = qdev_init_clock_out(DEVICE(s), "out");
775
}
776
777
+static void clock_mux_reset_enter(Object *obj, ResetType type)
778
+{
779
+ RccClockMuxState *s = RCC_CLOCK_MUX(obj);
780
+ set_clock_mux_init_info(s, s->id);
781
+}
782
+
783
static void clock_mux_reset_hold(Object *obj)
784
-{ }
785
+{
786
+ RccClockMuxState *s = RCC_CLOCK_MUX(obj);
787
+ clock_mux_update(s, true);
788
+}
789
+
790
+static void clock_mux_reset_exit(Object *obj)
791
+{
792
+ RccClockMuxState *s = RCC_CLOCK_MUX(obj);
793
+ clock_mux_update(s, false);
794
+}
795
796
static const VMStateDescription clock_mux_vmstate = {
797
.name = TYPE_RCC_CLOCK_MUX,
798
@@ -XXX,XX +XXX,XX @@ static void clock_mux_class_init(ObjectClass *klass, void *data)
799
DeviceClass *dc = DEVICE_CLASS(klass);
800
ResettableClass *rc = RESETTABLE_CLASS(klass);
801
802
+ rc->phases.enter = clock_mux_reset_enter;
803
rc->phases.hold = clock_mux_reset_hold;
804
+ rc->phases.exit = clock_mux_reset_exit;
805
dc->vmsd = &clock_mux_vmstate;
806
}
807
808
@@ -XXX,XX +XXX,XX @@ static void clock_mux_set_enable(RccClockMuxState *mux, bool enabled)
809
}
810
811
mux->enabled = enabled;
812
- clock_mux_update(mux);
813
+ clock_mux_update(mux, false);
814
}
815
816
static void clock_mux_set_factor(RccClockMuxState *mux,
817
@@ -XXX,XX +XXX,XX @@ static void clock_mux_set_factor(RccClockMuxState *mux,
818
819
mux->multiplier = multiplier;
820
mux->divider = divider;
821
- clock_mux_update(mux);
822
+ clock_mux_update(mux, false);
823
}
824
825
static void clock_mux_set_source(RccClockMuxState *mux, RccClockMuxSource src)
826
@@ -XXX,XX +XXX,XX @@ static void clock_mux_set_source(RccClockMuxState *mux, RccClockMuxSource src)
827
828
trace_stm32l4x5_rcc_mux_set_src(mux->id, mux->src, src);
829
mux->src = src;
830
- clock_mux_update(mux);
831
+ clock_mux_update(mux, false);
832
}
833
834
-static void pll_update(RccPllState *pll)
835
+/*
836
+ * Acknowledge and propagate changes in a PLL frequency.
837
+ * `bypass_source` allows to bypass the period of the current source and just
838
+ * consider it equal to 0. This is useful during the hold phase of reset.
839
+ */
840
+static void pll_update(RccPllState *pll, bool bypass_source)
841
{
842
uint64_t vco_freq, old_channel_freq, channel_freq;
843
int i;
844
@@ -XXX,XX +XXX,XX @@ static void pll_update(RccPllState *pll)
845
}
846
847
old_channel_freq = clock_get_hz(pll->channels[i]);
848
- if (!pll->enabled ||
849
+ if (bypass_source ||
850
+ !pll->enabled ||
851
!pll->channel_enabled[i] ||
852
!pll->channel_divider[i]) {
853
channel_freq = 0;
854
@@ -XXX,XX +XXX,XX @@ static void pll_update(RccPllState *pll)
855
static void pll_src_update(void *opaque, ClockEvent event)
856
{
857
RccPllState *s = opaque;
858
- pll_update(s);
859
+ pll_update(s, false);
860
}
861
862
static void pll_init(Object *obj)
863
@@ -XXX,XX +XXX,XX @@ static void pll_init(Object *obj)
864
}
865
}
866
867
+static void pll_reset_enter(Object *obj, ResetType type)
868
+{
869
+ RccPllState *s = RCC_PLL(obj);
870
+ set_pll_init_info(s, s->id);
871
+}
872
+
873
static void pll_reset_hold(Object *obj)
874
-{ }
875
+{
876
+ RccPllState *s = RCC_PLL(obj);
877
+ pll_update(s, true);
878
+}
879
+
880
+static void pll_reset_exit(Object *obj)
881
+{
882
+ RccPllState *s = RCC_PLL(obj);
883
+ pll_update(s, false);
884
+}
885
886
static const VMStateDescription pll_vmstate = {
887
.name = TYPE_RCC_PLL,
888
@@ -XXX,XX +XXX,XX @@ static void pll_class_init(ObjectClass *klass, void *data)
889
DeviceClass *dc = DEVICE_CLASS(klass);
890
ResettableClass *rc = RESETTABLE_CLASS(klass);
891
892
+ rc->phases.enter = pll_reset_enter;
893
rc->phases.hold = pll_reset_hold;
894
+ rc->phases.exit = pll_reset_exit;
895
dc->vmsd = &pll_vmstate;
896
}
897
898
@@ -XXX,XX +XXX,XX @@ static void pll_set_vco_multiplier(RccPllState *pll, uint32_t vco_multiplier)
899
pll->vco_multiplier, vco_multiplier);
900
901
pll->vco_multiplier = vco_multiplier;
902
- pll_update(pll);
903
+ pll_update(pll, false);
904
}
905
906
static void pll_set_enable(RccPllState *pll, bool enabled)
907
@@ -XXX,XX +XXX,XX @@ static void pll_set_enable(RccPllState *pll, bool enabled)
908
}
909
910
pll->enabled = enabled;
911
- pll_update(pll);
912
+ pll_update(pll, false);
913
}
914
915
static void pll_set_channel_enable(RccPllState *pll,
916
@@ -XXX,XX +XXX,XX @@ static void pll_set_channel_enable(RccPllState *pll,
917
}
918
919
pll->channel_enabled[channel] = enabled;
920
- pll_update(pll);
921
+ pll_update(pll, false);
922
}
923
924
static void pll_set_channel_divider(RccPllState *pll,
925
@@ -XXX,XX +XXX,XX @@ static void pll_set_channel_divider(RccPllState *pll,
926
channel, pll->channel_divider[channel], divider);
927
928
pll->channel_divider[channel] = divider;
929
- pll_update(pll);
930
+ pll_update(pll, false);
931
}
932
933
static void rcc_update_irq(Stm32l4x5RccState *s)
934
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_rcc_init(Object *obj)
935
qdev_init_clocks(DEVICE(s), stm32l4x5_rcc_clocks);
936
937
for (i = 0; i < RCC_NUM_PLL; i++) {
938
- object_initialize_child(obj, "pll[*]",
939
+ object_initialize_child(obj, PLL_INIT_INFO[i].name,
940
&s->plls[i], TYPE_RCC_PLL);
941
+ set_pll_init_info(&s->plls[i], i);
942
}
943
944
for (i = 0; i < RCC_NUM_CLOCK_MUX; i++) {
945
+ char *alias;
946
947
- object_initialize_child(obj, "clock[*]",
948
+ object_initialize_child(obj, CLOCK_MUX_INIT_INFO[i].name,
949
&s->clock_muxes[i],
950
TYPE_RCC_CLOCK_MUX);
951
+ set_clock_mux_init_info(&s->clock_muxes[i], i);
952
953
+ if (!CLOCK_MUX_INIT_INFO[i].hidden) {
954
+ /* Expose muxes output as RCC outputs */
955
+ alias = g_strdup_printf("%s-out", CLOCK_MUX_INIT_INFO[i].name);
956
+ qdev_alias_clock(DEVICE(&s->clock_muxes[i]), "out", DEVICE(obj), alias);
957
+ g_free(alias);
958
+ }
959
}
960
961
s->gnd = clock_new(obj, "gnd");
962
}
963
964
+static void connect_mux_sources(Stm32l4x5RccState *s,
965
+ RccClockMuxState *mux,
966
+ const RccClockMuxSource *clk_mapping)
967
+{
968
+ size_t i;
969
+
970
+ Clock * const CLK_SRC_MAPPING[] = {
971
+ [RCC_CLOCK_MUX_SRC_GND] = s->gnd,
972
+ [RCC_CLOCK_MUX_SRC_HSI] = s->hsi16_rc,
973
+ [RCC_CLOCK_MUX_SRC_HSE] = s->hse,
974
+ [RCC_CLOCK_MUX_SRC_MSI] = s->msi_rc,
975
+ [RCC_CLOCK_MUX_SRC_LSI] = s->lsi_rc,
976
+ [RCC_CLOCK_MUX_SRC_LSE] = s->lse_crystal,
977
+ [RCC_CLOCK_MUX_SRC_SAI1_EXTCLK] = s->sai1_extclk,
978
+ [RCC_CLOCK_MUX_SRC_SAI2_EXTCLK] = s->sai2_extclk,
979
+ [RCC_CLOCK_MUX_SRC_PLL] =
980
+ s->plls[RCC_PLL_PLL].channels[RCC_PLL_CHANNEL_PLLCLK],
981
+ [RCC_CLOCK_MUX_SRC_PLLSAI1] =
982
+ s->plls[RCC_PLL_PLLSAI1].channels[RCC_PLLSAI1_CHANNEL_PLLSAI1CLK],
983
+ [RCC_CLOCK_MUX_SRC_PLLSAI2] =
984
+ s->plls[RCC_PLL_PLLSAI2].channels[RCC_PLLSAI2_CHANNEL_PLLSAI2CLK],
985
+ [RCC_CLOCK_MUX_SRC_PLLSAI3] =
986
+ s->plls[RCC_PLL_PLL].channels[RCC_PLL_CHANNEL_PLLSAI3CLK],
987
+ [RCC_CLOCK_MUX_SRC_PLL48M1] =
988
+ s->plls[RCC_PLL_PLL].channels[RCC_PLL_CHANNEL_PLL48M1CLK],
989
+ [RCC_CLOCK_MUX_SRC_PLL48M2] =
990
+ s->plls[RCC_PLL_PLLSAI1].channels[RCC_PLLSAI1_CHANNEL_PLL48M2CLK],
991
+ [RCC_CLOCK_MUX_SRC_PLLADC1] =
992
+ s->plls[RCC_PLL_PLLSAI1].channels[RCC_PLLSAI1_CHANNEL_PLLADC1CLK],
993
+ [RCC_CLOCK_MUX_SRC_PLLADC2] =
994
+ s->plls[RCC_PLL_PLLSAI2] .channels[RCC_PLLSAI2_CHANNEL_PLLADC2CLK],
995
+ [RCC_CLOCK_MUX_SRC_SYSCLK] = s->clock_muxes[RCC_CLOCK_MUX_SYSCLK].out,
996
+ [RCC_CLOCK_MUX_SRC_HCLK] = s->clock_muxes[RCC_CLOCK_MUX_HCLK].out,
997
+ [RCC_CLOCK_MUX_SRC_PCLK1] = s->clock_muxes[RCC_CLOCK_MUX_PCLK1].out,
998
+ [RCC_CLOCK_MUX_SRC_PCLK2] = s->clock_muxes[RCC_CLOCK_MUX_PCLK2].out,
999
+ [RCC_CLOCK_MUX_SRC_HSE_OVER_32] = s->clock_muxes[RCC_CLOCK_MUX_HSE_OVER_32].out,
1000
+ [RCC_CLOCK_MUX_SRC_LCD_AND_RTC_COMMON] =
1001
+ s->clock_muxes[RCC_CLOCK_MUX_LCD_AND_RTC_COMMON].out,
1002
+ };
1003
+
1004
+ assert(ARRAY_SIZE(CLK_SRC_MAPPING) == RCC_CLOCK_MUX_SRC_NUMBER);
1005
+
1006
+ for (i = 0; i < RCC_NUM_CLOCK_MUX_SRC; i++) {
1007
+ RccClockMuxSource mapping = clk_mapping[i];
1008
+ clock_set_source(mux->srcs[i], CLK_SRC_MAPPING[mapping]);
1009
+ }
1010
+}
1011
+
1012
+
1013
static const VMStateDescription vmstate_stm32l4x5_rcc = {
1014
.name = TYPE_STM32L4X5_RCC,
1015
.version_id = 1,
1016
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp)
1017
for (i = 0; i < RCC_NUM_CLOCK_MUX; i++) {
1018
RccClockMuxState *clock_mux = &s->clock_muxes[i];
1019
1020
+ connect_mux_sources(s, clock_mux, CLOCK_MUX_INIT_INFO[i].src_mapping);
1021
+
1022
if (!qdev_realize(DEVICE(clock_mux), NULL, errp)) {
1023
return;
1024
}
158
}
1025
}
159
}
1026
160
1027
+ /*
161
+ if (rule == float_3nan_prop_none) {
1028
+ * Start clocks after everything is connected
162
#if defined(TARGET_ARM)
1029
+ * to propagate the frequencies along the tree.
163
-
1030
+ */
164
- /* This looks different from the ARM ARM pseudocode, because the ARM ARM
1031
clock_update_hz(s->msi_rc, MSI_DEFAULT_FRQ);
165
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
1032
clock_update_hz(s->sai1_extclk, s->sai1_extclk_frequency);
166
- */
1033
clock_update_hz(s->sai2_extclk, s->sai2_extclk_frequency);
167
- if (is_snan(c_cls)) {
1034
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_rcc_class_init(ObjectClass *klass, void *data)
168
- return 2;
1035
DeviceClass *dc = DEVICE_CLASS(klass);
169
- } else if (is_snan(a_cls)) {
1036
ResettableClass *rc = RESETTABLE_CLASS(klass);
170
- return 0;
1037
171
- } else if (is_snan(b_cls)) {
1038
+ assert(ARRAY_SIZE(CLOCK_MUX_INIT_INFO) == RCC_NUM_CLOCK_MUX);
172
- return 1;
1039
173
- } else if (is_qnan(c_cls)) {
1040
rc->phases.hold = stm32l4x5_rcc_reset_hold;
174
- return 2;
1041
device_class_set_props(dc, stm32l4x5_rcc_properties);
175
- } else if (is_qnan(a_cls)) {
176
- return 0;
177
- } else {
178
- return 1;
179
- }
180
+ /*
181
+ * This looks different from the ARM ARM pseudocode, because the ARM ARM
182
+ * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
183
+ */
184
+ rule = float_3nan_prop_s_cab;
185
#elif defined(TARGET_MIPS)
186
- if (snan_bit_is_one(status)) {
187
- /* Prefer sNaN over qNaN, in the a, b, c order. */
188
- if (is_snan(a_cls)) {
189
- return 0;
190
- } else if (is_snan(b_cls)) {
191
- return 1;
192
- } else if (is_snan(c_cls)) {
193
- return 2;
194
- } else if (is_qnan(a_cls)) {
195
- return 0;
196
- } else if (is_qnan(b_cls)) {
197
- return 1;
198
+ if (snan_bit_is_one(status)) {
199
+ rule = float_3nan_prop_s_abc;
200
} else {
201
- return 2;
202
+ rule = float_3nan_prop_s_cab;
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
239
- */
240
- if (is_nan(a_cls)) {
241
- return 0;
242
- } else if (is_nan(c_cls)) {
243
- return 2;
244
- } else {
245
- return 1;
246
- }
247
+ /*
248
+ * If fRA is a NaN return it; otherwise if fRB is a NaN return it;
249
+ * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
250
+ */
251
+ rule = float_3nan_prop_acb;
252
#elif defined(TARGET_S390X)
253
- if (is_snan(a_cls)) {
254
- return 0;
255
- } else if (is_snan(b_cls)) {
256
- return 1;
257
- } else if (is_snan(c_cls)) {
258
- return 2;
259
- } else if (is_qnan(a_cls)) {
260
- return 0;
261
- } else if (is_qnan(b_cls)) {
262
- return 1;
263
- } else {
264
- return 2;
265
- }
266
+ rule = float_3nan_prop_s_abc;
267
#elif defined(TARGET_SPARC)
268
- /* Prefer SNaN over QNaN, order C, B, A. */
269
- if (is_snan(c_cls)) {
270
- return 2;
271
- } else if (is_snan(b_cls)) {
272
- return 1;
273
- } else if (is_snan(a_cls)) {
274
- return 0;
275
- } else if (is_qnan(c_cls)) {
276
- return 2;
277
- } else if (is_qnan(b_cls)) {
278
- return 1;
279
- } else {
280
- return 0;
281
- }
282
+ rule = float_3nan_prop_s_cba;
283
#elif defined(TARGET_XTENSA)
284
- /*
285
- * For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
286
- * an input NaN if we have one (ie c).
287
- */
288
- if (status->use_first_nan) {
289
- if (is_nan(a_cls)) {
290
- return 0;
291
- } else if (is_nan(b_cls)) {
292
- return 1;
293
+ if (status->use_first_nan) {
294
+ rule = float_3nan_prop_abc;
295
} else {
296
- return 2;
297
+ rule = float_3nan_prop_cba;
298
}
299
- } else {
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
321
+ }
322
+
323
+ assert(rule != float_3nan_prop_none);
324
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
325
+ /* We have at least one SNaN input and should prefer it */
326
+ do {
327
+ which = rule & R_3NAN_1ST_MASK;
328
+ rule >>= R_3NAN_1ST_LENGTH;
329
+ } while (!is_snan(cls[which]));
330
+ } else {
331
+ do {
332
+ which = rule & R_3NAN_1ST_MASK;
333
+ rule >>= R_3NAN_1ST_LENGTH;
334
+ } while (!is_nan(cls[which]));
335
+ }
336
+ return which;
337
}
338
339
/*----------------------------------------------------------------------------
1042
--
340
--
1043
2.34.1
341
2.34.1
1044
1045
diff view generated by jsdifflib
New patch
1
Explicitly set a rule in the softfloat tests for propagating NaNs in
2
the muladd case. In meson.build we put -DTARGET_ARM in fpcflags, and
3
so we should select here the Arm rule of float_3nan_prop_s_cab.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241202131347.498124-17-peter.maydell@linaro.org
8
---
9
tests/fp/fp-bench.c | 1 +
10
tests/fp/fp-test.c | 1 +
11
2 files changed, 2 insertions(+)
12
13
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/fp/fp-bench.c
16
+++ b/tests/fp/fp-bench.c
17
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
18
* doesn't specify match those used by the Arm architecture.
19
*/
20
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
21
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &soft_status);
22
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
23
24
f = bench_funcs[operation][precision];
25
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/tests/fp/fp-test.c
28
+++ b/tests/fp/fp-test.c
29
@@ -XXX,XX +XXX,XX @@ void run_test(void)
30
* doesn't specify match those used by the Arm architecture.
31
*/
32
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
33
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &qsf);
34
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
35
36
genCases_setLevel(test_level);
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-18-peter.maydell@linaro.org
7
---
8
target/arm/cpu.c | 5 +++++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 6 insertions(+), 7 deletions(-)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
17
* * tininess-before-rounding
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
21
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
22
+ * but note that for QEMU muladd is a * b + c, whereas for
23
+ * the pseudocode function the arguments are in the order c, a, b.
24
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
25
* and the input NaN if it is signalling
26
*/
27
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
28
{
29
set_float_detect_tininess(float_tininess_before_rounding, s);
30
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
31
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
32
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
33
}
34
35
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
36
index XXXXXXX..XXXXXXX 100644
37
--- a/fpu/softfloat-specialize.c.inc
38
+++ b/fpu/softfloat-specialize.c.inc
39
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
40
}
41
42
if (rule == float_3nan_prop_none) {
43
-#if defined(TARGET_ARM)
44
- /*
45
- * This looks different from the ARM ARM pseudocode, because the ARM ARM
46
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
47
- */
48
- rule = float_3nan_prop_s_cab;
49
-#elif defined(TARGET_MIPS)
50
+#if defined(TARGET_MIPS)
51
if (snan_bit_is_one(status)) {
52
rule = float_3nan_prop_s_abc;
53
} else {
54
--
55
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for loongarch, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-19-peter.maydell@linaro.org
7
---
8
target/loongarch/tcg/fpu_helper.c | 1 +
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 1 insertion(+), 2 deletions(-)
11
12
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/loongarch/tcg/fpu_helper.c
15
+++ b/target/loongarch/tcg/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
17
* case sets InvalidOp and returns the input value 'c'
18
*/
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
21
}
22
23
int ieee_ex_to_loongarch(int xcpt)
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
29
} else {
30
rule = float_3nan_prop_s_cab;
31
}
32
-#elif defined(TARGET_LOONGARCH64)
33
- rule = float_3nan_prop_s_cab;
34
#elif defined(TARGET_PPC)
35
/*
36
* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for PPC, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-20-peter.maydell@linaro.org
7
---
8
target/ppc/cpu_init.c | 8 ++++++++
9
fpu/softfloat-specialize.c.inc | 6 ------
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
15
+++ b/target/ppc/cpu_init.c
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
21
+ * NaN propagation for fused multiply-add:
22
+ * if fRA is a NaN return it; otherwise if fRB is a NaN return it;
23
+ * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
24
+ * whereas QEMU labels the operands as (a * b) + c.
25
+ */
26
+ set_float_3nan_prop_rule(float_3nan_prop_acb, &env->fp_status);
27
+ set_float_3nan_prop_rule(float_3nan_prop_acb, &env->vec_status);
28
/*
29
* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
30
* to return an input NaN if we have one (ie c) rather than generating
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
} else {
37
rule = float_3nan_prop_s_cab;
38
}
39
-#elif defined(TARGET_PPC)
40
- /*
41
- * If fRA is a NaN return it; otherwise if fRB is a NaN return it;
42
- * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
43
- */
44
- rule = float_3nan_prop_acb;
45
#elif defined(TARGET_S390X)
46
rule = float_3nan_prop_s_abc;
47
#elif defined(TARGET_SPARC)
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for s390x, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-21-peter.maydell@linaro.org
7
---
8
target/s390x/cpu.c | 1 +
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 1 insertion(+), 2 deletions(-)
11
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/s390x/cpu.c
15
+++ b/target/s390x/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
17
set_float_detect_tininess(float_tininess_before_rounding,
18
&env->fpu_status);
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
20
+ set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
21
set_float_infzeronan_rule(float_infzeronan_dnan_always,
22
&env->fpu_status);
23
/* fall through */
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
29
} else {
30
rule = float_3nan_prop_s_cab;
31
}
32
-#elif defined(TARGET_S390X)
33
- rule = float_3nan_prop_s_abc;
34
#elif defined(TARGET_SPARC)
35
rule = float_3nan_prop_s_cba;
36
#elif defined(TARGET_XTENSA)
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for SPARC, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-22-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For fused-multiply add, prefer SNaN over QNaN, then C->B->A */
21
+ set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
22
/* For inf * 0 + NaN, return the input NaN */
23
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
} else {
31
rule = float_3nan_prop_s_cab;
32
}
33
-#elif defined(TARGET_SPARC)
34
- rule = float_3nan_prop_s_cba;
35
#elif defined(TARGET_XTENSA)
36
if (status->use_first_nan) {
37
rule = float_3nan_prop_abc;
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-23-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 4 ++++
9
target/mips/msa.c | 3 +++
10
fpu/softfloat-specialize.c.inc | 8 +-------
11
3 files changed, 8 insertions(+), 7 deletions(-)
12
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
18
{
19
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
20
FloatInfZeroNaNRule izn_rule;
21
+ Float3NaNPropRule nan3_rule;
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
28
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
29
+ nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
30
+ set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
31
+
32
}
33
34
static inline void restore_fp_status(CPUMIPSState *env)
35
diff --git a/target/mips/msa.c b/target/mips/msa.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/mips/msa.c
38
+++ b/target/mips/msa.c
39
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
40
set_float_2nan_prop_rule(float_2nan_prop_s_ab,
41
&env->active_tc.msa_fp_status);
42
43
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab,
44
+ &env->active_tc.msa_fp_status);
45
+
46
/* clear float_status exception flags */
47
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
48
49
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
50
index XXXXXXX..XXXXXXX 100644
51
--- a/fpu/softfloat-specialize.c.inc
52
+++ b/fpu/softfloat-specialize.c.inc
53
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
54
}
55
56
if (rule == float_3nan_prop_none) {
57
-#if defined(TARGET_MIPS)
58
- if (snan_bit_is_one(status)) {
59
- rule = float_3nan_prop_s_abc;
60
- } else {
61
- rule = float_3nan_prop_s_cab;
62
- }
63
-#elif defined(TARGET_XTENSA)
64
+#if defined(TARGET_XTENSA)
65
if (status->use_first_nan) {
66
rule = float_3nan_prop_abc;
67
} else {
68
--
69
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for xtensa, 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-24-peter.maydell@linaro.org
7
---
8
target/xtensa/fpu_helper.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 8 --------
10
2 files changed, 2 insertions(+), 8 deletions(-)
11
12
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/xtensa/fpu_helper.c
15
+++ b/target/xtensa/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
17
set_use_first_nan(use_first, &env->fp_status);
18
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
19
&env->fp_status);
20
+ set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
21
+ &env->fp_status);
22
}
23
24
void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
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
32
if (rule == float_3nan_prop_none) {
33
-#if defined(TARGET_XTENSA)
34
- if (status->use_first_nan) {
35
- rule = float_3nan_prop_abc;
36
- } else {
37
- rule = float_3nan_prop_cba;
38
- }
39
-#else
40
rule = float_3nan_prop_abc;
41
-#endif
42
}
43
44
assert(rule != float_3nan_prop_none);
45
--
46
2.34.1
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
New patch
1
In cf_fpu_gdb_get_reg() and cf_fpu_gdb_set_reg() we do the conversion
2
from float64 to floatx80 using a scratch float_status, because we
3
don't want the conversion to affect the CPU's floating point exception
4
status. Currently we use a zero-initialized float_status. This will
5
get steadily more awkward as we add config knobs to float_status
6
that the target must initialize. Avoid having to add any of that
7
configuration here by instead initializing our local float_status
8
from the env->fp_status.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-32-peter.maydell@linaro.org
13
---
14
target/m68k/helper.c | 6 ++++--
15
1 file changed, 4 insertions(+), 2 deletions(-)
16
17
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/m68k/helper.c
20
+++ b/target/m68k/helper.c
21
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_get_reg(CPUState *cs, GByteArray *mem_buf, int n)
22
CPUM68KState *env = &cpu->env;
23
24
if (n < 8) {
25
- float_status s = {};
26
+ /* Use scratch float_status so any exceptions don't change CPU state */
27
+ float_status s = env->fp_status;
28
return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
29
}
30
switch (n) {
31
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n)
32
CPUM68KState *env = &cpu->env;
33
34
if (n < 8) {
35
- float_status s = {};
36
+ /* Use scratch float_status so any exceptions don't change CPU state */
37
+ float_status s = env->fp_status;
38
env->fregs[n].d = float64_to_floatx80(ldq_be_p(mem_buf), &s);
39
return 8;
40
}
41
--
42
2.34.1
diff view generated by jsdifflib
1
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
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 object is used to represent every multiplexer in the clock tree as
8
To do this we need to pass the CPU env pointer in to the helper.
4
well as every clock output, every presecaler, frequency multiplier, etc.
5
This allows to use a generic approach for every component of the clock tree
6
(except the PLLs).
7
9
8
The migration handling is based on hw/misc/zynq_sclr.c.
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Three phase reset will be handled in a later commit.
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-33-peter.maydell@linaro.org
13
---
14
target/sparc/helper.h | 4 ++--
15
target/sparc/fop_helper.c | 8 ++++----
16
target/sparc/translate.c | 4 ++--
17
3 files changed, 8 insertions(+), 8 deletions(-)
10
18
11
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
19
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
12
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
13
Acked-by: Alistair Francis <alistair.francis@wdc.com>
14
Message-id: 20240303140643.81957-3-arnaud.minier@telecom-paris.fr
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
include/hw/misc/stm32l4x5_rcc.h | 119 ++++++++++++++++
19
include/hw/misc/stm32l4x5_rcc_internals.h | 29 ++++
20
hw/misc/stm32l4x5_rcc.c | 160 ++++++++++++++++++++++
21
hw/misc/trace-events | 5 +
22
4 files changed, 313 insertions(+)
23
24
diff --git a/include/hw/misc/stm32l4x5_rcc.h b/include/hw/misc/stm32l4x5_rcc.h
25
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/misc/stm32l4x5_rcc.h
21
--- a/target/sparc/helper.h
27
+++ b/include/hw/misc/stm32l4x5_rcc.h
22
+++ b/target/sparc/helper.h
28
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5RccState, STM32L4X5_RCC)
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
29
24
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
30
/* In the Stm32l4x5 clock tree, mux have at most 7 sources */
25
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128)
31
#define RCC_NUM_CLOCK_MUX_SRC 7
26
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128)
32
+/* NB: Prescaler are assimilated to mux with one source and one output */
27
-DEF_HELPER_FLAGS_2(flcmps, TCG_CALL_NO_RWG_SE, i32, f32, f32)
33
+typedef enum RccClockMux {
28
-DEF_HELPER_FLAGS_2(flcmpd, TCG_CALL_NO_RWG_SE, i32, f64, f64)
34
+ /* Internal muxes that arent't exposed publicly to other peripherals */
29
+DEF_HELPER_FLAGS_3(flcmps, TCG_CALL_NO_RWG_SE, i32, env, f32, f32)
35
+ RCC_CLOCK_MUX_SYSCLK,
30
+DEF_HELPER_FLAGS_3(flcmpd, TCG_CALL_NO_RWG_SE, i32, env, f64, f64)
36
+ RCC_CLOCK_MUX_PLL_INPUT,
31
DEF_HELPER_2(raise_exception, noreturn, env, int)
37
+ RCC_CLOCK_MUX_HCLK,
32
38
+ RCC_CLOCK_MUX_PCLK1,
33
DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64)
39
+ RCC_CLOCK_MUX_PCLK2,
34
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
40
+ RCC_CLOCK_MUX_HSE_OVER_32,
41
+ RCC_CLOCK_MUX_LCD_AND_RTC_COMMON,
42
+
43
+ /* Muxes with a publicly available output */
44
+ RCC_CLOCK_MUX_CORTEX_REFCLK,
45
+ RCC_CLOCK_MUX_USART1,
46
+ RCC_CLOCK_MUX_USART2,
47
+ RCC_CLOCK_MUX_USART3,
48
+ RCC_CLOCK_MUX_UART4,
49
+ RCC_CLOCK_MUX_UART5,
50
+ RCC_CLOCK_MUX_LPUART1,
51
+ RCC_CLOCK_MUX_I2C1,
52
+ RCC_CLOCK_MUX_I2C2,
53
+ RCC_CLOCK_MUX_I2C3,
54
+ RCC_CLOCK_MUX_LPTIM1,
55
+ RCC_CLOCK_MUX_LPTIM2,
56
+ RCC_CLOCK_MUX_SWPMI1,
57
+ RCC_CLOCK_MUX_MCO,
58
+ RCC_CLOCK_MUX_LSCO,
59
+ RCC_CLOCK_MUX_DFSDM1,
60
+ RCC_CLOCK_MUX_ADC,
61
+ RCC_CLOCK_MUX_CLK48,
62
+ RCC_CLOCK_MUX_SAI1,
63
+ RCC_CLOCK_MUX_SAI2,
64
+
65
+ /*
66
+ * Mux that have only one input and one output assigned to as peripheral.
67
+ * They could be direct lines but it is simpler
68
+ * to use the same logic for all outputs.
69
+ */
70
+ /* - AHB1 */
71
+ RCC_CLOCK_MUX_TSC,
72
+ RCC_CLOCK_MUX_CRC,
73
+ RCC_CLOCK_MUX_FLASH,
74
+ RCC_CLOCK_MUX_DMA2,
75
+ RCC_CLOCK_MUX_DMA1,
76
+
77
+ /* - AHB2 */
78
+ RCC_CLOCK_MUX_RNG,
79
+ RCC_CLOCK_MUX_AES,
80
+ RCC_CLOCK_MUX_OTGFS,
81
+ RCC_CLOCK_MUX_GPIOA,
82
+ RCC_CLOCK_MUX_GPIOB,
83
+ RCC_CLOCK_MUX_GPIOC,
84
+ RCC_CLOCK_MUX_GPIOD,
85
+ RCC_CLOCK_MUX_GPIOE,
86
+ RCC_CLOCK_MUX_GPIOF,
87
+ RCC_CLOCK_MUX_GPIOG,
88
+ RCC_CLOCK_MUX_GPIOH,
89
+
90
+ /* - AHB3 */
91
+ RCC_CLOCK_MUX_QSPI,
92
+ RCC_CLOCK_MUX_FMC,
93
+
94
+ /* - APB1 */
95
+ RCC_CLOCK_MUX_OPAMP,
96
+ RCC_CLOCK_MUX_DAC1,
97
+ RCC_CLOCK_MUX_PWR,
98
+ RCC_CLOCK_MUX_CAN1,
99
+ RCC_CLOCK_MUX_SPI3,
100
+ RCC_CLOCK_MUX_SPI2,
101
+ RCC_CLOCK_MUX_WWDG,
102
+ RCC_CLOCK_MUX_LCD,
103
+ RCC_CLOCK_MUX_TIM7,
104
+ RCC_CLOCK_MUX_TIM6,
105
+ RCC_CLOCK_MUX_TIM5,
106
+ RCC_CLOCK_MUX_TIM4,
107
+ RCC_CLOCK_MUX_TIM3,
108
+ RCC_CLOCK_MUX_TIM2,
109
+
110
+ /* - APB2 */
111
+ RCC_CLOCK_MUX_TIM17,
112
+ RCC_CLOCK_MUX_TIM16,
113
+ RCC_CLOCK_MUX_TIM15,
114
+ RCC_CLOCK_MUX_TIM8,
115
+ RCC_CLOCK_MUX_SPI1,
116
+ RCC_CLOCK_MUX_TIM1,
117
+ RCC_CLOCK_MUX_SDMMC1,
118
+ RCC_CLOCK_MUX_FW,
119
+ RCC_CLOCK_MUX_SYSCFG,
120
+
121
+ /* - BDCR */
122
+ RCC_CLOCK_MUX_RTC,
123
+
124
+ /* - OTHER */
125
+ RCC_CLOCK_MUX_CORTEX_FCLK,
126
+
127
+ RCC_NUM_CLOCK_MUX
128
+} RccClockMux;
129
+
130
+typedef struct RccClockMuxState {
131
+ DeviceState parent_obj;
132
+
133
+ RccClockMux id;
134
+ Clock *srcs[RCC_NUM_CLOCK_MUX_SRC];
135
+ Clock *out;
136
+ bool enabled;
137
+ uint32_t src;
138
+ uint32_t multiplier;
139
+ uint32_t divider;
140
+
141
+ /*
142
+ * Used by clock srcs update callback to retrieve both the clock and the
143
+ * source number.
144
+ */
145
+ struct RccClockMuxState *backref[RCC_NUM_CLOCK_MUX_SRC];
146
+} RccClockMuxState;
147
+
148
struct Stm32l4x5RccState {
149
SysBusDevice parent_obj;
150
151
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5RccState {
152
Clock *sai1_extclk;
153
Clock *sai2_extclk;
154
155
+ /* Muxes ~= outputs */
156
+ RccClockMuxState clock_muxes[RCC_NUM_CLOCK_MUX];
157
+
158
qemu_irq irq;
159
uint64_t hse_frequency;
160
uint64_t sai1_extclk_frequency;
161
diff --git a/include/hw/misc/stm32l4x5_rcc_internals.h b/include/hw/misc/stm32l4x5_rcc_internals.h
162
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
163
--- a/include/hw/misc/stm32l4x5_rcc_internals.h
36
--- a/target/sparc/fop_helper.c
164
+++ b/include/hw/misc/stm32l4x5_rcc_internals.h
37
+++ b/target/sparc/fop_helper.c
165
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@ uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
166
#include "hw/registerfields.h"
39
return finish_fcmp(env, r, GETPC());
167
#include "hw/misc/stm32l4x5_rcc.h"
40
}
168
41
169
+#define TYPE_RCC_CLOCK_MUX "stm32l4x5-rcc-clock-mux"
42
-uint32_t helper_flcmps(float32 src1, float32 src2)
170
+OBJECT_DECLARE_SIMPLE_TYPE(RccClockMuxState, RCC_CLOCK_MUX)
43
+uint32_t helper_flcmps(CPUSPARCState *env, float32 src1, float32 src2)
171
44
{
172
/* Register map */
45
/*
173
REG32(CR, 0x00)
46
* FLCMP never raises an exception nor modifies any FSR fields.
174
@@ -XXX,XX +XXX,XX @@ REG32(CSR, 0x94)
47
* Perform the comparison with a dummy fp environment.
175
R_CSR_FWRSTF_MASK | \
48
*/
176
R_CSR_LSIRDY_MASK)
49
- float_status discard = { };
177
50
+ float_status discard = env->fp_status;
178
+typedef enum RccClockMuxSource {
51
FloatRelation r;
179
+ RCC_CLOCK_MUX_SRC_GND = 0,
52
180
+ RCC_CLOCK_MUX_SRC_HSI,
53
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
181
+ RCC_CLOCK_MUX_SRC_HSE,
54
@@ -XXX,XX +XXX,XX @@ uint32_t helper_flcmps(float32 src1, float32 src2)
182
+ RCC_CLOCK_MUX_SRC_MSI,
55
g_assert_not_reached();
183
+ RCC_CLOCK_MUX_SRC_LSI,
56
}
184
+ RCC_CLOCK_MUX_SRC_LSE,
57
185
+ RCC_CLOCK_MUX_SRC_SAI1_EXTCLK,
58
-uint32_t helper_flcmpd(float64 src1, float64 src2)
186
+ RCC_CLOCK_MUX_SRC_SAI2_EXTCLK,
59
+uint32_t helper_flcmpd(CPUSPARCState *env, float64 src1, float64 src2)
187
+ RCC_CLOCK_MUX_SRC_PLL,
60
{
188
+ RCC_CLOCK_MUX_SRC_PLLSAI1,
61
- float_status discard = { };
189
+ RCC_CLOCK_MUX_SRC_PLLSAI2,
62
+ float_status discard = env->fp_status;
190
+ RCC_CLOCK_MUX_SRC_PLLSAI3,
63
FloatRelation r;
191
+ RCC_CLOCK_MUX_SRC_PLL48M1,
64
192
+ RCC_CLOCK_MUX_SRC_PLL48M2,
65
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
193
+ RCC_CLOCK_MUX_SRC_PLLADC1,
66
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
194
+ RCC_CLOCK_MUX_SRC_PLLADC2,
195
+ RCC_CLOCK_MUX_SRC_SYSCLK,
196
+ RCC_CLOCK_MUX_SRC_HCLK,
197
+ RCC_CLOCK_MUX_SRC_PCLK1,
198
+ RCC_CLOCK_MUX_SRC_PCLK2,
199
+ RCC_CLOCK_MUX_SRC_HSE_OVER_32,
200
+ RCC_CLOCK_MUX_SRC_LCD_AND_RTC_COMMON,
201
+
202
+ RCC_CLOCK_MUX_SRC_NUMBER,
203
+} RccClockMuxSource;
204
+
205
#endif /* HW_STM32L4X5_RCC_INTERNALS_H */
206
diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c
207
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
208
--- a/hw/misc/stm32l4x5_rcc.c
68
--- a/target/sparc/translate.c
209
+++ b/hw/misc/stm32l4x5_rcc.c
69
+++ b/target/sparc/translate.c
210
@@ -XXX,XX +XXX,XX @@
70
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a)
211
#define LSE_FRQ 32768ULL
71
212
#define LSI_FRQ 32000ULL
72
src1 = gen_load_fpr_F(dc, a->rs1);
213
73
src2 = gen_load_fpr_F(dc, a->rs2);
214
+static void clock_mux_update(RccClockMuxState *mux)
74
- gen_helper_flcmps(cpu_fcc[a->cc], src1, src2);
215
+{
75
+ gen_helper_flcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
216
+ uint64_t src_freq;
76
return advance_pc(dc);
217
+ Clock *current_source = mux->srcs[mux->src];
218
+ uint32_t freq_multiplier = 0;
219
+ /*
220
+ * To avoid rounding errors, we use the clock period instead of the
221
+ * frequency.
222
+ * This means that the multiplier of the mux becomes the divider of
223
+ * the clock and the divider of the mux becomes the multiplier of the
224
+ * clock.
225
+ */
226
+ if (mux->enabled && mux->divider) {
227
+ freq_multiplier = mux->divider;
228
+ }
229
+
230
+ clock_set_mul_div(mux->out, freq_multiplier, mux->multiplier);
231
+ clock_update(mux->out, clock_get(current_source));
232
+
233
+ src_freq = clock_get_hz(current_source);
234
+ /* TODO: can we simply detect if the config changed so that we reduce log spam ? */
235
+ trace_stm32l4x5_rcc_mux_update(mux->id, mux->src, src_freq,
236
+ mux->multiplier, mux->divider);
237
+}
238
+
239
+static void clock_mux_src_update(void *opaque, ClockEvent event)
240
+{
241
+ RccClockMuxState **backref = opaque;
242
+ RccClockMuxState *s = *backref;
243
+ /*
244
+ * The backref value is equal to:
245
+ * s->backref + (sizeof(RccClockMuxState *) * update_src).
246
+ * By subtracting we can get back the index of the updated clock.
247
+ */
248
+ const uint32_t update_src = backref - s->backref;
249
+ /* Only update if the clock that was updated is the current source */
250
+ if (update_src == s->src) {
251
+ clock_mux_update(s);
252
+ }
253
+}
254
+
255
+static void clock_mux_init(Object *obj)
256
+{
257
+ RccClockMuxState *s = RCC_CLOCK_MUX(obj);
258
+ size_t i;
259
+
260
+ for (i = 0; i < RCC_NUM_CLOCK_MUX_SRC; i++) {
261
+ char *name = g_strdup_printf("srcs[%zu]", i);
262
+ s->backref[i] = s;
263
+ s->srcs[i] = qdev_init_clock_in(DEVICE(s), name,
264
+ clock_mux_src_update,
265
+ &s->backref[i],
266
+ ClockUpdate);
267
+ g_free(name);
268
+ }
269
+
270
+ s->out = qdev_init_clock_out(DEVICE(s), "out");
271
+}
272
+
273
+static void clock_mux_reset_hold(Object *obj)
274
+{ }
275
+
276
+static const VMStateDescription clock_mux_vmstate = {
277
+ .name = TYPE_RCC_CLOCK_MUX,
278
+ .version_id = 1,
279
+ .minimum_version_id = 1,
280
+ .fields = (VMStateField[]) {
281
+ VMSTATE_UINT32(id, RccClockMuxState),
282
+ VMSTATE_ARRAY_CLOCK(srcs, RccClockMuxState,
283
+ RCC_NUM_CLOCK_MUX_SRC),
284
+ VMSTATE_BOOL(enabled, RccClockMuxState),
285
+ VMSTATE_UINT32(src, RccClockMuxState),
286
+ VMSTATE_UINT32(multiplier, RccClockMuxState),
287
+ VMSTATE_UINT32(divider, RccClockMuxState),
288
+ VMSTATE_END_OF_LIST()
289
+ }
290
+};
291
+
292
+static void clock_mux_class_init(ObjectClass *klass, void *data)
293
+{
294
+ DeviceClass *dc = DEVICE_CLASS(klass);
295
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
296
+
297
+ rc->phases.hold = clock_mux_reset_hold;
298
+ dc->vmsd = &clock_mux_vmstate;
299
+}
300
+
301
+static void clock_mux_set_enable(RccClockMuxState *mux, bool enabled)
302
+{
303
+ if (mux->enabled == enabled) {
304
+ return;
305
+ }
306
+
307
+ if (enabled) {
308
+ trace_stm32l4x5_rcc_mux_enable(mux->id);
309
+ } else {
310
+ trace_stm32l4x5_rcc_mux_disable(mux->id);
311
+ }
312
+
313
+ mux->enabled = enabled;
314
+ clock_mux_update(mux);
315
+}
316
+
317
+static void clock_mux_set_factor(RccClockMuxState *mux,
318
+ uint32_t multiplier, uint32_t divider)
319
+{
320
+ if (mux->multiplier == multiplier && mux->divider == divider) {
321
+ return;
322
+ }
323
+ trace_stm32l4x5_rcc_mux_set_factor(mux->id,
324
+ mux->multiplier, multiplier, mux->divider, divider);
325
+
326
+ mux->multiplier = multiplier;
327
+ mux->divider = divider;
328
+ clock_mux_update(mux);
329
+}
330
+
331
+static void clock_mux_set_source(RccClockMuxState *mux, RccClockMuxSource src)
332
+{
333
+ if (mux->src == src) {
334
+ return;
335
+ }
336
+
337
+ trace_stm32l4x5_rcc_mux_set_src(mux->id, mux->src, src);
338
+ mux->src = src;
339
+ clock_mux_update(mux);
340
+}
341
+
342
static void rcc_update_irq(Stm32l4x5RccState *s)
343
{
344
if (s->cifr & CIFR_IRQ_MASK) {
345
@@ -XXX,XX +XXX,XX @@ static const ClockPortInitArray stm32l4x5_rcc_clocks = {
346
static void stm32l4x5_rcc_init(Object *obj)
347
{
348
Stm32l4x5RccState *s = STM32L4X5_RCC(obj);
349
+ size_t i;
350
351
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
352
353
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_rcc_init(Object *obj)
354
355
qdev_init_clocks(DEVICE(s), stm32l4x5_rcc_clocks);
356
357
+ for (i = 0; i < RCC_NUM_CLOCK_MUX; i++) {
358
+
359
+ object_initialize_child(obj, "clock[*]",
360
+ &s->clock_muxes[i],
361
+ TYPE_RCC_CLOCK_MUX);
362
+
363
+ }
364
+
365
s->gnd = clock_new(obj, "gnd");
366
}
77
}
367
78
368
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stm32l4x5_rcc = {
79
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
369
static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp)
80
370
{
81
src1 = gen_load_fpr_D(dc, a->rs1);
371
Stm32l4x5RccState *s = STM32L4X5_RCC(dev);
82
src2 = gen_load_fpr_D(dc, a->rs2);
372
+ size_t i;
83
- gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
373
84
+ gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
374
if (s->hse_frequency < 4000000ULL ||
85
return advance_pc(dc);
375
s->hse_frequency > 48000000ULL) {
376
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp)
377
return;
378
}
379
380
+ for (i = 0; i < RCC_NUM_CLOCK_MUX; i++) {
381
+ RccClockMuxState *clock_mux = &s->clock_muxes[i];
382
+
383
+ if (!qdev_realize(DEVICE(clock_mux), NULL, errp)) {
384
+ return;
385
+ }
386
+ }
387
+
388
clock_update_hz(s->msi_rc, MSI_DEFAULT_FRQ);
389
clock_update_hz(s->sai1_extclk, s->sai1_extclk_frequency);
390
clock_update_hz(s->sai2_extclk, s->sai2_extclk_frequency);
391
clock_update(s->gnd, 0);
392
+
393
+ /*
394
+ * Dummy values to make compilation pass.
395
+ * Removed in later commits.
396
+ */
397
+ clock_mux_set_source(&s->clock_muxes[0], RCC_CLOCK_MUX_SRC_GND);
398
+ clock_mux_set_enable(&s->clock_muxes[0], true);
399
+ clock_mux_set_factor(&s->clock_muxes[0], 1, 1);
400
}
86
}
401
87
402
static Property stm32l4x5_rcc_properties[] = {
403
@@ -XXX,XX +XXX,XX @@ static const TypeInfo stm32l4x5_rcc_types[] = {
404
.instance_size = sizeof(Stm32l4x5RccState),
405
.instance_init = stm32l4x5_rcc_init,
406
.class_init = stm32l4x5_rcc_class_init,
407
+ }, {
408
+ .name = TYPE_RCC_CLOCK_MUX,
409
+ .parent = TYPE_DEVICE,
410
+ .instance_size = sizeof(RccClockMuxState),
411
+ .instance_init = clock_mux_init,
412
+ .class_init = clock_mux_class_init,
413
}
414
};
415
416
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
417
index XXXXXXX..XXXXXXX 100644
418
--- a/hw/misc/trace-events
419
+++ b/hw/misc/trace-events
420
@@ -XXX,XX +XXX,XX @@ stm32l4x5_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64
421
# stm32l4x5_rcc.c
422
stm32l4x5_rcc_read(uint64_t addr, uint32_t data) "RCC: Read <0x%" PRIx64 "> -> 0x%" PRIx32
423
stm32l4x5_rcc_write(uint64_t addr, uint32_t data) "RCC: Write <0x%" PRIx64 "> <- 0x%" PRIx32
424
+stm32l4x5_rcc_mux_enable(uint32_t mux_id) "RCC: Mux %d enabled"
425
+stm32l4x5_rcc_mux_disable(uint32_t mux_id) "RCC: Mux %d disabled"
426
+stm32l4x5_rcc_mux_set_factor(uint32_t mux_id, uint32_t old_multiplier, uint32_t new_multiplier, uint32_t old_divider, uint32_t new_divider) "RCC: Mux %d factor changed: multiplier (%u -> %u), divider (%u -> %u)"
427
+stm32l4x5_rcc_mux_set_src(uint32_t mux_id, uint32_t old_src, uint32_t new_src) "RCC: Mux %d source changed: from %u to %u"
428
+stm32l4x5_rcc_mux_update(uint32_t mux_id, uint32_t src, uint64_t src_freq, uint32_t multiplier, uint32_t divider) "RCC: Mux %d src %d update: src_freq %" PRIu64 " multiplier %" PRIu32 " divider %" PRIu32
429
430
# tz-mpc.c
431
tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u"
432
--
88
--
433
2.34.1
89
2.34.1
434
435
diff view generated by jsdifflib
New patch
1
In the helper_compute_fprf functions, we pass a dummy float_status
2
in to the is_signaling_nan() function. This is unnecessary, because
3
we have convenient access to the CPU env pointer here and that
4
is already set up with the correct values for the snan_bit_is_one
5
and no_signaling_nans config settings. is_signaling_nan() doesn't
6
ever update the fp_status with any exception flags, so there is
7
no reason not to use env->fp_status here.
1
8
9
Use env->fp_status instead of the dummy fp_status.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20241202131347.498124-34-peter.maydell@linaro.org
14
---
15
target/ppc/fpu_helper.c | 3 +--
16
1 file changed, 1 insertion(+), 2 deletions(-)
17
18
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/ppc/fpu_helper.c
21
+++ b/target/ppc/fpu_helper.c
22
@@ -XXX,XX +XXX,XX @@ void helper_compute_fprf_##tp(CPUPPCState *env, tp arg) \
23
} else if (tp##_is_infinity(arg)) { \
24
fprf = neg ? 0x09 << FPSCR_FPRF : 0x05 << FPSCR_FPRF; \
25
} else { \
26
- float_status dummy = { }; /* snan_bit_is_one = 0 */ \
27
- if (tp##_is_signaling_nan(arg, &dummy)) { \
28
+ if (tp##_is_signaling_nan(arg, &env->fp_status)) { \
29
fprf = 0x00 << FPSCR_FPRF; \
30
} else { \
31
fprf = 0x11 << FPSCR_FPRF; \
32
--
33
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This creates a per-page method for checking of alignment.
3
Now that float_status has a bunch of fp parameters,
4
it is easier to copy an existing structure than create
5
one from scratch. Begin by copying the structure that
6
corresponds to the FPSR and make only the adjustments
7
required for BFloat16 semantics.
4
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20240301204110.656742-5-richard.henderson@linaro.org
12
Message-id: 20241203203949.483774-2-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
14
---
10
include/exec/cpu-all.h | 4 +++-
15
target/arm/tcg/vec_helper.c | 20 +++++++-------------
11
accel/tcg/cputlb.c | 30 +++++++++++++++++++++++++++---
16
1 file changed, 7 insertions(+), 13 deletions(-)
12
2 files changed, 30 insertions(+), 4 deletions(-)
13
17
14
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
18
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/cpu-all.h
20
--- a/target/arm/tcg/vec_helper.c
17
+++ b/include/exec/cpu-all.h
21
+++ b/target/arm/tcg/vec_helper.c
18
@@ -XXX,XX +XXX,XX @@ static inline int cpu_mmu_index(CPUState *cs, bool ifetch)
22
@@ -XXX,XX +XXX,XX @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp)
19
#define TLB_BSWAP (1 << 0)
23
* no effect on AArch32 instructions.
20
/* Set if TLB entry contains a watchpoint. */
24
*/
21
#define TLB_WATCHPOINT (1 << 1)
25
bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF;
22
+/* Set if TLB entry requires aligned accesses. */
26
- *statusp = (float_status){
23
+#define TLB_CHECK_ALIGNED (1 << 2)
27
- .tininess_before_rounding = float_tininess_before_rounding,
24
28
- .float_rounding_mode = float_round_to_odd_inf,
25
-#define TLB_SLOW_FLAGS_MASK (TLB_BSWAP | TLB_WATCHPOINT)
29
- .flush_to_zero = true,
26
+#define TLB_SLOW_FLAGS_MASK (TLB_BSWAP | TLB_WATCHPOINT | TLB_CHECK_ALIGNED)
30
- .flush_inputs_to_zero = true,
27
31
- .default_nan_mode = true,
28
/* The two sets of flags must not overlap. */
32
- };
29
QEMU_BUILD_BUG_ON(TLB_FLAGS_MASK & TLB_SLOW_FLAGS_MASK);
33
+
30
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
34
+ *statusp = env->vfp.fp_status;
31
index XXXXXXX..XXXXXXX 100644
35
+ set_default_nan_mode(true, statusp);
32
--- a/accel/tcg/cputlb.c
36
33
+++ b/accel/tcg/cputlb.c
37
if (ebf) {
34
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUState *cpu, vaddr addr,
38
- float_status *fpst = &env->vfp.fp_status;
35
flags |= full->slow_flags[access_type];
39
- set_flush_to_zero(get_flush_to_zero(fpst), statusp);
36
40
- set_flush_inputs_to_zero(get_flush_inputs_to_zero(fpst), statusp);
37
/* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */
41
- set_float_rounding_mode(get_float_rounding_mode(fpst), statusp);
38
- if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY))
42
-
39
- ||
43
/* EBF=1 needs to do a step with round-to-odd semantics */
40
- (access_type != MMU_INST_FETCH && force_mmio)) {
44
*oddstatusp = *statusp;
41
+ if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY | TLB_CHECK_ALIGNED))
45
set_float_rounding_mode(float_round_to_odd, oddstatusp);
42
+ || (access_type != MMU_INST_FETCH && force_mmio)) {
46
+ } else {
43
*phost = NULL;
47
+ set_flush_to_zero(true, statusp);
44
return TLB_MMIO;
48
+ set_flush_inputs_to_zero(true, statusp);
49
+ set_float_rounding_mode(float_round_to_odd_inf, statusp);
45
}
50
}
46
@@ -XXX,XX +XXX,XX @@ static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
51
-
47
tcg_debug_assert((flags & TLB_BSWAP) == 0);
52
return ebf;
48
}
49
50
+ /*
51
+ * This alignment check differs from the one above, in that this is
52
+ * based on the atomicity of the operation. The intended use case is
53
+ * the ARM memory type field of each PTE, where access to pages with
54
+ * Device memory type require alignment.
55
+ */
56
+ if (unlikely(flags & TLB_CHECK_ALIGNED)) {
57
+ MemOp size = l->memop & MO_SIZE;
58
+
59
+ switch (l->memop & MO_ATOM_MASK) {
60
+ case MO_ATOM_NONE:
61
+ size = MO_8;
62
+ break;
63
+ case MO_ATOM_IFALIGN_PAIR:
64
+ case MO_ATOM_WITHIN16_PAIR:
65
+ size = size ? size - 1 : 0;
66
+ break;
67
+ default:
68
+ break;
69
+ }
70
+ if (addr & ((1 << size) - 1)) {
71
+ cpu_unaligned_access(cpu, addr, type, l->mmu_idx, ra);
72
+ }
73
+ }
74
+
75
return crosspage;
76
}
53
}
77
54
78
--
55
--
79
2.34.1
56
2.34.1
80
57
81
58
diff view generated by jsdifflib
1
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
1
Currently we hardcode the default NaN value in parts64_default_nan()
2
using a compile-time ifdef ladder. This is awkward for two cases:
3
* for single-QEMU-binary we can't hard-code target-specifics like this
4
* for Arm FEAT_AFP the default NaN value depends on FPCR.AH
5
(specifically the sign bit is different)
2
6
3
This object represents the PLLs and their channels. The PLLs allow for a
7
Add a field to float_status to specify the default NaN value; fall
4
more fine-grained control of the clocks frequency.
8
back to the old ifdef behaviour if these are not set.
5
9
6
The migration handling is based on hw/misc/zynq_sclr.c.
10
The default NaN value is specified by setting a uint8_t to a
7
Three phase reset will be handled in a later commit.
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.
8
14
9
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
10
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
11
Message-id: 20240303140643.81957-4-arnaud.minier@telecom-paris.fr
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-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
14
---
18
---
15
include/hw/misc/stm32l4x5_rcc.h | 40 +++++
19
include/fpu/softfloat-helpers.h | 11 +++++++
16
include/hw/misc/stm32l4x5_rcc_internals.h | 22 +++
20
include/fpu/softfloat-types.h | 10 ++++++
17
hw/misc/stm32l4x5_rcc.c | 176 ++++++++++++++++++++++
21
fpu/softfloat-specialize.c.inc | 55 ++++++++++++++++++++-------------
18
hw/misc/trace-events | 5 +
22
3 files changed, 54 insertions(+), 22 deletions(-)
19
4 files changed, 243 insertions(+)
20
23
21
diff --git a/include/hw/misc/stm32l4x5_rcc.h b/include/hw/misc/stm32l4x5_rcc.h
24
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
22
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/misc/stm32l4x5_rcc.h
26
--- a/include/fpu/softfloat-helpers.h
24
+++ b/include/hw/misc/stm32l4x5_rcc.h
27
+++ b/include/fpu/softfloat-helpers.h
25
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5RccState, STM32L4X5_RCC)
28
@@ -XXX,XX +XXX,XX @@ static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
26
29
status->float_infzeronan_rule = rule;
27
/* In the Stm32l4x5 clock tree, mux have at most 7 sources */
28
#define RCC_NUM_CLOCK_MUX_SRC 7
29
+
30
+typedef enum PllCommonChannels {
31
+ RCC_PLL_COMMON_CHANNEL_P = 0,
32
+ RCC_PLL_COMMON_CHANNEL_Q = 1,
33
+ RCC_PLL_COMMON_CHANNEL_R = 2,
34
+
35
+ RCC_NUM_CHANNEL_PLL_OUT = 3
36
+} PllCommonChannels;
37
+
38
/* NB: Prescaler are assimilated to mux with one source and one output */
39
typedef enum RccClockMux {
40
/* Internal muxes that arent't exposed publicly to other peripherals */
41
@@ -XXX,XX +XXX,XX @@ typedef enum RccClockMux {
42
RCC_NUM_CLOCK_MUX
43
} RccClockMux;
44
45
+typedef enum RccPll {
46
+ RCC_PLL_PLL,
47
+ RCC_PLL_PLLSAI1,
48
+ RCC_PLL_PLLSAI2,
49
+
50
+ RCC_NUM_PLL
51
+} RccPll;
52
+
53
typedef struct RccClockMuxState {
54
DeviceState parent_obj;
55
56
@@ -XXX,XX +XXX,XX @@ typedef struct RccClockMuxState {
57
struct RccClockMuxState *backref[RCC_NUM_CLOCK_MUX_SRC];
58
} RccClockMuxState;
59
60
+typedef struct RccPllState {
61
+ DeviceState parent_obj;
62
+
63
+ RccPll id;
64
+ Clock *in;
65
+ uint32_t vco_multiplier;
66
+ Clock *channels[RCC_NUM_CHANNEL_PLL_OUT];
67
+ /* Global pll enabled flag */
68
+ bool enabled;
69
+ /* 'enabled' refers to the runtime configuration */
70
+ bool channel_enabled[RCC_NUM_CHANNEL_PLL_OUT];
71
+ /*
72
+ * 'exists' refers to the physical configuration
73
+ * It should only be set at pll initialization.
74
+ * e.g. pllsai2 doesn't have a Q output.
75
+ */
76
+ bool channel_exists[RCC_NUM_CHANNEL_PLL_OUT];
77
+ uint32_t channel_divider[RCC_NUM_CHANNEL_PLL_OUT];
78
+} RccPllState;
79
+
80
struct Stm32l4x5RccState {
81
SysBusDevice parent_obj;
82
83
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5RccState {
84
Clock *sai1_extclk;
85
Clock *sai2_extclk;
86
87
+ /* PLLs */
88
+ RccPllState plls[RCC_NUM_PLL];
89
+
90
/* Muxes ~= outputs */
91
RccClockMuxState clock_muxes[RCC_NUM_CLOCK_MUX];
92
93
diff --git a/include/hw/misc/stm32l4x5_rcc_internals.h b/include/hw/misc/stm32l4x5_rcc_internals.h
94
index XXXXXXX..XXXXXXX 100644
95
--- a/include/hw/misc/stm32l4x5_rcc_internals.h
96
+++ b/include/hw/misc/stm32l4x5_rcc_internals.h
97
@@ -XXX,XX +XXX,XX @@
98
#include "hw/misc/stm32l4x5_rcc.h"
99
100
#define TYPE_RCC_CLOCK_MUX "stm32l4x5-rcc-clock-mux"
101
+#define TYPE_RCC_PLL "stm32l4x5-rcc-pll"
102
+
103
OBJECT_DECLARE_SIMPLE_TYPE(RccClockMuxState, RCC_CLOCK_MUX)
104
+OBJECT_DECLARE_SIMPLE_TYPE(RccPllState, RCC_PLL)
105
106
/* Register map */
107
REG32(CR, 0x00)
108
@@ -XXX,XX +XXX,XX @@ REG32(CSR, 0x94)
109
R_CSR_FWRSTF_MASK | \
110
R_CSR_LSIRDY_MASK)
111
112
+/* Pll Channels */
113
+enum PllChannels {
114
+ RCC_PLL_CHANNEL_PLLSAI3CLK = 0,
115
+ RCC_PLL_CHANNEL_PLL48M1CLK = 1,
116
+ RCC_PLL_CHANNEL_PLLCLK = 2,
117
+};
118
+
119
+enum PllSai1Channels {
120
+ RCC_PLLSAI1_CHANNEL_PLLSAI1CLK = 0,
121
+ RCC_PLLSAI1_CHANNEL_PLL48M2CLK = 1,
122
+ RCC_PLLSAI1_CHANNEL_PLLADC1CLK = 2,
123
+};
124
+
125
+enum PllSai2Channels {
126
+ RCC_PLLSAI2_CHANNEL_PLLSAI2CLK = 0,
127
+ /* No Q channel */
128
+ RCC_PLLSAI2_CHANNEL_PLLADC2CLK = 2,
129
+};
130
+
131
typedef enum RccClockMuxSource {
132
RCC_CLOCK_MUX_SRC_GND = 0,
133
RCC_CLOCK_MUX_SRC_HSI,
134
diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/hw/misc/stm32l4x5_rcc.c
137
+++ b/hw/misc/stm32l4x5_rcc.c
138
@@ -XXX,XX +XXX,XX @@ static void clock_mux_set_source(RccClockMuxState *mux, RccClockMuxSource src)
139
clock_mux_update(mux);
140
}
30
}
141
31
142
+static void pll_update(RccPllState *pll)
32
+static inline void set_float_default_nan_pattern(uint8_t dnan_pattern,
33
+ float_status *status)
143
+{
34
+{
144
+ uint64_t vco_freq, old_channel_freq, channel_freq;
35
+ status->default_nan_pattern = dnan_pattern;
145
+ int i;
146
+
147
+ /* The common PLLM factor is handled by the PLL mux */
148
+ vco_freq = muldiv64(clock_get_hz(pll->in), pll->vco_multiplier, 1);
149
+
150
+ for (i = 0; i < RCC_NUM_CHANNEL_PLL_OUT; i++) {
151
+ if (!pll->channel_exists[i]) {
152
+ continue;
153
+ }
154
+
155
+ old_channel_freq = clock_get_hz(pll->channels[i]);
156
+ if (!pll->enabled ||
157
+ !pll->channel_enabled[i] ||
158
+ !pll->channel_divider[i]) {
159
+ channel_freq = 0;
160
+ } else {
161
+ channel_freq = muldiv64(vco_freq,
162
+ 1,
163
+ pll->channel_divider[i]);
164
+ }
165
+
166
+ /* No change, early continue to avoid log spam and useless propagation */
167
+ if (old_channel_freq == channel_freq) {
168
+ continue;
169
+ }
170
+
171
+ clock_update_hz(pll->channels[i], channel_freq);
172
+ trace_stm32l4x5_rcc_pll_update(pll->id, i, vco_freq,
173
+ old_channel_freq, channel_freq);
174
+ }
175
+}
36
+}
176
+
37
+
177
+static void pll_src_update(void *opaque, ClockEvent event)
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)
178
+{
46
+{
179
+ RccPllState *s = opaque;
47
+ return status->default_nan_pattern;
180
+ pll_update(s);
181
+}
48
+}
182
+
49
+
183
+static void pll_init(Object *obj)
50
static inline bool get_flush_to_zero(float_status *status)
184
+{
51
{
185
+ RccPllState *s = RCC_PLL(obj);
52
return status->flush_to_zero;
186
+ size_t i;
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);
187
+
136
+
188
+ s->in = qdev_init_clock_in(DEVICE(s), "in",
137
+ sign = dnan_pattern >> 7;
189
+ pll_src_update, s, ClockUpdate);
138
+ /*
190
+
139
+ * Place default_nan_pattern [6:0] into bits [62:56],
191
+ const char *names[] = {
140
+ * and replecate bit [0] down into [55:0]
192
+ "out-p", "out-q", "out-r",
141
+ */
193
+ };
142
+ frac = deposit64(0, DECOMPOSED_BINARY_POINT - 7, 7, dnan_pattern);
194
+
143
+ frac = deposit64(frac, 0, DECOMPOSED_BINARY_POINT - 7, -(dnan_pattern & 1));
195
+ for (i = 0; i < RCC_NUM_CHANNEL_PLL_OUT; i++) {
144
196
+ s->channels[i] = qdev_init_clock_out(DEVICE(s), names[i]);
145
*p = (FloatParts64) {
197
+ }
146
.cls = float_class_qnan,
198
+}
199
+
200
+static void pll_reset_hold(Object *obj)
201
+{ }
202
+
203
+static const VMStateDescription pll_vmstate = {
204
+ .name = TYPE_RCC_PLL,
205
+ .version_id = 1,
206
+ .minimum_version_id = 1,
207
+ .fields = (VMStateField[]) {
208
+ VMSTATE_UINT32(id, RccPllState),
209
+ VMSTATE_CLOCK(in, RccPllState),
210
+ VMSTATE_ARRAY_CLOCK(channels, RccPllState,
211
+ RCC_NUM_CHANNEL_PLL_OUT),
212
+ VMSTATE_BOOL(enabled, RccPllState),
213
+ VMSTATE_UINT32(vco_multiplier, RccPllState),
214
+ VMSTATE_BOOL_ARRAY(channel_enabled, RccPllState, RCC_NUM_CHANNEL_PLL_OUT),
215
+ VMSTATE_BOOL_ARRAY(channel_exists, RccPllState, RCC_NUM_CHANNEL_PLL_OUT),
216
+ VMSTATE_UINT32_ARRAY(channel_divider, RccPllState, RCC_NUM_CHANNEL_PLL_OUT),
217
+ VMSTATE_END_OF_LIST()
218
+ }
219
+};
220
+
221
+static void pll_class_init(ObjectClass *klass, void *data)
222
+{
223
+ DeviceClass *dc = DEVICE_CLASS(klass);
224
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
225
+
226
+ rc->phases.hold = pll_reset_hold;
227
+ dc->vmsd = &pll_vmstate;
228
+}
229
+
230
+static void pll_set_vco_multiplier(RccPllState *pll, uint32_t vco_multiplier)
231
+{
232
+ if (pll->vco_multiplier == vco_multiplier) {
233
+ return;
234
+ }
235
+
236
+ if (vco_multiplier < 8 || vco_multiplier > 86) {
237
+ qemu_log_mask(LOG_GUEST_ERROR,
238
+ "%s: VCO multiplier is out of bound (%u) for PLL %u\n",
239
+ __func__, vco_multiplier, pll->id);
240
+ return;
241
+ }
242
+
243
+ trace_stm32l4x5_rcc_pll_set_vco_multiplier(pll->id,
244
+ pll->vco_multiplier, vco_multiplier);
245
+
246
+ pll->vco_multiplier = vco_multiplier;
247
+ pll_update(pll);
248
+}
249
+
250
+static void pll_set_enable(RccPllState *pll, bool enabled)
251
+{
252
+ if (pll->enabled == enabled) {
253
+ return;
254
+ }
255
+
256
+ pll->enabled = enabled;
257
+ pll_update(pll);
258
+}
259
+
260
+static void pll_set_channel_enable(RccPllState *pll,
261
+ PllCommonChannels channel,
262
+ bool enabled)
263
+{
264
+ if (pll->channel_enabled[channel] == enabled) {
265
+ return;
266
+ }
267
+
268
+ if (enabled) {
269
+ trace_stm32l4x5_rcc_pll_channel_enable(pll->id, channel);
270
+ } else {
271
+ trace_stm32l4x5_rcc_pll_channel_disable(pll->id, channel);
272
+ }
273
+
274
+ pll->channel_enabled[channel] = enabled;
275
+ pll_update(pll);
276
+}
277
+
278
+static void pll_set_channel_divider(RccPllState *pll,
279
+ PllCommonChannels channel,
280
+ uint32_t divider)
281
+{
282
+ if (pll->channel_divider[channel] == divider) {
283
+ return;
284
+ }
285
+
286
+ trace_stm32l4x5_rcc_pll_set_channel_divider(pll->id,
287
+ channel, pll->channel_divider[channel], divider);
288
+
289
+ pll->channel_divider[channel] = divider;
290
+ pll_update(pll);
291
+}
292
+
293
static void rcc_update_irq(Stm32l4x5RccState *s)
294
{
295
if (s->cifr & CIFR_IRQ_MASK) {
296
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_rcc_init(Object *obj)
297
298
qdev_init_clocks(DEVICE(s), stm32l4x5_rcc_clocks);
299
300
+ for (i = 0; i < RCC_NUM_PLL; i++) {
301
+ object_initialize_child(obj, "pll[*]",
302
+ &s->plls[i], TYPE_RCC_PLL);
303
+ }
304
+
305
for (i = 0; i < RCC_NUM_CLOCK_MUX; i++) {
306
307
object_initialize_child(obj, "clock[*]",
308
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp)
309
return;
310
}
311
312
+ for (i = 0; i < RCC_NUM_PLL; i++) {
313
+ RccPllState *pll = &s->plls[i];
314
+
315
+ clock_set_source(pll->in, s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT].out);
316
+
317
+ if (!qdev_realize(DEVICE(pll), NULL, errp)) {
318
+ return;
319
+ }
320
+ }
321
+
322
for (i = 0; i < RCC_NUM_CLOCK_MUX; i++) {
323
RccClockMuxState *clock_mux = &s->clock_muxes[i];
324
325
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp)
326
clock_mux_set_source(&s->clock_muxes[0], RCC_CLOCK_MUX_SRC_GND);
327
clock_mux_set_enable(&s->clock_muxes[0], true);
328
clock_mux_set_factor(&s->clock_muxes[0], 1, 1);
329
+ pll_set_channel_divider(&s->plls[0], 0, 1);
330
+ pll_set_enable(&s->plls[0], true);
331
+ pll_set_channel_enable(&s->plls[0], 0, true);
332
+ pll_set_vco_multiplier(&s->plls[0], 1);
333
}
334
335
static Property stm32l4x5_rcc_properties[] = {
336
@@ -XXX,XX +XXX,XX @@ static const TypeInfo stm32l4x5_rcc_types[] = {
337
.instance_size = sizeof(RccClockMuxState),
338
.instance_init = clock_mux_init,
339
.class_init = clock_mux_class_init,
340
+ }, {
341
+ .name = TYPE_RCC_PLL,
342
+ .parent = TYPE_DEVICE,
343
+ .instance_size = sizeof(RccPllState),
344
+ .instance_init = pll_init,
345
+ .class_init = pll_class_init,
346
}
347
};
348
349
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
350
index XXXXXXX..XXXXXXX 100644
351
--- a/hw/misc/trace-events
352
+++ b/hw/misc/trace-events
353
@@ -XXX,XX +XXX,XX @@ stm32l4x5_rcc_mux_disable(uint32_t mux_id) "RCC: Mux %d disabled"
354
stm32l4x5_rcc_mux_set_factor(uint32_t mux_id, uint32_t old_multiplier, uint32_t new_multiplier, uint32_t old_divider, uint32_t new_divider) "RCC: Mux %d factor changed: multiplier (%u -> %u), divider (%u -> %u)"
355
stm32l4x5_rcc_mux_set_src(uint32_t mux_id, uint32_t old_src, uint32_t new_src) "RCC: Mux %d source changed: from %u to %u"
356
stm32l4x5_rcc_mux_update(uint32_t mux_id, uint32_t src, uint64_t src_freq, uint32_t multiplier, uint32_t divider) "RCC: Mux %d src %d update: src_freq %" PRIu64 " multiplier %" PRIu32 " divider %" PRIu32
357
+stm32l4x5_rcc_pll_set_vco_multiplier(uint32_t pll_id, uint32_t old_multiplier, uint32_t new_multiplier) "RCC: PLL %u: vco_multiplier changed (%u -> %u)"
358
+stm32l4x5_rcc_pll_channel_enable(uint32_t pll_id, uint32_t channel_id) "RCC: PLL %u, channel %u enabled"
359
+stm32l4x5_rcc_pll_channel_disable(uint32_t pll_id, uint32_t channel_id) "RCC: PLL %u, channel %u disabled"
360
+stm32l4x5_rcc_pll_set_channel_divider(uint32_t pll_id, uint32_t channel_id, uint32_t old_divider, uint32_t new_divider) "RCC: PLL %u, channel %u: divider changed (%u -> %u)"
361
+stm32l4x5_rcc_pll_update(uint32_t pll_id, uint32_t channel_id, uint64_t vco_freq, uint64_t old_freq, uint64_t new_freq) "RCC: PLL %d channel %d update: vco_freq %" PRIu64 " old_freq %" PRIu64 " new_freq %" PRIu64
362
363
# tz-mpc.c
364
tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u"
365
--
147
--
366
2.34.1
148
2.34.1
367
368
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for the tests/fp code.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-36-peter.maydell@linaro.org
6
---
7
tests/fp/fp-bench.c | 1 +
8
tests/fp/fp-test-log2.c | 1 +
9
tests/fp/fp-test.c | 1 +
10
3 files changed, 3 insertions(+)
11
12
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/fp/fp-bench.c
15
+++ b/tests/fp/fp-bench.c
16
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
17
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
18
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &soft_status);
19
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
20
+ set_float_default_nan_pattern(0b01000000, &soft_status);
21
22
f = bench_funcs[operation][precision];
23
g_assert(f);
24
diff --git a/tests/fp/fp-test-log2.c b/tests/fp/fp-test-log2.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/tests/fp/fp-test-log2.c
27
+++ b/tests/fp/fp-test-log2.c
28
@@ -XXX,XX +XXX,XX @@ int main(int ac, char **av)
29
int i;
30
31
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
32
+ set_float_default_nan_pattern(0b01000000, &qsf);
33
set_float_rounding_mode(float_round_nearest_even, &qsf);
34
35
test.d = 0.0;
36
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/fp/fp-test.c
39
+++ b/tests/fp/fp-test.c
40
@@ -XXX,XX +XXX,XX @@ void run_test(void)
41
*/
42
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
43
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &qsf);
44
+ set_float_default_nan_pattern(0b01000000, &qsf);
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
46
47
genCases_setLevel(test_level);
48
--
49
2.34.1
diff view generated by jsdifflib
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-37-peter.maydell@linaro.org
7
---
8
target/microblaze/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 +--
10
2 files changed, 3 insertions(+), 2 deletions(-)
11
12
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/microblaze/cpu.c
15
+++ b/target/microblaze/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_reset_hold(Object *obj, ResetType type)
17
* this architecture.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
20
+ /* Default NaN: sign bit set, most significant frac bit set */
21
+ set_float_default_nan_pattern(0b11000000, &env->fp_status);
22
23
#if defined(CONFIG_USER_ONLY)
24
/* start in user mode with interrupts enabled. */
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_I386) || defined(TARGET_X86_64) \
34
- || defined(TARGET_MICROBLAZE)
35
+#elif defined(TARGET_I386) || defined(TARGET_X86_64)
36
/* Sign bit set, most significant frac bit set */
37
dnan_pattern = 0b11000000;
38
#elif defined(TARGET_HPPA)
39
--
40
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-38-peter.maydell@linaro.org
7
---
8
target/i386/tcg/fpu_helper.c | 4 ++++
9
fpu/softfloat-specialize.c.inc | 3 ---
10
2 files changed, 4 insertions(+), 3 deletions(-)
11
12
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/i386/tcg/fpu_helper.c
15
+++ b/target/i386/tcg/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
17
*/
18
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
19
set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
20
+ /* Default NaN: sign bit set, most significant frac bit set */
21
+ set_float_default_nan_pattern(0b11000000, &env->fp_status);
22
+ set_float_default_nan_pattern(0b11000000, &env->mmx_status);
23
+ set_float_default_nan_pattern(0b11000000, &env->sse_status);
24
}
25
26
static inline uint8_t save_exception_flags(CPUX86State *env)
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
index XXXXXXX..XXXXXXX 100644
29
--- a/fpu/softfloat-specialize.c.inc
30
+++ b/fpu/softfloat-specialize.c.inc
31
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
32
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
33
/* Sign bit clear, all frac bits set */
34
dnan_pattern = 0b01111111;
35
-#elif defined(TARGET_I386) || defined(TARGET_X86_64)
36
- /* Sign bit set, most significant frac bit set */
37
- dnan_pattern = 0b11000000;
38
#elif defined(TARGET_HPPA)
39
/* Sign bit clear, msb-1 frac bit set */
40
dnan_pattern = 0b00100000;
41
--
42
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
parts64_default_nan().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-39-peter.maydell@linaro.org
7
---
8
target/hppa/fpu_helper.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 ---
10
2 files changed, 2 insertions(+), 3 deletions(-)
11
12
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/hppa/fpu_helper.c
15
+++ b/target/hppa/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
17
set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
18
/* For inf * 0 + NaN, return the input NaN */
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ /* Default NaN: sign bit clear, msb-1 frac bit set */
21
+ set_float_default_nan_pattern(0b00100000, &env->fp_status);
22
}
23
24
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
30
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
31
/* Sign bit clear, all frac bits set */
32
dnan_pattern = 0b01111111;
33
-#elif defined(TARGET_HPPA)
34
- /* Sign bit clear, msb-1 frac bit set */
35
- dnan_pattern = 0b00100000;
36
#elif defined(TARGET_HEXAGON)
37
/* Sign bit set, all frac bits set. */
38
dnan_pattern = 0b11111111;
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for the alpha target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-40-peter.maydell@linaro.org
6
---
7
target/alpha/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/alpha/cpu.c
13
+++ b/target/alpha/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_initfn(Object *obj)
15
* operand in Fa. That is float_2nan_prop_ba.
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
18
+ /* Default NaN: sign bit clear, msb frac bit set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
#if defined(CONFIG_USER_ONLY)
21
env->flags = ENV_FLAG_PS_USER | ENV_FLAG_FEN;
22
cpu_alpha_store_fpcr(env, (uint64_t)(FPCR_INVD | FPCR_DZED | FPCR_OVFD
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for the arm target.
2
This includes setting it for the old linux-user nwfpe emulation.
3
For nwfpe, our default doesn't match the real kernel, but we
4
avoid making a behaviour change in this commit.
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-41-peter.maydell@linaro.org
9
---
10
linux-user/arm/nwfpe/fpa11.c | 5 +++++
11
target/arm/cpu.c | 2 ++
12
2 files changed, 7 insertions(+)
13
14
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/arm/nwfpe/fpa11.c
17
+++ b/linux-user/arm/nwfpe/fpa11.c
18
@@ -XXX,XX +XXX,XX @@ void resetFPA11(void)
19
* this late date.
20
*/
21
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &fpa11->fp_status);
22
+ /*
23
+ * Use the same default NaN value as Arm VFP. This doesn't match
24
+ * the Linux kernel's nwfpe emulation, which uses an all-1s value.
25
+ */
26
+ set_float_default_nan_pattern(0b01000000, &fpa11->fp_status);
27
}
28
29
void SetRoundingMode(const unsigned int opcode)
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
34
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
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);
47
}
48
49
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
50
--
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
New patch
1
Set the default NaN pattern explicitly for m68k.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-43-peter.maydell@linaro.org
6
---
7
target/m68k/cpu.c | 2 ++
8
fpu/softfloat-specialize.c.inc | 2 +-
9
2 files changed, 3 insertions(+), 1 deletion(-)
10
11
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/m68k/cpu.c
14
+++ b/target/m68k/cpu.c
15
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
16
* preceding paragraph for nonsignaling NaNs.
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
+ /* Default NaN: sign bit clear, all frac bits set */
20
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
21
22
nan = floatx80_default_nan(&env->fp_status);
23
for (i = 0; i < 8; i++) {
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
29
uint8_t dnan_pattern = status->default_nan_pattern;
30
31
if (dnan_pattern == 0) {
32
-#if defined(TARGET_SPARC) || defined(TARGET_M68K)
33
+#if defined(TARGET_SPARC)
34
/* Sign bit clear, all frac bits set */
35
dnan_pattern = 0b01111111;
36
#elif defined(TARGET_HEXAGON)
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for MIPS. Note that this
2
is our only target which currently changes the default NaN
3
at runtime (which it was previously doing indirectly when it
4
changed the snan_bit_is_one setting).
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241202131347.498124-44-peter.maydell@linaro.org
9
---
10
target/mips/fpu_helper.h | 7 +++++++
11
target/mips/msa.c | 3 +++
12
2 files changed, 10 insertions(+)
13
14
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/mips/fpu_helper.h
17
+++ b/target/mips/fpu_helper.h
18
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
19
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
20
nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
21
set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
22
+ /*
23
+ * With nan2008, the default NaN value has the sign bit clear and the
24
+ * frac msb set; with the older mode, the sign bit is clear, and all
25
+ * frac bits except the msb are set.
26
+ */
27
+ set_float_default_nan_pattern(nan2008 ? 0b01000000 : 0b00111111,
28
+ &env->active_fpu.fp_status);
29
30
}
31
32
diff --git a/target/mips/msa.c b/target/mips/msa.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/mips/msa.c
35
+++ b/target/mips/msa.c
36
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
37
/* Inf * 0 + NaN returns the input NaN */
38
set_float_infzeronan_rule(float_infzeronan_dnan_never,
39
&env->active_tc.msa_fp_status);
40
+ /* Default NaN: sign bit clear, frac msb set */
41
+ set_float_default_nan_pattern(0b01000000,
42
+ &env->active_tc.msa_fp_status);
43
}
44
--
45
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for openrisc.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-45-peter.maydell@linaro.org
6
---
7
target/openrisc/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/openrisc/cpu.c
13
+++ b/target/openrisc/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_reset_hold(Object *obj, ResetType type)
15
*/
16
set_float_2nan_prop_rule(float_2nan_prop_x87, &cpu->env.fp_status);
17
18
+ /* Default NaN: sign bit clear, frac msb set */
19
+ set_float_default_nan_pattern(0b01000000, &cpu->env.fp_status);
20
21
#ifndef CONFIG_USER_ONLY
22
cpu->env.picmr = 0x00000000;
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for ppc.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-46-peter.maydell@linaro.org
6
---
7
target/ppc/cpu_init.c | 4 ++++
8
1 file changed, 4 insertions(+)
9
10
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/ppc/cpu_init.c
13
+++ b/target/ppc/cpu_init.c
14
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
15
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
17
18
+ /* Default NaN: sign bit clear, set frac msb */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
+ set_float_default_nan_pattern(0b01000000, &env->vec_status);
21
+
22
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
23
ppc_spr_t *spr = &env->spr_cb[i];
24
25
--
26
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for sh4. Note that sh4
2
is one of the only three targets (the others being HPPA and
3
sometimes MIPS) that has snan_bit_is_one set.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241202131347.498124-47-peter.maydell@linaro.org
8
---
9
target/sh4/cpu.c | 2 ++
10
1 file changed, 2 insertions(+)
11
12
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sh4/cpu.c
15
+++ b/target/sh4/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
17
set_flush_to_zero(1, &env->fp_status);
18
#endif
19
set_default_nan_mode(1, &env->fp_status);
20
+ /* sign bit clear, set all frac bits other than msb */
21
+ set_float_default_nan_pattern(0b00111111, &env->fp_status);
22
}
23
24
static void superh_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
25
--
26
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for rx.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-48-peter.maydell@linaro.org
6
---
7
target/rx/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/rx/cpu.c
13
+++ b/target/rx/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_reset_hold(Object *obj, ResetType type)
15
* then prefer dest over source", which is float_2nan_prop_s_ab.
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
18
+ /* Default NaN value: sign bit clear, set frac msb */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
}
21
22
static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for s390x.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-49-peter.maydell@linaro.org
6
---
7
target/s390x/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/s390x/cpu.c
13
+++ b/target/s390x/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
15
set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
16
set_float_infzeronan_rule(float_infzeronan_dnan_always,
17
&env->fpu_status);
18
+ /* Default NaN value: sign bit clear, frac msb set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fpu_status);
20
/* fall through */
21
case RESET_TYPE_S390_CPU_NORMAL:
22
env->psw.mask &= ~PSW_MASK_RI;
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for SPARC, and remove
2
the ifdef from parts64_default_nan.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-50-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 5 +----
10
2 files changed, 3 insertions(+), 4 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
18
/* For inf * 0 + NaN, return the input NaN */
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ /* Default NaN value: sign bit clear, all frac bits set */
21
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
22
23
cpu_exec_realizefn(cs, &local_err);
24
if (local_err != NULL) {
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
30
uint8_t dnan_pattern = status->default_nan_pattern;
31
32
if (dnan_pattern == 0) {
33
-#if defined(TARGET_SPARC)
34
- /* Sign bit clear, all frac bits set */
35
- dnan_pattern = 0b01111111;
36
-#elif defined(TARGET_HEXAGON)
37
+#if defined(TARGET_HEXAGON)
38
/* Sign bit set, all frac bits set. */
39
dnan_pattern = 0b11111111;
40
#else
41
--
42
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for xtensa.
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-51-peter.maydell@linaro.org
6
---
7
target/xtensa/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/xtensa/cpu.c
13
+++ b/target/xtensa/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
15
/* For inf * 0 + NaN, return the input NaN */
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
17
set_no_signaling_nans(!dfpu, &env->fp_status);
18
+ /* Default NaN value: sign bit clear, set frac msb */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
xtensa_use_first_nan(env, !dfpu);
21
}
22
23
--
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
1
The qatomic_cmpxchg() and qatomic_cmpxchg__nocheck() macros have
1
Now that all our targets have bene converted to explicitly specify
2
a comment that reads:
2
their pattern for the default NaN value we can remove the remaining
3
Returns the eventual value, failed or not
3
fallback code in parts64_default_nan().
4
5
This is somewhere between cryptic and wrong, since the value actually
6
returned is the value that was in memory before the cmpxchg. Reword
7
to match how we describe these macros in atomics.rst.
8
4
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
7
Message-id: 20241202131347.498124-55-peter.maydell@linaro.org
12
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
13
Message-id: 20240223182035.1048541-1-peter.maydell@linaro.org
14
---
8
---
15
include/qemu/atomic.h | 2 +-
9
fpu/softfloat-specialize.c.inc | 14 --------------
16
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 14 deletions(-)
17
11
18
diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h
12
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/include/qemu/atomic.h
14
--- a/fpu/softfloat-specialize.c.inc
21
+++ b/include/qemu/atomic.h
15
+++ b/fpu/softfloat-specialize.c.inc
22
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
23
qatomic_xchg__nocheck(ptr, i); \
17
uint64_t frac;
24
})
18
uint8_t dnan_pattern = status->default_nan_pattern;
25
19
26
-/* Returns the eventual value, failed or not */
20
- if (dnan_pattern == 0) {
27
+/* Returns the old value of '*ptr' (whether the cmpxchg failed or not) */
21
- /*
28
#define qatomic_cmpxchg__nocheck(ptr, old, new) ({ \
22
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
29
typeof_strip_qual(*ptr) _old = (old); \
23
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
30
(void)__atomic_compare_exchange_n(ptr, &_old, new, false, \
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;
31
--
37
--
32
2.34.1
38
2.34.1
diff view generated by jsdifflib
1
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Update the RCC state and propagate frequency changes when writing to the
3
Inline pickNaNMulAdd into its only caller. This makes
4
RCC registers. Currently, ICSCR, CIER, the reset registers and the stop
4
one assert redundant with the immediately preceding IF.
5
mode registers are not implemented.
6
5
7
Some fields have not been implemented due to uncertainty about
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
how to handle them (Like the clock security system or bypassing
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
mecanisms).
8
Message-id: 20241203203949.483774-3-richard.henderson@linaro.org
9
[PMM: keep comment from old code in new location]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
fpu/softfloat-parts.c.inc | 41 +++++++++++++++++++++++++-
13
fpu/softfloat-specialize.c.inc | 54 ----------------------------------
14
2 files changed, 40 insertions(+), 55 deletions(-)
10
15
11
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
12
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
13
Message-id: 20240303140643.81957-6-arnaud.minier@telecom-paris.fr
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/misc/stm32l4x5_rcc.c | 524 +++++++++++++++++++++++++++++++++++++++-
18
1 file changed, 512 insertions(+), 12 deletions(-)
19
20
diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c
21
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/stm32l4x5_rcc.c
18
--- a/fpu/softfloat-parts.c.inc
23
+++ b/hw/misc/stm32l4x5_rcc.c
19
+++ b/fpu/softfloat-parts.c.inc
24
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
25
#include "hw/qdev-clock.h"
21
}
26
#include "hw/qdev-properties.h"
22
27
#include "hw/qdev-properties-system.h"
23
if (s->default_nan_mode) {
28
+#include "hw/registerfields.h"
24
+ /*
29
#include "trace.h"
25
+ * We guarantee not to require the target to tell us how to
30
26
+ * pick a NaN if we're always returning the default NaN.
31
#define HSE_DEFAULT_FRQ 48000000ULL
27
+ * But if we're not in default-NaN mode then the target must
32
@@ -XXX,XX +XXX,XX @@ static void pll_set_channel_divider(RccPllState *pll,
28
+ * specify.
33
29
+ */
34
static void rcc_update_irq(Stm32l4x5RccState *s)
30
which = 3;
35
{
31
+ } else if (infzero) {
36
+ /*
32
+ /*
37
+ * TODO: Handle LSECSSF and CSSF flags when the CSS is implemented.
33
+ * Inf * 0 + NaN -- some implementations return the
38
+ */
34
+ * default NaN here, and some return the input NaN.
39
if (s->cifr & CIFR_IRQ_MASK) {
35
+ */
40
qemu_irq_raise(s->irq);
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
+ }
41
} else {
49
} else {
42
@@ -XXX,XX +XXX,XX @@ static void rcc_update_irq(Stm32l4x5RccState *s)
50
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
51
+ FloatClass cls[3] = { a->cls, b->cls, c->cls };
52
+ Float3NaNPropRule rule = s->float_3nan_prop_rule;
53
+
54
+ assert(rule != float_3nan_prop_none);
55
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
56
+ /* We have at least one SNaN input and should prefer it */
57
+ do {
58
+ which = rule & R_3NAN_1ST_MASK;
59
+ rule >>= R_3NAN_1ST_LENGTH;
60
+ } while (!is_snan(cls[which]));
61
+ } else {
62
+ do {
63
+ which = rule & R_3NAN_1ST_MASK;
64
+ rule >>= R_3NAN_1ST_LENGTH;
65
+ } while (!is_nan(cls[which]));
66
+ }
67
}
68
69
if (which == 3) {
70
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
71
index XXXXXXX..XXXXXXX 100644
72
--- a/fpu/softfloat-specialize.c.inc
73
+++ b/fpu/softfloat-specialize.c.inc
74
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
43
}
75
}
44
}
76
}
45
77
46
+static void rcc_update_cr_register(Stm32l4x5RccState *s)
78
-/*----------------------------------------------------------------------------
47
+{
79
-| Select which NaN to propagate for a three-input operation.
48
+ int val;
80
-| For the moment we assume that no CPU needs the 'larger significand'
49
+
81
-| information.
50
+ /* PLLSAI2ON and update PLLSAI2RDY */
82
-| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
51
+ val = FIELD_EX32(s->cr, CR, PLLSAI2ON);
83
-*----------------------------------------------------------------------------*/
52
+ pll_set_enable(&s->plls[RCC_PLL_PLLSAI2], val);
84
-static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
53
+ s->cr = (s->cr & ~R_CR_PLLSAI2RDY_MASK) |
85
- bool infzero, bool have_snan, float_status *status)
54
+ (val << R_CR_PLLSAI2RDY_SHIFT);
86
-{
55
+ if (s->cier & R_CIER_PLLSAI2RDYIE_MASK) {
87
- FloatClass cls[3] = { a_cls, b_cls, c_cls };
56
+ s->cifr |= R_CIFR_PLLSAI2RDYF_MASK;
88
- Float3NaNPropRule rule = status->float_3nan_prop_rule;
57
+ }
89
- int which;
58
+
59
+ /* PLLSAI1ON and update PLLSAI1RDY */
60
+ val = FIELD_EX32(s->cr, CR, PLLSAI1ON);
61
+ pll_set_enable(&s->plls[RCC_PLL_PLLSAI1], val);
62
+ s->cr = (s->cr & ~R_CR_PLLSAI1RDY_MASK) |
63
+ (val << R_CR_PLLSAI1RDY_SHIFT);
64
+ if (s->cier & R_CIER_PLLSAI1RDYIE_MASK) {
65
+ s->cifr |= R_CIFR_PLLSAI1RDYF_MASK;
66
+ }
67
+
68
+ /* PLLON and update PLLRDY */
69
+ val = FIELD_EX32(s->cr, CR, PLLON);
70
+ pll_set_enable(&s->plls[RCC_PLL_PLL], val);
71
+ s->cr = (s->cr & ~R_CR_PLLRDY_MASK) |
72
+ (val << R_CR_PLLRDY_SHIFT);
73
+ if (s->cier & R_CIER_PLLRDYIE_MASK) {
74
+ s->cifr |= R_CIFR_PLLRDYF_MASK;
75
+ }
76
+
77
+ /* CSSON: TODO */
78
+ /* HSEBYP: TODO */
79
+
80
+ /* HSEON and update HSERDY */
81
+ val = FIELD_EX32(s->cr, CR, HSEON);
82
+ s->cr = (s->cr & ~R_CR_HSERDY_MASK) |
83
+ (val << R_CR_HSERDY_SHIFT);
84
+ if (val) {
85
+ clock_update_hz(s->hse, s->hse_frequency);
86
+ if (s->cier & R_CIER_HSERDYIE_MASK) {
87
+ s->cifr |= R_CIFR_HSERDYF_MASK;
88
+ }
89
+ } else {
90
+ clock_update(s->hse, 0);
91
+ }
92
+
93
+ /* HSIAFS: TODO*/
94
+ /* HSIKERON: TODO*/
95
+
96
+ /* HSION and update HSIRDY*/
97
+ val = FIELD_EX32(s->cr, CR, HSION);
98
+ s->cr = (s->cr & ~R_CR_HSIRDY_MASK) |
99
+ (val << R_CR_HSIRDY_SHIFT);
100
+ if (val) {
101
+ clock_update_hz(s->hsi16_rc, HSI_FRQ);
102
+ if (s->cier & R_CIER_HSIRDYIE_MASK) {
103
+ s->cifr |= R_CIFR_HSIRDYF_MASK;
104
+ }
105
+ } else {
106
+ clock_update(s->hsi16_rc, 0);
107
+ }
108
+
109
+ static const uint32_t msirange[] = {
110
+ 100000, 200000, 400000, 800000, 1000000, 2000000,
111
+ 4000000, 8000000, 16000000, 24000000, 32000000, 48000000
112
+ };
113
+ /* MSIRANGE and MSIRGSEL */
114
+ val = FIELD_EX32(s->cr, CR, MSIRGSEL);
115
+ if (val) {
116
+ /* MSIRGSEL is set, use the MSIRANGE field */
117
+ val = FIELD_EX32(s->cr, CR, MSIRANGE);
118
+ } else {
119
+ /* MSIRGSEL is not set, use the MSISRANGE field */
120
+ val = FIELD_EX32(s->csr, CSR, MSISRANGE);
121
+ }
122
+
123
+ if (val < ARRAY_SIZE(msirange)) {
124
+ clock_update_hz(s->msi_rc, msirange[val]);
125
+ } else {
126
+ clock_update_hz(s->msi_rc, MSI_DEFAULT_FRQ);
127
+ /* TODO: there is a write protection if the value is out of bound,
128
+ implement that instead of setting the default */
129
+ }
130
+
131
+ /* MSIPLLEN */
132
+
133
+ /* MSION and update MSIRDY */
134
+ val = FIELD_EX32(s->cr, CR, MSION);
135
+ s->cr = (s->cr & ~R_CR_MSIRDY_MASK) |
136
+ (val << R_CR_MSIRDY_SHIFT);
137
+ if (s->cier & R_CIER_MSIRDYIE_MASK) {
138
+ s->cifr |= R_CIFR_MSIRDYF_MASK;
139
+ }
140
+ rcc_update_irq(s);
141
+}
142
+
143
+static void rcc_update_cfgr_register(Stm32l4x5RccState *s)
144
+{
145
+ uint32_t val;
146
+ /* MCOPRE */
147
+ val = FIELD_EX32(s->cfgr, CFGR, MCOPRE);
148
+ assert(val <= 0b100);
149
+ clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_MCO],
150
+ 1, 1 << val);
151
+
152
+ /* MCOSEL */
153
+ val = FIELD_EX32(s->cfgr, CFGR, MCOSEL);
154
+ assert(val <= 0b111);
155
+ if (val == 0) {
156
+ clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_MCO], false);
157
+ } else {
158
+ clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_MCO], true);
159
+ clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_MCO],
160
+ val - 1);
161
+ }
162
+
163
+ /* STOPWUCK */
164
+ /* TODO */
165
+
166
+ /* PPRE2 */
167
+ val = FIELD_EX32(s->cfgr, CFGR, PPRE2);
168
+ if (val < 0b100) {
169
+ clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_PCLK2],
170
+ 1, 1);
171
+ } else {
172
+ clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_PCLK2],
173
+ 1, 1 << (val - 0b11));
174
+ }
175
+
176
+ /* PPRE1 */
177
+ val = FIELD_EX32(s->cfgr, CFGR, PPRE1);
178
+ if (val < 0b100) {
179
+ clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_PCLK1],
180
+ 1, 1);
181
+ } else {
182
+ clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_PCLK1],
183
+ 1, 1 << (val - 0b11));
184
+ }
185
+
186
+ /* HPRE */
187
+ val = FIELD_EX32(s->cfgr, CFGR, HPRE);
188
+ if (val < 0b1000) {
189
+ clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_HCLK],
190
+ 1, 1);
191
+ } else {
192
+ clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_HCLK],
193
+ 1, 1 << (val - 0b111));
194
+ }
195
+
196
+ /* Update SWS */
197
+ val = FIELD_EX32(s->cfgr, CFGR, SW);
198
+ clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_SYSCLK],
199
+ val);
200
+ s->cfgr &= ~R_CFGR_SWS_MASK;
201
+ s->cfgr |= val << R_CFGR_SWS_SHIFT;
202
+}
203
+
204
+static void rcc_update_ahb1enr(Stm32l4x5RccState *s)
205
+{
206
+ #define AHB1ENR_SET_ENABLE(_peripheral_name) \
207
+ clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
208
+ FIELD_EX32(s->ahb1enr, AHB1ENR, _peripheral_name##EN))
209
+
210
+ /* DMA2DEN: reserved for STM32L475xx */
211
+ AHB1ENR_SET_ENABLE(TSC);
212
+ AHB1ENR_SET_ENABLE(CRC);
213
+ AHB1ENR_SET_ENABLE(FLASH);
214
+ AHB1ENR_SET_ENABLE(DMA2);
215
+ AHB1ENR_SET_ENABLE(DMA1);
216
+
217
+ #undef AHB1ENR_SET_ENABLE
218
+}
219
+
220
+static void rcc_update_ahb2enr(Stm32l4x5RccState *s)
221
+{
222
+ #define AHB2ENR_SET_ENABLE(_peripheral_name) \
223
+ clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
224
+ FIELD_EX32(s->ahb2enr, AHB2ENR, _peripheral_name##EN))
225
+
226
+ AHB2ENR_SET_ENABLE(RNG);
227
+ /* HASHEN: reserved for STM32L475xx */
228
+ AHB2ENR_SET_ENABLE(AES);
229
+ /* DCMIEN: reserved for STM32L475xx */
230
+ AHB2ENR_SET_ENABLE(ADC);
231
+ AHB2ENR_SET_ENABLE(OTGFS);
232
+ /* GPIOIEN: reserved for STM32L475xx */
233
+ AHB2ENR_SET_ENABLE(GPIOA);
234
+ AHB2ENR_SET_ENABLE(GPIOB);
235
+ AHB2ENR_SET_ENABLE(GPIOC);
236
+ AHB2ENR_SET_ENABLE(GPIOD);
237
+ AHB2ENR_SET_ENABLE(GPIOE);
238
+ AHB2ENR_SET_ENABLE(GPIOF);
239
+ AHB2ENR_SET_ENABLE(GPIOG);
240
+ AHB2ENR_SET_ENABLE(GPIOH);
241
+
242
+ #undef AHB2ENR_SET_ENABLE
243
+}
244
+
245
+static void rcc_update_ahb3enr(Stm32l4x5RccState *s)
246
+{
247
+ #define AHB3ENR_SET_ENABLE(_peripheral_name) \
248
+ clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
249
+ FIELD_EX32(s->ahb3enr, AHB3ENR, _peripheral_name##EN))
250
+
251
+ AHB3ENR_SET_ENABLE(QSPI);
252
+ AHB3ENR_SET_ENABLE(FMC);
253
+
254
+ #undef AHB3ENR_SET_ENABLE
255
+}
256
+
257
+static void rcc_update_apb1enr(Stm32l4x5RccState *s)
258
+{
259
+ #define APB1ENR1_SET_ENABLE(_peripheral_name) \
260
+ clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
261
+ FIELD_EX32(s->apb1enr1, APB1ENR1, _peripheral_name##EN))
262
+ #define APB1ENR2_SET_ENABLE(_peripheral_name) \
263
+ clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
264
+ FIELD_EX32(s->apb1enr2, APB1ENR2, _peripheral_name##EN))
265
+
266
+ /* APB1ENR1 */
267
+ APB1ENR1_SET_ENABLE(LPTIM1);
268
+ APB1ENR1_SET_ENABLE(OPAMP);
269
+ APB1ENR1_SET_ENABLE(DAC1);
270
+ APB1ENR1_SET_ENABLE(PWR);
271
+ /* CAN2: reserved for STM32L4x5 */
272
+ APB1ENR1_SET_ENABLE(CAN1);
273
+ /* CRSEN: reserved for STM32L4x5 */
274
+ APB1ENR1_SET_ENABLE(I2C3);
275
+ APB1ENR1_SET_ENABLE(I2C2);
276
+ APB1ENR1_SET_ENABLE(I2C1);
277
+ APB1ENR1_SET_ENABLE(UART5);
278
+ APB1ENR1_SET_ENABLE(UART4);
279
+ APB1ENR1_SET_ENABLE(USART3);
280
+ APB1ENR1_SET_ENABLE(USART2);
281
+ APB1ENR1_SET_ENABLE(SPI3);
282
+ APB1ENR1_SET_ENABLE(SPI2);
283
+ APB1ENR1_SET_ENABLE(WWDG);
284
+ /* RTCAPB: reserved for STM32L4x5 */
285
+ APB1ENR1_SET_ENABLE(LCD);
286
+ APB1ENR1_SET_ENABLE(TIM7);
287
+ APB1ENR1_SET_ENABLE(TIM6);
288
+ APB1ENR1_SET_ENABLE(TIM5);
289
+ APB1ENR1_SET_ENABLE(TIM4);
290
+ APB1ENR1_SET_ENABLE(TIM3);
291
+ APB1ENR1_SET_ENABLE(TIM2);
292
+
293
+ /* APB1ENR2 */
294
+ APB1ENR2_SET_ENABLE(LPTIM2);
295
+ APB1ENR2_SET_ENABLE(SWPMI1);
296
+ /* I2C4EN: reserved for STM32L4x5 */
297
+ APB1ENR2_SET_ENABLE(LPUART1);
298
+
299
+ #undef APB1ENR1_SET_ENABLE
300
+ #undef APB1ENR2_SET_ENABLE
301
+}
302
+
303
+static void rcc_update_apb2enr(Stm32l4x5RccState *s)
304
+{
305
+ #define APB2ENR_SET_ENABLE(_peripheral_name) \
306
+ clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
307
+ FIELD_EX32(s->apb2enr, APB2ENR, _peripheral_name##EN))
308
+
309
+ APB2ENR_SET_ENABLE(DFSDM1);
310
+ APB2ENR_SET_ENABLE(SAI2);
311
+ APB2ENR_SET_ENABLE(SAI1);
312
+ APB2ENR_SET_ENABLE(TIM17);
313
+ APB2ENR_SET_ENABLE(TIM16);
314
+ APB2ENR_SET_ENABLE(TIM15);
315
+ APB2ENR_SET_ENABLE(USART1);
316
+ APB2ENR_SET_ENABLE(TIM8);
317
+ APB2ENR_SET_ENABLE(SPI1);
318
+ APB2ENR_SET_ENABLE(TIM1);
319
+ APB2ENR_SET_ENABLE(SDMMC1);
320
+ APB2ENR_SET_ENABLE(FW);
321
+ APB2ENR_SET_ENABLE(SYSCFG);
322
+
323
+ #undef APB2ENR_SET_ENABLE
324
+}
325
+
326
+/*
327
+ * The 3 PLLs share the same register layout
328
+ * so we can use the same function for all of them
329
+ * Note: no frequency bounds checking is done here.
330
+ */
331
+static void rcc_update_pllsaixcfgr(Stm32l4x5RccState *s, RccPll pll_id)
332
+{
333
+ uint32_t reg, val;
334
+ switch (pll_id) {
335
+ case RCC_PLL_PLL:
336
+ reg = s->pllcfgr;
337
+ break;
338
+ case RCC_PLL_PLLSAI1:
339
+ reg = s->pllsai1cfgr;
340
+ break;
341
+ case RCC_PLL_PLLSAI2:
342
+ reg = s->pllsai2cfgr;
343
+ break;
344
+ default:
345
+ qemu_log_mask(LOG_GUEST_ERROR,
346
+ "%s: Invalid PLL ID: %u\n", __func__, pll_id);
347
+ return;
348
+ }
349
+
350
+ /* PLLPDIV */
351
+ val = FIELD_EX32(reg, PLLCFGR, PLLPDIV);
352
+ /* 1 is a reserved value */
353
+ if (val == 0) {
354
+ /* Get PLLP value */
355
+ val = FIELD_EX32(reg, PLLCFGR, PLLP);
356
+ pll_set_channel_divider(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_P,
357
+ (val ? 17 : 7));
358
+ } else if (val > 1) {
359
+ pll_set_channel_divider(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_P,
360
+ val);
361
+ }
362
+
363
+
364
+ /* PLLR */
365
+ val = FIELD_EX32(reg, PLLCFGR, PLLR);
366
+ pll_set_channel_divider(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_R,
367
+ 2 * (val + 1));
368
+
369
+ /* PLLREN */
370
+ val = FIELD_EX32(reg, PLLCFGR, PLLREN);
371
+ pll_set_channel_enable(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_R, val);
372
+
373
+ /* PLLQ */
374
+ val = FIELD_EX32(reg, PLLCFGR, PLLQ);
375
+ pll_set_channel_divider(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_Q,
376
+ 2 * (val + 1));
377
+
378
+ /* PLLQEN */
379
+ val = FIELD_EX32(reg, PLLCFGR, PLLQEN);
380
+ pll_set_channel_enable(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_Q, val);
381
+
382
+ /* PLLPEN */
383
+ val = FIELD_EX32(reg, PLLCFGR, PLLPEN);
384
+ pll_set_channel_enable(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_P, val);
385
+
386
+ /* PLLN */
387
+ val = FIELD_EX32(reg, PLLCFGR, PLLN);
388
+ pll_set_vco_multiplier(&s->plls[pll_id], val);
389
+}
390
+
391
+static void rcc_update_pllcfgr(Stm32l4x5RccState *s)
392
+{
393
+ int val;
394
+
395
+ /* Use common layout */
396
+ rcc_update_pllsaixcfgr(s, RCC_PLL_PLL);
397
+
398
+ /* Fetch specific fields for pllcfgr */
399
+
400
+ /* PLLM */
401
+ val = FIELD_EX32(s->pllcfgr, PLLCFGR, PLLM);
402
+ clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT], 1, (val + 1));
403
+
404
+ /* PLLSRC */
405
+ val = FIELD_EX32(s->pllcfgr, PLLCFGR, PLLSRC);
406
+ if (val == 0) {
407
+ clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT], false);
408
+ } else {
409
+ clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT], val - 1);
410
+ clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT], true);
411
+ }
412
+}
413
+
414
+static void rcc_update_ccipr(Stm32l4x5RccState *s)
415
+{
416
+ #define CCIPR_SET_SOURCE(_peripheral_name) \
417
+ clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \
418
+ FIELD_EX32(s->ccipr, CCIPR, _peripheral_name##SEL))
419
+
420
+ CCIPR_SET_SOURCE(DFSDM1);
421
+ CCIPR_SET_SOURCE(SWPMI1);
422
+ CCIPR_SET_SOURCE(ADC);
423
+ CCIPR_SET_SOURCE(CLK48);
424
+ CCIPR_SET_SOURCE(SAI2);
425
+ CCIPR_SET_SOURCE(SAI1);
426
+ CCIPR_SET_SOURCE(LPTIM2);
427
+ CCIPR_SET_SOURCE(LPTIM1);
428
+ CCIPR_SET_SOURCE(I2C3);
429
+ CCIPR_SET_SOURCE(I2C2);
430
+ CCIPR_SET_SOURCE(I2C1);
431
+ CCIPR_SET_SOURCE(LPUART1);
432
+ CCIPR_SET_SOURCE(UART5);
433
+ CCIPR_SET_SOURCE(UART4);
434
+ CCIPR_SET_SOURCE(USART3);
435
+ CCIPR_SET_SOURCE(USART2);
436
+ CCIPR_SET_SOURCE(USART1);
437
+
438
+ #undef CCIPR_SET_SOURCE
439
+}
440
+
441
+static void rcc_update_bdcr(Stm32l4x5RccState *s)
442
+{
443
+ int val;
444
+
445
+ /* LSCOSEL */
446
+ val = FIELD_EX32(s->bdcr, BDCR, LSCOSEL);
447
+ clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_LSCO], val);
448
+
449
+ val = FIELD_EX32(s->bdcr, BDCR, LSCOEN);
450
+ clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_LSCO], val);
451
+
452
+ /* BDRST */
453
+ /*
454
+ * The documentation is not clear if the RTCEN flag disables the RTC and
455
+ * the LCD common mux or if it only affects the RTC.
456
+ * As the LCDEN flag exists, we assume here that it only affects the RTC.
457
+ */
458
+ val = FIELD_EX32(s->bdcr, BDCR, RTCEN);
459
+ clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_RTC], val);
460
+ /* LCD and RTC share the same clock */
461
+ val = FIELD_EX32(s->bdcr, BDCR, RTCSEL);
462
+ clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_LCD_AND_RTC_COMMON], val);
463
+
464
+ /* LSECSSON */
465
+ /* LSEDRV[1:0] */
466
+ /* LSEBYP */
467
+
468
+ /* LSEON: Update LSERDY at the same time */
469
+ val = FIELD_EX32(s->bdcr, BDCR, LSEON);
470
+ if (val) {
471
+ clock_update_hz(s->lse_crystal, LSE_FRQ);
472
+ s->bdcr |= R_BDCR_LSERDY_MASK;
473
+ if (s->cier & R_CIER_LSERDYIE_MASK) {
474
+ s->cifr |= R_CIFR_LSERDYF_MASK;
475
+ }
476
+ } else {
477
+ clock_update(s->lse_crystal, 0);
478
+ s->bdcr &= ~R_BDCR_LSERDY_MASK;
479
+ }
480
+
481
+ rcc_update_irq(s);
482
+}
483
+
484
+static void rcc_update_csr(Stm32l4x5RccState *s)
485
+{
486
+ int val;
487
+
488
+ /* Reset flags: Not implemented */
489
+ /* MSISRANGE: Not implemented after reset */
490
+
491
+ /* LSION: Update LSIRDY at the same time */
492
+ val = FIELD_EX32(s->csr, CSR, LSION);
493
+ if (val) {
494
+ clock_update_hz(s->lsi_rc, LSI_FRQ);
495
+ s->csr |= R_CSR_LSIRDY_MASK;
496
+ if (s->cier & R_CIER_LSIRDYIE_MASK) {
497
+ s->cifr |= R_CIFR_LSIRDYF_MASK;
498
+ }
499
+ } else {
500
+ /*
501
+ * TODO: Handle when the LSI is set independently of LSION.
502
+ * E.g. when the LSI is set by the RTC.
503
+ * See the reference manual for more details.
504
+ */
505
+ clock_update(s->lsi_rc, 0);
506
+ s->csr &= ~R_CSR_LSIRDY_MASK;
507
+ }
508
+
509
+ rcc_update_irq(s);
510
+}
511
+
512
static void stm32l4x5_rcc_reset_hold(Object *obj)
513
{
514
Stm32l4x5RccState *s = STM32L4X5_RCC(obj);
515
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_rcc_write(void *opaque, hwaddr addr,
516
case A_CR:
517
s->cr = (s->cr & CR_READ_SET_MASK) |
518
(value & (CR_READ_SET_MASK | ~CR_READ_ONLY_MASK));
519
+ rcc_update_cr_register(s);
520
break;
521
case A_ICSCR:
522
s->icscr = value & ~ICSCR_READ_ONLY_MASK;
523
+ qemu_log_mask(LOG_UNIMP,
524
+ "%s: Side-effects not implemented for ICSCR\n", __func__);
525
break;
526
case A_CFGR:
527
s->cfgr = value & ~CFGR_READ_ONLY_MASK;
528
+ rcc_update_cfgr_register(s);
529
break;
530
case A_PLLCFGR:
531
s->pllcfgr = value;
532
+ rcc_update_pllcfgr(s);
533
break;
534
case A_PLLSAI1CFGR:
535
s->pllsai1cfgr = value;
536
+ rcc_update_pllsaixcfgr(s, RCC_PLL_PLLSAI1);
537
break;
538
case A_PLLSAI2CFGR:
539
s->pllsai2cfgr = value;
540
+ rcc_update_pllsaixcfgr(s, RCC_PLL_PLLSAI2);
541
break;
542
case A_CIER:
543
s->cier = value;
544
+ qemu_log_mask(LOG_UNIMP,
545
+ "%s: Side-effects not implemented for CIER\n", __func__);
546
break;
547
case A_CIFR:
548
qemu_log_mask(LOG_GUEST_ERROR,
549
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_rcc_write(void *opaque, hwaddr addr,
550
/* Reset behaviors are not implemented */
551
case A_AHB1RSTR:
552
s->ahb1rstr = value;
553
+ qemu_log_mask(LOG_UNIMP,
554
+ "%s: Side-effects not implemented for AHB1RSTR\n", __func__);
555
break;
556
case A_AHB2RSTR:
557
s->ahb2rstr = value;
558
+ qemu_log_mask(LOG_UNIMP,
559
+ "%s: Side-effects not implemented for AHB2RSTR\n", __func__);
560
break;
561
case A_AHB3RSTR:
562
s->ahb3rstr = value;
563
+ qemu_log_mask(LOG_UNIMP,
564
+ "%s: Side-effects not implemented for AHB3RSTR\n", __func__);
565
break;
566
case A_APB1RSTR1:
567
s->apb1rstr1 = value;
568
+ qemu_log_mask(LOG_UNIMP,
569
+ "%s: Side-effects not implemented for APB1RSTR1\n", __func__);
570
break;
571
case A_APB1RSTR2:
572
s->apb1rstr2 = value;
573
+ qemu_log_mask(LOG_UNIMP,
574
+ "%s: Side-effects not implemented for APB1RSTR2\n", __func__);
575
break;
576
case A_APB2RSTR:
577
s->apb2rstr = value;
578
+ qemu_log_mask(LOG_UNIMP,
579
+ "%s: Side-effects not implemented for APB2RSTR\n", __func__);
580
break;
581
case A_AHB1ENR:
582
s->ahb1enr = value;
583
+ rcc_update_ahb1enr(s);
584
break;
585
case A_AHB2ENR:
586
s->ahb2enr = value;
587
+ rcc_update_ahb2enr(s);
588
break;
589
case A_AHB3ENR:
590
s->ahb3enr = value;
591
+ rcc_update_ahb3enr(s);
592
break;
593
case A_APB1ENR1:
594
s->apb1enr1 = value;
595
+ rcc_update_apb1enr(s);
596
break;
597
case A_APB1ENR2:
598
s->apb1enr2 = value;
599
+ rcc_update_apb1enr(s);
600
break;
601
case A_APB2ENR:
602
s->apb2enr = (s->apb2enr & APB2ENR_READ_SET_MASK) | value;
603
+ rcc_update_apb2enr(s);
604
break;
605
/* Behaviors for Sleep and Stop modes are not implemented */
606
case A_AHB1SMENR:
607
s->ahb1smenr = value;
608
+ qemu_log_mask(LOG_UNIMP,
609
+ "%s: Side-effects not implemented for AHB1SMENR\n", __func__);
610
break;
611
case A_AHB2SMENR:
612
s->ahb2smenr = value;
613
+ qemu_log_mask(LOG_UNIMP,
614
+ "%s: Side-effects not implemented for AHB2SMENR\n", __func__);
615
break;
616
case A_AHB3SMENR:
617
s->ahb3smenr = value;
618
+ qemu_log_mask(LOG_UNIMP,
619
+ "%s: Side-effects not implemented for AHB3SMENR\n", __func__);
620
break;
621
case A_APB1SMENR1:
622
s->apb1smenr1 = value;
623
+ qemu_log_mask(LOG_UNIMP,
624
+ "%s: Side-effects not implemented for APB1SMENR1\n", __func__);
625
break;
626
case A_APB1SMENR2:
627
s->apb1smenr2 = value;
628
+ qemu_log_mask(LOG_UNIMP,
629
+ "%s: Side-effects not implemented for APB1SMENR2\n", __func__);
630
break;
631
case A_APB2SMENR:
632
s->apb2smenr = value;
633
+ qemu_log_mask(LOG_UNIMP,
634
+ "%s: Side-effects not implemented for APB2SMENR\n", __func__);
635
break;
636
case A_CCIPR:
637
s->ccipr = value;
638
+ rcc_update_ccipr(s);
639
break;
640
case A_BDCR:
641
s->bdcr = value & ~BDCR_READ_ONLY_MASK;
642
+ rcc_update_bdcr(s);
643
break;
644
case A_CSR:
645
s->csr = value & ~CSR_READ_ONLY_MASK;
646
+ rcc_update_csr(s);
647
break;
648
default:
649
qemu_log_mask(LOG_GUEST_ERROR,
650
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp)
651
clock_update_hz(s->sai1_extclk, s->sai1_extclk_frequency);
652
clock_update_hz(s->sai2_extclk, s->sai2_extclk_frequency);
653
clock_update(s->gnd, 0);
654
-
90
-
655
- /*
91
- /*
656
- * Dummy values to make compilation pass.
92
- * We guarantee not to require the target to tell us how to
657
- * Removed in later commits.
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.
658
- */
96
- */
659
- clock_mux_set_source(&s->clock_muxes[0], RCC_CLOCK_MUX_SRC_GND);
97
- assert(!status->default_nan_mode);
660
- clock_mux_set_enable(&s->clock_muxes[0], true);
98
-
661
- clock_mux_set_factor(&s->clock_muxes[0], 1, 1);
99
- if (infzero) {
662
- pll_set_channel_divider(&s->plls[0], 0, 1);
100
- /*
663
- pll_set_enable(&s->plls[0], true);
101
- * Inf * 0 + NaN -- some implementations return the default NaN here,
664
- pll_set_channel_enable(&s->plls[0], 0, true);
102
- * and some return the input NaN.
665
- pll_set_vco_multiplier(&s->plls[0], 1);
103
- */
666
}
104
- switch (status->float_infzeronan_rule) {
667
105
- case float_infzeronan_dnan_never:
668
static Property stm32l4x5_rcc_properties[] = {
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.
669
--
135
--
670
2.34.1
136
2.34.1
671
137
672
138
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
If translation is disabled, the default memory type is Device, which
3
Remove "3" as a special case for which and simply
4
requires alignment checking. This is more optimally done early via
4
branch to return the desired value.
5
the MemOp given to the TCG memory operation.
6
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reported-by: Idan Horowitz <idan.horowitz@gmail.com>
8
Message-id: 20241203203949.483774-4-richard.henderson@linaro.org
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20240301204110.656742-6-richard.henderson@linaro.org
11
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1204
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
10
---
15
target/arm/tcg/hflags.c | 34 ++++++++++++++++++++++++++++++++--
11
fpu/softfloat-parts.c.inc | 20 ++++++++++----------
16
1 file changed, 32 insertions(+), 2 deletions(-)
12
1 file changed, 10 insertions(+), 10 deletions(-)
17
13
18
diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/tcg/hflags.c
16
--- a/fpu/softfloat-parts.c.inc
21
+++ b/target/arm/tcg/hflags.c
17
+++ b/fpu/softfloat-parts.c.inc
22
@@ -XXX,XX +XXX,XX @@ static inline bool fgt_svc(CPUARMState *env, int el)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
23
FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL1);
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;
24
}
70
}
25
71
26
+/* Return true if memory alignment should be enforced. */
72
/*
27
+static bool aprofile_require_alignment(CPUARMState *env, int el, uint64_t sctlr)
28
+{
29
+#ifdef CONFIG_USER_ONLY
30
+ return false;
31
+#else
32
+ /* Check the alignment enable bit. */
33
+ if (sctlr & SCTLR_A) {
34
+ return true;
35
+ }
36
+
37
+ /*
38
+ * If translation is disabled, then the default memory type is
39
+ * Device(-nGnRnE) instead of Normal, which requires that alignment
40
+ * be enforced. Since this affects all ram, it is most efficient
41
+ * to handle this during translation.
42
+ */
43
+ if (sctlr & SCTLR_M) {
44
+ /* Translation enabled: memory type in PTE via MAIR_ELx. */
45
+ return false;
46
+ }
47
+ if (el < 2 && (arm_hcr_el2_eff(env) & (HCR_DC | HCR_VM))) {
48
+ /* Stage 2 translation enabled: memory type in PTE. */
49
+ return false;
50
+ }
51
+ return true;
52
+#endif
53
+}
54
+
55
static CPUARMTBFlags rebuild_hflags_common(CPUARMState *env, int fp_el,
56
ARMMMUIdx mmu_idx,
57
CPUARMTBFlags flags)
58
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
59
{
60
CPUARMTBFlags flags = {};
61
int el = arm_current_el(env);
62
+ uint64_t sctlr = arm_sctlr(env, el);
63
64
- if (arm_sctlr(env, el) & SCTLR_A) {
65
+ if (aprofile_require_alignment(env, el, sctlr)) {
66
DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
67
}
68
69
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
70
71
sctlr = regime_sctlr(env, stage1);
72
73
- if (sctlr & SCTLR_A) {
74
+ if (aprofile_require_alignment(env, el, sctlr)) {
75
DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
76
}
77
78
--
73
--
79
2.34.1
74
2.34.1
80
75
81
76
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
These fields are no longer used since 937f224559.
3
Assign the pointer return value to 'a' directly,
4
Target specific extensions to the page tables should be done
4
rather than going through an intermediary index.
5
with TARGET_PAGE_ENTRY_EXTRA.
6
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241203203949.483774-5-richard.henderson@linaro.org
9
Message-id: 20240301204110.656742-3-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
include/exec/memattrs.h | 10 ----------
11
fpu/softfloat-parts.c.inc | 32 ++++++++++----------------------
13
1 file changed, 10 deletions(-)
12
1 file changed, 10 insertions(+), 22 deletions(-)
14
13
15
diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/include/exec/memattrs.h
16
--- a/fpu/softfloat-parts.c.inc
18
+++ b/include/exec/memattrs.h
17
+++ b/fpu/softfloat-parts.c.inc
19
@@ -XXX,XX +XXX,XX @@ typedef struct MemTxAttrs {
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
20
unsigned int requester_id:16;
19
FloatPartsN *c, float_status *s,
21
/* Invert endianness for this page */
20
int ab_mask, int abc_mask)
22
unsigned int byte_swap:1;
21
{
23
- /*
22
- int which;
24
- * The following are target-specific page-table bits. These are not
23
bool infzero = (ab_mask == float_cmask_infzero);
25
- * related to actual memory transactions at all. However, this structure
24
bool have_snan = (abc_mask & float_cmask_snan);
26
- * is part of the tlb_fill interface, cached in the cputlb structure,
25
+ FloatPartsN *ret;
27
- * and has unused bits. These fields will be read by target-specific
26
28
- * helpers using env->iotlb[mmu_idx][tlb_index()].attrs.target_tlb_bitN.
27
if (unlikely(have_snan)) {
29
- */
28
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
30
- unsigned int target_tlb_bit0 : 1;
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
31
- unsigned int target_tlb_bit1 : 1;
30
default:
32
- unsigned int target_tlb_bit2 : 1;
31
g_assert_not_reached();
33
} MemTxAttrs;
32
}
34
33
- which = 2;
35
/* Bus masters which don't specify any attributes will get this,
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);
36
--
81
--
37
2.34.1
82
2.34.1
38
83
39
84
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Allow the target to set tlb flags to apply to all of the
3
While all indices into val[] should be in [0-2], the mask
4
comparators. Remove MemTxAttrs.byte_swap, as the bit is
4
applied is two bits. To help static analysis see there is
5
not relevant to memory transactions, only the page mapping.
5
no possibility of read beyond the end of the array, pad the
6
Adjust target/sparc to set TLB_BSWAP directly.
6
array to 4 entries, with the final being (implicitly) NULL.
7
7
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241203203949.483774-6-richard.henderson@linaro.org
10
Message-id: 20240301204110.656742-4-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
12
---
13
include/exec/memattrs.h | 2 --
13
fpu/softfloat-parts.c.inc | 2 +-
14
include/hw/core/cpu.h | 3 +++
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
accel/tcg/cputlb.c | 5 +----
16
target/sparc/mmu_helper.c | 2 +-
17
4 files changed, 5 insertions(+), 7 deletions(-)
18
15
19
diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
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/include/exec/memattrs.h
18
--- a/fpu/softfloat-parts.c.inc
22
+++ b/include/exec/memattrs.h
19
+++ b/fpu/softfloat-parts.c.inc
23
@@ -XXX,XX +XXX,XX @@ typedef struct MemTxAttrs {
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
24
unsigned int memory:1;
21
}
25
/* Requester ID (for MSI for example) */
22
ret = c;
26
unsigned int requester_id:16;
23
} else {
27
- /* Invert endianness for this page */
24
- FloatPartsN *val[3] = { a, b, c };
28
- unsigned int byte_swap:1;
25
+ FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
29
} MemTxAttrs;
26
Float3NaNPropRule rule = s->float_3nan_prop_rule;
30
27
31
/* Bus masters which don't specify any attributes will get this,
28
assert(rule != float_3nan_prop_none);
32
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/hw/core/cpu.h
35
+++ b/include/hw/core/cpu.h
36
@@ -XXX,XX +XXX,XX @@ typedef struct CPUTLBEntryFull {
37
/* @lg_page_size contains the log2 of the page size. */
38
uint8_t lg_page_size;
39
40
+ /* Additional tlb flags requested by tlb_fill. */
41
+ uint8_t tlb_fill_flags;
42
+
43
/*
44
* Additional tlb flags for use by the slow path. If non-zero,
45
* the corresponding CPUTLBEntry comparator must have TLB_FORCE_SLOW.
46
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/accel/tcg/cputlb.c
49
+++ b/accel/tcg/cputlb.c
50
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,
51
" prot=%x idx=%d\n",
52
addr, full->phys_addr, prot, mmu_idx);
53
54
- read_flags = 0;
55
+ read_flags = full->tlb_fill_flags;
56
if (full->lg_page_size < TARGET_PAGE_BITS) {
57
/* Repeat the MMU check and TLB fill on every access. */
58
read_flags |= TLB_INVALID_MASK;
59
}
60
- if (full->attrs.byte_swap) {
61
- read_flags |= TLB_BSWAP;
62
- }
63
64
is_ram = memory_region_is_ram(section->mr);
65
is_romd = memory_region_is_romd(section->mr);
66
diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/sparc/mmu_helper.c
69
+++ b/target/sparc/mmu_helper.c
70
@@ -XXX,XX +XXX,XX @@ static int get_physical_address_data(CPUSPARCState *env, CPUTLBEntryFull *full,
71
int do_fault = 0;
72
73
if (TTE_IS_IE(env->dtlb[i].tte)) {
74
- full->attrs.byte_swap = true;
75
+ full->tlb_fill_flags |= TLB_BSWAP;
76
}
77
78
/* access ok? */
79
--
29
--
80
2.34.1
30
2.34.1
81
31
82
32
diff view generated by jsdifflib
1
From: Tong Ho <tong.ho@amd.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This patch adds loopback for sent characters, sent BREAK,
3
This function is part of the public interface and
4
and modem-control signals.
4
is not "specialized" to any target in any way.
5
5
6
Loopback of send and modem-control is often used for uart
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
self tests in real hardware but missing from current pl011
8
model, resulting in self-test failures when running in QEMU.
9
10
This implementation matches what is observed in real pl011
11
hardware placed in loopback mode:
12
1. Input characters and BREAK events from serial backend
13
are ignored, but
14
2. Both TX characters and BREAK events are still sent to
15
serial backend, in addition to be looped back to RX.
16
17
Signed-off-by: Tong Ho <tong.ho@amd.com>
18
Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com>
19
Message-id: 20240227054855.44204-1-tong.ho@amd.com
20
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
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
10
---
23
hw/char/pl011.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++-
11
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++++++++
24
1 file changed, 108 insertions(+), 2 deletions(-)
12
fpu/softfloat-specialize.c.inc | 52 ----------------------------------
13
2 files changed, 52 insertions(+), 52 deletions(-)
25
14
26
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
27
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/char/pl011.c
17
--- a/fpu/softfloat.c
29
+++ b/hw/char/pl011.c
18
+++ b/fpu/softfloat.c
30
@@ -XXX,XX +XXX,XX @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr)
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
20
*zExpPtr = 1 - shiftCount;
31
}
21
}
32
22
33
/* Flag Register, UARTFR */
23
+/*----------------------------------------------------------------------------
34
+#define PL011_FLAG_RI 0x100
24
+| Takes two extended double-precision floating-point values `a' and `b', one
35
#define PL011_FLAG_TXFE 0x80
25
+| of which is a NaN, and returns the appropriate NaN result. If either `a' or
36
#define PL011_FLAG_RXFF 0x40
26
+| `b' is a signaling NaN, the invalid exception is raised.
37
#define PL011_FLAG_TXFF 0x20
27
+*----------------------------------------------------------------------------*/
38
#define PL011_FLAG_RXFE 0x10
39
+#define PL011_FLAG_DCD 0x04
40
+#define PL011_FLAG_DSR 0x02
41
+#define PL011_FLAG_CTS 0x01
42
43
/* Data Register, UARTDR */
44
#define DR_BE (1 << 10)
45
@@ -XXX,XX +XXX,XX @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr)
46
#define LCR_FEN (1 << 4)
47
#define LCR_BRK (1 << 0)
48
49
+/* Control Register, UARTCR */
50
+#define CR_OUT2 (1 << 13)
51
+#define CR_OUT1 (1 << 12)
52
+#define CR_RTS (1 << 11)
53
+#define CR_DTR (1 << 10)
54
+#define CR_LBE (1 << 7)
55
+
28
+
56
static const unsigned char pl011_id_arm[8] =
29
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
57
{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
58
static const unsigned char pl011_id_luminary[8] =
59
@@ -XXX,XX +XXX,XX @@ static void pl011_trace_baudrate_change(const PL011State *s)
60
s->ibrd, s->fbrd);
61
}
62
63
+static bool pl011_loopback_enabled(PL011State *s)
64
+{
30
+{
65
+ return !!(s->cr & CR_LBE);
31
+ bool aIsLargerSignificand;
66
+}
32
+ FloatClass a_cls, b_cls;
67
+
33
+
68
+static void pl011_loopback_mdmctrl(PL011State *s)
34
+ /* This is not complete, but is good enough for pickNaN. */
69
+{
35
+ a_cls = (!floatx80_is_any_nan(a)
70
+ uint32_t cr, fr, il;
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);
71
+
45
+
72
+ if (!pl011_loopback_enabled(s)) {
46
+ if (is_snan(a_cls) || is_snan(b_cls)) {
73
+ return;
47
+ float_raise(float_flag_invalid, status);
74
+ }
48
+ }
75
+
49
+
76
+ /*
50
+ if (status->default_nan_mode) {
77
+ * Loopback software-driven modem control outputs to modem status inputs:
51
+ return floatx80_default_nan(status);
78
+ * FR.RI <= CR.Out2
79
+ * FR.DCD <= CR.Out1
80
+ * FR.CTS <= CR.RTS
81
+ * FR.DSR <= CR.DTR
82
+ *
83
+ * The loopback happens immediately even if this call is triggered
84
+ * by setting only CR.LBE.
85
+ *
86
+ * CTS/RTS updates due to enabled hardware flow controls are not
87
+ * dealt with here.
88
+ */
89
+ cr = s->cr;
90
+ fr = s->flags & ~(PL011_FLAG_RI | PL011_FLAG_DCD |
91
+ PL011_FLAG_DSR | PL011_FLAG_CTS);
92
+ fr |= (cr & CR_OUT2) ? PL011_FLAG_RI : 0;
93
+ fr |= (cr & CR_OUT1) ? PL011_FLAG_DCD : 0;
94
+ fr |= (cr & CR_RTS) ? PL011_FLAG_CTS : 0;
95
+ fr |= (cr & CR_DTR) ? PL011_FLAG_DSR : 0;
96
+
97
+ /* Change interrupts based on updated FR */
98
+ il = s->int_level & ~(INT_DSR | INT_DCD | INT_CTS | INT_RI);
99
+ il |= (fr & PL011_FLAG_DSR) ? INT_DSR : 0;
100
+ il |= (fr & PL011_FLAG_DCD) ? INT_DCD : 0;
101
+ il |= (fr & PL011_FLAG_CTS) ? INT_CTS : 0;
102
+ il |= (fr & PL011_FLAG_RI) ? INT_RI : 0;
103
+
104
+ s->flags = fr;
105
+ s->int_level = il;
106
+ pl011_update(s);
107
+}
108
+
109
+static void pl011_put_fifo(void *opaque, uint32_t value);
110
+
111
+static void pl011_loopback_tx(PL011State *s, uint32_t value)
112
+{
113
+ if (!pl011_loopback_enabled(s)) {
114
+ return;
115
+ }
52
+ }
116
+
53
+
117
+ /*
54
+ if (a.low < b.low) {
118
+ * Caveat:
55
+ aIsLargerSignificand = 0;
119
+ *
56
+ } else if (b.low < a.low) {
120
+ * In real hardware, TX loopback happens at the serial-bit level
57
+ aIsLargerSignificand = 1;
121
+ * and then reassembled by the RX logics back into bytes and placed
58
+ } else {
122
+ * into the RX fifo. That is, loopback happens after TX fifo.
59
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
123
+ *
60
+ }
124
+ * Because the real hardware TX fifo is time-drained at the frame
125
+ * rate governed by the configured serial format, some loopback
126
+ * bytes in TX fifo may still be able to get into the RX fifo
127
+ * that could be full at times while being drained at software
128
+ * pace.
129
+ *
130
+ * In such scenario, the RX draining pace is the major factor
131
+ * deciding which loopback bytes get into the RX fifo, unless
132
+ * hardware flow-control is enabled.
133
+ *
134
+ * For simplicity, the above described is not emulated.
135
+ */
136
+ pl011_put_fifo(s, value);
137
+}
138
+
61
+
139
+static void pl011_loopback_break(PL011State *s, int brk_enable)
62
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
140
+{
63
+ if (is_snan(b_cls)) {
141
+ if (brk_enable) {
64
+ return floatx80_silence_nan(b, status);
142
+ pl011_loopback_tx(s, DR_BE);
65
+ }
66
+ return b;
67
+ } else {
68
+ if (is_snan(a_cls)) {
69
+ return floatx80_silence_nan(a, status);
70
+ }
71
+ return a;
143
+ }
72
+ }
144
+}
73
+}
145
+
74
+
146
static void pl011_write(void *opaque, hwaddr offset,
75
/*----------------------------------------------------------------------------
147
uint64_t value, unsigned size)
76
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
148
{
77
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
149
@@ -XXX,XX +XXX,XX @@ static void pl011_write(void *opaque, hwaddr offset,
78
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
150
/* XXX this blocks entire thread. Rewrite to use
79
index XXXXXXX..XXXXXXX 100644
151
* qemu_chr_fe_write and background I/O callbacks */
80
--- a/fpu/softfloat-specialize.c.inc
152
qemu_chr_fe_write_all(&s->chr, &ch, 1);
81
+++ b/fpu/softfloat-specialize.c.inc
153
+ pl011_loopback_tx(s, ch);
82
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
154
s->int_level |= INT_TX;
83
return a;
155
pl011_update(s);
156
break;
157
@@ -XXX,XX +XXX,XX @@ static void pl011_write(void *opaque, hwaddr offset,
158
int break_enable = value & LCR_BRK;
159
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
160
&break_enable);
161
+ pl011_loopback_break(s, break_enable);
162
}
163
s->lcr = value;
164
pl011_set_read_trigger(s);
165
break;
166
case 12: /* UARTCR */
167
- /* ??? Need to implement the enable and loopback bits. */
168
+ /* ??? Need to implement the enable bit. */
169
s->cr = value;
170
+ pl011_loopback_mdmctrl(s);
171
break;
172
case 13: /* UARTIFS */
173
s->ifl = value;
174
@@ -XXX,XX +XXX,XX @@ static void pl011_put_fifo(void *opaque, uint32_t value)
175
176
static void pl011_receive(void *opaque, const uint8_t *buf, int size)
177
{
178
+ /*
179
+ * In loopback mode, the RX input signal is internally disconnected
180
+ * from the entire receiving logics; thus, all inputs are ignored,
181
+ * and BREAK detection on RX input signal is also not performed.
182
+ */
183
+ if (pl011_loopback_enabled(opaque)) {
184
+ return;
185
+ }
186
+
187
pl011_put_fifo(opaque, *buf);
188
}
84
}
189
85
190
static void pl011_event(void *opaque, QEMUChrEvent event)
86
-/*----------------------------------------------------------------------------
191
{
87
-| Takes two extended double-precision floating-point values `a' and `b', one
192
- if (event == CHR_EVENT_BREAK) {
88
-| of which is a NaN, and returns the appropriate NaN result. If either `a' or
193
+ if (event == CHR_EVENT_BREAK && !pl011_loopback_enabled(opaque)) {
89
-| `b' is a signaling NaN, the invalid exception is raised.
194
pl011_put_fifo(opaque, DR_BE);
90
-*----------------------------------------------------------------------------*/
195
}
91
-
196
}
92
-floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
93
-{
94
- bool aIsLargerSignificand;
95
- FloatClass a_cls, b_cls;
96
-
97
- /* This is not complete, but is good enough for pickNaN. */
98
- a_cls = (!floatx80_is_any_nan(a)
99
- ? float_class_normal
100
- : floatx80_is_signaling_nan(a, status)
101
- ? float_class_snan
102
- : float_class_qnan);
103
- b_cls = (!floatx80_is_any_nan(b)
104
- ? float_class_normal
105
- : floatx80_is_signaling_nan(b, status)
106
- ? float_class_snan
107
- : float_class_qnan);
108
-
109
- if (is_snan(a_cls) || is_snan(b_cls)) {
110
- float_raise(float_flag_invalid, status);
111
- }
112
-
113
- if (status->default_nan_mode) {
114
- return floatx80_default_nan(status);
115
- }
116
-
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.
197
--
141
--
198
2.34.1
142
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
If translation is enabled, and the PTE memory type is Device,
3
Unpacking and repacking the parts may be slightly more work
4
enable checking alignment via TLB_CHECK_ALIGNMENT. While the
4
than we did before, but we get to reuse more code. For a
5
check is done later than it should be per the ARM, it's better
5
code path handling exceptional values, this is an improvement.
6
than not performing the check at all.
7
6
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20240301204110.656742-7-richard.henderson@linaro.org
8
Message-id: 20241203203949.483774-8-richard.henderson@linaro.org
10
[PMM: tweaks to comment text]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
target/arm/ptw.c | 39 +++++++++++++++++++++++++++++++++++++++
12
fpu/softfloat.c | 43 +++++--------------------------------------
15
1 file changed, 39 insertions(+)
13
1 file changed, 5 insertions(+), 38 deletions(-)
16
14
17
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/ptw.c
17
--- a/fpu/softfloat.c
20
+++ b/target/arm/ptw.c
18
+++ b/fpu/softfloat.c
21
@@ -XXX,XX +XXX,XX @@ static bool granule_protection_check(CPUARMState *env, uint64_t paddress,
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
22
return false;
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);
23
}
70
}
24
71
25
+static bool S1_attrs_are_device(uint8_t attrs)
72
/*----------------------------------------------------------------------------
26
+{
27
+ /*
28
+ * This slightly under-decodes the MAIR_ELx field:
29
+ * 0b0000dd01 is Device with FEAT_XS, otherwise UNPREDICTABLE;
30
+ * 0b0000dd1x is UNPREDICTABLE.
31
+ */
32
+ return (attrs & 0xf0) == 0;
33
+}
34
+
35
static bool S2_attrs_are_device(uint64_t hcr, uint8_t attrs)
36
{
37
/*
38
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
39
bool aarch64 = arm_el_is_aa64(env, el);
40
uint64_t descriptor, new_descriptor;
41
ARMSecuritySpace out_space;
42
+ bool device;
43
44
/* TODO: This code does not support shareability levels. */
45
if (aarch64) {
46
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
47
if (regime_is_stage2(mmu_idx)) {
48
result->cacheattrs.is_s2_format = true;
49
result->cacheattrs.attrs = extract32(attrs, 2, 4);
50
+ /*
51
+ * Security state does not really affect HCR_EL2.FWB;
52
+ * we only need to filter FWB for aa32 or other FEAT.
53
+ */
54
+ device = S2_attrs_are_device(arm_hcr_el2_eff(env),
55
+ result->cacheattrs.attrs);
56
} else {
57
/* Index into MAIR registers for cache attributes */
58
uint8_t attrindx = extract32(attrs, 2, 3);
59
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
60
if (aarch64 && cpu_isar_feature(aa64_bti, cpu)) {
61
result->f.extra.arm.guarded = extract64(attrs, 50, 1); /* GP */
62
}
63
+ device = S1_attrs_are_device(result->cacheattrs.attrs);
64
+ }
65
+
66
+ /*
67
+ * Enable alignment checks on Device memory.
68
+ *
69
+ * Per R_XCHFJ, this check is mis-ordered. The correct ordering
70
+ * for alignment, permission, and stage 2 faults should be:
71
+ * - Alignment fault caused by the memory type
72
+ * - Permission fault
73
+ * - A stage 2 fault on the memory access
74
+ * but due to the way the TCG softmmu TLB operates, we will have
75
+ * implicitly done the permission check and the stage2 lookup in
76
+ * finding the TLB entry, so the alignment check cannot be done sooner.
77
+ *
78
+ * In v7, for a CPU without the Virtualization Extensions this
79
+ * access is UNPREDICTABLE; we choose to make it take the alignment
80
+ * fault as is required for a v7VE CPU. (QEMU doesn't emulate any
81
+ * CPUs with ARM_FEATURE_LPAE but not ARM_FEATURE_V7VE anyway.)
82
+ */
83
+ if (device) {
84
+ result->f.tlb_fill_flags |= TLB_CHECK_ALIGNED;
85
}
86
87
/*
88
--
73
--
89
2.34.1
74
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
Now that we have removed TARGET_PAGE_BITS_MIN-6 from
3
Inline pickNaN into its only caller. This makes one assert
4
TLB_FLAGS_MASK, we can test for 32-byte alignment.
4
redundant with the immediately preceding IF.
5
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-9-richard.henderson@linaro.org
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20240301204110.656742-2-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/tcg/translate.c | 8 +-------
11
fpu/softfloat-parts.c.inc | 82 +++++++++++++++++++++++++----
13
1 file changed, 1 insertion(+), 7 deletions(-)
12
fpu/softfloat-specialize.c.inc | 96 ----------------------------------
14
13
2 files changed, 73 insertions(+), 105 deletions(-)
15
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
14
15
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/tcg/translate.c
17
--- a/fpu/softfloat-parts.c.inc
18
+++ b/target/arm/tcg/translate.c
18
+++ b/fpu/softfloat-parts.c.inc
19
@@ -XXX,XX +XXX,XX @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
19
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
20
MemOp pow2_align(unsigned i)
20
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
21
float_status *s)
21
{
22
{
22
static const MemOp mop_align[] = {
23
+ int cmp, which;
23
- 0, MO_ALIGN_2, MO_ALIGN_4, MO_ALIGN_8, MO_ALIGN_16,
24
+
25
if (is_snan(a->cls) || is_snan(b->cls)) {
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
27
}
28
29
if (s->default_nan_mode) {
30
parts_default_nan(a, s);
31
- } else {
32
- int cmp = frac_cmp(a, b);
33
- if (cmp == 0) {
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
118
index XXXXXXX..XXXXXXX 100644
119
--- a/fpu/softfloat-specialize.c.inc
120
+++ b/fpu/softfloat-specialize.c.inc
121
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
122
}
123
}
124
125
-/*----------------------------------------------------------------------------
126
-| Select which NaN to propagate for a two-input operation.
127
-| IEEE754 doesn't specify all the details of this, so the
128
-| algorithm is target-specific.
129
-| The routine is passed various bits of information about the
130
-| two NaNs and should return 0 to select NaN a and 1 for NaN b.
131
-| Note that signalling NaNs are always squashed to quiet NaNs
132
-| by the caller, by calling floatXX_silence_nan() before
133
-| returning them.
134
-|
135
-| aIsLargerSignificand is only valid if both a and b are NaNs
136
-| of some kind, and is true if a has the larger significand,
137
-| or if both a and b have the same significand but a is
138
-| positive but b is negative. It is only needed for the x87
139
-| tie-break rule.
140
-*----------------------------------------------------------------------------*/
141
-
142
-static int pickNaN(FloatClass a_cls, FloatClass b_cls,
143
- bool aIsLargerSignificand, float_status *status)
144
-{
145
- /*
146
- * We guarantee not to require the target to tell us how to
147
- * pick a NaN if we're always returning the default NaN.
148
- * But if we're not in default-NaN mode then the target must
149
- * specify via set_float_2nan_prop_rule().
150
- */
151
- assert(!status->default_nan_mode);
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:
24
- /*
191
- /*
25
- * FIXME: TARGET_PAGE_BITS_MIN affects TLB_FLAGS_MASK such
192
- * This implements x87 NaN propagation rules:
26
- * that 256-bit alignment (MO_ALIGN_32) cannot be supported:
193
- * SNaN + QNaN => return the QNaN
27
- * see get_alignment_bits(). Enforce only 128-bit alignment for now.
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).
28
- */
201
- */
29
- MO_ALIGN_16
202
- if (is_snan(a_cls)) {
30
+ 0, MO_ALIGN_2, MO_ALIGN_4, MO_ALIGN_8, MO_ALIGN_16, MO_ALIGN_32
203
- if (is_snan(b_cls)) {
31
};
204
- return aIsLargerSignificand ? 0 : 1;
32
g_assert(i < ARRAY_SIZE(mop_align));
205
- }
33
return mop_align[i];
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.
34
--
224
--
35
2.34.1
225
2.34.1
36
226
37
227
diff view generated by jsdifflib
1
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Tests:
3
Remember if there was an SNaN, and use that to simplify
4
- the ability to change the sysclk of the device
4
float_2nan_prop_s_{ab,ba} to only the snan component.
5
- the ability to enable/disable/configure the PLLs
5
Then, fall through to the corresponding
6
- if the clock multiplexers work
6
float_2nan_prop_{ab,ba} case to handle any remaining
7
- the register flags and the generation of irqs
7
nans, which must be quiet.
8
8
9
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Acked-by: Thomas Huth <thuth@redhat.com>
11
Message-id: 20241203203949.483774-10-richard.henderson@linaro.org
12
Message-id: 20240303140643.81957-9-arnaud.minier@telecom-paris.fr
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
---
13
---
16
tests/qtest/stm32l4x5_rcc-test.c | 189 +++++++++++++++++++++++++++++++
14
fpu/softfloat-parts.c.inc | 32 ++++++++++++--------------------
17
tests/qtest/meson.build | 3 +-
15
1 file changed, 12 insertions(+), 20 deletions(-)
18
2 files changed, 191 insertions(+), 1 deletion(-)
19
create mode 100644 tests/qtest/stm32l4x5_rcc-test.c
20
16
21
diff --git a/tests/qtest/stm32l4x5_rcc-test.c b/tests/qtest/stm32l4x5_rcc-test.c
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
22
new file mode 100644
23
index XXXXXXX..XXXXXXX
24
--- /dev/null
25
+++ b/tests/qtest/stm32l4x5_rcc-test.c
26
@@ -XXX,XX +XXX,XX @@
27
+/*
28
+ * QTest testcase for STM32L4x5_RCC
29
+ *
30
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
31
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
32
+ *
33
+ * SPDX-License-Identifier: GPL-2.0-or-later
34
+ *
35
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
36
+ * See the COPYING file in the top-level directory.
37
+ */
38
+
39
+#include "qemu/osdep.h"
40
+#include "hw/registerfields.h"
41
+#include "libqtest-single.h"
42
+#include "hw/misc/stm32l4x5_rcc_internals.h"
43
+
44
+#define RCC_BASE_ADDR 0x40021000
45
+#define NVIC_ISER 0xE000E100
46
+#define NVIC_ISPR 0xE000E200
47
+#define NVIC_ICPR 0xE000E280
48
+#define RCC_IRQ 5
49
+
50
+static void enable_nvic_irq(unsigned int n)
51
+{
52
+ writel(NVIC_ISER, 1 << n);
53
+}
54
+
55
+static void unpend_nvic_irq(unsigned int n)
56
+{
57
+ writel(NVIC_ICPR, 1 << n);
58
+}
59
+
60
+static bool check_nvic_pending(unsigned int n)
61
+{
62
+ return readl(NVIC_ISPR) & (1 << n);
63
+}
64
+
65
+static void rcc_writel(unsigned int offset, uint32_t value)
66
+{
67
+ writel(RCC_BASE_ADDR + offset, value);
68
+}
69
+
70
+static uint32_t rcc_readl(unsigned int offset)
71
+{
72
+ return readl(RCC_BASE_ADDR + offset);
73
+}
74
+
75
+static void test_init_msi(void)
76
+{
77
+ /* MSIRANGE can be set only when MSI is OFF or READY */
78
+ rcc_writel(A_CR, R_CR_MSION_MASK);
79
+ /* Wait until MSI is stable */
80
+ g_assert_true((rcc_readl(A_CR) & R_CR_MSIRDY_MASK) == R_CR_MSIRDY_MASK);
81
+ /* TODO find a way to test MSI value */
82
+}
83
+
84
+static void test_set_msi_as_sysclk(void)
85
+{
86
+ /* Clocking from MSI, in case MSI was not the default source */
87
+ rcc_writel(A_CFGR, 0);
88
+ /* Wait until MSI is selected and stable */
89
+ g_assert_true((rcc_readl(A_CFGR) & R_CFGR_SWS_MASK) == 0);
90
+}
91
+
92
+static void test_init_pll(void)
93
+{
94
+ uint32_t value;
95
+
96
+ /*
97
+ * Update PLL and set MSI as the source clock.
98
+ * PLLM = 1 --> 000
99
+ * PLLN = 40 --> 40
100
+ * PPLLR = 2 --> 00
101
+ * PLLDIV = unused, PLLP = unused (SAI3), PLLQ = unused (48M1)
102
+ * SRC = MSI --> 01
103
+ */
104
+ rcc_writel(A_PLLCFGR, R_PLLCFGR_PLLREN_MASK |
105
+ (40 << R_PLLCFGR_PLLN_SHIFT) |
106
+ (0b01 << R_PLLCFGR_PLLSRC_SHIFT));
107
+
108
+ /* PLL activation */
109
+ value = rcc_readl(A_CR);
110
+ rcc_writel(A_CR, value | R_CR_PLLON_MASK);
111
+
112
+ /* Waiting for PLL lock. */
113
+ g_assert_true((rcc_readl(A_CR) & R_CR_PLLRDY_MASK) == R_CR_PLLRDY_MASK);
114
+
115
+ /* Switches on the PLL clock source */
116
+ value = rcc_readl(A_CFGR);
117
+ rcc_writel(A_CFGR, (value & ~R_CFGR_SW_MASK) |
118
+ (0b11 << R_CFGR_SW_SHIFT));
119
+
120
+ /* Wait until SYSCLK is stable. */
121
+ g_assert_true((rcc_readl(A_CFGR) & R_CFGR_SWS_MASK) ==
122
+ (0b11 << R_CFGR_SWS_SHIFT));
123
+}
124
+
125
+static void test_activate_lse(void)
126
+{
127
+ /* LSE activation, no LSE Bypass */
128
+ rcc_writel(A_BDCR, R_BDCR_LSEDRV_MASK | R_BDCR_LSEON_MASK);
129
+ g_assert_true((rcc_readl(A_BDCR) & R_BDCR_LSERDY_MASK) == R_BDCR_LSERDY_MASK);
130
+}
131
+
132
+static void test_irq(void)
133
+{
134
+ enable_nvic_irq(RCC_IRQ);
135
+
136
+ rcc_writel(A_CIER, R_CIER_LSIRDYIE_MASK);
137
+ rcc_writel(A_CSR, R_CSR_LSION_MASK);
138
+ g_assert_true(check_nvic_pending(RCC_IRQ));
139
+ rcc_writel(A_CICR, R_CICR_LSIRDYC_MASK);
140
+ unpend_nvic_irq(RCC_IRQ);
141
+
142
+ rcc_writel(A_CIER, R_CIER_LSERDYIE_MASK);
143
+ rcc_writel(A_BDCR, R_BDCR_LSEON_MASK);
144
+ g_assert_true(check_nvic_pending(RCC_IRQ));
145
+ rcc_writel(A_CICR, R_CICR_LSERDYC_MASK);
146
+ unpend_nvic_irq(RCC_IRQ);
147
+
148
+ /*
149
+ * MSI has been enabled by previous tests,
150
+ * shouln't generate an interruption.
151
+ */
152
+ rcc_writel(A_CIER, R_CIER_MSIRDYIE_MASK);
153
+ rcc_writel(A_CR, R_CR_MSION_MASK);
154
+ g_assert_false(check_nvic_pending(RCC_IRQ));
155
+
156
+ rcc_writel(A_CIER, R_CIER_HSIRDYIE_MASK);
157
+ rcc_writel(A_CR, R_CR_HSION_MASK);
158
+ g_assert_true(check_nvic_pending(RCC_IRQ));
159
+ rcc_writel(A_CICR, R_CICR_HSIRDYC_MASK);
160
+ unpend_nvic_irq(RCC_IRQ);
161
+
162
+ rcc_writel(A_CIER, R_CIER_HSERDYIE_MASK);
163
+ rcc_writel(A_CR, R_CR_HSEON_MASK);
164
+ g_assert_true(check_nvic_pending(RCC_IRQ));
165
+ rcc_writel(A_CICR, R_CICR_HSERDYC_MASK);
166
+ unpend_nvic_irq(RCC_IRQ);
167
+
168
+ /*
169
+ * PLL has been enabled by previous tests,
170
+ * shouln't generate an interruption.
171
+ */
172
+ rcc_writel(A_CIER, R_CIER_PLLRDYIE_MASK);
173
+ rcc_writel(A_CR, R_CR_PLLON_MASK);
174
+ g_assert_false(check_nvic_pending(RCC_IRQ));
175
+
176
+ rcc_writel(A_CIER, R_CIER_PLLSAI1RDYIE_MASK);
177
+ rcc_writel(A_CR, R_CR_PLLSAI1ON_MASK);
178
+ g_assert_true(check_nvic_pending(RCC_IRQ));
179
+ rcc_writel(A_CICR, R_CICR_PLLSAI1RDYC_MASK);
180
+ unpend_nvic_irq(RCC_IRQ);
181
+
182
+ rcc_writel(A_CIER, R_CIER_PLLSAI2RDYIE_MASK);
183
+ rcc_writel(A_CR, R_CR_PLLSAI2ON_MASK);
184
+ g_assert_true(check_nvic_pending(RCC_IRQ));
185
+ rcc_writel(A_CICR, R_CICR_PLLSAI2RDYC_MASK);
186
+ unpend_nvic_irq(RCC_IRQ);
187
+}
188
+
189
+int main(int argc, char **argv)
190
+{
191
+ int ret;
192
+
193
+ g_test_init(&argc, &argv, NULL);
194
+ g_test_set_nonfatal_assertions();
195
+ /*
196
+ * These test separately that we can enable the plls, change the sysclk,
197
+ * and enable different devices.
198
+ * They are dependent on one another.
199
+ * We assume that all operations that would take some time to have an effect
200
+ * (e.g. changing the PLL frequency) are done instantaneously.
201
+ */
202
+ qtest_add_func("stm32l4x5/rcc/init_msi", test_init_msi);
203
+ qtest_add_func("stm32l4x5/rcc/set_msi_as_sysclk",
204
+ test_set_msi_as_sysclk);
205
+ qtest_add_func("stm32l4x5/rcc/activate_lse", test_activate_lse);
206
+ qtest_add_func("stm32l4x5/rcc/init_pll", test_init_pll);
207
+
208
+ qtest_add_func("stm32l4x5/rcc/irq", test_irq);
209
+
210
+ qtest_start("-machine b-l475e-iot01a");
211
+ ret = g_test_run();
212
+ qtest_end();
213
+
214
+ return ret;
215
+}
216
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
217
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
218
--- a/tests/qtest/meson.build
19
--- a/fpu/softfloat-parts.c.inc
219
+++ b/tests/qtest/meson.build
20
+++ b/fpu/softfloat-parts.c.inc
220
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
21
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
221
22
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
222
qtests_stm32l4x5 = \
23
float_status *s)
223
['stm32l4x5_exti-test',
24
{
224
- 'stm32l4x5_syscfg-test']
25
+ bool have_snan = false;
225
+ 'stm32l4x5_syscfg-test',
26
int cmp, which;
226
+ 'stm32l4x5_rcc-test']
27
227
28
if (is_snan(a->cls) || is_snan(b->cls)) {
228
qtests_arm = \
29
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
229
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
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;
230
--
75
--
231
2.34.1
76
2.34.1
232
233
diff view generated by jsdifflib
1
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Now that we can generate reliable clock frequencies from the RCC, remove
3
Move the fractional comparison to the end of the
4
the hacky definition of the sysclk in the b_l475e_iot01a initialisation
4
float_2nan_prop_x87 case. This is not required for
5
code and use the correct RCC clock.
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: Arnaud Minier <arnaud.minier@telecom-paris.fr>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20240303140643.81957-8-arnaud.minier@telecom-paris.fr
11
Message-id: 20241203203949.483774-11-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
13
---
14
include/hw/arm/stm32l4x5_soc.h | 3 ---
14
fpu/softfloat-parts.c.inc | 19 +++++++++----------
15
hw/arm/b-l475e-iot01a.c | 10 +---------
15
1 file changed, 9 insertions(+), 10 deletions(-)
16
hw/arm/stm32l4x5_soc.c | 33 ++++-----------------------------
17
3 files changed, 5 insertions(+), 41 deletions(-)
18
16
19
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/arm/stm32l4x5_soc.h
19
--- a/fpu/softfloat-parts.c.inc
22
+++ b/include/hw/arm/stm32l4x5_soc.h
20
+++ b/fpu/softfloat-parts.c.inc
23
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
21
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
24
MemoryRegion sram2;
22
return a;
25
MemoryRegion flash;
26
MemoryRegion flash_alias;
27
-
28
- Clock *sysclk;
29
- Clock *refclk;
30
};
31
32
struct Stm32l4x5SocClass {
33
diff --git a/hw/arm/b-l475e-iot01a.c b/hw/arm/b-l475e-iot01a.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/b-l475e-iot01a.c
36
+++ b/hw/arm/b-l475e-iot01a.c
37
@@ -XXX,XX +XXX,XX @@
38
#include "qapi/error.h"
39
#include "hw/boards.h"
40
#include "hw/qdev-properties.h"
41
-#include "hw/qdev-clock.h"
42
#include "qemu/error-report.h"
43
#include "hw/arm/stm32l4x5_soc.h"
44
#include "hw/arm/boot.h"
45
46
-/* Main SYSCLK frequency in Hz (80MHz) */
47
-#define MAIN_SYSCLK_FREQ_HZ 80000000ULL
48
+/* B-L475E-IOT01A implementation is derived from netduinoplus2 */
49
50
static void b_l475e_iot01a_init(MachineState *machine)
51
{
52
const Stm32l4x5SocClass *sc;
53
DeviceState *dev;
54
- Clock *sysclk;
55
-
56
- /* This clock doesn't need migration because it is fixed-frequency */
57
- sysclk = clock_new(OBJECT(machine), "SYSCLK");
58
- clock_set_hz(sysclk, MAIN_SYSCLK_FREQ_HZ);
59
60
dev = qdev_new(TYPE_STM32L4X5XG_SOC);
61
object_property_add_child(OBJECT(machine), "soc", OBJECT(dev));
62
- qdev_connect_clock_in(dev, "sysclk", sysclk);
63
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
64
65
sc = STM32L4X5_SOC_GET_CLASS(dev);
66
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/stm32l4x5_soc.c
69
+++ b/hw/arm/stm32l4x5_soc.c
70
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
71
}
23
}
72
object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
24
73
object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32L4X5_RCC);
25
- cmp = frac_cmp(a, b);
74
-
26
- if (cmp == 0) {
75
- s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
27
- cmp = a->sign < b->sign;
76
- s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
77
}
78
79
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
80
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
81
DeviceState *armv7m;
82
SysBusDevice *busdev;
83
84
- /*
85
- * We use s->refclk internally and only define it with qdev_init_clock_in()
86
- * so it is correctly parented and not leaked on an init/deinit; it is not
87
- * intended as an externally exposed clock.
88
- */
89
- if (clock_has_source(s->refclk)) {
90
- error_setg(errp, "refclk clock must not be wired up by the board code");
91
- return;
92
- }
28
- }
93
-
29
-
94
- if (!clock_has_source(s->sysclk)) {
30
switch (s->float_2nan_prop_rule) {
95
- error_setg(errp, "sysclk clock must be wired up by the board code");
31
case float_2nan_prop_s_ab:
96
- return;
32
if (have_snan) {
97
- }
33
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
98
-
34
* return the NaN with the positive sign bit (if any).
99
- /*
35
*/
100
- * TODO: ideally we should model the SoC RCC and its ability to
36
if (is_snan(a->cls)) {
101
- * change the sysclk frequency and define different sysclk sources.
37
- if (is_snan(b->cls)) {
102
- */
38
- which = cmp > 0 ? 0 : 1;
103
-
39
- } else {
104
- /* The refclk always runs at frequency HCLK / 8 */
40
+ if (!is_snan(b->cls)) {
105
- clock_set_mul_div(s->refclk, 8, 1);
41
which = is_qnan(b->cls) ? 1 : 0;
106
- clock_set_source(s->refclk, s->sysclk);
42
+ break;
107
-
43
}
108
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
44
} else if (is_qnan(a->cls)) {
109
sc->flash_size, errp)) {
45
if (is_snan(b->cls) || !is_qnan(b->cls)) {
110
return;
46
which = 0;
111
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
47
- } else {
112
qdev_prop_set_uint32(armv7m, "num-prio-bits", 4);
48
- which = cmp > 0 ? 0 : 1;
113
qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
49
+ break;
114
qdev_prop_set_bit(armv7m, "enable-bitband", true);
50
}
115
- qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
51
} else {
116
- qdev_connect_clock_in(armv7m, "refclk", s->refclk);
52
which = 1;
117
+ qdev_connect_clock_in(armv7m, "cpuclk",
53
+ break;
118
+ qdev_get_clock_out(DEVICE(&(s->rcc)), "cortex-fclk-out"));
54
}
119
+ qdev_connect_clock_in(armv7m, "refclk",
55
+ cmp = frac_cmp(a, b);
120
+ qdev_get_clock_out(DEVICE(&(s->rcc)), "cortex-refclk-out"));
56
+ if (cmp == 0) {
121
object_property_set_link(OBJECT(&s->armv7m), "memory",
57
+ cmp = a->sign < b->sign;
122
OBJECT(system_memory), &error_abort);
58
+ }
123
if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
59
+ which = cmp > 0 ? 0 : 1;
60
break;
61
default:
62
g_assert_not_reached();
124
--
63
--
125
2.34.1
64
2.34.1
126
127
diff view generated by jsdifflib
1
From: Rayhan Faizel <rayhan.faizel@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
BCM2835 has three I2C controllers. All of them share the same interrupt line.
3
Replace the "index" selecting between A and B with a result variable
4
of the proper type. This improves clarity within the function.
4
5
5
Signed-off-by: Rayhan Faizel <rayhan.faizel@gmail.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Message-id: 20240224191038.2409945-3-rayhan.faizel@gmail.com
8
Message-id: 20241203203949.483774-12-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
include/hw/arm/bcm2835_peripherals.h | 4 ++-
11
fpu/softfloat-parts.c.inc | 28 +++++++++++++---------------
11
hw/arm/bcm2835_peripherals.c | 45 ++++++++++++++++++++++++++--
12
1 file changed, 13 insertions(+), 15 deletions(-)
12
hw/arm/Kconfig | 1 +
13
3 files changed, 46 insertions(+), 4 deletions(-)
14
13
15
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/bcm2835_peripherals.h
16
--- a/fpu/softfloat-parts.c.inc
18
+++ b/include/hw/arm/bcm2835_peripherals.h
17
+++ b/fpu/softfloat-parts.c.inc
19
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
20
#include "hw/timer/bcm2835_systmr.h"
19
float_status *s)
21
#include "hw/usb/hcd-dwc2.h"
20
{
22
#include "hw/ssi/bcm2835_spi.h"
21
bool have_snan = false;
23
+#include "hw/i2c/bcm2835_i2c.h"
22
- int cmp, which;
24
#include "hw/misc/unimp.h"
23
+ FloatPartsN *ret;
25
#include "qom/object.h"
24
+ int cmp;
26
25
27
@@ -XXX,XX +XXX,XX @@ struct BCMSocPeripheralBaseState {
26
if (is_snan(a->cls) || is_snan(b->cls)) {
28
BCM2835SDHostState sdhost;
27
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
29
UnimplementedDeviceState i2s;
28
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
30
BCM2835SPIState spi[1];
29
switch (s->float_2nan_prop_rule) {
31
- UnimplementedDeviceState i2c[3];
30
case float_2nan_prop_s_ab:
32
+ BCM2835I2CState i2c[3];
31
if (have_snan) {
33
+ OrIRQState orgated_i2c_irq;
32
- which = is_snan(a->cls) ? 0 : 1;
34
UnimplementedDeviceState otp;
33
+ ret = is_snan(a->cls) ? a : b;
35
UnimplementedDeviceState dbus;
34
break;
36
UnimplementedDeviceState ave0;
35
}
37
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
36
/* fall through */
38
index XXXXXXX..XXXXXXX 100644
37
case float_2nan_prop_ab:
39
--- a/hw/arm/bcm2835_peripherals.c
38
- which = is_nan(a->cls) ? 0 : 1;
40
+++ b/hw/arm/bcm2835_peripherals.c
39
+ ret = is_nan(a->cls) ? a : b;
41
@@ -XXX,XX +XXX,XX @@
40
break;
42
#define SEPARATE_DMA_IRQ_MAX 10
41
case float_2nan_prop_s_ba:
43
#define ORGATED_DMA_IRQ_COUNT 4
42
if (have_snan) {
44
43
- which = is_snan(b->cls) ? 1 : 0;
45
+/* All three I2C controllers share the same IRQ */
44
+ ret = is_snan(b->cls) ? b : a;
46
+#define ORGATED_I2C_IRQ_COUNT 3
45
break;
47
+
46
}
48
void create_unimp(BCMSocPeripheralBaseState *ps,
47
/* fall through */
49
UnimplementedDeviceState *uds,
48
case float_2nan_prop_ba:
50
const char *name, hwaddr ofs, hwaddr size)
49
- which = is_nan(b->cls) ? 1 : 0;
51
@@ -XXX,XX +XXX,XX @@ static void raspi_peripherals_base_init(Object *obj)
50
+ ret = is_nan(b->cls) ? b : a;
52
/* SPI */
51
break;
53
object_initialize_child(obj, "bcm2835-spi0", &s->spi[0],
52
case float_2nan_prop_x87:
54
TYPE_BCM2835_SPI);
53
/*
55
+
54
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
56
+ /* I2C */
55
*/
57
+ object_initialize_child(obj, "bcm2835-i2c0", &s->i2c[0],
56
if (is_snan(a->cls)) {
58
+ TYPE_BCM2835_I2C);
57
if (!is_snan(b->cls)) {
59
+ object_initialize_child(obj, "bcm2835-i2c1", &s->i2c[1],
58
- which = is_qnan(b->cls) ? 1 : 0;
60
+ TYPE_BCM2835_I2C);
59
+ ret = is_qnan(b->cls) ? b : a;
61
+ object_initialize_child(obj, "bcm2835-i2c2", &s->i2c[2],
60
break;
62
+ TYPE_BCM2835_I2C);
61
}
63
+
62
} else if (is_qnan(a->cls)) {
64
+ object_initialize_child(obj, "orgated-i2c-irq",
63
if (is_snan(b->cls) || !is_qnan(b->cls)) {
65
+ &s->orgated_i2c_irq, TYPE_OR_IRQ);
64
- which = 0;
66
+ object_property_set_int(OBJECT(&s->orgated_i2c_irq), "num-lines",
65
+ ret = a;
67
+ ORGATED_I2C_IRQ_COUNT, &error_abort);
66
break;
67
}
68
} else {
69
- which = 1;
70
+ ret = b;
71
break;
72
}
73
cmp = frac_cmp(a, b);
74
if (cmp == 0) {
75
cmp = a->sign < b->sign;
76
}
77
- which = cmp > 0 ? 0 : 1;
78
+ ret = cmp > 0 ? a : b;
79
break;
80
default:
81
g_assert_not_reached();
82
}
83
84
- if (which) {
85
- a = b;
86
+ if (is_snan(ret->cls)) {
87
+ parts_silence_nan(ret, s);
88
}
89
- if (is_snan(a->cls)) {
90
- parts_silence_nan(a, s);
91
- }
92
- return a;
93
+ return ret;
68
}
94
}
69
95
70
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
96
static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
71
@@ -XXX,XX +XXX,XX @@ void bcm_soc_peripherals_common_realize(DeviceState *dev, Error **errp)
72
BCM2835_IC_GPU_IRQ,
73
INTERRUPT_SPI));
74
75
+ /* I2C */
76
+ for (n = 0; n < 3; n++) {
77
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c[n]), errp)) {
78
+ return;
79
+ }
80
+ }
81
+
82
+ memory_region_add_subregion(&s->peri_mr, BSC0_OFFSET,
83
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i2c[0]), 0));
84
+ memory_region_add_subregion(&s->peri_mr, BSC1_OFFSET,
85
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i2c[1]), 0));
86
+ memory_region_add_subregion(&s->peri_mr, BSC2_OFFSET,
87
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i2c[2]), 0));
88
+
89
+ if (!qdev_realize(DEVICE(&s->orgated_i2c_irq), NULL, errp)) {
90
+ return;
91
+ }
92
+ for (n = 0; n < ORGATED_I2C_IRQ_COUNT; n++) {
93
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[n]), 0,
94
+ qdev_get_gpio_in(DEVICE(&s->orgated_i2c_irq), n));
95
+ }
96
+ qdev_connect_gpio_out(DEVICE(&s->orgated_i2c_irq), 0,
97
+ qdev_get_gpio_in_named(DEVICE(&s->ic),
98
+ BCM2835_IC_GPU_IRQ,
99
+ INTERRUPT_I2C));
100
+
101
create_unimp(s, &s->txp, "bcm2835-txp", TXP_OFFSET, 0x1000);
102
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
103
create_unimp(s, &s->i2s, "bcm2835-i2s", I2S_OFFSET, 0x100);
104
create_unimp(s, &s->smi, "bcm2835-smi", SMI_OFFSET, 0x100);
105
create_unimp(s, &s->bscsl, "bcm2835-spis", BSC_SL_OFFSET, 0x100);
106
- create_unimp(s, &s->i2c[0], "bcm2835-i2c0", BSC0_OFFSET, 0x20);
107
- create_unimp(s, &s->i2c[1], "bcm2835-i2c1", BSC1_OFFSET, 0x20);
108
- create_unimp(s, &s->i2c[2], "bcm2835-i2c2", BSC2_OFFSET, 0x20);
109
create_unimp(s, &s->otp, "bcm2835-otp", OTP_OFFSET, 0x80);
110
create_unimp(s, &s->dbus, "bcm2835-dbus", DBUS_OFFSET, 0x8000);
111
create_unimp(s, &s->ave0, "bcm2835-ave0", AVE0_OFFSET, 0x8000);
112
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
113
index XXXXXXX..XXXXXXX 100644
114
--- a/hw/arm/Kconfig
115
+++ b/hw/arm/Kconfig
116
@@ -XXX,XX +XXX,XX @@ config RASPI
117
select SDHCI
118
select USB_DWC2
119
select BCM2835_SPI
120
+ select BCM2835_I2C
121
122
config STM32F100_SOC
123
bool
124
--
97
--
125
2.34.1
98
2.34.1
126
99
127
100
diff view generated by jsdifflib
1
From: Arnaud Minier <arnaud.minier@telecom-paris.fr>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
Add the necessary files to add a simple RCC implementation with just
3
I'm migrating to Qualcomm's new open source email infrastructure, so
4
reads from and writes to registers. Also instantiate the RCC in the
4
update my email address, and update the mailmap to match.
5
STM32L4x5_SoC. It is needed for accurate emulation of all the SoC
6
clocks and timers.
7
5
8
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
6
Signed-off-by: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
9
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
10
Acked-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20240303140643.81957-2-arnaud.minier@telecom-paris.fr
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20241205114047.1125842-1-leif.lindholm@oss.qualcomm.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
13
---
15
MAINTAINERS | 5 +-
14
MAINTAINERS | 2 +-
16
docs/system/arm/b-l475e-iot01a.rst | 2 +-
15
.mailmap | 5 +++--
17
include/hw/arm/stm32l4x5_soc.h | 2 +
16
2 files changed, 4 insertions(+), 3 deletions(-)
18
include/hw/misc/stm32l4x5_rcc.h | 80 ++++
19
include/hw/misc/stm32l4x5_rcc_internals.h | 286 ++++++++++++++
20
hw/arm/stm32l4x5_soc.c | 12 +-
21
hw/misc/stm32l4x5_rcc.c | 446 ++++++++++++++++++++++
22
hw/arm/Kconfig | 1 +
23
hw/misc/Kconfig | 3 +
24
hw/misc/meson.build | 1 +
25
hw/misc/trace-events | 4 +
26
11 files changed, 839 insertions(+), 3 deletions(-)
27
create mode 100644 include/hw/misc/stm32l4x5_rcc.h
28
create mode 100644 include/hw/misc/stm32l4x5_rcc_internals.h
29
create mode 100644 hw/misc/stm32l4x5_rcc.c
30
17
31
diff --git a/MAINTAINERS b/MAINTAINERS
18
diff --git a/MAINTAINERS b/MAINTAINERS
32
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
33
--- a/MAINTAINERS
20
--- a/MAINTAINERS
34
+++ b/MAINTAINERS
21
+++ b/MAINTAINERS
35
@@ -XXX,XX +XXX,XX @@ M: Inès Varhol <ines.varhol@telecom-paris.fr>
22
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
23
SBSA-REF
24
M: Radoslaw Biernacki <rad@semihalf.com>
25
M: Peter Maydell <peter.maydell@linaro.org>
26
-R: Leif Lindholm <quic_llindhol@quicinc.com>
27
+R: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
28
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
36
L: qemu-arm@nongnu.org
29
L: qemu-arm@nongnu.org
37
S: Maintained
30
S: Maintained
38
F: hw/arm/stm32l4x5_soc.c
31
diff --git a/.mailmap b/.mailmap
39
-F: include/hw/arm/stm32l4x5_soc.h
40
+F: hw/misc/stm32l4x5_exti.c
41
+F: hw/misc/stm32l4x5_syscfg.c
42
+F: hw/misc/stm32l4x5_rcc.c
43
+F: include/hw/*/stm32l4x5_*.h
44
45
B-L475E-IOT01A IoT Node
46
M: Arnaud Minier <arnaud.minier@telecom-paris.fr>
47
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
48
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
49
--- a/docs/system/arm/b-l475e-iot01a.rst
33
--- a/.mailmap
50
+++ b/docs/system/arm/b-l475e-iot01a.rst
34
+++ b/.mailmap
51
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
35
@@ -XXX,XX +XXX,XX @@ Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
52
- Cortex-M4F based STM32L4x5 SoC
36
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
53
- STM32L4x5 EXTI (Extended interrupts and events controller)
37
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
54
- STM32L4x5 SYSCFG (System configuration controller)
38
Juan Quintela <quintela@trasno.org> <quintela@redhat.com>
55
+- STM32L4x5 RCC (Reset and clock control)
39
-Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
56
40
-Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
57
Missing devices
41
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <quic_llindhol@quicinc.com>
58
"""""""""""""""
42
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif.lindholm@linaro.org>
59
43
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif@nuviainc.com>
60
The B-L475E-IOT01A does *not* support the following devices:
44
Luc Michel <luc@lmichel.fr> <luc.michel@git.antfield.fr>
61
45
Luc Michel <luc@lmichel.fr> <luc.michel@greensocs.com>
62
-- Reset and clock control (RCC)
46
Luc Michel <luc@lmichel.fr> <lmichel@kalray.eu>
63
- Serial ports (UART)
64
- General-purpose I/Os (GPIO)
65
- Analog to Digital Converter (ADC)
66
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
67
index XXXXXXX..XXXXXXX 100644
68
--- a/include/hw/arm/stm32l4x5_soc.h
69
+++ b/include/hw/arm/stm32l4x5_soc.h
70
@@ -XXX,XX +XXX,XX @@
71
#include "hw/or-irq.h"
72
#include "hw/misc/stm32l4x5_syscfg.h"
73
#include "hw/misc/stm32l4x5_exti.h"
74
+#include "hw/misc/stm32l4x5_rcc.h"
75
#include "qom/object.h"
76
77
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
78
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
79
Stm32l4x5ExtiState exti;
80
OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
81
Stm32l4x5SyscfgState syscfg;
82
+ Stm32l4x5RccState rcc;
83
84
MemoryRegion sram1;
85
MemoryRegion sram2;
86
diff --git a/include/hw/misc/stm32l4x5_rcc.h b/include/hw/misc/stm32l4x5_rcc.h
87
new file mode 100644
88
index XXXXXXX..XXXXXXX
89
--- /dev/null
90
+++ b/include/hw/misc/stm32l4x5_rcc.h
91
@@ -XXX,XX +XXX,XX @@
92
+/*
93
+ * STM32L4X5 RCC (Reset and clock control)
94
+ *
95
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
96
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
97
+ *
98
+ * SPDX-License-Identifier: GPL-2.0-or-later
99
+ *
100
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
101
+ * See the COPYING file in the top-level directory.
102
+ *
103
+ * The reference used is the STMicroElectronics RM0351 Reference manual
104
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
105
+ *
106
+ * Inspired by the BCM2835 CPRMAN clock manager by Luc Michel.
107
+ */
108
+
109
+#ifndef HW_STM32L4X5_RCC_H
110
+#define HW_STM32L4X5_RCC_H
111
+
112
+#include "hw/sysbus.h"
113
+#include "qom/object.h"
114
+
115
+#define TYPE_STM32L4X5_RCC "stm32l4x5-rcc"
116
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5RccState, STM32L4X5_RCC)
117
+
118
+/* In the Stm32l4x5 clock tree, mux have at most 7 sources */
119
+#define RCC_NUM_CLOCK_MUX_SRC 7
120
+struct Stm32l4x5RccState {
121
+ SysBusDevice parent_obj;
122
+
123
+ MemoryRegion mmio;
124
+
125
+ uint32_t cr;
126
+ uint32_t icscr;
127
+ uint32_t cfgr;
128
+ uint32_t pllcfgr;
129
+ uint32_t pllsai1cfgr;
130
+ uint32_t pllsai2cfgr;
131
+ uint32_t cier;
132
+ uint32_t cifr;
133
+ uint32_t ahb1rstr;
134
+ uint32_t ahb2rstr;
135
+ uint32_t ahb3rstr;
136
+ uint32_t apb1rstr1;
137
+ uint32_t apb1rstr2;
138
+ uint32_t apb2rstr;
139
+ uint32_t ahb1enr;
140
+ uint32_t ahb2enr;
141
+ uint32_t ahb3enr;
142
+ uint32_t apb1enr1;
143
+ uint32_t apb1enr2;
144
+ uint32_t apb2enr;
145
+ uint32_t ahb1smenr;
146
+ uint32_t ahb2smenr;
147
+ uint32_t ahb3smenr;
148
+ uint32_t apb1smenr1;
149
+ uint32_t apb1smenr2;
150
+ uint32_t apb2smenr;
151
+ uint32_t ccipr;
152
+ uint32_t bdcr;
153
+ uint32_t csr;
154
+
155
+ /* Clock sources */
156
+ Clock *gnd;
157
+ Clock *hsi16_rc;
158
+ Clock *msi_rc;
159
+ Clock *hse;
160
+ Clock *lsi_rc;
161
+ Clock *lse_crystal;
162
+ Clock *sai1_extclk;
163
+ Clock *sai2_extclk;
164
+
165
+ qemu_irq irq;
166
+ uint64_t hse_frequency;
167
+ uint64_t sai1_extclk_frequency;
168
+ uint64_t sai2_extclk_frequency;
169
+};
170
+
171
+#endif /* HW_STM32L4X5_RCC_H */
172
diff --git a/include/hw/misc/stm32l4x5_rcc_internals.h b/include/hw/misc/stm32l4x5_rcc_internals.h
173
new file mode 100644
174
index XXXXXXX..XXXXXXX
175
--- /dev/null
176
+++ b/include/hw/misc/stm32l4x5_rcc_internals.h
177
@@ -XXX,XX +XXX,XX @@
178
+/*
179
+ * STM32L4X5 RCC (Reset and clock control)
180
+ *
181
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
182
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
183
+ *
184
+ * SPDX-License-Identifier: GPL-2.0-or-later
185
+ *
186
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
187
+ * See the COPYING file in the top-level directory.
188
+ *
189
+ * The reference used is the STMicroElectronics RM0351 Reference manual
190
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
191
+ *
192
+ * Inspired by the BCM2835 CPRMAN clock manager implementation by Luc Michel.
193
+ */
194
+
195
+#ifndef HW_STM32L4X5_RCC_INTERNALS_H
196
+#define HW_STM32L4X5_RCC_INTERNALS_H
197
+
198
+#include "hw/registerfields.h"
199
+#include "hw/misc/stm32l4x5_rcc.h"
200
+
201
+
202
+/* Register map */
203
+REG32(CR, 0x00)
204
+ FIELD(CR, PLLSAI2RDY, 29, 1)
205
+ FIELD(CR, PLLSAI2ON, 28, 1)
206
+ FIELD(CR, PLLSAI1RDY, 27, 1)
207
+ FIELD(CR, PLLSAI1ON, 26, 1)
208
+ FIELD(CR, PLLRDY, 25, 1)
209
+ FIELD(CR, PLLON, 24, 1)
210
+ FIELD(CR, CSSON, 19, 1)
211
+ FIELD(CR, HSEBYP, 18, 1)
212
+ FIELD(CR, HSERDY, 17, 1)
213
+ FIELD(CR, HSEON, 16, 1)
214
+ FIELD(CR, HSIASFS, 11, 1)
215
+ FIELD(CR, HSIRDY, 10, 1)
216
+ FIELD(CR, HSIKERON, 9, 1)
217
+ FIELD(CR, HSION, 8, 1)
218
+ FIELD(CR, MSIRANGE, 4, 4)
219
+ FIELD(CR, MSIRGSEL, 3, 1)
220
+ FIELD(CR, MSIPLLEN, 2, 1)
221
+ FIELD(CR, MSIRDY, 1, 1)
222
+ FIELD(CR, MSION, 0, 1)
223
+REG32(ICSCR, 0x04)
224
+ FIELD(ICSCR, HSITRIM, 24, 7)
225
+ FIELD(ICSCR, HSICAL, 16, 8)
226
+ FIELD(ICSCR, MSITRIM, 8, 8)
227
+ FIELD(ICSCR, MSICAL, 0, 8)
228
+REG32(CFGR, 0x08)
229
+ FIELD(CFGR, MCOPRE, 28, 3)
230
+ /* MCOSEL[2:0] only for STM32L475xx/476xx/486xx devices */
231
+ FIELD(CFGR, MCOSEL, 24, 3)
232
+ FIELD(CFGR, STOPWUCK, 15, 1)
233
+ FIELD(CFGR, PPRE2, 11, 3)
234
+ FIELD(CFGR, PPRE1, 8, 3)
235
+ FIELD(CFGR, HPRE, 4, 4)
236
+ FIELD(CFGR, SWS, 2, 2)
237
+ FIELD(CFGR, SW, 0, 2)
238
+REG32(PLLCFGR, 0x0C)
239
+ FIELD(PLLCFGR, PLLPDIV, 27, 5)
240
+ FIELD(PLLCFGR, PLLR, 25, 2)
241
+ FIELD(PLLCFGR, PLLREN, 24, 1)
242
+ FIELD(PLLCFGR, PLLQ, 21, 2)
243
+ FIELD(PLLCFGR, PLLQEN, 20, 1)
244
+ FIELD(PLLCFGR, PLLP, 17, 1)
245
+ FIELD(PLLCFGR, PLLPEN, 16, 1)
246
+ FIELD(PLLCFGR, PLLN, 8, 7)
247
+ FIELD(PLLCFGR, PLLM, 4, 3)
248
+ FIELD(PLLCFGR, PLLSRC, 0, 2)
249
+REG32(PLLSAI1CFGR, 0x10)
250
+ FIELD(PLLSAI1CFGR, PLLSAI1PDIV, 27, 5)
251
+ FIELD(PLLSAI1CFGR, PLLSAI1R, 25, 2)
252
+ FIELD(PLLSAI1CFGR, PLLSAI1REN, 24, 1)
253
+ FIELD(PLLSAI1CFGR, PLLSAI1Q, 21, 2)
254
+ FIELD(PLLSAI1CFGR, PLLSAI1QEN, 20, 1)
255
+ FIELD(PLLSAI1CFGR, PLLSAI1P, 17, 1)
256
+ FIELD(PLLSAI1CFGR, PLLSAI1PEN, 16, 1)
257
+ FIELD(PLLSAI1CFGR, PLLSAI1N, 8, 7)
258
+REG32(PLLSAI2CFGR, 0x14)
259
+ FIELD(PLLSAI2CFGR, PLLSAI2PDIV, 27, 5)
260
+ FIELD(PLLSAI2CFGR, PLLSAI2R, 25, 2)
261
+ FIELD(PLLSAI2CFGR, PLLSAI2REN, 24, 1)
262
+ FIELD(PLLSAI2CFGR, PLLSAI2Q, 21, 2)
263
+ FIELD(PLLSAI2CFGR, PLLSAI2QEN, 20, 1)
264
+ FIELD(PLLSAI2CFGR, PLLSAI2P, 17, 1)
265
+ FIELD(PLLSAI2CFGR, PLLSAI2PEN, 16, 1)
266
+ FIELD(PLLSAI2CFGR, PLLSAI2N, 8, 7)
267
+REG32(CIER, 0x18)
268
+ /* HSI48RDYIE: only on STM32L496xx/4A6xx devices */
269
+ FIELD(CIER, LSECSSIE, 9, 1)
270
+ FIELD(CIER, PLLSAI2RDYIE, 7, 1)
271
+ FIELD(CIER, PLLSAI1RDYIE, 6, 1)
272
+ FIELD(CIER, PLLRDYIE, 5, 1)
273
+ FIELD(CIER, HSERDYIE, 4, 1)
274
+ FIELD(CIER, HSIRDYIE, 3, 1)
275
+ FIELD(CIER, MSIRDYIE, 2, 1)
276
+ FIELD(CIER, LSERDYIE, 1, 1)
277
+ FIELD(CIER, LSIRDYIE, 0, 1)
278
+REG32(CIFR, 0x1C)
279
+ /* HSI48RDYF: only on STM32L496xx/4A6xx devices */
280
+ FIELD(CIFR, LSECSSF, 9, 1)
281
+ FIELD(CIFR, CSSF, 8, 1)
282
+ FIELD(CIFR, PLLSAI2RDYF, 7, 1)
283
+ FIELD(CIFR, PLLSAI1RDYF, 6, 1)
284
+ FIELD(CIFR, PLLRDYF, 5, 1)
285
+ FIELD(CIFR, HSERDYF, 4, 1)
286
+ FIELD(CIFR, HSIRDYF, 3, 1)
287
+ FIELD(CIFR, MSIRDYF, 2, 1)
288
+ FIELD(CIFR, LSERDYF, 1, 1)
289
+ FIELD(CIFR, LSIRDYF, 0, 1)
290
+REG32(CICR, 0x20)
291
+ /* HSI48RDYC: only on STM32L496xx/4A6xx devices */
292
+ FIELD(CICR, LSECSSC, 9, 1)
293
+ FIELD(CICR, CSSC, 8, 1)
294
+ FIELD(CICR, PLLSAI2RDYC, 7, 1)
295
+ FIELD(CICR, PLLSAI1RDYC, 6, 1)
296
+ FIELD(CICR, PLLRDYC, 5, 1)
297
+ FIELD(CICR, HSERDYC, 4, 1)
298
+ FIELD(CICR, HSIRDYC, 3, 1)
299
+ FIELD(CICR, MSIRDYC, 2, 1)
300
+ FIELD(CICR, LSERDYC, 1, 1)
301
+ FIELD(CICR, LSIRDYC, 0, 1)
302
+REG32(AHB1RSTR, 0x28)
303
+REG32(AHB2RSTR, 0x2C)
304
+REG32(AHB3RSTR, 0x30)
305
+REG32(APB1RSTR1, 0x38)
306
+REG32(APB1RSTR2, 0x3C)
307
+REG32(APB2RSTR, 0x40)
308
+REG32(AHB1ENR, 0x48)
309
+ /* DMA2DEN: reserved for STM32L475xx */
310
+ FIELD(AHB1ENR, TSCEN, 16, 1)
311
+ FIELD(AHB1ENR, CRCEN, 12, 1)
312
+ FIELD(AHB1ENR, FLASHEN, 8, 1)
313
+ FIELD(AHB1ENR, DMA2EN, 1, 1)
314
+ FIELD(AHB1ENR, DMA1EN, 0, 1)
315
+REG32(AHB2ENR, 0x4C)
316
+ FIELD(AHB2ENR, RNGEN, 18, 1)
317
+ /* HASHEN: reserved for STM32L475xx */
318
+ FIELD(AHB2ENR, AESEN, 16, 1)
319
+ /* DCMIEN: reserved for STM32L475xx */
320
+ FIELD(AHB2ENR, ADCEN, 13, 1)
321
+ FIELD(AHB2ENR, OTGFSEN, 12, 1)
322
+ /* GPIOIEN: reserved for STM32L475xx */
323
+ FIELD(AHB2ENR, GPIOHEN, 7, 1)
324
+ FIELD(AHB2ENR, GPIOGEN, 6, 1)
325
+ FIELD(AHB2ENR, GPIOFEN, 5, 1)
326
+ FIELD(AHB2ENR, GPIOEEN, 4, 1)
327
+ FIELD(AHB2ENR, GPIODEN, 3, 1)
328
+ FIELD(AHB2ENR, GPIOCEN, 2, 1)
329
+ FIELD(AHB2ENR, GPIOBEN, 1, 1)
330
+ FIELD(AHB2ENR, GPIOAEN, 0, 1)
331
+REG32(AHB3ENR, 0x50)
332
+ FIELD(AHB3ENR, QSPIEN, 8, 1)
333
+ FIELD(AHB3ENR, FMCEN, 0, 1)
334
+REG32(APB1ENR1, 0x58)
335
+ FIELD(APB1ENR1, LPTIM1EN, 31, 1)
336
+ FIELD(APB1ENR1, OPAMPEN, 30, 1)
337
+ FIELD(APB1ENR1, DAC1EN, 29, 1)
338
+ FIELD(APB1ENR1, PWREN, 28, 1)
339
+ FIELD(APB1ENR1, CAN2EN, 26, 1)
340
+ FIELD(APB1ENR1, CAN1EN, 25, 1)
341
+ /* CRSEN: reserved for STM32L475xx */
342
+ FIELD(APB1ENR1, I2C3EN, 23, 1)
343
+ FIELD(APB1ENR1, I2C2EN, 22, 1)
344
+ FIELD(APB1ENR1, I2C1EN, 21, 1)
345
+ FIELD(APB1ENR1, UART5EN, 20, 1)
346
+ FIELD(APB1ENR1, UART4EN, 19, 1)
347
+ FIELD(APB1ENR1, USART3EN, 18, 1)
348
+ FIELD(APB1ENR1, USART2EN, 17, 1)
349
+ FIELD(APB1ENR1, SPI3EN, 15, 1)
350
+ FIELD(APB1ENR1, SPI2EN, 14, 1)
351
+ FIELD(APB1ENR1, WWDGEN, 11, 1)
352
+ /* RTCAPBEN: reserved for STM32L475xx */
353
+ FIELD(APB1ENR1, LCDEN, 9, 1)
354
+ FIELD(APB1ENR1, TIM7EN, 5, 1)
355
+ FIELD(APB1ENR1, TIM6EN, 4, 1)
356
+ FIELD(APB1ENR1, TIM5EN, 3, 1)
357
+ FIELD(APB1ENR1, TIM4EN, 2, 1)
358
+ FIELD(APB1ENR1, TIM3EN, 1, 1)
359
+ FIELD(APB1ENR1, TIM2EN, 0, 1)
360
+REG32(APB1ENR2, 0x5C)
361
+ FIELD(APB1ENR2, LPTIM2EN, 5, 1)
362
+ FIELD(APB1ENR2, SWPMI1EN, 2, 1)
363
+ /* I2C4EN: reserved for STM32L475xx */
364
+ FIELD(APB1ENR2, LPUART1EN, 0, 1)
365
+REG32(APB2ENR, 0x60)
366
+ FIELD(APB2ENR, DFSDM1EN, 24, 1)
367
+ FIELD(APB2ENR, SAI2EN, 22, 1)
368
+ FIELD(APB2ENR, SAI1EN, 21, 1)
369
+ FIELD(APB2ENR, TIM17EN, 18, 1)
370
+ FIELD(APB2ENR, TIM16EN, 17, 1)
371
+ FIELD(APB2ENR, TIM15EN, 16, 1)
372
+ FIELD(APB2ENR, USART1EN, 14, 1)
373
+ FIELD(APB2ENR, TIM8EN, 13, 1)
374
+ FIELD(APB2ENR, SPI1EN, 12, 1)
375
+ FIELD(APB2ENR, TIM1EN, 11, 1)
376
+ FIELD(APB2ENR, SDMMC1EN, 10, 1)
377
+ FIELD(APB2ENR, FWEN, 7, 1)
378
+ FIELD(APB2ENR, SYSCFGEN, 0, 1)
379
+REG32(AHB1SMENR, 0x68)
380
+REG32(AHB2SMENR, 0x6C)
381
+REG32(AHB3SMENR, 0x70)
382
+REG32(APB1SMENR1, 0x78)
383
+REG32(APB1SMENR2, 0x7C)
384
+REG32(APB2SMENR, 0x80)
385
+REG32(CCIPR, 0x88)
386
+ FIELD(CCIPR, DFSDM1SEL, 31, 1)
387
+ FIELD(CCIPR, SWPMI1SEL, 30, 1)
388
+ FIELD(CCIPR, ADCSEL, 28, 2)
389
+ FIELD(CCIPR, CLK48SEL, 26, 2)
390
+ FIELD(CCIPR, SAI2SEL, 24, 2)
391
+ FIELD(CCIPR, SAI1SEL, 22, 2)
392
+ FIELD(CCIPR, LPTIM2SEL, 20, 2)
393
+ FIELD(CCIPR, LPTIM1SEL, 18, 2)
394
+ FIELD(CCIPR, I2C3SEL, 16, 2)
395
+ FIELD(CCIPR, I2C2SEL, 14, 2)
396
+ FIELD(CCIPR, I2C1SEL, 12, 2)
397
+ FIELD(CCIPR, LPUART1SEL, 10, 2)
398
+ FIELD(CCIPR, UART5SEL, 8, 2)
399
+ FIELD(CCIPR, UART4SEL, 6, 2)
400
+ FIELD(CCIPR, USART3SEL, 4, 2)
401
+ FIELD(CCIPR, USART2SEL, 2, 2)
402
+ FIELD(CCIPR, USART1SEL, 0, 2)
403
+REG32(BDCR, 0x90)
404
+ FIELD(BDCR, LSCOSEL, 25, 1)
405
+ FIELD(BDCR, LSCOEN, 24, 1)
406
+ FIELD(BDCR, BDRST, 16, 1)
407
+ FIELD(BDCR, RTCEN, 15, 1)
408
+ FIELD(BDCR, RTCSEL, 8, 2)
409
+ FIELD(BDCR, LSECSSD, 6, 1)
410
+ FIELD(BDCR, LSECSSON, 5, 1)
411
+ FIELD(BDCR, LSEDRV, 3, 2)
412
+ FIELD(BDCR, LSEBYP, 2, 1)
413
+ FIELD(BDCR, LSERDY, 1, 1)
414
+ FIELD(BDCR, LSEON, 0, 1)
415
+REG32(CSR, 0x94)
416
+ FIELD(CSR, LPWRRSTF, 31, 1)
417
+ FIELD(CSR, WWDGRSTF, 30, 1)
418
+ FIELD(CSR, IWWGRSTF, 29, 1)
419
+ FIELD(CSR, SFTRSTF, 28, 1)
420
+ FIELD(CSR, BORRSTF, 27, 1)
421
+ FIELD(CSR, PINRSTF, 26, 1)
422
+ FIELD(CSR, OBLRSTF, 25, 1)
423
+ FIELD(CSR, FWRSTF, 24, 1)
424
+ FIELD(CSR, RMVF, 23, 1)
425
+ FIELD(CSR, MSISRANGE, 8, 4)
426
+ FIELD(CSR, LSIRDY, 1, 1)
427
+ FIELD(CSR, LSION, 0, 1)
428
+/* CRRCR and CCIPR2 registers are present on L496/L4A6 devices only. */
429
+
430
+/* Read Only masks to prevent writes in unauthorized bits */
431
+#define CR_READ_ONLY_MASK (R_CR_PLLSAI2RDY_MASK | \
432
+ R_CR_PLLSAI1RDY_MASK | \
433
+ R_CR_PLLRDY_MASK | \
434
+ R_CR_HSERDY_MASK | \
435
+ R_CR_HSIRDY_MASK | \
436
+ R_CR_MSIRDY_MASK)
437
+#define CR_READ_SET_MASK (R_CR_CSSON_MASK | R_CR_MSIRGSEL_MASK)
438
+#define ICSCR_READ_ONLY_MASK (R_ICSCR_HSICAL_MASK | R_ICSCR_MSICAL_MASK)
439
+#define CFGR_READ_ONLY_MASK (R_CFGR_SWS_MASK)
440
+#define CIFR_READ_ONLY_MASK (R_CIFR_LSECSSF_MASK | \
441
+ R_CIFR_CSSF_MASK | \
442
+ R_CIFR_PLLSAI2RDYF_MASK | \
443
+ R_CIFR_PLLSAI1RDYF_MASK | \
444
+ R_CIFR_PLLRDYF_MASK | \
445
+ R_CIFR_HSERDYF_MASK | \
446
+ R_CIFR_HSIRDYF_MASK | \
447
+ R_CIFR_MSIRDYF_MASK | \
448
+ R_CIFR_LSERDYF_MASK | \
449
+ R_CIFR_LSIRDYF_MASK)
450
+#define CIFR_IRQ_MASK CIFR_READ_ONLY_MASK
451
+#define APB2ENR_READ_SET_MASK (R_APB2ENR_FWEN_MASK)
452
+#define BDCR_READ_ONLY_MASK (R_BDCR_LSECSSD_MASK | R_BDCR_LSERDY_MASK)
453
+#define CSR_READ_ONLY_MASK (R_CSR_LPWRRSTF_MASK | \
454
+ R_CSR_WWDGRSTF_MASK | \
455
+ R_CSR_IWWGRSTF_MASK | \
456
+ R_CSR_SFTRSTF_MASK | \
457
+ R_CSR_BORRSTF_MASK | \
458
+ R_CSR_PINRSTF_MASK | \
459
+ R_CSR_OBLRSTF_MASK | \
460
+ R_CSR_FWRSTF_MASK | \
461
+ R_CSR_LSIRDY_MASK)
462
+
463
+#endif /* HW_STM32L4X5_RCC_INTERNALS_H */
464
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
465
index XXXXXXX..XXXXXXX 100644
466
--- a/hw/arm/stm32l4x5_soc.c
467
+++ b/hw/arm/stm32l4x5_soc.c
468
@@ -XXX,XX +XXX,XX @@ static const int exti_irq[NUM_EXTI_IRQ] = {
469
-1, -1, -1, -1, /* PVM[1..4] OR gate 1 */
470
78 /* LCD wakeup, Direct */
471
};
472
+#define RCC_BASE_ADDRESS 0x40021000
473
+#define RCC_IRQ 5
474
475
static const int exti_or_gates_out[NUM_EXTI_OR_GATES] = {
476
23, 40, 63, 1,
477
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
478
TYPE_OR_IRQ);
479
}
480
object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
481
+ object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32L4X5_RCC);
482
483
s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
484
s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
485
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
486
qdev_get_gpio_in(DEVICE(&s->exti), i));
487
}
488
489
+ /* RCC device */
490
+ busdev = SYS_BUS_DEVICE(&s->rcc);
491
+ if (!sysbus_realize(busdev, errp)) {
492
+ return;
493
+ }
494
+ sysbus_mmio_map(busdev, 0, RCC_BASE_ADDRESS);
495
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, RCC_IRQ));
496
+
497
/* APB1 BUS */
498
create_unimplemented_device("TIM2", 0x40000000, 0x400);
499
create_unimplemented_device("TIM3", 0x40000400, 0x400);
500
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
501
create_unimplemented_device("DMA1", 0x40020000, 0x400);
502
create_unimplemented_device("DMA2", 0x40020400, 0x400);
503
/* RESERVED: 0x40020800, 0x800 */
504
- create_unimplemented_device("RCC", 0x40021000, 0x400);
505
/* RESERVED: 0x40021400, 0xC00 */
506
create_unimplemented_device("FLASH", 0x40022000, 0x400);
507
/* RESERVED: 0x40022400, 0xC00 */
508
diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c
509
new file mode 100644
510
index XXXXXXX..XXXXXXX
511
--- /dev/null
512
+++ b/hw/misc/stm32l4x5_rcc.c
513
@@ -XXX,XX +XXX,XX @@
514
+/*
515
+ * STM32L4X5 RCC (Reset and clock control)
516
+ *
517
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
518
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
519
+ *
520
+ * SPDX-License-Identifier: GPL-2.0-or-later
521
+ *
522
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
523
+ * See the COPYING file in the top-level directory.
524
+ *
525
+ * The reference used is the STMicroElectronics RM0351 Reference manual
526
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
527
+ *
528
+ * Inspired by the BCM2835 CPRMAN clock manager implementation by Luc Michel.
529
+ */
530
+
531
+#include "qemu/osdep.h"
532
+#include "qemu/log.h"
533
+#include "qemu/module.h"
534
+#include "qemu/timer.h"
535
+#include "qapi/error.h"
536
+#include "migration/vmstate.h"
537
+#include "hw/misc/stm32l4x5_rcc.h"
538
+#include "hw/misc/stm32l4x5_rcc_internals.h"
539
+#include "hw/clock.h"
540
+#include "hw/irq.h"
541
+#include "hw/qdev-clock.h"
542
+#include "hw/qdev-properties.h"
543
+#include "hw/qdev-properties-system.h"
544
+#include "trace.h"
545
+
546
+#define HSE_DEFAULT_FRQ 48000000ULL
547
+#define HSI_FRQ 16000000ULL
548
+#define MSI_DEFAULT_FRQ 4000000ULL
549
+#define LSE_FRQ 32768ULL
550
+#define LSI_FRQ 32000ULL
551
+
552
+static void rcc_update_irq(Stm32l4x5RccState *s)
553
+{
554
+ if (s->cifr & CIFR_IRQ_MASK) {
555
+ qemu_irq_raise(s->irq);
556
+ } else {
557
+ qemu_irq_lower(s->irq);
558
+ }
559
+}
560
+
561
+static void stm32l4x5_rcc_reset_hold(Object *obj)
562
+{
563
+ Stm32l4x5RccState *s = STM32L4X5_RCC(obj);
564
+ s->cr = 0x00000063;
565
+ /*
566
+ * Factory-programmed calibration data
567
+ * From the reference manual: 0x10XX 00XX
568
+ * Value taken from a real card.
569
+ */
570
+ s->icscr = 0x106E0082;
571
+ s->cfgr = 0x0;
572
+ s->pllcfgr = 0x00001000;
573
+ s->pllsai1cfgr = 0x00001000;
574
+ s->pllsai2cfgr = 0x00001000;
575
+ s->cier = 0x0;
576
+ s->cifr = 0x0;
577
+ s->ahb1rstr = 0x0;
578
+ s->ahb2rstr = 0x0;
579
+ s->ahb3rstr = 0x0;
580
+ s->apb1rstr1 = 0x0;
581
+ s->apb1rstr2 = 0x0;
582
+ s->apb2rstr = 0x0;
583
+ s->ahb1enr = 0x00000100;
584
+ s->ahb2enr = 0x0;
585
+ s->ahb3enr = 0x0;
586
+ s->apb1enr1 = 0x0;
587
+ s->apb1enr2 = 0x0;
588
+ s->apb2enr = 0x0;
589
+ s->ahb1smenr = 0x00011303;
590
+ s->ahb2smenr = 0x000532FF;
591
+ s->ahb3smenr = 0x00000101;
592
+ s->apb1smenr1 = 0xF2FECA3F;
593
+ s->apb1smenr2 = 0x00000025;
594
+ s->apb2smenr = 0x01677C01;
595
+ s->ccipr = 0x0;
596
+ s->bdcr = 0x0;
597
+ s->csr = 0x0C000600;
598
+}
599
+
600
+static uint64_t stm32l4x5_rcc_read(void *opaque, hwaddr addr,
601
+ unsigned int size)
602
+{
603
+ Stm32l4x5RccState *s = opaque;
604
+ uint64_t retvalue = 0;
605
+
606
+ switch (addr) {
607
+ case A_CR:
608
+ retvalue = s->cr;
609
+ break;
610
+ case A_ICSCR:
611
+ retvalue = s->icscr;
612
+ break;
613
+ case A_CFGR:
614
+ retvalue = s->cfgr;
615
+ break;
616
+ case A_PLLCFGR:
617
+ retvalue = s->pllcfgr;
618
+ break;
619
+ case A_PLLSAI1CFGR:
620
+ retvalue = s->pllsai1cfgr;
621
+ break;
622
+ case A_PLLSAI2CFGR:
623
+ retvalue = s->pllsai2cfgr;
624
+ break;
625
+ case A_CIER:
626
+ retvalue = s->cier;
627
+ break;
628
+ case A_CIFR:
629
+ retvalue = s->cifr;
630
+ break;
631
+ case A_CICR:
632
+ /* CICR is write only, return the reset value = 0 */
633
+ break;
634
+ case A_AHB1RSTR:
635
+ retvalue = s->ahb1rstr;
636
+ break;
637
+ case A_AHB2RSTR:
638
+ retvalue = s->ahb2rstr;
639
+ break;
640
+ case A_AHB3RSTR:
641
+ retvalue = s->ahb3rstr;
642
+ break;
643
+ case A_APB1RSTR1:
644
+ retvalue = s->apb1rstr1;
645
+ break;
646
+ case A_APB1RSTR2:
647
+ retvalue = s->apb1rstr2;
648
+ break;
649
+ case A_APB2RSTR:
650
+ retvalue = s->apb2rstr;
651
+ break;
652
+ case A_AHB1ENR:
653
+ retvalue = s->ahb1enr;
654
+ break;
655
+ case A_AHB2ENR:
656
+ retvalue = s->ahb2enr;
657
+ break;
658
+ case A_AHB3ENR:
659
+ retvalue = s->ahb3enr;
660
+ break;
661
+ case A_APB1ENR1:
662
+ retvalue = s->apb1enr1;
663
+ break;
664
+ case A_APB1ENR2:
665
+ retvalue = s->apb1enr2;
666
+ break;
667
+ case A_APB2ENR:
668
+ retvalue = s->apb2enr;
669
+ break;
670
+ case A_AHB1SMENR:
671
+ retvalue = s->ahb1smenr;
672
+ break;
673
+ case A_AHB2SMENR:
674
+ retvalue = s->ahb2smenr;
675
+ break;
676
+ case A_AHB3SMENR:
677
+ retvalue = s->ahb3smenr;
678
+ break;
679
+ case A_APB1SMENR1:
680
+ retvalue = s->apb1smenr1;
681
+ break;
682
+ case A_APB1SMENR2:
683
+ retvalue = s->apb1smenr2;
684
+ break;
685
+ case A_APB2SMENR:
686
+ retvalue = s->apb2smenr;
687
+ break;
688
+ case A_CCIPR:
689
+ retvalue = s->ccipr;
690
+ break;
691
+ case A_BDCR:
692
+ retvalue = s->bdcr;
693
+ break;
694
+ case A_CSR:
695
+ retvalue = s->csr;
696
+ break;
697
+ default:
698
+ qemu_log_mask(LOG_GUEST_ERROR,
699
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
700
+ break;
701
+ }
702
+
703
+ trace_stm32l4x5_rcc_read(addr, retvalue);
704
+
705
+ return retvalue;
706
+}
707
+
708
+static void stm32l4x5_rcc_write(void *opaque, hwaddr addr,
709
+ uint64_t val64, unsigned int size)
710
+{
711
+ Stm32l4x5RccState *s = opaque;
712
+ const uint32_t value = val64;
713
+
714
+ trace_stm32l4x5_rcc_write(addr, value);
715
+
716
+ switch (addr) {
717
+ case A_CR:
718
+ s->cr = (s->cr & CR_READ_SET_MASK) |
719
+ (value & (CR_READ_SET_MASK | ~CR_READ_ONLY_MASK));
720
+ break;
721
+ case A_ICSCR:
722
+ s->icscr = value & ~ICSCR_READ_ONLY_MASK;
723
+ break;
724
+ case A_CFGR:
725
+ s->cfgr = value & ~CFGR_READ_ONLY_MASK;
726
+ break;
727
+ case A_PLLCFGR:
728
+ s->pllcfgr = value;
729
+ break;
730
+ case A_PLLSAI1CFGR:
731
+ s->pllsai1cfgr = value;
732
+ break;
733
+ case A_PLLSAI2CFGR:
734
+ s->pllsai2cfgr = value;
735
+ break;
736
+ case A_CIER:
737
+ s->cier = value;
738
+ break;
739
+ case A_CIFR:
740
+ qemu_log_mask(LOG_GUEST_ERROR,
741
+ "%s: Write attempt into read-only register (CIFR) 0x%"PRIx32"\n",
742
+ __func__, value);
743
+ break;
744
+ case A_CICR:
745
+ /* Clear interrupt flags by writing a 1 to the CICR register */
746
+ s->cifr &= ~value;
747
+ rcc_update_irq(s);
748
+ break;
749
+ /* Reset behaviors are not implemented */
750
+ case A_AHB1RSTR:
751
+ s->ahb1rstr = value;
752
+ break;
753
+ case A_AHB2RSTR:
754
+ s->ahb2rstr = value;
755
+ break;
756
+ case A_AHB3RSTR:
757
+ s->ahb3rstr = value;
758
+ break;
759
+ case A_APB1RSTR1:
760
+ s->apb1rstr1 = value;
761
+ break;
762
+ case A_APB1RSTR2:
763
+ s->apb1rstr2 = value;
764
+ break;
765
+ case A_APB2RSTR:
766
+ s->apb2rstr = value;
767
+ break;
768
+ case A_AHB1ENR:
769
+ s->ahb1enr = value;
770
+ break;
771
+ case A_AHB2ENR:
772
+ s->ahb2enr = value;
773
+ break;
774
+ case A_AHB3ENR:
775
+ s->ahb3enr = value;
776
+ break;
777
+ case A_APB1ENR1:
778
+ s->apb1enr1 = value;
779
+ break;
780
+ case A_APB1ENR2:
781
+ s->apb1enr2 = value;
782
+ break;
783
+ case A_APB2ENR:
784
+ s->apb2enr = (s->apb2enr & APB2ENR_READ_SET_MASK) | value;
785
+ break;
786
+ /* Behaviors for Sleep and Stop modes are not implemented */
787
+ case A_AHB1SMENR:
788
+ s->ahb1smenr = value;
789
+ break;
790
+ case A_AHB2SMENR:
791
+ s->ahb2smenr = value;
792
+ break;
793
+ case A_AHB3SMENR:
794
+ s->ahb3smenr = value;
795
+ break;
796
+ case A_APB1SMENR1:
797
+ s->apb1smenr1 = value;
798
+ break;
799
+ case A_APB1SMENR2:
800
+ s->apb1smenr2 = value;
801
+ break;
802
+ case A_APB2SMENR:
803
+ s->apb2smenr = value;
804
+ break;
805
+ case A_CCIPR:
806
+ s->ccipr = value;
807
+ break;
808
+ case A_BDCR:
809
+ s->bdcr = value & ~BDCR_READ_ONLY_MASK;
810
+ break;
811
+ case A_CSR:
812
+ s->csr = value & ~CSR_READ_ONLY_MASK;
813
+ break;
814
+ default:
815
+ qemu_log_mask(LOG_GUEST_ERROR,
816
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
817
+ }
818
+}
819
+
820
+static const MemoryRegionOps stm32l4x5_rcc_ops = {
821
+ .read = stm32l4x5_rcc_read,
822
+ .write = stm32l4x5_rcc_write,
823
+ .endianness = DEVICE_NATIVE_ENDIAN,
824
+ .valid = {
825
+ .max_access_size = 4,
826
+ .min_access_size = 4,
827
+ .unaligned = false
828
+ },
829
+ .impl = {
830
+ .max_access_size = 4,
831
+ .min_access_size = 4,
832
+ .unaligned = false
833
+ },
834
+};
835
+
836
+static const ClockPortInitArray stm32l4x5_rcc_clocks = {
837
+ QDEV_CLOCK_IN(Stm32l4x5RccState, hsi16_rc, NULL, 0),
838
+ QDEV_CLOCK_IN(Stm32l4x5RccState, msi_rc, NULL, 0),
839
+ QDEV_CLOCK_IN(Stm32l4x5RccState, hse, NULL, 0),
840
+ QDEV_CLOCK_IN(Stm32l4x5RccState, lsi_rc, NULL, 0),
841
+ QDEV_CLOCK_IN(Stm32l4x5RccState, lse_crystal, NULL, 0),
842
+ QDEV_CLOCK_IN(Stm32l4x5RccState, sai1_extclk, NULL, 0),
843
+ QDEV_CLOCK_IN(Stm32l4x5RccState, sai2_extclk, NULL, 0),
844
+ QDEV_CLOCK_END
845
+};
846
+
847
+
848
+static void stm32l4x5_rcc_init(Object *obj)
849
+{
850
+ Stm32l4x5RccState *s = STM32L4X5_RCC(obj);
851
+
852
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
853
+
854
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_rcc_ops, s,
855
+ TYPE_STM32L4X5_RCC, 0x400);
856
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
857
+
858
+ qdev_init_clocks(DEVICE(s), stm32l4x5_rcc_clocks);
859
+
860
+ s->gnd = clock_new(obj, "gnd");
861
+}
862
+
863
+static const VMStateDescription vmstate_stm32l4x5_rcc = {
864
+ .name = TYPE_STM32L4X5_RCC,
865
+ .version_id = 1,
866
+ .minimum_version_id = 1,
867
+ .fields = (VMStateField[]) {
868
+ VMSTATE_UINT32(cr, Stm32l4x5RccState),
869
+ VMSTATE_UINT32(icscr, Stm32l4x5RccState),
870
+ VMSTATE_UINT32(cfgr, Stm32l4x5RccState),
871
+ VMSTATE_UINT32(pllcfgr, Stm32l4x5RccState),
872
+ VMSTATE_UINT32(pllsai1cfgr, Stm32l4x5RccState),
873
+ VMSTATE_UINT32(pllsai2cfgr, Stm32l4x5RccState),
874
+ VMSTATE_UINT32(cier, Stm32l4x5RccState),
875
+ VMSTATE_UINT32(cifr, Stm32l4x5RccState),
876
+ VMSTATE_UINT32(ahb1rstr, Stm32l4x5RccState),
877
+ VMSTATE_UINT32(ahb2rstr, Stm32l4x5RccState),
878
+ VMSTATE_UINT32(ahb3rstr, Stm32l4x5RccState),
879
+ VMSTATE_UINT32(apb1rstr1, Stm32l4x5RccState),
880
+ VMSTATE_UINT32(apb1rstr2, Stm32l4x5RccState),
881
+ VMSTATE_UINT32(apb2rstr, Stm32l4x5RccState),
882
+ VMSTATE_UINT32(ahb1enr, Stm32l4x5RccState),
883
+ VMSTATE_UINT32(ahb2enr, Stm32l4x5RccState),
884
+ VMSTATE_UINT32(ahb3enr, Stm32l4x5RccState),
885
+ VMSTATE_UINT32(apb1enr1, Stm32l4x5RccState),
886
+ VMSTATE_UINT32(apb1enr2, Stm32l4x5RccState),
887
+ VMSTATE_UINT32(apb2enr, Stm32l4x5RccState),
888
+ VMSTATE_UINT32(ahb1smenr, Stm32l4x5RccState),
889
+ VMSTATE_UINT32(ahb2smenr, Stm32l4x5RccState),
890
+ VMSTATE_UINT32(ahb3smenr, Stm32l4x5RccState),
891
+ VMSTATE_UINT32(apb1smenr1, Stm32l4x5RccState),
892
+ VMSTATE_UINT32(apb1smenr2, Stm32l4x5RccState),
893
+ VMSTATE_UINT32(apb2smenr, Stm32l4x5RccState),
894
+ VMSTATE_UINT32(ccipr, Stm32l4x5RccState),
895
+ VMSTATE_UINT32(bdcr, Stm32l4x5RccState),
896
+ VMSTATE_UINT32(csr, Stm32l4x5RccState),
897
+ VMSTATE_CLOCK(hsi16_rc, Stm32l4x5RccState),
898
+ VMSTATE_CLOCK(msi_rc, Stm32l4x5RccState),
899
+ VMSTATE_CLOCK(hse, Stm32l4x5RccState),
900
+ VMSTATE_CLOCK(lsi_rc, Stm32l4x5RccState),
901
+ VMSTATE_CLOCK(lse_crystal, Stm32l4x5RccState),
902
+ VMSTATE_CLOCK(sai1_extclk, Stm32l4x5RccState),
903
+ VMSTATE_CLOCK(sai2_extclk, Stm32l4x5RccState),
904
+ VMSTATE_END_OF_LIST()
905
+ }
906
+};
907
+
908
+
909
+static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp)
910
+{
911
+ Stm32l4x5RccState *s = STM32L4X5_RCC(dev);
912
+
913
+ if (s->hse_frequency < 4000000ULL ||
914
+ s->hse_frequency > 48000000ULL) {
915
+ error_setg(errp,
916
+ "HSE frequency is outside of the allowed [4-48]Mhz range: %" PRIx64 "",
917
+ s->hse_frequency);
918
+ return;
919
+ }
920
+
921
+ clock_update_hz(s->msi_rc, MSI_DEFAULT_FRQ);
922
+ clock_update_hz(s->sai1_extclk, s->sai1_extclk_frequency);
923
+ clock_update_hz(s->sai2_extclk, s->sai2_extclk_frequency);
924
+ clock_update(s->gnd, 0);
925
+}
926
+
927
+static Property stm32l4x5_rcc_properties[] = {
928
+ DEFINE_PROP_UINT64("hse_frequency", Stm32l4x5RccState,
929
+ hse_frequency, HSE_DEFAULT_FRQ),
930
+ DEFINE_PROP_UINT64("sai1_extclk_frequency", Stm32l4x5RccState,
931
+ sai1_extclk_frequency, 0),
932
+ DEFINE_PROP_UINT64("sai2_extclk_frequency", Stm32l4x5RccState,
933
+ sai2_extclk_frequency, 0),
934
+ DEFINE_PROP_END_OF_LIST(),
935
+};
936
+
937
+static void stm32l4x5_rcc_class_init(ObjectClass *klass, void *data)
938
+{
939
+ DeviceClass *dc = DEVICE_CLASS(klass);
940
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
941
+
942
+
943
+ rc->phases.hold = stm32l4x5_rcc_reset_hold;
944
+ device_class_set_props(dc, stm32l4x5_rcc_properties);
945
+ dc->realize = stm32l4x5_rcc_realize;
946
+ dc->vmsd = &vmstate_stm32l4x5_rcc;
947
+}
948
+
949
+static const TypeInfo stm32l4x5_rcc_types[] = {
950
+ {
951
+ .name = TYPE_STM32L4X5_RCC,
952
+ .parent = TYPE_SYS_BUS_DEVICE,
953
+ .instance_size = sizeof(Stm32l4x5RccState),
954
+ .instance_init = stm32l4x5_rcc_init,
955
+ .class_init = stm32l4x5_rcc_class_init,
956
+ }
957
+};
958
+
959
+DEFINE_TYPES(stm32l4x5_rcc_types)
960
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
961
index XXXXXXX..XXXXXXX 100644
962
--- a/hw/arm/Kconfig
963
+++ b/hw/arm/Kconfig
964
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
965
select OR_IRQ
966
select STM32L4X5_SYSCFG
967
select STM32L4X5_EXTI
968
+ select STM32L4X5_RCC
969
970
config XLNX_ZYNQMP_ARM
971
bool
972
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
973
index XXXXXXX..XXXXXXX 100644
974
--- a/hw/misc/Kconfig
975
+++ b/hw/misc/Kconfig
976
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_EXTI
977
config STM32L4X5_SYSCFG
978
bool
979
980
+config STM32L4X5_RCC
981
+ bool
982
+
983
config MIPS_ITU
984
bool
985
986
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
987
index XXXXXXX..XXXXXXX 100644
988
--- a/hw/misc/meson.build
989
+++ b/hw/misc/meson.build
990
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.
991
system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c'))
992
system_ss.add(when: 'CONFIG_STM32L4X5_EXTI', if_true: files('stm32l4x5_exti.c'))
993
system_ss.add(when: 'CONFIG_STM32L4X5_SYSCFG', if_true: files('stm32l4x5_syscfg.c'))
994
+system_ss.add(when: 'CONFIG_STM32L4X5_RCC', if_true: files('stm32l4x5_rcc.c'))
995
system_ss.add(when: 'CONFIG_MPS2_FPGAIO', if_true: files('mps2-fpgaio.c'))
996
system_ss.add(when: 'CONFIG_MPS2_SCC', if_true: files('mps2-scc.c'))
997
998
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
999
index XXXXXXX..XXXXXXX 100644
1000
--- a/hw/misc/trace-events
1001
+++ b/hw/misc/trace-events
1002
@@ -XXX,XX +XXX,XX @@ stm32l4x5_exti_set_irq(int irq, int level) "Set EXTI: %d to %d"
1003
stm32l4x5_exti_read(uint64_t addr, uint64_t data) "reg read: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
1004
stm32l4x5_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
1005
1006
+# stm32l4x5_rcc.c
1007
+stm32l4x5_rcc_read(uint64_t addr, uint32_t data) "RCC: Read <0x%" PRIx64 "> -> 0x%" PRIx32
1008
+stm32l4x5_rcc_write(uint64_t addr, uint32_t data) "RCC: Write <0x%" PRIx64 "> <- 0x%" PRIx32
1009
+
1010
# tz-mpc.c
1011
tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u"
1012
tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs write: offset 0x%x data 0x%" PRIx64 " size %u"
1013
--
47
--
1014
2.34.1
48
2.34.1
1015
49
1016
50
diff view generated by jsdifflib
1
From: Rayhan Faizel <rayhan.faizel@gmail.com>
1
From: Vikram Garhwal <vikram.garhwal@bytedance.com>
2
2
3
Simple testcase for validating proper operation of read and write for all
3
Previously, maintainer role was paused due to inactive email id. Commit id:
4
three BSC controllers.
4
c009d715721861984c4987bcc78b7ee183e86d75.
5
5
6
Signed-off-by: Rayhan Faizel <rayhan.faizel@gmail.com>
6
Signed-off-by: Vikram Garhwal <vikram.garhwal@bytedance.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20240224191038.2409945-4-rayhan.faizel@gmail.com
8
Message-id: 20241204184205.12952-1-vikram.garhwal@bytedance.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
tests/qtest/bcm2835-i2c-test.c | 115 +++++++++++++++++++++++++++++++++
11
MAINTAINERS | 2 ++
12
tests/qtest/meson.build | 2 +-
12
1 file changed, 2 insertions(+)
13
2 files changed, 116 insertions(+), 1 deletion(-)
14
create mode 100644 tests/qtest/bcm2835-i2c-test.c
15
13
16
diff --git a/tests/qtest/bcm2835-i2c-test.c b/tests/qtest/bcm2835-i2c-test.c
14
diff --git a/MAINTAINERS b/MAINTAINERS
17
new file mode 100644
18
index XXXXXXX..XXXXXXX
19
--- /dev/null
20
+++ b/tests/qtest/bcm2835-i2c-test.c
21
@@ -XXX,XX +XXX,XX @@
22
+/*
23
+ * QTest testcase for Broadcom Serial Controller (BSC)
24
+ *
25
+ * Copyright (c) 2024 Rayhan Faizel <rayhan.faizel@gmail.com>
26
+ *
27
+ * SPDX-License-Identifier: MIT
28
+ *
29
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ * of this software and associated documentation files (the "Software"), to deal
31
+ * in the Software without restriction, including without limitation the rights
32
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
+ * copies of the Software, and to permit persons to whom the Software is
34
+ * furnished to do so, subject to the following conditions:
35
+ *
36
+ * The above copyright notice and this permission notice shall be included in
37
+ * all copies or substantial portions of the Software.
38
+ *
39
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
42
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
+ * THE SOFTWARE.
46
+ */
47
+
48
+#include "qemu/osdep.h"
49
+#include "libqtest-single.h"
50
+
51
+#include "hw/i2c/bcm2835_i2c.h"
52
+#include "hw/sensor/tmp105_regs.h"
53
+
54
+static const uint32_t bsc_base_addrs[] = {
55
+ 0x3f205000, /* I2C0 */
56
+ 0x3f804000, /* I2C1 */
57
+ 0x3f805000, /* I2C2 */
58
+};
59
+
60
+static void bcm2835_i2c_init_transfer(uint32_t base_addr, bool read)
61
+{
62
+ /* read flag is bit 0 so we can write it directly */
63
+ int interrupt = read ? BCM2835_I2C_C_INTR : BCM2835_I2C_C_INTT;
64
+
65
+ writel(base_addr + BCM2835_I2C_C,
66
+ BCM2835_I2C_C_I2CEN | BCM2835_I2C_C_INTD |
67
+ BCM2835_I2C_C_ST | BCM2835_I2C_C_CLEAR | interrupt | read);
68
+}
69
+
70
+static void test_i2c_read_write(gconstpointer data)
71
+{
72
+ uint32_t i2cdata;
73
+ intptr_t index = (intptr_t) data;
74
+ uint32_t base_addr = bsc_base_addrs[index];
75
+
76
+ /* Write to TMP105 register */
77
+ writel(base_addr + BCM2835_I2C_A, 0x50);
78
+ writel(base_addr + BCM2835_I2C_DLEN, 3);
79
+
80
+ bcm2835_i2c_init_transfer(base_addr, 0);
81
+
82
+ writel(base_addr + BCM2835_I2C_FIFO, TMP105_REG_T_HIGH);
83
+ writel(base_addr + BCM2835_I2C_FIFO, 0xde);
84
+ writel(base_addr + BCM2835_I2C_FIFO, 0xad);
85
+
86
+ /* Clear flags */
87
+ writel(base_addr + BCM2835_I2C_S, BCM2835_I2C_S_DONE | BCM2835_I2C_S_ERR |
88
+ BCM2835_I2C_S_CLKT);
89
+
90
+ /* Read from TMP105 register */
91
+ writel(base_addr + BCM2835_I2C_A, 0x50);
92
+ writel(base_addr + BCM2835_I2C_DLEN, 1);
93
+
94
+ bcm2835_i2c_init_transfer(base_addr, 0);
95
+
96
+ writel(base_addr + BCM2835_I2C_FIFO, TMP105_REG_T_HIGH);
97
+
98
+ writel(base_addr + BCM2835_I2C_DLEN, 2);
99
+ bcm2835_i2c_init_transfer(base_addr, 1);
100
+
101
+ i2cdata = readl(base_addr + BCM2835_I2C_FIFO);
102
+ g_assert_cmpint(i2cdata, ==, 0xde);
103
+
104
+ i2cdata = readl(base_addr + BCM2835_I2C_FIFO);
105
+ g_assert_cmpint(i2cdata, ==, 0xad);
106
+
107
+ /* Clear flags */
108
+ writel(base_addr + BCM2835_I2C_S, BCM2835_I2C_S_DONE | BCM2835_I2C_S_ERR |
109
+ BCM2835_I2C_S_CLKT);
110
+
111
+}
112
+
113
+int main(int argc, char **argv)
114
+{
115
+ int ret;
116
+ int i;
117
+
118
+ g_test_init(&argc, &argv, NULL);
119
+
120
+ for (i = 0; i < 3; i++) {
121
+ g_autofree char *test_name =
122
+ g_strdup_printf("/bcm2835/bcm2835-i2c%d/read_write", i);
123
+ qtest_add_data_func(test_name, (void *)(intptr_t) i,
124
+ test_i2c_read_write);
125
+ }
126
+
127
+ /* Run I2C tests with TMP105 slaves on all three buses */
128
+ qtest_start("-M raspi3b "
129
+ "-device tmp105,address=0x50,bus=i2c-bus.0 "
130
+ "-device tmp105,address=0x50,bus=i2c-bus.1 "
131
+ "-device tmp105,address=0x50,bus=i2c-bus.2");
132
+ ret = g_test_run();
133
+ qtest_end();
134
+
135
+ return ret;
136
+}
137
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
138
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
139
--- a/tests/qtest/meson.build
16
--- a/MAINTAINERS
140
+++ b/tests/qtest/meson.build
17
+++ b/MAINTAINERS
141
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
18
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-sb16-test.c
142
['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) + \
19
143
(config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \
20
Xilinx CAN
144
(config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test', 'xlnx-versal-trng-test'] : []) + \
21
M: Francisco Iglesias <francisco.iglesias@amd.com>
145
- (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + \
22
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
146
+ (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test', 'bcm2835-i2c-test'] : []) + \
23
S: Maintained
147
(config_all_accel.has_key('CONFIG_TCG') and \
24
F: hw/net/can/xlnx-*
148
config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
25
F: include/hw/net/xlnx-*
149
['arm-cpu-features',
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/*
150
--
34
--
151
2.34.1
35
2.34.1
diff view generated by jsdifflib