1
Another lump of target-arm patches. I still have some patches in
1
First arm pullreq of the cycle; this is mostly my softfloat NaN
2
my to-review queue, but this is a big enough set that I wanted
2
handling series. (Lots more in my to-review queue, but I don't
3
to send it out.
3
like pullreqs growing too close to a hundred patches at a time :-))
4
4
5
thanks
5
thanks
6
-- PMM
6
-- PMM
7
7
8
The following changes since commit 04bb7fe2bf55bdf66d5b7a5a719b40bbb4048178:
8
The following changes since commit 97f2796a3736ed37a1b85dc1c76a6c45b829dd17:
9
9
10
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20180208' into staging (2018-02-08 17:41:15 +0000)
10
Open 10.0 development tree (2024-12-10 17:41:17 +0000)
11
11
12
are available in the Git repository at:
12
are available in the Git repository at:
13
13
14
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180209
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20241211
15
15
16
for you to fetch changes up to bbba7757bacc9f890a3f028d328b4b429dbe78ec:
16
for you to fetch changes up to 1abe28d519239eea5cf9620bb13149423e5665f8:
17
17
18
hw/core/generic-loader: Allow PC to be set on command line (2018-02-09 10:55:40 +0000)
18
MAINTAINERS: Add correct email address for Vikram Garhwal (2024-12-11 15:31:09 +0000)
19
19
20
----------------------------------------------------------------
20
----------------------------------------------------------------
21
target-arm queue:
21
target-arm queue:
22
* Support M profile derived exceptions on exception entry and exit
22
* hw/net/lan9118: Extract PHY model, reuse with imx_fec, fix bugs
23
* Implement AArch64 v8.2 crypto insns (SHA-512, SHA-3, SM3, SM4)
23
* fpu: Make muladd NaN handling runtime-selected, not compile-time
24
* Implement working i.MX6 SD controller
24
* fpu: Make default NaN pattern runtime-selected, not compile-time
25
* Various devices preparatory to i.MX7 support
25
* fpu: Minor NaN-related cleanups
26
* Preparatory patches for SVE emulation
26
* MAINTAINERS: email address updates
27
* v8M: Fix bug in implementation of 'TT' insn
28
* Give useful error if user tries to use userspace GICv3 with KVM
29
27
30
----------------------------------------------------------------
28
----------------------------------------------------------------
31
Andrey Smirnov (10):
29
Bernhard Beschow (5):
32
sdhci: Add i.MX specific subtype of SDHCI
30
hw/net/lan9118: Extract lan9118_phy
33
hw: i.MX: Convert i.MX6 to use TYPE_IMX_USDHC
31
hw/net/lan9118_phy: Reuse in imx_fec and consolidate implementations
34
i.MX: Add code to emulate i.MX7 CCM, PMU and ANALOG IP blocks
32
hw/net/lan9118_phy: Fix off-by-one error in MII_ANLPAR register
35
i.MX: Add code to emulate i.MX2 watchdog IP block
33
hw/net/lan9118_phy: Reuse MII constants
36
i.MX: Add code to emulate i.MX7 SNVS IP-block
34
hw/net/lan9118_phy: Add missing 100 mbps full duplex advertisement
37
i.MX: Add code to emulate GPCv2 IP block
38
i.MX: Add i.MX7 GPT variant
39
i.MX: Add implementation of i.MX7 GPR IP block
40
usb: Add basic code to emulate Chipidea USB IP
41
hw/arm: Move virt's PSCI DT fixup code to arm/boot.c
42
35
43
Ard Biesheuvel (5):
36
Leif Lindholm (1):
44
target/arm: implement SHA-512 instructions
37
MAINTAINERS: update email address for Leif Lindholm
45
target/arm: implement SHA-3 instructions
46
target/arm: implement SM3 instructions
47
target/arm: implement SM4 instructions
48
target/arm: enable user-mode SHA-3, SM3, SM4 and SHA-512 instruction support
49
38
50
Christoffer Dall (1):
39
Peter Maydell (54):
51
target/arm/kvm: gic: Prevent creating userspace GICv3 with KVM
40
fpu: handle raising Invalid for infzero in pick_nan_muladd
41
fpu: Check for default_nan_mode before calling pickNaNMulAdd
42
softfloat: Allow runtime choice of inf * 0 + NaN result
43
tests/fp: Explicitly set inf-zero-nan rule
44
target/arm: Set FloatInfZeroNaNRule explicitly
45
target/s390: Set FloatInfZeroNaNRule explicitly
46
target/ppc: Set FloatInfZeroNaNRule explicitly
47
target/mips: Set FloatInfZeroNaNRule explicitly
48
target/sparc: Set FloatInfZeroNaNRule explicitly
49
target/xtensa: Set FloatInfZeroNaNRule explicitly
50
target/x86: Set FloatInfZeroNaNRule explicitly
51
target/loongarch: Set FloatInfZeroNaNRule explicitly
52
target/hppa: Set FloatInfZeroNaNRule explicitly
53
softfloat: Pass have_snan to pickNaNMulAdd
54
softfloat: Allow runtime choice of NaN propagation for muladd
55
tests/fp: Explicitly set 3-NaN propagation rule
56
target/arm: Set Float3NaNPropRule explicitly
57
target/loongarch: Set Float3NaNPropRule explicitly
58
target/ppc: Set Float3NaNPropRule explicitly
59
target/s390x: Set Float3NaNPropRule explicitly
60
target/sparc: Set Float3NaNPropRule explicitly
61
target/mips: Set Float3NaNPropRule explicitly
62
target/xtensa: Set Float3NaNPropRule explicitly
63
target/i386: Set Float3NaNPropRule explicitly
64
target/hppa: Set Float3NaNPropRule explicitly
65
fpu: Remove use_first_nan field from float_status
66
target/m68k: Don't pass NULL float_status to floatx80_default_nan()
67
softfloat: Create floatx80 default NaN from parts64_default_nan
68
target/loongarch: Use normal float_status in fclass_s and fclass_d helpers
69
target/m68k: In frem helper, initialize local float_status from env->fp_status
70
target/m68k: Init local float_status from env fp_status in gdb get/set reg
71
target/sparc: Initialize local scratch float_status from env->fp_status
72
target/ppc: Use env->fp_status in helper_compute_fprf functions
73
fpu: Allow runtime choice of default NaN value
74
tests/fp: Set default NaN pattern explicitly
75
target/microblaze: Set default NaN pattern explicitly
76
target/i386: Set default NaN pattern explicitly
77
target/hppa: Set default NaN pattern explicitly
78
target/alpha: Set default NaN pattern explicitly
79
target/arm: Set default NaN pattern explicitly
80
target/loongarch: Set default NaN pattern explicitly
81
target/m68k: Set default NaN pattern explicitly
82
target/mips: Set default NaN pattern explicitly
83
target/openrisc: Set default NaN pattern explicitly
84
target/ppc: Set default NaN pattern explicitly
85
target/sh4: Set default NaN pattern explicitly
86
target/rx: Set default NaN pattern explicitly
87
target/s390x: Set default NaN pattern explicitly
88
target/sparc: Set default NaN pattern explicitly
89
target/xtensa: Set default NaN pattern explicitly
90
target/hexagon: Set default NaN pattern explicitly
91
target/riscv: Set default NaN pattern explicitly
92
target/tricore: Set default NaN pattern explicitly
93
fpu: Remove default handling for dnan_pattern
52
94
53
Peter Maydell (9):
95
Richard Henderson (11):
54
target/arm: Add armv7m_nvic_set_pending_derived()
96
target/arm: Copy entire float_status in is_ebf
55
target/arm: Split "get pending exception info" from "acknowledge it"
97
softfloat: Inline pickNaNMulAdd
56
target/arm: Add ignore_stackfaults argument to v7m_exception_taken()
98
softfloat: Use goto for default nan case in pick_nan_muladd
57
target/arm: Make v7M exception entry stack push check MPU
99
softfloat: Remove which from parts_pick_nan_muladd
58
target/arm: Make v7m_push_callee_stack() honour MPU
100
softfloat: Pad array size in pick_nan_muladd
59
target/arm: Make exception vector loads honour the SAU
101
softfloat: Move propagateFloatx80NaN to softfloat.c
60
target/arm: Handle exceptions during exception stack pop
102
softfloat: Use parts_pick_nan in propagateFloatx80NaN
61
target/arm/translate.c: Fix missing 'break' for TT insns
103
softfloat: Inline pickNaN
62
hw/core/generic-loader: Allow PC to be set on command line
104
softfloat: Share code between parts_pick_nan cases
105
softfloat: Sink frac_cmp in parts_pick_nan until needed
106
softfloat: Replace WHICH with RET in parts_pick_nan
63
107
64
Richard Henderson (5):
108
Vikram Garhwal (1):
65
target/arm: Expand vector registers for SVE
109
MAINTAINERS: Add correct email address for Vikram Garhwal
66
target/arm: Add predicate registers for SVE
67
target/arm: Add SVE to migration state
68
target/arm: Add ZCR_ELx
69
target/arm: Add SVE state to TB->FLAGS
70
110
71
hw/intc/Makefile.objs | 2 +-
111
MAINTAINERS | 4 +-
72
hw/misc/Makefile.objs | 4 +
112
include/fpu/softfloat-helpers.h | 38 +++-
73
hw/usb/Makefile.objs | 1 +
113
include/fpu/softfloat-types.h | 89 +++++++-
74
hw/sd/sdhci-internal.h | 23 ++
114
include/hw/net/imx_fec.h | 9 +-
75
include/hw/intc/imx_gpcv2.h | 22 ++
115
include/hw/net/lan9118_phy.h | 37 ++++
76
include/hw/misc/imx2_wdt.h | 33 +++
116
include/hw/net/mii.h | 6 +
77
include/hw/misc/imx7_ccm.h | 139 +++++++++++
117
target/mips/fpu_helper.h | 20 ++
78
include/hw/misc/imx7_gpr.h | 28 +++
118
target/sparc/helper.h | 4 +-
79
include/hw/misc/imx7_snvs.h | 35 +++
119
fpu/softfloat.c | 19 ++
80
include/hw/sd/sdhci.h | 13 ++
120
hw/net/imx_fec.c | 146 ++------------
81
include/hw/timer/imx_gpt.h | 1 +
121
hw/net/lan9118.c | 137 ++-----------
82
include/hw/usb/chipidea.h | 16 ++
122
hw/net/lan9118_phy.c | 222 ++++++++++++++++++++
83
target/arm/cpu.h | 120 ++++++++--
123
linux-user/arm/nwfpe/fpa11.c | 5 +
84
target/arm/helper.h | 12 +
124
target/alpha/cpu.c | 2 +
85
target/arm/kvm_arm.h | 4 +
125
target/arm/cpu.c | 10 +
86
target/arm/translate.h | 2 +
126
target/arm/tcg/vec_helper.c | 20 +-
87
hw/arm/boot.c | 65 ++++++
127
target/hexagon/cpu.c | 2 +
88
hw/arm/fsl-imx6.c | 2 +-
128
target/hppa/fpu_helper.c | 12 ++
89
hw/arm/virt.c | 61 -----
129
target/i386/tcg/fpu_helper.c | 12 ++
90
hw/core/generic-loader.c | 2 +-
130
target/loongarch/tcg/fpu_helper.c | 14 +-
91
hw/intc/armv7m_nvic.c | 98 +++++++-
131
target/m68k/cpu.c | 14 +-
92
hw/intc/imx_gpcv2.c | 125 ++++++++++
132
target/m68k/fpu_helper.c | 6 +-
93
hw/misc/imx2_wdt.c | 89 +++++++
133
target/m68k/helper.c | 6 +-
94
hw/misc/imx7_ccm.c | 277 ++++++++++++++++++++++
134
target/microblaze/cpu.c | 2 +
95
hw/misc/imx7_gpr.c | 124 ++++++++++
135
target/mips/msa.c | 10 +
96
hw/misc/imx7_snvs.c | 83 +++++++
136
target/openrisc/cpu.c | 2 +
97
hw/sd/sdhci.c | 230 ++++++++++++++++++-
137
target/ppc/cpu_init.c | 19 ++
98
hw/timer/imx_gpt.c | 25 ++
138
target/ppc/fpu_helper.c | 3 +-
99
hw/usb/chipidea.c | 176 ++++++++++++++
139
target/riscv/cpu.c | 2 +
100
linux-user/elfload.c | 19 ++
140
target/rx/cpu.c | 2 +
101
target/arm/cpu64.c | 4 +
141
target/s390x/cpu.c | 5 +
102
target/arm/crypto_helper.c | 277 +++++++++++++++++++++-
142
target/sh4/cpu.c | 2 +
103
target/arm/helper.c | 548 +++++++++++++++++++++++++++++++++++++-------
143
target/sparc/cpu.c | 6 +
104
target/arm/machine.c | 88 ++++++-
144
target/sparc/fop_helper.c | 8 +-
105
target/arm/translate-a64.c | 350 +++++++++++++++++++++++++++-
145
target/sparc/translate.c | 4 +-
106
target/arm/translate.c | 8 +-
146
target/tricore/helper.c | 2 +
107
hw/intc/trace-events | 5 +-
147
target/xtensa/cpu.c | 4 +
108
hw/misc/trace-events | 4 +
148
target/xtensa/fpu_helper.c | 3 +-
109
38 files changed, 2928 insertions(+), 187 deletions(-)
149
tests/fp/fp-bench.c | 7 +
110
create mode 100644 include/hw/intc/imx_gpcv2.h
150
tests/fp/fp-test-log2.c | 1 +
111
create mode 100644 include/hw/misc/imx2_wdt.h
151
tests/fp/fp-test.c | 7 +
112
create mode 100644 include/hw/misc/imx7_ccm.h
152
fpu/softfloat-parts.c.inc | 152 +++++++++++---
113
create mode 100644 include/hw/misc/imx7_gpr.h
153
fpu/softfloat-specialize.c.inc | 412 ++------------------------------------
114
create mode 100644 include/hw/misc/imx7_snvs.h
154
.mailmap | 5 +-
115
create mode 100644 include/hw/usb/chipidea.h
155
hw/net/Kconfig | 5 +
116
create mode 100644 hw/intc/imx_gpcv2.c
156
hw/net/meson.build | 1 +
117
create mode 100644 hw/misc/imx2_wdt.c
157
hw/net/trace-events | 10 +-
118
create mode 100644 hw/misc/imx7_ccm.c
158
47 files changed, 778 insertions(+), 730 deletions(-)
119
create mode 100644 hw/misc/imx7_gpr.c
159
create mode 100644 include/hw/net/lan9118_phy.h
120
create mode 100644 hw/misc/imx7_snvs.c
160
create mode 100644 hw/net/lan9118_phy.c
121
create mode 100644 hw/usb/chipidea.c
122
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Add code to emulate SNVS IP-block. Currently only the bits needed to
3
A very similar implementation of the same device exists in imx_fec. Prepare for
4
be able to emulate machine shutdown are implemented.
4
a common implementation by extracting a device model into its own files.
5
5
6
Cc: Peter Maydell <peter.maydell@linaro.org>
6
Some migration state has been moved into the new device model which breaks
7
Cc: Jason Wang <jasowang@redhat.com>
7
migration compatibility for the following machines:
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
* smdkc210
9
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
9
* realview-*
10
Cc: Michael S. Tsirkin <mst@redhat.com>
10
* vexpress-*
11
Cc: qemu-devel@nongnu.org
11
* kzm
12
Cc: qemu-arm@nongnu.org
12
* mps2-*
13
Cc: yurovsky@gmail.com
13
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>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
20
Message-id: 20241102125724.532843-2-shentey@gmail.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
22
---
18
hw/misc/Makefile.objs | 1 +
23
include/hw/net/lan9118_phy.h | 37 ++++++++
19
include/hw/misc/imx7_snvs.h | 35 +++++++++++++++++++
24
hw/net/lan9118.c | 137 +++++-----------------------
20
hw/misc/imx7_snvs.c | 83 +++++++++++++++++++++++++++++++++++++++++++++
25
hw/net/lan9118_phy.c | 169 +++++++++++++++++++++++++++++++++++
21
3 files changed, 119 insertions(+)
26
hw/net/Kconfig | 4 +
22
create mode 100644 include/hw/misc/imx7_snvs.h
27
hw/net/meson.build | 1 +
23
create mode 100644 hw/misc/imx7_snvs.c
28
5 files changed, 233 insertions(+), 115 deletions(-)
29
create mode 100644 include/hw/net/lan9118_phy.h
30
create mode 100644 hw/net/lan9118_phy.c
24
31
25
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
32
diff --git a/include/hw/net/lan9118_phy.h b/include/hw/net/lan9118_phy.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/misc/Makefile.objs
28
+++ b/hw/misc/Makefile.objs
29
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IMX) += imx6_ccm.o
30
obj-$(CONFIG_IMX) += imx6_src.o
31
obj-$(CONFIG_IMX) += imx7_ccm.o
32
obj-$(CONFIG_IMX) += imx2_wdt.o
33
+obj-$(CONFIG_IMX) += imx7_snvs.o
34
obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
35
obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
36
obj-$(CONFIG_MAINSTONE) += mst_fpga.o
37
diff --git a/include/hw/misc/imx7_snvs.h b/include/hw/misc/imx7_snvs.h
38
new file mode 100644
33
new file mode 100644
39
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
40
--- /dev/null
35
--- /dev/null
41
+++ b/include/hw/misc/imx7_snvs.h
36
+++ b/include/hw/net/lan9118_phy.h
42
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
43
+/*
38
+/*
44
+ * Copyright (c) 2017, Impinj, Inc.
39
+ * SMSC LAN9118 PHY emulation
45
+ *
40
+ *
46
+ * i.MX7 SNVS block emulation code
41
+ * Copyright (c) 2009 CodeSourcery, LLC.
47
+ *
42
+ * Written by Paul Brook
48
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
49
+ *
43
+ *
50
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
51
+ * See the COPYING file in the top-level directory.
45
+ * See the COPYING file in the top-level directory.
52
+ */
46
+ */
53
+
47
+
54
+#ifndef IMX7_SNVS_H
48
+#ifndef HW_NET_LAN9118_PHY_H
55
+#define IMX7_SNVS_H
49
+#define HW_NET_LAN9118_PHY_H
56
+
50
+
57
+#include "qemu/bitops.h"
51
+#include "qom/object.h"
58
+#include "hw/sysbus.h"
52
+#include "hw/sysbus.h"
59
+
53
+
60
+
54
+#define TYPE_LAN9118_PHY "lan9118-phy"
61
+enum IMX7SNVSRegisters {
55
+OBJECT_DECLARE_SIMPLE_TYPE(Lan9118PhyState, LAN9118_PHY)
62
+ SNVS_LPCR = 0x38,
56
+
63
+ SNVS_LPCR_TOP = BIT(6),
57
+typedef struct Lan9118PhyState {
64
+ SNVS_LPCR_DP_EN = BIT(5)
65
+};
66
+
67
+#define TYPE_IMX7_SNVS "imx7.snvs"
68
+#define IMX7_SNVS(obj) OBJECT_CHECK(IMX7SNVSState, (obj), TYPE_IMX7_SNVS)
69
+
70
+typedef struct IMX7SNVSState {
71
+ /* <private> */
72
+ SysBusDevice parent_obj;
58
+ SysBusDevice parent_obj;
73
+
59
+
74
+ MemoryRegion mmio;
60
+ uint16_t status;
75
+} IMX7SNVSState;
61
+ uint16_t control;
76
+
62
+ uint16_t advertise;
77
+#endif /* IMX7_SNVS_H */
63
+ uint16_t ints;
78
diff --git a/hw/misc/imx7_snvs.c b/hw/misc/imx7_snvs.c
64
+ uint16_t int_mask;
65
+ qemu_irq irq;
66
+ bool link_down;
67
+} Lan9118PhyState;
68
+
69
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down);
70
+void lan9118_phy_reset(Lan9118PhyState *s);
71
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg);
72
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val);
73
+
74
+#endif
75
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
76
index XXXXXXX..XXXXXXX 100644
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
79
new file mode 100644
312
new file mode 100644
80
index XXXXXXX..XXXXXXX
313
index XXXXXXX..XXXXXXX
81
--- /dev/null
314
--- /dev/null
82
+++ b/hw/misc/imx7_snvs.c
315
+++ b/hw/net/lan9118_phy.c
83
@@ -XXX,XX +XXX,XX @@
316
@@ -XXX,XX +XXX,XX @@
84
+/*
317
+/*
85
+ * IMX7 Secure Non-Volatile Storage
318
+ * SMSC LAN9118 PHY emulation
86
+ *
319
+ *
87
+ * Copyright (c) 2018, Impinj, Inc.
320
+ * Copyright (c) 2009 CodeSourcery, LLC.
321
+ * Written by Paul Brook
88
+ *
322
+ *
89
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
323
+ * This code is licensed under the GNU GPL v2
90
+ *
324
+ *
91
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
325
+ * Contributions after 2012-01-13 are licensed under the terms of the
92
+ * See the COPYING file in the top-level directory.
326
+ * GNU GPL, version 2 or (at your option) any later version.
93
+ *
94
+ * Bare minimum emulation code needed to support being able to shut
95
+ * down linux guest gracefully.
96
+ */
327
+ */
97
+
328
+
98
+#include "qemu/osdep.h"
329
+#include "qemu/osdep.h"
99
+#include "hw/misc/imx7_snvs.h"
330
+#include "hw/net/lan9118_phy.h"
331
+#include "hw/irq.h"
332
+#include "hw/resettable.h"
333
+#include "migration/vmstate.h"
100
+#include "qemu/log.h"
334
+#include "qemu/log.h"
101
+#include "sysemu/sysemu.h"
335
+
102
+
336
+#define PHY_INT_ENERGYON (1 << 7)
103
+static uint64_t imx7_snvs_read(void *opaque, hwaddr offset, unsigned size)
337
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
104
+{
338
+#define PHY_INT_FAULT (1 << 5)
105
+ return 0;
339
+#define PHY_INT_DOWN (1 << 4)
106
+}
340
+#define PHY_INT_AUTONEG_LP (1 << 3)
107
+
341
+#define PHY_INT_PARFAULT (1 << 2)
108
+static void imx7_snvs_write(void *opaque, hwaddr offset,
342
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
109
+ uint64_t v, unsigned size)
343
+
110
+{
344
+static void lan9118_phy_update_irq(Lan9118PhyState *s)
111
+ const uint32_t value = v;
345
+{
112
+ const uint32_t mask = SNVS_LPCR_TOP | SNVS_LPCR_DP_EN;
346
+ qemu_set_irq(s->irq, !!(s->ints & s->int_mask));
113
+
347
+}
114
+ if (offset == SNVS_LPCR && ((value & mask) == mask)) {
348
+
115
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
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;
116
+ }
380
+ }
117
+}
381
+}
118
+
382
+
119
+static const struct MemoryRegionOps imx7_snvs_ops = {
383
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
120
+ .read = imx7_snvs_read,
384
+{
121
+ .write = imx7_snvs_write,
385
+ switch (reg) {
122
+ .endianness = DEVICE_NATIVE_ENDIAN,
386
+ case 0: /* Basic Control */
123
+ .impl = {
387
+ if (val & 0x8000) {
124
+ /*
388
+ lan9118_phy_reset(s);
125
+ * Our device would not work correctly if the guest was doing
389
+ break;
126
+ * unaligned access. This might not be a limitation on the real
390
+ }
127
+ * device but in practice there is no reason for a guest to access
391
+ s->control = val & 0x7980;
128
+ * this device unaligned.
392
+ /* Complete autonegotiation immediately. */
129
+ */
393
+ if (val & 0x1000) {
130
+ .min_access_size = 4,
394
+ s->status |= 0x0020;
131
+ .max_access_size = 4,
395
+ }
132
+ .unaligned = false,
396
+ break;
133
+ },
397
+ case 4: /* Auto-neg advertisement */
398
+ s->advertise = (val & 0x2d7f) | 0x80;
399
+ break;
400
+ /* TODO 17, 18, 27, 31 */
401
+ case 30: /* Interrupt mask */
402
+ s->int_mask = val & 0xff;
403
+ lan9118_phy_update_irq(s);
404
+ break;
405
+ default:
406
+ qemu_log_mask(LOG_GUEST_ERROR,
407
+ "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
408
+ }
409
+}
410
+
411
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
412
+{
413
+ s->link_down = link_down;
414
+
415
+ /* Autonegotiation status mirrors link status. */
416
+ if (link_down) {
417
+ s->status &= ~0x0024;
418
+ s->ints |= PHY_INT_DOWN;
419
+ } else {
420
+ s->status |= 0x0024;
421
+ s->ints |= PHY_INT_ENERGYON;
422
+ s->ints |= PHY_INT_AUTONEG_COMPLETE;
423
+ }
424
+ lan9118_phy_update_irq(s);
425
+}
426
+
427
+void lan9118_phy_reset(Lan9118PhyState *s)
428
+{
429
+ s->control = 0x3000;
430
+ s->status = 0x7809;
431
+ s->advertise = 0x01e1;
432
+ s->int_mask = 0;
433
+ s->ints = 0;
434
+ lan9118_phy_update_link(s, s->link_down);
435
+}
436
+
437
+static void lan9118_phy_reset_hold(Object *obj, ResetType type)
438
+{
439
+ Lan9118PhyState *s = LAN9118_PHY(obj);
440
+
441
+ lan9118_phy_reset(s);
442
+}
443
+
444
+static void lan9118_phy_init(Object *obj)
445
+{
446
+ Lan9118PhyState *s = LAN9118_PHY(obj);
447
+
448
+ qdev_init_gpio_out(DEVICE(s), &s->irq, 1);
449
+}
450
+
451
+static const VMStateDescription vmstate_lan9118_phy = {
452
+ .name = "lan9118-phy",
453
+ .version_id = 1,
454
+ .minimum_version_id = 1,
455
+ .fields = (const VMStateField[]) {
456
+ VMSTATE_UINT16(control, Lan9118PhyState),
457
+ VMSTATE_UINT16(status, Lan9118PhyState),
458
+ VMSTATE_UINT16(advertise, Lan9118PhyState),
459
+ VMSTATE_UINT16(ints, Lan9118PhyState),
460
+ VMSTATE_UINT16(int_mask, Lan9118PhyState),
461
+ VMSTATE_BOOL(link_down, Lan9118PhyState),
462
+ VMSTATE_END_OF_LIST()
463
+ }
134
+};
464
+};
135
+
465
+
136
+static void imx7_snvs_init(Object *obj)
466
+static void lan9118_phy_class_init(ObjectClass *klass, void *data)
137
+{
467
+{
138
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
468
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
139
+ IMX7SNVSState *s = IMX7_SNVS(obj);
140
+
141
+ memory_region_init_io(&s->mmio, obj, &imx7_snvs_ops, s,
142
+ TYPE_IMX7_SNVS, 0x1000);
143
+
144
+ sysbus_init_mmio(sd, &s->mmio);
145
+}
146
+
147
+static void imx7_snvs_class_init(ObjectClass *klass, void *data)
148
+{
149
+ DeviceClass *dc = DEVICE_CLASS(klass);
469
+ DeviceClass *dc = DEVICE_CLASS(klass);
150
+
470
+
151
+ dc->desc = "i.MX7 Secure Non-Volatile Storage Module";
471
+ rc->phases.hold = lan9118_phy_reset_hold;
152
+}
472
+ dc->vmsd = &vmstate_lan9118_phy;
153
+
473
+}
154
+static const TypeInfo imx7_snvs_info = {
474
+
155
+ .name = TYPE_IMX7_SNVS,
475
+static const TypeInfo types[] = {
156
+ .parent = TYPE_SYS_BUS_DEVICE,
476
+ {
157
+ .instance_size = sizeof(IMX7SNVSState),
477
+ .name = TYPE_LAN9118_PHY,
158
+ .instance_init = imx7_snvs_init,
478
+ .parent = TYPE_SYS_BUS_DEVICE,
159
+ .class_init = imx7_snvs_class_init,
479
+ .instance_size = sizeof(Lan9118PhyState),
480
+ .instance_init = lan9118_phy_init,
481
+ .class_init = lan9118_phy_class_init,
482
+ }
160
+};
483
+};
161
+
484
+
162
+static void imx7_snvs_register_type(void)
485
+DEFINE_TYPES(types)
163
+{
486
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
164
+ type_register_static(&imx7_snvs_info);
487
index XXXXXXX..XXXXXXX 100644
165
+}
488
--- a/hw/net/Kconfig
166
+type_init(imx7_snvs_register_type)
489
+++ b/hw/net/Kconfig
490
@@ -XXX,XX +XXX,XX @@ config VMXNET3_PCI
491
config SMC91C111
492
bool
493
494
+config LAN9118_PHY
495
+ bool
496
+
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
504
index XXXXXXX..XXXXXXX 100644
505
--- a/hw/net/meson.build
506
+++ b/hw/net/meson.build
507
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('vmxnet3.c'))
508
509
system_ss.add(when: 'CONFIG_SMC91C111', if_true: files('smc91c111.c'))
510
system_ss.add(when: 'CONFIG_LAN9118', if_true: files('lan9118.c'))
511
+system_ss.add(when: 'CONFIG_LAN9118_PHY', if_true: files('lan9118_phy.c'))
512
system_ss.add(when: 'CONFIG_NE2000_ISA', if_true: files('ne2000-isa.c'))
513
system_ss.add(when: 'CONFIG_OPENCORES_ETH', if_true: files('opencores_eth.c'))
514
system_ss.add(when: 'CONFIG_XGMAC', if_true: files('xgmac.c'))
167
--
515
--
168
2.16.1
516
2.34.1
169
170
diff view generated by jsdifflib
1
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
This implements emulation of the new SHA-512 instructions that have
3
imx_fec models the same PHY as lan9118_phy. The code is almost the same with
4
been added as an optional extensions to the ARMv8 Crypto Extensions
4
imx_fec having more logging and tracing. Merge these improvements into
5
in ARM v8.2.
5
lan9118_phy and reuse in imx_fec to fix the code duplication.
6
6
7
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
7
Some migration state how resides in the new device model which breaks migration
8
Message-id: 20180207111729.15737-2-ard.biesheuvel@linaro.org
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>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Message-id: 20241102125724.532843-3-shentey@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
19
---
12
target/arm/cpu.h | 1 +
20
include/hw/net/imx_fec.h | 9 ++-
13
target/arm/helper.h | 5 +++
21
hw/net/imx_fec.c | 146 ++++-----------------------------------
14
target/arm/crypto_helper.c | 90 ++++++++++++++++++++++++++++++++++++-
22
hw/net/lan9118_phy.c | 82 ++++++++++++++++------
15
target/arm/translate-a64.c | 110 +++++++++++++++++++++++++++++++++++++++++++++
23
hw/net/Kconfig | 1 +
16
4 files changed, 205 insertions(+), 1 deletion(-)
24
hw/net/trace-events | 10 +--
25
5 files changed, 85 insertions(+), 163 deletions(-)
17
26
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
19
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
29
--- a/include/hw/net/imx_fec.h
21
+++ b/target/arm/cpu.h
30
+++ b/include/hw/net/imx_fec.h
22
@@ -XXX,XX +XXX,XX @@ enum arm_features {
31
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC)
23
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
32
#define TYPE_IMX_ENET "imx.enet"
24
ARM_FEATURE_JAZELLE, /* has (trivial) Jazelle implementation */
33
25
ARM_FEATURE_SVE, /* has Scalable Vector Extension */
34
#include "hw/sysbus.h"
26
+ ARM_FEATURE_V8_SHA512, /* implements SHA512 part of v8 Crypto Extensions */
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
},
27
};
80
};
28
81
29
static inline int arm_feature(CPUARMState *env, int feature)
82
-#define PHY_INT_ENERGYON (1 << 7)
30
diff --git a/target/arm/helper.h b/target/arm/helper.h
83
-#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
31
index XXXXXXX..XXXXXXX 100644
84
-#define PHY_INT_FAULT (1 << 5)
32
--- a/target/arm/helper.h
85
-#define PHY_INT_DOWN (1 << 4)
33
+++ b/target/arm/helper.h
86
-#define PHY_INT_AUTONEG_LP (1 << 3)
34
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
87
-#define PHY_INT_PARFAULT (1 << 2)
35
DEF_HELPER_FLAGS_2(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr)
88
-#define PHY_INT_AUTONEG_PAGE (1 << 1)
36
DEF_HELPER_FLAGS_3(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
89
-
37
90
static void imx_eth_update(IMXFECState *s);
38
+DEF_HELPER_FLAGS_3(crypto_sha512h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
91
39
+DEF_HELPER_FLAGS_3(crypto_sha512h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
40
+DEF_HELPER_FLAGS_2(crypto_sha512su0, TCG_CALL_NO_RWG, void, ptr, ptr)
41
+DEF_HELPER_FLAGS_3(crypto_sha512su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
42
+
43
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
44
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
45
DEF_HELPER_2(dc_zva, void, env, i64)
46
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/crypto_helper.c
49
+++ b/target/arm/crypto_helper.c
50
@@ -XXX,XX +XXX,XX @@
51
/*
92
/*
52
* crypto_helper.c - emulate v8 Crypto Extensions instructions
93
@@ -XXX,XX +XXX,XX @@ static void imx_eth_update(IMXFECState *s);
53
*
94
* For now we don't handle any GPIO/interrupt line, so the OS will
54
- * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
95
* have to poll for the PHY status.
55
+ * Copyright (C) 2013 - 2018 Linaro Ltd <ard.biesheuvel@linaro.org>
96
*/
56
*
97
-static void imx_phy_update_irq(IMXFECState *s)
57
* This library is free software; you can redistribute it and/or
98
+static void imx_phy_update_irq(void *opaque, int n, int level)
58
* modify it under the terms of the GNU Lesser General Public
99
{
59
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm)
100
- imx_eth_update(s);
60
rd[0] = d.l[0];
101
-}
61
rd[1] = d.l[1];
102
-
62
}
103
-static void imx_phy_update_link(IMXFECState *s)
63
+
104
-{
64
+/*
105
- /* Autonegotiation status mirrors link status. */
65
+ * The SHA-512 logical functions (same as above but using 64-bit operands)
106
- if (qemu_get_queue(s->nic)->link_down) {
66
+ */
107
- trace_imx_phy_update_link("down");
67
+
108
- s->phy_status &= ~0x0024;
68
+static uint64_t cho512(uint64_t x, uint64_t y, uint64_t z)
109
- s->phy_int |= PHY_INT_DOWN;
69
+{
110
- } else {
70
+ return (x & (y ^ z)) ^ z;
111
- trace_imx_phy_update_link("up");
71
+}
112
- s->phy_status |= 0x0024;
72
+
113
- s->phy_int |= PHY_INT_ENERGYON;
73
+static uint64_t maj512(uint64_t x, uint64_t y, uint64_t z)
114
- s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
74
+{
115
- }
75
+ return (x & y) | ((x | y) & z);
116
- imx_phy_update_irq(s);
76
+}
117
+ imx_eth_update(opaque);
77
+
118
}
78
+static uint64_t S0_512(uint64_t x)
119
79
+{
120
static void imx_eth_set_link(NetClientState *nc)
80
+ return ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39);
121
{
81
+}
122
- imx_phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
82
+
123
-}
83
+static uint64_t S1_512(uint64_t x)
124
-
84
+{
125
-static void imx_phy_reset(IMXFECState *s)
85
+ return ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41);
126
-{
86
+}
127
- trace_imx_phy_reset();
87
+
128
-
88
+static uint64_t s0_512(uint64_t x)
129
- s->phy_status = 0x7809;
89
+{
130
- s->phy_control = 0x3000;
90
+ return ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7);
131
- s->phy_advertise = 0x01e1;
91
+}
132
- s->phy_int_mask = 0;
92
+
133
- s->phy_int = 0;
93
+static uint64_t s1_512(uint64_t x)
134
- imx_phy_update_link(s);
94
+{
135
+ lan9118_phy_update_link(&IMX_FEC(qemu_get_nic_opaque(nc))->mii,
95
+ return ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6);
136
+ nc->link_down);
96
+}
137
}
97
+
138
98
+void HELPER(crypto_sha512h)(void *vd, void *vn, void *vm)
139
static uint32_t imx_phy_read(IMXFECState *s, int reg)
99
+{
140
{
100
+ uint64_t *rd = vd;
141
- uint32_t val;
101
+ uint64_t *rn = vn;
142
uint32_t phy = reg / 32;
102
+ uint64_t *rm = vm;
143
103
+ uint64_t d0 = rd[0];
144
if (!s->phy_connected) {
104
+ uint64_t d1 = rd[1];
145
@@ -XXX,XX +XXX,XX @@ static uint32_t imx_phy_read(IMXFECState *s, int reg)
105
+
146
106
+ d1 += S1_512(rm[1]) + cho512(rm[1], rn[0], rn[1]);
147
reg %= 32;
107
+ d0 += S1_512(d1 + rm[0]) + cho512(d1 + rm[0], rm[1], rn[0]);
148
108
+
149
- switch (reg) {
109
+ rd[0] = d0;
150
- case 0: /* Basic Control */
110
+ rd[1] = d1;
151
- val = s->phy_control;
111
+}
152
- break;
112
+
153
- case 1: /* Basic Status */
113
+void HELPER(crypto_sha512h2)(void *vd, void *vn, void *vm)
154
- val = s->phy_status;
114
+{
155
- break;
115
+ uint64_t *rd = vd;
156
- case 2: /* ID1 */
116
+ uint64_t *rn = vn;
157
- val = 0x0007;
117
+ uint64_t *rm = vm;
158
- break;
118
+ uint64_t d0 = rd[0];
159
- case 3: /* ID2 */
119
+ uint64_t d1 = rd[1];
160
- val = 0xc0d1;
120
+
161
- break;
121
+ d1 += S0_512(rm[0]) + maj512(rn[0], rm[1], rm[0]);
162
- case 4: /* Auto-neg advertisement */
122
+ d0 += S0_512(d1) + maj512(d1, rm[0], rm[1]);
163
- val = s->phy_advertise;
123
+
164
- break;
124
+ rd[0] = d0;
165
- case 5: /* Auto-neg Link Partner Ability */
125
+ rd[1] = d1;
166
- val = 0x0f71;
126
+}
167
- break;
127
+
168
- case 6: /* Auto-neg Expansion */
128
+void HELPER(crypto_sha512su0)(void *vd, void *vn)
169
- val = 1;
129
+{
170
- break;
130
+ uint64_t *rd = vd;
171
- case 29: /* Interrupt source. */
131
+ uint64_t *rn = vn;
172
- val = s->phy_int;
132
+ uint64_t d0 = rd[0];
173
- s->phy_int = 0;
133
+ uint64_t d1 = rd[1];
174
- imx_phy_update_irq(s);
134
+
175
- break;
135
+ d0 += s0_512(rd[1]);
176
- case 30: /* Interrupt mask */
136
+ d1 += s0_512(rn[0]);
177
- val = s->phy_int_mask;
137
+
178
- break;
138
+ rd[0] = d0;
179
- case 17:
139
+ rd[1] = d1;
180
- case 18:
140
+}
181
- case 27:
141
+
182
- case 31:
142
+void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm)
183
- qemu_log_mask(LOG_UNIMP, "[%s.phy]%s: reg %d not implemented\n",
143
+{
184
- TYPE_IMX_FEC, __func__, reg);
144
+ uint64_t *rd = vd;
185
- val = 0;
145
+ uint64_t *rn = vn;
186
- break;
146
+ uint64_t *rm = vm;
187
- default:
147
+
188
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
148
+ rd[0] += s1_512(rn[0]) + rm[0];
189
- TYPE_IMX_FEC, __func__, reg);
149
+ rd[1] += s1_512(rn[1]) + rm[1];
190
- val = 0;
150
+}
191
- break;
151
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
192
- }
152
index XXXXXXX..XXXXXXX 100644
193
-
153
--- a/target/arm/translate-a64.c
194
- trace_imx_phy_read(val, phy, reg);
154
+++ b/target/arm/translate-a64.c
195
-
155
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
196
- return val;
156
tcg_temp_free_ptr(tcg_rn_ptr);
197
+ return lan9118_phy_read(&s->mii, reg);
157
}
198
}
158
199
159
+/* Crypto three-reg SHA512
200
static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
160
+ * 31 21 20 16 15 14 13 12 11 10 9 5 4 0
201
@@ -XXX,XX +XXX,XX @@ static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
161
+ * +-----------------------+------+---+---+-----+--------+------+------+
202
162
+ * | 1 1 0 0 1 1 1 0 0 1 1 | Rm | 1 | O | 0 0 | opcode | Rn | Rd |
203
reg %= 32;
163
+ * +-----------------------+------+---+---+-----+--------+------+------+
204
164
+ */
205
- trace_imx_phy_write(val, phy, reg);
165
+static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
206
-
166
+{
207
- switch (reg) {
167
+ int opcode = extract32(insn, 10, 2);
208
- case 0: /* Basic Control */
168
+ int o = extract32(insn, 14, 1);
209
- if (val & 0x8000) {
169
+ int rm = extract32(insn, 16, 5);
210
- imx_phy_reset(s);
170
+ int rn = extract32(insn, 5, 5);
211
- } else {
171
+ int rd = extract32(insn, 0, 5);
212
- s->phy_control = val & 0x7980;
172
+ int feature;
213
- /* Complete autonegotiation immediately. */
173
+ CryptoThreeOpFn *genfn;
214
- if (val & 0x1000) {
174
+
215
- s->phy_status |= 0x0020;
175
+ if (o == 0) {
216
- }
176
+ switch (opcode) {
217
- }
177
+ case 0: /* SHA512H */
218
- break;
178
+ feature = ARM_FEATURE_V8_SHA512;
219
- case 4: /* Auto-neg advertisement */
179
+ genfn = gen_helper_crypto_sha512h;
220
- s->phy_advertise = (val & 0x2d7f) | 0x80;
180
+ break;
221
- break;
181
+ case 1: /* SHA512H2 */
222
- case 30: /* Interrupt mask */
182
+ feature = ARM_FEATURE_V8_SHA512;
223
- s->phy_int_mask = val & 0xff;
183
+ genfn = gen_helper_crypto_sha512h2;
224
- imx_phy_update_irq(s);
184
+ break;
225
- break;
185
+ case 2: /* SHA512SU1 */
226
- case 17:
186
+ feature = ARM_FEATURE_V8_SHA512;
227
- case 18:
187
+ genfn = gen_helper_crypto_sha512su1;
228
- case 27:
188
+ break;
229
- case 31:
189
+ default:
230
- qemu_log_mask(LOG_UNIMP, "[%s.phy)%s: reg %d not implemented\n",
190
+ unallocated_encoding(s);
231
- TYPE_IMX_FEC, __func__, reg);
191
+ return;
232
- break;
192
+ }
233
- default:
193
+ } else {
234
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
194
+ unallocated_encoding(s);
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)) {
195
+ return;
259
+ return;
196
+ }
260
+ }
197
+
261
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
198
+ if (!arm_dc_feature(s, feature)) {
262
+
199
+ unallocated_encoding(s);
263
qemu_macaddr_default_if_unset(&s->conf.macaddr);
200
+ return;
264
201
+ }
265
s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
202
+
266
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
203
+ if (!fp_access_check(s)) {
267
index XXXXXXX..XXXXXXX 100644
204
+ return;
268
--- a/hw/net/lan9118_phy.c
205
+ }
269
+++ b/hw/net/lan9118_phy.c
206
+
270
@@ -XXX,XX +XXX,XX @@
207
+ if (genfn) {
271
* Copyright (c) 2009 CodeSourcery, LLC.
208
+ TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
272
* Written by Paul Brook
209
+
210
+ tcg_rd_ptr = vec_full_reg_ptr(s, rd);
211
+ tcg_rn_ptr = vec_full_reg_ptr(s, rn);
212
+ tcg_rm_ptr = vec_full_reg_ptr(s, rm);
213
+
214
+ genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
215
+
216
+ tcg_temp_free_ptr(tcg_rd_ptr);
217
+ tcg_temp_free_ptr(tcg_rn_ptr);
218
+ tcg_temp_free_ptr(tcg_rm_ptr);
219
+ } else {
220
+ g_assert_not_reached();
221
+ }
222
+}
223
+
224
+/* Crypto two-reg SHA512
225
+ * 31 12 11 10 9 5 4 0
226
+ * +-----------------------------------------+--------+------+------+
227
+ * | 1 1 0 0 1 1 1 0 1 1 0 0 0 0 0 0 1 0 0 0 | opcode | Rn | Rd |
228
+ * +-----------------------------------------+--------+------+------+
229
+ */
230
+static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
231
+{
232
+ int opcode = extract32(insn, 10, 2);
233
+ int rn = extract32(insn, 5, 5);
234
+ int rd = extract32(insn, 0, 5);
235
+ TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
236
+ int feature;
237
+ CryptoTwoOpFn *genfn;
238
+
239
+ switch (opcode) {
240
+ case 0: /* SHA512SU0 */
241
+ feature = ARM_FEATURE_V8_SHA512;
242
+ genfn = gen_helper_crypto_sha512su0;
243
+ break;
244
+ default:
245
+ unallocated_encoding(s);
246
+ return;
247
+ }
248
+
249
+ if (!arm_dc_feature(s, feature)) {
250
+ unallocated_encoding(s);
251
+ return;
252
+ }
253
+
254
+ if (!fp_access_check(s)) {
255
+ return;
256
+ }
257
+
258
+ tcg_rd_ptr = vec_full_reg_ptr(s, rd);
259
+ tcg_rn_ptr = vec_full_reg_ptr(s, rn);
260
+
261
+ genfn(tcg_rd_ptr, tcg_rn_ptr);
262
+
263
+ tcg_temp_free_ptr(tcg_rd_ptr);
264
+ tcg_temp_free_ptr(tcg_rn_ptr);
265
+}
266
+
267
/* C3.6 Data processing - SIMD, inc Crypto
268
*
273
*
269
* As the decode gets a little complex we are using a table based
274
+ * Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
270
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
275
+ *
271
{ 0x4e280800, 0xff3e0c00, disas_crypto_aes },
276
* This code is licensed under the GNU GPL v2
272
{ 0x5e000000, 0xff208c00, disas_crypto_three_reg_sha },
277
*
273
{ 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha },
278
* Contributions after 2012-01-13 are licensed under the terms of the
274
+ { 0xce608000, 0xffe0b000, disas_crypto_three_reg_sha512 },
279
@@ -XXX,XX +XXX,XX @@
275
+ { 0xcec08000, 0xfffff000, disas_crypto_two_reg_sha512 },
280
#include "hw/resettable.h"
276
{ 0x00000000, 0x00000000, NULL }
281
#include "migration/vmstate.h"
277
};
282
#include "qemu/log.h"
278
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"
279
--
471
--
280
2.16.1
472
2.34.1
281
282
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Add minimal code needed to allow upstream Linux guest to boot.
3
Turns 0x70 into 0xe0 (== 0x70 << 1) which adds the missing MII_ANLPAR_TX and
4
fixes the MSB of selector field to be zero, as specified in the datasheet.
4
5
5
Cc: Peter Maydell <peter.maydell@linaro.org>
6
Fixes: 2a424990170b "LAN9118 emulation"
6
Cc: Jason Wang <jasowang@redhat.com>
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
7
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Tested-by: Guenter Roeck <linux@roeck-us.net>
8
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
9
Cc: Michael S. Tsirkin <mst@redhat.com>
10
Cc: qemu-devel@nongnu.org
11
Cc: qemu-arm@nongnu.org
12
Cc: yurovsky@gmail.com
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
10
Message-id: 20241102125724.532843-4-shentey@gmail.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
12
---
18
hw/misc/Makefile.objs | 1 +
13
hw/net/lan9118_phy.c | 2 +-
19
include/hw/misc/imx7_gpr.h | 28 ++++++++++
14
1 file changed, 1 insertion(+), 1 deletion(-)
20
hw/misc/imx7_gpr.c | 124 +++++++++++++++++++++++++++++++++++++++++++++
21
hw/misc/trace-events | 4 ++
22
4 files changed, 157 insertions(+)
23
create mode 100644 include/hw/misc/imx7_gpr.h
24
create mode 100644 hw/misc/imx7_gpr.c
25
15
26
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
27
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/misc/Makefile.objs
18
--- a/hw/net/lan9118_phy.c
29
+++ b/hw/misc/Makefile.objs
19
+++ b/hw/net/lan9118_phy.c
30
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IMX) += imx6_src.o
20
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
31
obj-$(CONFIG_IMX) += imx7_ccm.o
21
val = s->advertise;
32
obj-$(CONFIG_IMX) += imx2_wdt.o
22
break;
33
obj-$(CONFIG_IMX) += imx7_snvs.o
23
case 5: /* Auto-neg Link Partner Ability */
34
+obj-$(CONFIG_IMX) += imx7_gpr.o
24
- val = 0x0f71;
35
obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
25
+ val = 0x0fe1;
36
obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
26
break;
37
obj-$(CONFIG_MAINSTONE) += mst_fpga.o
27
case 6: /* Auto-neg Expansion */
38
diff --git a/include/hw/misc/imx7_gpr.h b/include/hw/misc/imx7_gpr.h
28
val = 1;
39
new file mode 100644
40
index XXXXXXX..XXXXXXX
41
--- /dev/null
42
+++ b/include/hw/misc/imx7_gpr.h
43
@@ -XXX,XX +XXX,XX @@
44
+/*
45
+ * Copyright (c) 2017, Impinj, Inc.
46
+ *
47
+ * i.MX7 GPR IP block emulation code
48
+ *
49
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
50
+ *
51
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
52
+ * See the COPYING file in the top-level directory.
53
+ */
54
+
55
+#ifndef IMX7_GPR_H
56
+#define IMX7_GPR_H
57
+
58
+#include "qemu/bitops.h"
59
+#include "hw/sysbus.h"
60
+
61
+#define TYPE_IMX7_GPR "imx7.gpr"
62
+#define IMX7_GPR(obj) OBJECT_CHECK(IMX7GPRState, (obj), TYPE_IMX7_GPR)
63
+
64
+typedef struct IMX7GPRState {
65
+ /* <private> */
66
+ SysBusDevice parent_obj;
67
+
68
+ MemoryRegion mmio;
69
+} IMX7GPRState;
70
+
71
+#endif /* IMX7_GPR_H */
72
diff --git a/hw/misc/imx7_gpr.c b/hw/misc/imx7_gpr.c
73
new file mode 100644
74
index XXXXXXX..XXXXXXX
75
--- /dev/null
76
+++ b/hw/misc/imx7_gpr.c
77
@@ -XXX,XX +XXX,XX @@
78
+/*
79
+ * Copyright (c) 2018, Impinj, Inc.
80
+ *
81
+ * i.MX7 GPR IP block emulation code
82
+ *
83
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
84
+ *
85
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
86
+ * See the COPYING file in the top-level directory.
87
+ *
88
+ * Bare minimum emulation code needed to support being able to shut
89
+ * down linux guest gracefully.
90
+ */
91
+
92
+#include "qemu/osdep.h"
93
+#include "hw/misc/imx7_gpr.h"
94
+#include "qemu/log.h"
95
+#include "sysemu/sysemu.h"
96
+
97
+#include "trace.h"
98
+
99
+enum IMX7GPRRegisters {
100
+ IOMUXC_GPR0 = 0x00,
101
+ IOMUXC_GPR1 = 0x04,
102
+ IOMUXC_GPR2 = 0x08,
103
+ IOMUXC_GPR3 = 0x0c,
104
+ IOMUXC_GPR4 = 0x10,
105
+ IOMUXC_GPR5 = 0x14,
106
+ IOMUXC_GPR6 = 0x18,
107
+ IOMUXC_GPR7 = 0x1c,
108
+ IOMUXC_GPR8 = 0x20,
109
+ IOMUXC_GPR9 = 0x24,
110
+ IOMUXC_GPR10 = 0x28,
111
+ IOMUXC_GPR11 = 0x2c,
112
+ IOMUXC_GPR12 = 0x30,
113
+ IOMUXC_GPR13 = 0x34,
114
+ IOMUXC_GPR14 = 0x38,
115
+ IOMUXC_GPR15 = 0x3c,
116
+ IOMUXC_GPR16 = 0x40,
117
+ IOMUXC_GPR17 = 0x44,
118
+ IOMUXC_GPR18 = 0x48,
119
+ IOMUXC_GPR19 = 0x4c,
120
+ IOMUXC_GPR20 = 0x50,
121
+ IOMUXC_GPR21 = 0x54,
122
+ IOMUXC_GPR22 = 0x58,
123
+};
124
+
125
+#define IMX7D_GPR1_IRQ_MASK BIT(12)
126
+#define IMX7D_GPR1_ENET1_TX_CLK_SEL_MASK BIT(13)
127
+#define IMX7D_GPR1_ENET2_TX_CLK_SEL_MASK BIT(14)
128
+#define IMX7D_GPR1_ENET_TX_CLK_SEL_MASK (0x3 << 13)
129
+#define IMX7D_GPR1_ENET1_CLK_DIR_MASK BIT(17)
130
+#define IMX7D_GPR1_ENET2_CLK_DIR_MASK BIT(18)
131
+#define IMX7D_GPR1_ENET_CLK_DIR_MASK (0x3 << 17)
132
+
133
+#define IMX7D_GPR5_CSI_MUX_CONTROL_MIPI BIT(4)
134
+#define IMX7D_GPR12_PCIE_PHY_REFCLK_SEL BIT(5)
135
+#define IMX7D_GPR22_PCIE_PHY_PLL_LOCKED BIT(31)
136
+
137
+
138
+static uint64_t imx7_gpr_read(void *opaque, hwaddr offset, unsigned size)
139
+{
140
+ trace_imx7_gpr_read(offset);
141
+
142
+ if (offset == IOMUXC_GPR22) {
143
+ return IMX7D_GPR22_PCIE_PHY_PLL_LOCKED;
144
+ }
145
+
146
+ return 0;
147
+}
148
+
149
+static void imx7_gpr_write(void *opaque, hwaddr offset,
150
+ uint64_t v, unsigned size)
151
+{
152
+ trace_imx7_gpr_write(offset, v);
153
+}
154
+
155
+static const struct MemoryRegionOps imx7_gpr_ops = {
156
+ .read = imx7_gpr_read,
157
+ .write = imx7_gpr_write,
158
+ .endianness = DEVICE_NATIVE_ENDIAN,
159
+ .impl = {
160
+ /*
161
+ * Our device would not work correctly if the guest was doing
162
+ * unaligned access. This might not be a limitation on the
163
+ * real device but in practice there is no reason for a guest
164
+ * to access this device unaligned.
165
+ */
166
+ .min_access_size = 4,
167
+ .max_access_size = 4,
168
+ .unaligned = false,
169
+ },
170
+};
171
+
172
+static void imx7_gpr_init(Object *obj)
173
+{
174
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
175
+ IMX7GPRState *s = IMX7_GPR(obj);
176
+
177
+ memory_region_init_io(&s->mmio, obj, &imx7_gpr_ops, s,
178
+ TYPE_IMX7_GPR, 64 * 1024);
179
+ sysbus_init_mmio(sd, &s->mmio);
180
+}
181
+
182
+static void imx7_gpr_class_init(ObjectClass *klass, void *data)
183
+{
184
+ DeviceClass *dc = DEVICE_CLASS(klass);
185
+
186
+ dc->desc = "i.MX7 General Purpose Registers Module";
187
+}
188
+
189
+static const TypeInfo imx7_gpr_info = {
190
+ .name = TYPE_IMX7_GPR,
191
+ .parent = TYPE_SYS_BUS_DEVICE,
192
+ .instance_size = sizeof(IMX7GPRState),
193
+ .instance_init = imx7_gpr_init,
194
+ .class_init = imx7_gpr_class_init,
195
+};
196
+
197
+static void imx7_gpr_register_type(void)
198
+{
199
+ type_register_static(&imx7_gpr_info);
200
+}
201
+type_init(imx7_gpr_register_type)
202
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
203
index XXXXXXX..XXXXXXX 100644
204
--- a/hw/misc/trace-events
205
+++ b/hw/misc/trace-events
206
@@ -XXX,XX +XXX,XX @@ mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC
207
msf2_sysreg_write(uint64_t offset, uint32_t val, uint32_t prev) "msf2-sysreg write: addr 0x%08" HWADDR_PRIx " data 0x%" PRIx32 " prev 0x%" PRIx32
208
msf2_sysreg_read(uint64_t offset, uint32_t val) "msf2-sysreg read: addr 0x%08" HWADDR_PRIx " data 0x%08" PRIx32
209
msf2_sysreg_write_pll_status(void) "Invalid write to read only PLL status register"
210
+
211
+#hw/misc/imx7_gpr.c
212
+imx7_gpr_read(uint64_t offset) "addr 0x%08" HWADDR_PRIx
213
+imx7_gpr_write(uint64_t offset, uint64_t value) "addr 0x%08" HWADDR_PRIx "value 0x%08" HWADDR_PRIx
214
--
29
--
215
2.16.1
30
2.34.1
216
217
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Add minimal code needed to allow upstream Linux guest to boot.
3
Prefer named constants over magic values for better readability.
4
4
5
Cc: Peter Maydell <peter.maydell@linaro.org>
6
Cc: Jason Wang <jasowang@redhat.com>
7
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
9
Cc: Michael S. Tsirkin <mst@redhat.com>
10
Cc: qemu-devel@nongnu.org
11
Cc: qemu-arm@nongnu.org
12
Cc: yurovsky@gmail.com
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
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
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
10
---
17
hw/intc/Makefile.objs | 2 +-
11
include/hw/net/mii.h | 6 +++++
18
include/hw/intc/imx_gpcv2.h | 22 ++++++++
12
hw/net/lan9118_phy.c | 63 ++++++++++++++++++++++++++++----------------
19
hw/intc/imx_gpcv2.c | 125 ++++++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 46 insertions(+), 23 deletions(-)
20
3 files changed, 148 insertions(+), 1 deletion(-)
21
create mode 100644 include/hw/intc/imx_gpcv2.h
22
create mode 100644 hw/intc/imx_gpcv2.c
23
14
24
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
15
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/intc/Makefile.objs
17
--- a/include/hw/net/mii.h
27
+++ b/hw/intc/Makefile.objs
18
+++ b/include/hw/net/mii.h
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_XILINX) += xilinx_intc.o
29
common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-pmu-iomod-intc.o
30
common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-ipi.o
31
common-obj-$(CONFIG_ETRAXFS) += etraxfs_pic.o
32
-common-obj-$(CONFIG_IMX) += imx_avic.o
33
+common-obj-$(CONFIG_IMX) += imx_avic.o imx_gpcv2.o
34
common-obj-$(CONFIG_LM32) += lm32_pic.o
35
common-obj-$(CONFIG_REALVIEW) += realview_gic.o
36
common-obj-$(CONFIG_SLAVIO) += slavio_intctl.o
37
diff --git a/include/hw/intc/imx_gpcv2.h b/include/hw/intc/imx_gpcv2.h
38
new file mode 100644
39
index XXXXXXX..XXXXXXX
40
--- /dev/null
41
+++ b/include/hw/intc/imx_gpcv2.h
42
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
43
+#ifndef IMX_GPCV2_H
20
#define MII_BMSR_JABBER (1 << 1) /* Jabber detected */
44
+#define IMX_GPCV2_H
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
45
+
42
+
46
+#include "hw/sysbus.h"
43
/* RealTek 8211E */
47
+
44
#define RTL8211E_PHYID1 0x001c
48
+enum IMXGPCv2Registers {
45
#define RTL8211E_PHYID2 0xc915
49
+ GPC_NUM = 0xE00 / sizeof(uint32_t),
46
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
50
+};
47
index XXXXXXX..XXXXXXX 100644
51
+
48
--- a/hw/net/lan9118_phy.c
52
+typedef struct IMXGPCv2State {
49
+++ b/hw/net/lan9118_phy.c
53
+ /*< private >*/
54
+ SysBusDevice parent_obj;
55
+
56
+ /*< public >*/
57
+ MemoryRegion iomem;
58
+ uint32_t regs[GPC_NUM];
59
+} IMXGPCv2State;
60
+
61
+#define TYPE_IMX_GPCV2 "imx-gpcv2"
62
+#define IMX_GPCV2(obj) OBJECT_CHECK(IMXGPCv2State, (obj), TYPE_IMX_GPCV2)
63
+
64
+#endif /* IMX_GPCV2_H */
65
diff --git a/hw/intc/imx_gpcv2.c b/hw/intc/imx_gpcv2.c
66
new file mode 100644
67
index XXXXXXX..XXXXXXX
68
--- /dev/null
69
+++ b/hw/intc/imx_gpcv2.c
70
@@ -XXX,XX +XXX,XX @@
50
@@ -XXX,XX +XXX,XX @@
71
+/*
51
72
+ * Copyright (c) 2018, Impinj, Inc.
52
#include "qemu/osdep.h"
73
+ *
53
#include "hw/net/lan9118_phy.h"
74
+ * i.MX7 GPCv2 block emulation code
54
+#include "hw/net/mii.h"
75
+ *
55
#include "hw/irq.h"
76
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
56
#include "hw/resettable.h"
77
+ *
57
#include "migration/vmstate.h"
78
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
58
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
79
+ * See the COPYING file in the top-level directory.
59
uint16_t val;
80
+ */
60
81
+
61
switch (reg) {
82
+#include "qemu/osdep.h"
62
- case 0: /* Basic Control */
83
+#include "hw/intc/imx_gpcv2.h"
63
+ case MII_BMCR:
84
+#include "qemu/log.h"
64
val = s->control;
85
+
65
break;
86
+#define GPC_PU_PGC_SW_PUP_REQ 0x0f8
66
- case 1: /* Basic Status */
87
+#define GPC_PU_PGC_SW_PDN_REQ 0x104
67
+ case MII_BMSR:
88
+
68
val = s->status;
89
+#define USB_HSIC_PHY_SW_Pxx_REQ BIT(4)
69
break;
90
+#define USB_OTG2_PHY_SW_Pxx_REQ BIT(3)
70
- case 2: /* ID1 */
91
+#define USB_OTG1_PHY_SW_Pxx_REQ BIT(2)
71
- val = 0x0007;
92
+#define PCIE_PHY_SW_Pxx_REQ BIT(1)
72
+ case MII_PHYID1:
93
+#define MIPI_PHY_SW_Pxx_REQ BIT(0)
73
+ val = SMSCLAN9118_PHYID1;
94
+
74
break;
95
+
75
- case 3: /* ID2 */
96
+static void imx_gpcv2_reset(DeviceState *dev)
76
- val = 0xc0d1;
97
+{
77
+ case MII_PHYID2:
98
+ IMXGPCv2State *s = IMX_GPCV2(dev);
78
+ val = SMSCLAN9118_PHYID2;
99
+
79
break;
100
+ memset(s->regs, 0, sizeof(s->regs));
80
- case 4: /* Auto-neg advertisement */
101
+}
81
+ case MII_ANAR:
102
+
82
val = s->advertise;
103
+static uint64_t imx_gpcv2_read(void *opaque, hwaddr offset,
83
break;
104
+ unsigned size)
84
- case 5: /* Auto-neg Link Partner Ability */
105
+{
85
- val = 0x0fe1;
106
+ IMXGPCv2State *s = opaque;
86
+ case MII_ANLPAR:
107
+
87
+ val = MII_ANLPAR_PAUSEASY | MII_ANLPAR_PAUSE | MII_ANLPAR_T4 |
108
+ return s->regs[offset / sizeof(uint32_t)];
88
+ MII_ANLPAR_TXFD | MII_ANLPAR_TX | MII_ANLPAR_10FD |
109
+}
89
+ MII_ANLPAR_10 | MII_ANLPAR_CSMACD;
110
+
90
break;
111
+static void imx_gpcv2_write(void *opaque, hwaddr offset,
91
- case 6: /* Auto-neg Expansion */
112
+ uint64_t value, unsigned size)
92
- val = 1;
113
+{
93
+ case MII_ANER:
114
+ IMXGPCv2State *s = opaque;
94
+ val = MII_ANER_NWAY;
115
+ const size_t idx = offset / sizeof(uint32_t);
95
break;
116
+
96
case 29: /* Interrupt source. */
117
+ s->regs[idx] = value;
97
val = s->ints;
118
+
98
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
119
+ /*
99
trace_lan9118_phy_write(val, reg);
120
+ * Real HW will clear those bits once as a way to indicate that
100
121
+ * power up request is complete
101
switch (reg) {
122
+ */
102
- case 0: /* Basic Control */
123
+ if (offset == GPC_PU_PGC_SW_PUP_REQ ||
103
- if (val & 0x8000) {
124
+ offset == GPC_PU_PGC_SW_PDN_REQ) {
104
+ case MII_BMCR:
125
+ s->regs[idx] &= ~(USB_HSIC_PHY_SW_Pxx_REQ |
105
+ if (val & MII_BMCR_RESET) {
126
+ USB_OTG2_PHY_SW_Pxx_REQ |
106
lan9118_phy_reset(s);
127
+ USB_OTG1_PHY_SW_Pxx_REQ |
107
} else {
128
+ PCIE_PHY_SW_Pxx_REQ |
108
- s->control = val & 0x7980;
129
+ MIPI_PHY_SW_Pxx_REQ);
109
+ s->control = val & (MII_BMCR_LOOPBACK | MII_BMCR_SPEED100 |
130
+ }
110
+ MII_BMCR_AUTOEN | MII_BMCR_PDOWN | MII_BMCR_FD |
131
+}
111
+ MII_BMCR_CTST);
132
+
112
/* Complete autonegotiation immediately. */
133
+static const struct MemoryRegionOps imx_gpcv2_ops = {
113
- if (val & 0x1000) {
134
+ .read = imx_gpcv2_read,
114
- s->status |= 0x0020;
135
+ .write = imx_gpcv2_write,
115
+ if (val & MII_BMCR_AUTOEN) {
136
+ .endianness = DEVICE_NATIVE_ENDIAN,
116
+ s->status |= MII_BMSR_AN_COMP;
137
+ .impl = {
117
}
138
+ /*
118
}
139
+ * Our device would not work correctly if the guest was doing
119
break;
140
+ * unaligned access. This might not be a limitation on the real
120
- case 4: /* Auto-neg advertisement */
141
+ * device but in practice there is no reason for a guest to access
121
- s->advertise = (val & 0x2d7f) | 0x80;
142
+ * this device unaligned.
122
+ case MII_ANAR:
143
+ */
123
+ s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
144
+ .min_access_size = 4,
124
+ MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
145
+ .max_access_size = 4,
125
+ MII_ANAR_SELECT))
146
+ .unaligned = false,
126
+ | MII_ANAR_TX;
147
+ },
127
break;
148
+};
128
case 30: /* Interrupt mask */
149
+
129
s->int_mask = val & 0xff;
150
+static void imx_gpcv2_init(Object *obj)
130
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
151
+{
131
/* Autonegotiation status mirrors link status. */
152
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
132
if (link_down) {
153
+ IMXGPCv2State *s = IMX_GPCV2(obj);
133
trace_lan9118_phy_update_link("down");
154
+
134
- s->status &= ~0x0024;
155
+ memory_region_init_io(&s->iomem,
135
+ s->status &= ~(MII_BMSR_AN_COMP | MII_BMSR_LINK_ST);
156
+ obj,
136
s->ints |= PHY_INT_DOWN;
157
+ &imx_gpcv2_ops,
137
} else {
158
+ s,
138
trace_lan9118_phy_update_link("up");
159
+ TYPE_IMX_GPCV2 ".iomem",
139
- s->status |= 0x0024;
160
+ sizeof(s->regs));
140
+ s->status |= MII_BMSR_AN_COMP | MII_BMSR_LINK_ST;
161
+ sysbus_init_mmio(sd, &s->iomem);
141
s->ints |= PHY_INT_ENERGYON;
162
+}
142
s->ints |= PHY_INT_AUTONEG_COMPLETE;
163
+
143
}
164
+static const VMStateDescription vmstate_imx_gpcv2 = {
144
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_reset(Lan9118PhyState *s)
165
+ .name = TYPE_IMX_GPCV2,
145
{
166
+ .version_id = 1,
146
trace_lan9118_phy_reset();
167
+ .minimum_version_id = 1,
147
168
+ .fields = (VMStateField[]) {
148
- s->control = 0x3000;
169
+ VMSTATE_UINT32_ARRAY(regs, IMXGPCv2State, GPC_NUM),
149
- s->status = 0x7809;
170
+ VMSTATE_END_OF_LIST()
150
- s->advertise = 0x01e1;
171
+ },
151
+ s->control = MII_BMCR_AUTOEN | MII_BMCR_SPEED100;
172
+};
152
+ s->status = MII_BMSR_100TX_FD
173
+
153
+ | MII_BMSR_100TX_HD
174
+static void imx_gpcv2_class_init(ObjectClass *klass, void *data)
154
+ | MII_BMSR_10T_FD
175
+{
155
+ | MII_BMSR_10T_HD
176
+ DeviceClass *dc = DEVICE_CLASS(klass);
156
+ | MII_BMSR_AUTONEG
177
+
157
+ | MII_BMSR_EXTCAP;
178
+ dc->reset = imx_gpcv2_reset;
158
+ s->advertise = MII_ANAR_TXFD
179
+ dc->vmsd = &vmstate_imx_gpcv2;
159
+ | MII_ANAR_TX
180
+ dc->desc = "i.MX GPCv2 Module";
160
+ | MII_ANAR_10FD
181
+}
161
+ | MII_ANAR_10
182
+
162
+ | MII_ANAR_CSMACD;
183
+static const TypeInfo imx_gpcv2_info = {
163
s->int_mask = 0;
184
+ .name = TYPE_IMX_GPCV2,
164
s->ints = 0;
185
+ .parent = TYPE_SYS_BUS_DEVICE,
165
lan9118_phy_update_link(s, s->link_down);
186
+ .instance_size = sizeof(IMXGPCv2State),
187
+ .instance_init = imx_gpcv2_init,
188
+ .class_init = imx_gpcv2_class_init,
189
+};
190
+
191
+static void imx_gpcv2_register_type(void)
192
+{
193
+ type_register_static(&imx_gpcv2_info);
194
+}
195
+type_init(imx_gpcv2_register_type)
196
--
166
--
197
2.16.1
167
2.34.1
198
199
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Add code to emulate Chipidea USB IP (used in i.MX SoCs). Tested to
3
The real device advertises this mode and the device model already advertises
4
work against:
4
100 mbps half duplex and 10 mbps full+half duplex. So advertise this mode to
5
make the model more realistic.
5
6
6
-usb -drive if=none,id=stick,file=usb.img,format=raw -device \
7
usb-storage,bus=usb-bus.0,drive=stick
8
9
Cc: Peter Maydell <peter.maydell@linaro.org>
10
Cc: Jason Wang <jasowang@redhat.com>
11
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
13
Cc: Michael S. Tsirkin <mst@redhat.com>
14
Cc: qemu-devel@nongnu.org
15
Cc: qemu-arm@nongnu.org
16
Cc: yurovsky@gmail.com
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
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
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
12
---
21
hw/usb/Makefile.objs | 1 +
13
hw/net/lan9118_phy.c | 4 ++--
22
include/hw/usb/chipidea.h | 16 +++++
14
1 file changed, 2 insertions(+), 2 deletions(-)
23
hw/usb/chipidea.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++
24
3 files changed, 193 insertions(+)
25
create mode 100644 include/hw/usb/chipidea.h
26
create mode 100644 hw/usb/chipidea.c
27
15
28
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
29
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/usb/Makefile.objs
18
--- a/hw/net/lan9118_phy.c
31
+++ b/hw/usb/Makefile.objs
19
+++ b/hw/net/lan9118_phy.c
32
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_USB_XHCI_NEC) += hcd-xhci-nec.o
20
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
33
common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o
21
break;
34
22
case MII_ANAR:
35
obj-$(CONFIG_TUSB6010) += tusb6010.o
23
s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
36
+obj-$(CONFIG_IMX) += chipidea.o
24
- MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
37
25
- MII_ANAR_SELECT))
38
# emulated usb devices
26
+ MII_ANAR_PAUSE | MII_ANAR_TXFD | MII_ANAR_10FD |
39
common-obj-$(CONFIG_USB) += dev-hub.o
27
+ MII_ANAR_10 | MII_ANAR_SELECT))
40
diff --git a/include/hw/usb/chipidea.h b/include/hw/usb/chipidea.h
28
| MII_ANAR_TX;
41
new file mode 100644
29
break;
42
index XXXXXXX..XXXXXXX
30
case 30: /* Interrupt mask */
43
--- /dev/null
44
+++ b/include/hw/usb/chipidea.h
45
@@ -XXX,XX +XXX,XX @@
46
+#ifndef CHIPIDEA_H
47
+#define CHIPIDEA_H
48
+
49
+#include "hw/usb/hcd-ehci.h"
50
+
51
+typedef struct ChipideaState {
52
+ /*< private >*/
53
+ EHCISysBusState parent_obj;
54
+
55
+ MemoryRegion iomem[3];
56
+} ChipideaState;
57
+
58
+#define TYPE_CHIPIDEA "usb-chipidea"
59
+#define CHIPIDEA(obj) OBJECT_CHECK(ChipideaState, (obj), TYPE_CHIPIDEA)
60
+
61
+#endif /* CHIPIDEA_H */
62
diff --git a/hw/usb/chipidea.c b/hw/usb/chipidea.c
63
new file mode 100644
64
index XXXXXXX..XXXXXXX
65
--- /dev/null
66
+++ b/hw/usb/chipidea.c
67
@@ -XXX,XX +XXX,XX @@
68
+/*
69
+ * Copyright (c) 2018, Impinj, Inc.
70
+ *
71
+ * Chipidea USB block emulation code
72
+ *
73
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
74
+ *
75
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
76
+ * See the COPYING file in the top-level directory.
77
+ */
78
+
79
+#include "qemu/osdep.h"
80
+#include "hw/usb/hcd-ehci.h"
81
+#include "hw/usb/chipidea.h"
82
+#include "qemu/log.h"
83
+
84
+enum {
85
+ CHIPIDEA_USBx_DCIVERSION = 0x000,
86
+ CHIPIDEA_USBx_DCCPARAMS = 0x004,
87
+ CHIPIDEA_USBx_DCCPARAMS_HC = BIT(8),
88
+};
89
+
90
+static uint64_t chipidea_read(void *opaque, hwaddr offset,
91
+ unsigned size)
92
+{
93
+ return 0;
94
+}
95
+
96
+static void chipidea_write(void *opaque, hwaddr offset,
97
+ uint64_t value, unsigned size)
98
+{
99
+}
100
+
101
+static const struct MemoryRegionOps chipidea_ops = {
102
+ .read = chipidea_read,
103
+ .write = chipidea_write,
104
+ .endianness = DEVICE_NATIVE_ENDIAN,
105
+ .impl = {
106
+ /*
107
+ * Our device would not work correctly if the guest was doing
108
+ * unaligned access. This might not be a limitation on the
109
+ * real device but in practice there is no reason for a guest
110
+ * to access this device unaligned.
111
+ */
112
+ .min_access_size = 4,
113
+ .max_access_size = 4,
114
+ .unaligned = false,
115
+ },
116
+};
117
+
118
+static uint64_t chipidea_dc_read(void *opaque, hwaddr offset,
119
+ unsigned size)
120
+{
121
+ switch (offset) {
122
+ case CHIPIDEA_USBx_DCIVERSION:
123
+ return 0x1;
124
+ case CHIPIDEA_USBx_DCCPARAMS:
125
+ /*
126
+ * Real hardware (at least i.MX7) will also report the
127
+ * controller as "Device Capable" (and 8 supported endpoints),
128
+ * but there doesn't seem to be much point in doing so, since
129
+ * we don't emulate that part.
130
+ */
131
+ return CHIPIDEA_USBx_DCCPARAMS_HC;
132
+ }
133
+
134
+ return 0;
135
+}
136
+
137
+static void chipidea_dc_write(void *opaque, hwaddr offset,
138
+ uint64_t value, unsigned size)
139
+{
140
+}
141
+
142
+static const struct MemoryRegionOps chipidea_dc_ops = {
143
+ .read = chipidea_dc_read,
144
+ .write = chipidea_dc_write,
145
+ .endianness = DEVICE_NATIVE_ENDIAN,
146
+ .impl = {
147
+ /*
148
+ * Our device would not work correctly if the guest was doing
149
+ * unaligned access. This might not be a limitation on the real
150
+ * device but in practice there is no reason for a guest to access
151
+ * this device unaligned.
152
+ */
153
+ .min_access_size = 4,
154
+ .max_access_size = 4,
155
+ .unaligned = false,
156
+ },
157
+};
158
+
159
+static void chipidea_init(Object *obj)
160
+{
161
+ EHCIState *ehci = &SYS_BUS_EHCI(obj)->ehci;
162
+ ChipideaState *ci = CHIPIDEA(obj);
163
+ int i;
164
+
165
+ for (i = 0; i < ARRAY_SIZE(ci->iomem); i++) {
166
+ const struct {
167
+ const char *name;
168
+ hwaddr offset;
169
+ uint64_t size;
170
+ const struct MemoryRegionOps *ops;
171
+ } regions[ARRAY_SIZE(ci->iomem)] = {
172
+ /*
173
+ * Registers located between offsets 0x000 and 0xFC
174
+ */
175
+ {
176
+ .name = TYPE_CHIPIDEA ".misc",
177
+ .offset = 0x000,
178
+ .size = 0x100,
179
+ .ops = &chipidea_ops,
180
+ },
181
+ /*
182
+ * Registers located between offsets 0x1A4 and 0x1DC
183
+ */
184
+ {
185
+ .name = TYPE_CHIPIDEA ".endpoints",
186
+ .offset = 0x1A4,
187
+ .size = 0x1DC - 0x1A4 + 4,
188
+ .ops = &chipidea_ops,
189
+ },
190
+ /*
191
+ * USB_x_DCIVERSION and USB_x_DCCPARAMS
192
+ */
193
+ {
194
+ .name = TYPE_CHIPIDEA ".dc",
195
+ .offset = 0x120,
196
+ .size = 8,
197
+ .ops = &chipidea_dc_ops,
198
+ },
199
+ };
200
+
201
+ memory_region_init_io(&ci->iomem[i],
202
+ obj,
203
+ regions[i].ops,
204
+ ci,
205
+ regions[i].name,
206
+ regions[i].size);
207
+
208
+ memory_region_add_subregion(&ehci->mem,
209
+ regions[i].offset,
210
+ &ci->iomem[i]);
211
+ }
212
+}
213
+
214
+static void chipidea_class_init(ObjectClass *klass, void *data)
215
+{
216
+ DeviceClass *dc = DEVICE_CLASS(klass);
217
+ SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(klass);
218
+
219
+ /*
220
+ * Offsets used were taken from i.MX7Dual Applications Processor
221
+ * Reference Manual, Rev 0.1, p. 3177, Table 11-59
222
+ */
223
+ sec->capsbase = 0x100;
224
+ sec->opregbase = 0x140;
225
+ sec->portnr = 1;
226
+
227
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
228
+ dc->desc = "Chipidea USB Module";
229
+}
230
+
231
+static const TypeInfo chipidea_info = {
232
+ .name = TYPE_CHIPIDEA,
233
+ .parent = TYPE_SYS_BUS_EHCI,
234
+ .instance_size = sizeof(ChipideaState),
235
+ .instance_init = chipidea_init,
236
+ .class_init = chipidea_class_init,
237
+};
238
+
239
+static void chipidea_register_type(void)
240
+{
241
+ type_register_static(&chipidea_info);
242
+}
243
+type_init(chipidea_register_type)
244
--
31
--
245
2.16.1
32
2.34.1
246
247
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
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.
2
6
3
IP block found on several generations of i.MX family does not use
7
For the cases where the infzero test in pickNaNMulAdd was
4
vanilla SDHCI implementation and it comes with a number of quirks.
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".
5
13
6
Introduce i.MX SDHCI subtype of SDHCI block to add code necessary to
14
For Arm, this looks like it might be a behaviour change because we
7
support unmodified Linux guest driver.
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.
8
20
9
Cc: Peter Maydell <peter.maydell@linaro.org>
21
For any target architecture using the "default implementation" at the
10
Cc: Jason Wang <jasowang@redhat.com>
22
bottom of the ifdef, this is a behaviour change but will be fixing a
11
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
bug (where we failed to raise the Invalid exception for (0 * inf +
12
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
24
QNaN). The architectures using the default case are:
13
Cc: Michael S. Tsirkin <mst@redhat.com>
25
* hppa
14
Cc: qemu-devel@nongnu.org
26
* i386
15
Cc: qemu-arm@nongnu.org
27
* sh4
16
Cc: yurovsky@gmail.com
28
* tricore
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
29
18
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
30
The x86, Tricore and SH4 CPU architecture manuals are clear that this
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
31
should have raised Invalid; HPPA is a bit vaguer but still seems
20
[PMM: define and use ESDHC_UNDOCUMENTED_REG27]
32
clear enough.
33
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
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
22
---
37
---
23
hw/sd/sdhci-internal.h | 23 +++++
38
fpu/softfloat-parts.c.inc | 13 +++++++------
24
include/hw/sd/sdhci.h | 13 +++
39
fpu/softfloat-specialize.c.inc | 29 +----------------------------
25
hw/sd/sdhci.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++++-
40
2 files changed, 8 insertions(+), 34 deletions(-)
26
3 files changed, 265 insertions(+), 1 deletion(-)
27
41
28
diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
42
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
29
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/sd/sdhci-internal.h
44
--- a/fpu/softfloat-parts.c.inc
31
+++ b/hw/sd/sdhci-internal.h
45
+++ b/fpu/softfloat-parts.c.inc
32
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
33
47
int ab_mask, int abc_mask)
34
/* R/W Host control Register 0x0 */
48
{
35
#define SDHC_HOSTCTL 0x28
49
int which;
36
+#define SDHC_CTRL_LED 0x01
50
+ bool infzero = (ab_mask == float_cmask_infzero);
37
#define SDHC_CTRL_DMA_CHECK_MASK 0x18
51
38
#define SDHC_CTRL_SDMA 0x00
52
if (unlikely(abc_mask & float_cmask_snan)) {
39
#define SDHC_CTRL_ADMA1_32 0x08
53
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
40
#define SDHC_CTRL_ADMA2_32 0x10
41
#define SDHC_CTRL_ADMA2_64 0x18
42
#define SDHC_DMA_TYPE(x) ((x) & SDHC_CTRL_DMA_CHECK_MASK)
43
+#define SDHC_CTRL_4BITBUS 0x02
44
+#define SDHC_CTRL_8BITBUS 0x20
45
+#define SDHC_CTRL_CDTEST_INS 0x40
46
+#define SDHC_CTRL_CDTEST_EN 0x80
47
+
48
49
/* R/W Power Control Register 0x0 */
50
#define SDHC_PWRCON 0x29
51
@@ -XXX,XX +XXX,XX @@ enum {
52
sdhc_gap_write = 2 /* SDHC stopped at block gap during write operation */
53
};
54
55
+extern const VMStateDescription sdhci_vmstate;
56
+
57
+
58
+#define ESDHC_MIX_CTRL 0x48
59
+#define ESDHC_VENDOR_SPEC 0xc0
60
+#define ESDHC_DLL_CTRL 0x60
61
+
62
+#define ESDHC_TUNING_CTRL 0xcc
63
+#define ESDHC_TUNE_CTRL_STATUS 0x68
64
+#define ESDHC_WTMK_LVL 0x44
65
+
66
+/* Undocumented register used by guests working around erratum ERR004536 */
67
+#define ESDHC_UNDOCUMENTED_REG27 0x6c
68
+
69
+#define ESDHC_CTRL_4BITBUS (0x1 << 1)
70
+#define ESDHC_CTRL_8BITBUS (0x2 << 1)
71
+
72
#endif
73
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
74
index XXXXXXX..XXXXXXX 100644
75
--- a/include/hw/sd/sdhci.h
76
+++ b/include/hw/sd/sdhci.h
77
@@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState {
78
AddressSpace sysbus_dma_as;
79
AddressSpace *dma_as;
80
MemoryRegion *dma_mr;
81
+ const MemoryRegionOps *io_ops;
82
83
QEMUTimer *insert_timer; /* timer for 'changing' sd card. */
84
QEMUTimer *transfer_timer;
85
@@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState {
86
87
/* Configurable properties */
88
bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
89
+ uint32_t quirks;
90
} SDHCIState;
91
92
+/*
93
+ * Controller does not provide transfer-complete interrupt when not
94
+ * busy.
95
+ *
96
+ * NOTE: This definition is taken out of Linux kernel and so the
97
+ * original bit number is preserved
98
+ */
99
+#define SDHCI_QUIRK_NO_BUSY_IRQ BIT(14)
100
+
101
#define TYPE_PCI_SDHCI "sdhci-pci"
102
#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI)
103
104
@@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState {
105
#define SYSBUS_SDHCI(obj) \
106
OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI)
107
108
+#define TYPE_IMX_USDHC "imx-usdhc"
109
+
110
#endif /* SDHCI_H */
111
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/hw/sd/sdhci.c
114
+++ b/hw/sd/sdhci.c
115
@@ -XXX,XX +XXX,XX @@ static void sdhci_send_command(SDHCIState *s)
116
}
117
}
118
119
- if ((s->norintstsen & SDHC_NISEN_TRSCMP) &&
120
+ if (!(s->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
121
+ (s->norintstsen & SDHC_NISEN_TRSCMP) &&
122
(s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY) {
123
s->norintsts |= SDHC_NIS_TRSCMP;
124
}
125
@@ -XXX,XX +XXX,XX @@ static void sdhci_initfn(SDHCIState *s)
126
127
s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_raise_insertion_irq, s);
128
s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, s);
129
+
130
+ s->io_ops = &sdhci_mmio_ops;
131
}
132
133
static void sdhci_uninitfn(SDHCIState *s)
134
@@ -XXX,XX +XXX,XX @@ static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp)
135
}
54
}
136
55
137
sysbus_init_irq(sbd, &s->irq);
56
- which = pickNaNMulAdd(a->cls, b->cls, c->cls,
138
+
57
- ab_mask == float_cmask_infzero, s);
139
+ memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci",
58
+ if (infzero) {
140
+ SDHC_REGISTERS_MAP_SIZE);
59
+ /* This is (0 * inf) + NaN or (inf * 0) + NaN */
141
+
60
+ float_raise(float_flag_invalid | float_flag_invalid_imz, s);
142
sysbus_init_mmio(sbd, &s->iomem);
143
}
144
145
@@ -XXX,XX +XXX,XX @@ static const TypeInfo sdhci_bus_info = {
146
.class_init = sdhci_bus_class_init,
147
};
148
149
+static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
150
+{
151
+ SDHCIState *s = SYSBUS_SDHCI(opaque);
152
+ uint32_t ret;
153
+ uint16_t hostctl;
154
+
155
+ switch (offset) {
156
+ default:
157
+ return sdhci_read(opaque, offset, size);
158
+
159
+ case SDHC_HOSTCTL:
160
+ /*
161
+ * For a detailed explanation on the following bit
162
+ * manipulation code see comments in a similar part of
163
+ * usdhc_write()
164
+ */
165
+ hostctl = SDHC_DMA_TYPE(s->hostctl) << (8 - 3);
166
+
167
+ if (s->hostctl & SDHC_CTRL_8BITBUS) {
168
+ hostctl |= ESDHC_CTRL_8BITBUS;
169
+ }
170
+
171
+ if (s->hostctl & SDHC_CTRL_4BITBUS) {
172
+ hostctl |= ESDHC_CTRL_4BITBUS;
173
+ }
174
+
175
+ ret = hostctl;
176
+ ret |= (uint32_t)s->blkgap << 16;
177
+ ret |= (uint32_t)s->wakcon << 24;
178
+
179
+ break;
180
+
181
+ case ESDHC_DLL_CTRL:
182
+ case ESDHC_TUNE_CTRL_STATUS:
183
+ case ESDHC_UNDOCUMENTED_REG27:
184
+ case ESDHC_TUNING_CTRL:
185
+ case ESDHC_VENDOR_SPEC:
186
+ case ESDHC_MIX_CTRL:
187
+ case ESDHC_WTMK_LVL:
188
+ ret = 0;
189
+ break;
190
+ }
61
+ }
191
+
62
+
192
+ return ret;
63
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
193
+}
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
- }
194
+
112
+
195
+static void
113
/* Prefer sNaN over qNaN, in the c, a, b order. */
196
+usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
114
if (is_snan(c_cls)) {
197
+{
115
return 2;
198
+ SDHCIState *s = SYSBUS_SDHCI(opaque);
116
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
199
+ uint8_t hostctl;
117
* to return an input NaN if we have one (ie c) rather than generating
200
+ uint32_t value = (uint32_t)val;
118
* a default NaN
201
+
119
*/
202
+ switch (offset) {
120
- if (infzero) {
203
+ case ESDHC_DLL_CTRL:
121
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
204
+ case ESDHC_TUNE_CTRL_STATUS:
122
- return 2;
205
+ case ESDHC_UNDOCUMENTED_REG27:
123
- }
206
+ case ESDHC_TUNING_CTRL:
124
207
+ case ESDHC_WTMK_LVL:
125
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
208
+ case ESDHC_VENDOR_SPEC:
126
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
209
+ break;
127
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
210
+
128
return 1;
211
+ case SDHC_HOSTCTL:
129
}
212
+ /*
130
#elif defined(TARGET_RISCV)
213
+ * Here's What ESDHCI has at offset 0x28 (SDHC_HOSTCTL)
131
- /* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
214
+ *
132
- if (infzero) {
215
+ * 7 6 5 4 3 2 1 0
133
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
216
+ * |-----------+--------+--------+-----------+----------+---------|
134
- }
217
+ * | Card | Card | Endian | DATA3 | Data | Led |
135
return 3; /* default NaN */
218
+ * | Detect | Detect | Mode | as Card | Transfer | Control |
136
#elif defined(TARGET_S390X)
219
+ * | Signal | Test | | Detection | Width | |
137
if (infzero) {
220
+ * | Selection | Level | | Pin | | |
138
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
221
+ * |-----------+--------+--------+-----------+----------+---------|
139
return 3;
222
+ *
140
}
223
+ * and 0x29
141
224
+ *
142
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
225
+ * 15 10 9 8
143
return 2;
226
+ * |----------+------|
144
}
227
+ * | Reserved | DMA |
145
#elif defined(TARGET_SPARC)
228
+ * | | Sel. |
146
- /* For (inf,0,nan) return c. */
229
+ * | | |
147
- if (infzero) {
230
+ * |----------+------|
148
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
231
+ *
149
- return 2;
232
+ * and here's what SDCHI spec expects those offsets to be:
150
- }
233
+ *
151
/* Prefer SNaN over QNaN, order C, B, A. */
234
+ * 0x28 (Host Control Register)
152
if (is_snan(c_cls)) {
235
+ *
153
return 2;
236
+ * 7 6 5 4 3 2 1 0
154
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
237
+ * |--------+--------+----------+------+--------+----------+---------|
155
* For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
238
+ * | Card | Card | Extended | DMA | High | Data | LED |
156
* an input NaN if we have one (ie c).
239
+ * | Detect | Detect | Data | Sel. | Speed | Transfer | Control |
157
*/
240
+ * | Signal | Test | Transfer | | Enable | Width | |
158
- if (infzero) {
241
+ * | Sel. | Level | Width | | | | |
159
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
242
+ * |--------+--------+----------+------+--------+----------+---------|
160
- return 2;
243
+ *
161
- }
244
+ * and 0x29 (Power Control Register)
162
if (status->use_first_nan) {
245
+ *
163
if (is_nan(a_cls)) {
246
+ * |----------------------------------|
164
return 0;
247
+ * | Power Control Register |
248
+ * | |
249
+ * | Description omitted, |
250
+ * | since it has no analog in ESDHCI |
251
+ * | |
252
+ * |----------------------------------|
253
+ *
254
+ * Since offsets 0x2A and 0x2B should be compatible between
255
+ * both IP specs we only need to reconcile least 16-bit of the
256
+ * word we've been given.
257
+ */
258
+
259
+ /*
260
+ * First, save bits 7 6 and 0 since they are identical
261
+ */
262
+ hostctl = value & (SDHC_CTRL_LED |
263
+ SDHC_CTRL_CDTEST_INS |
264
+ SDHC_CTRL_CDTEST_EN);
265
+ /*
266
+ * Second, split "Data Transfer Width" from bits 2 and 1 in to
267
+ * bits 5 and 1
268
+ */
269
+ if (value & ESDHC_CTRL_8BITBUS) {
270
+ hostctl |= SDHC_CTRL_8BITBUS;
271
+ }
272
+
273
+ if (value & ESDHC_CTRL_4BITBUS) {
274
+ hostctl |= ESDHC_CTRL_4BITBUS;
275
+ }
276
+
277
+ /*
278
+ * Third, move DMA select from bits 9 and 8 to bits 4 and 3
279
+ */
280
+ hostctl |= SDHC_DMA_TYPE(value >> (8 - 3));
281
+
282
+ /*
283
+ * Now place the corrected value into low 16-bit of the value
284
+ * we are going to give standard SDHCI write function
285
+ *
286
+ * NOTE: This transformation should be the inverse of what can
287
+ * be found in drivers/mmc/host/sdhci-esdhc-imx.c in Linux
288
+ * kernel
289
+ */
290
+ value &= ~UINT16_MAX;
291
+ value |= hostctl;
292
+ value |= (uint16_t)s->pwrcon << 8;
293
+
294
+ sdhci_write(opaque, offset, value, size);
295
+ break;
296
+
297
+ case ESDHC_MIX_CTRL:
298
+ /*
299
+ * So, when SD/MMC stack in Linux tries to write to "Transfer
300
+ * Mode Register", ESDHC i.MX quirk code will translate it
301
+ * into a write to ESDHC_MIX_CTRL, so we do the opposite in
302
+ * order to get where we started
303
+ *
304
+ * Note that Auto CMD23 Enable bit is located in a wrong place
305
+ * on i.MX, but since it is not used by QEMU we do not care.
306
+ *
307
+ * We don't want to call sdhci_write(.., SDHC_TRNMOD, ...)
308
+ * here becuase it will result in a call to
309
+ * sdhci_send_command(s) which we don't want.
310
+ *
311
+ */
312
+ s->trnmod = value & UINT16_MAX;
313
+ break;
314
+ case SDHC_TRNMOD:
315
+ /*
316
+ * Similar to above, but this time a write to "Command
317
+ * Register" will be translated into a 4-byte write to
318
+ * "Transfer Mode register" where lower 16-bit of value would
319
+ * be set to zero. So what we do is fill those bits with
320
+ * cached value from s->trnmod and let the SDHCI
321
+ * infrastructure handle the rest
322
+ */
323
+ sdhci_write(opaque, offset, val | s->trnmod, size);
324
+ break;
325
+ case SDHC_BLKSIZE:
326
+ /*
327
+ * ESDHCI does not implement "Host SDMA Buffer Boundary", and
328
+ * Linux driver will try to zero this field out which will
329
+ * break the rest of SDHCI emulation.
330
+ *
331
+ * Linux defaults to maximum possible setting (512K boundary)
332
+ * and it seems to be the only option that i.MX IP implements,
333
+ * so we artificially set it to that value.
334
+ */
335
+ val |= 0x7 << 12;
336
+ /* FALLTHROUGH */
337
+ default:
338
+ sdhci_write(opaque, offset, val, size);
339
+ break;
340
+ }
341
+}
342
+
343
+
344
+static const MemoryRegionOps usdhc_mmio_ops = {
345
+ .read = usdhc_read,
346
+ .write = usdhc_write,
347
+ .valid = {
348
+ .min_access_size = 1,
349
+ .max_access_size = 4,
350
+ .unaligned = false
351
+ },
352
+ .endianness = DEVICE_LITTLE_ENDIAN,
353
+};
354
+
355
+static void imx_usdhc_init(Object *obj)
356
+{
357
+ SDHCIState *s = SYSBUS_SDHCI(obj);
358
+
359
+ s->io_ops = &usdhc_mmio_ops;
360
+ s->quirks = SDHCI_QUIRK_NO_BUSY_IRQ;
361
+}
362
+
363
+static const TypeInfo imx_usdhc_info = {
364
+ .name = TYPE_IMX_USDHC,
365
+ .parent = TYPE_SYSBUS_SDHCI,
366
+ .instance_init = imx_usdhc_init,
367
+};
368
+
369
static void sdhci_register_types(void)
370
{
371
type_register_static(&sdhci_pci_info);
372
type_register_static(&sdhci_sysbus_info);
373
type_register_static(&sdhci_bus_info);
374
+ type_register_static(&imx_usdhc_info);
375
}
376
377
type_init(sdhci_register_types)
378
--
165
--
379
2.16.1
166
2.34.1
380
381
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
Make the load of the exception vector from the vector table honour
1
IEEE 758 does not define a fixed rule for what NaN to return in
2
the SAU and any bus error on the load (possibly provoking a derived
2
the case of a fused multiply-add of inf * 0 + NaN. Different
3
exception), rather than simply aborting if the load fails.
3
architectures thus do different things:
4
* some return the default NaN
5
* some return the input NaN
6
* Arm returns the default NaN if the input NaN is quiet,
7
and the input NaN if it is signalling
8
9
We want to make this logic be runtime selected rather than
10
hardcoded into the binary, because:
11
* this will let us have multiple targets in one QEMU binary
12
* the Arm FEAT_AFP architectural feature includes letting
13
the guest select a NaN propagation rule at runtime
14
15
In this commit we add an enum for the propagation rule, the field in
16
float_status, and the corresponding getters and setters. We change
17
pickNaNMulAdd to honour this, but because all targets still leave
18
this field at its default 0 value, the fallback logic will pick the
19
rule type with the old ifdef ladder.
20
21
Note that four architectures both use the muladd softfloat functions
22
and did not have a branch of the ifdef ladder to specify their
23
behaviour (and so were ending up with the "default" case, probably
24
wrongly): i386, HPPA, SH4 and Tricore. SH4 and Tricore both set
25
default_nan_mode, and so will never get into pickNaNMulAdd(). For
26
HPPA and i386 we retain the same behaviour as the old default-case,
27
which is to not ever return the default NaN. This might not be
28
correct but it is not a behaviour change.
4
29
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 1517324542-6607-7-git-send-email-peter.maydell@linaro.org
32
Message-id: 20241202131347.498124-4-peter.maydell@linaro.org
8
---
33
---
9
target/arm/helper.c | 71 +++++++++++++++++++++++++++++++++++++++++------------
34
include/fpu/softfloat-helpers.h | 11 ++++
10
1 file changed, 55 insertions(+), 16 deletions(-)
35
include/fpu/softfloat-types.h | 23 +++++++++
11
36
fpu/softfloat-specialize.c.inc | 91 ++++++++++++++++++++++-----------
12
diff --git a/target/arm/helper.c b/target/arm/helper.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
13
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
41
--- a/include/fpu/softfloat-helpers.h
15
+++ b/target/arm/helper.c
42
+++ b/include/fpu/softfloat-helpers.h
16
@@ -XXX,XX +XXX,XX @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
43
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
17
}
44
status->float_2nan_prop_rule = rule;
18
}
45
}
19
46
20
-static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure)
47
+static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
21
+static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure,
48
+ float_status *status)
22
+ uint32_t *pvec)
49
+{
50
+ status->float_infzeronan_rule = rule;
51
+}
52
+
53
static inline void set_flush_to_zero(bool val, float_status *status)
23
{
54
{
24
CPUState *cs = CPU(cpu);
55
status->flush_to_zero = val;
25
CPUARMState *env = &cpu->env;
56
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
26
MemTxResult result;
57
return status->float_2nan_prop_rule;
27
- hwaddr vec = env->v7m.vecbase[targets_secure] + exc * 4;
58
}
28
- uint32_t addr;
59
29
+ uint32_t addr = env->v7m.vecbase[targets_secure] + exc * 4;
60
+static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
30
+ uint32_t vector_entry;
61
+{
31
+ MemTxAttrs attrs = {};
62
+ return status->float_infzeronan_rule;
32
+ ARMMMUIdx mmu_idx;
63
+}
33
+ bool exc_secure;
64
+
34
+
65
static inline bool get_flush_to_zero(float_status *status)
35
+ mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, targets_secure, true);
66
{
36
67
return status->flush_to_zero;
37
- addr = address_space_ldl(cs->as, vec,
68
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
38
- MEMTXATTRS_UNSPECIFIED, &result);
69
index XXXXXXX..XXXXXXX 100644
39
+ /* We don't do a get_phys_addr() here because the rules for vector
70
--- a/include/fpu/softfloat-types.h
40
+ * loads are special: they always use the default memory map, and
71
+++ b/include/fpu/softfloat-types.h
41
+ * the default memory map permits reads from all addresses.
72
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
42
+ * Since there's no easy way to pass through to pmsav8_mpu_lookup()
73
float_2nan_prop_x87,
43
+ * that we want this special case which would always say "yes",
74
} Float2NaNPropRule;
44
+ * we just do the SAU lookup here followed by a direct physical load.
75
45
+ */
76
+/*
46
+ attrs.secure = targets_secure;
77
+ * Rule for result of fused multiply-add 0 * Inf + NaN.
47
+ attrs.user = false;
78
+ * This must be a NaN, but implementations differ on whether this
48
+
79
+ * is the input NaN or the default NaN.
49
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
80
+ *
50
+ V8M_SAttributes sattrs = {};
81
+ * You don't need to set this if default_nan_mode is enabled.
51
+
82
+ * When not in default-NaN mode, it is an error for the target
52
+ v8m_security_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, &sattrs);
83
+ * not to set the rule in float_status if it uses muladd, and we
53
+ if (sattrs.ns) {
84
+ * will assert if we need to handle an input NaN and no rule was
54
+ attrs.secure = false;
85
+ * selected.
55
+ } else if (!targets_secure) {
86
+ */
56
+ /* NS access to S memory */
87
+typedef enum __attribute__((__packed__)) {
57
+ goto load_fail;
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();
58
+ }
188
+ }
59
+ }
189
+ }
60
+
190
+
61
+ vector_entry = address_space_ldl(arm_addressspace(cs, attrs), addr,
191
+#if defined(TARGET_ARM)
62
+ attrs, &result);
192
+
63
if (result != MEMTX_OK) {
193
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
64
- /* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
194
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
65
- * which would then be immediately followed by our failing to load
195
*/
66
- * the entry vector for that HardFault, which is a Lockup case.
196
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
67
- * Since we don't model Lockup, we just report this guest error
197
}
68
- * via cpu_abort().
198
#elif defined(TARGET_MIPS)
199
if (snan_bit_is_one(status)) {
200
- /*
201
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
202
- * case sets InvalidOp and returns the default NaN
69
- */
203
- */
70
- cpu_abort(cs, "Failed to read from %s exception vector table "
204
- if (infzero) {
71
- "entry %08x\n", targets_secure ? "secure" : "nonsecure",
205
- return 3;
72
- (unsigned)vec);
206
- }
73
+ goto load_fail;
207
/* Prefer sNaN over qNaN, in the a, b, c order. */
74
}
208
if (is_snan(a_cls)) {
75
- return addr;
209
return 0;
76
+ *pvec = vector_entry;
210
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
77
+ return true;
211
return 2;
78
+
212
}
79
+load_fail:
213
} else {
80
+ /* All vector table fetch fails are reported as HardFault, with
214
- /*
81
+ * HFSR.VECTTBL and .FORCED set. (FORCED is set because
215
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
82
+ * technically the underlying exception is a MemManage or BusFault
216
- * case sets InvalidOp and returns the input value 'c'
83
+ * that is escalated to HardFault.) This is a terminal exception,
217
- */
84
+ * so we will either take the HardFault immediately or else enter
218
/* Prefer sNaN over qNaN, in the c, a, b order. */
85
+ * lockup (the latter case is handled in armv7m_nvic_set_pending_derived()).
219
if (is_snan(c_cls)) {
86
+ */
220
return 2;
87
+ exc_secure = targets_secure ||
221
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
88
+ !(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK);
222
}
89
+ env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
223
}
90
+ armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
224
#elif defined(TARGET_LOONGARCH64)
91
+ return false;
225
- /*
92
}
226
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
93
227
- * case sets InvalidOp and returns the input value 'c'
94
static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
228
- */
95
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
229
-
96
return;
230
/* Prefer sNaN over qNaN, in the c, a, b order. */
97
}
231
if (is_snan(c_cls)) {
98
232
return 2;
99
- addr = arm_v7m_load_vector(cpu, exc, targets_secure);
233
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
100
+ if (!arm_v7m_load_vector(cpu, exc, targets_secure, &addr)) {
234
return 1;
101
+ /* Vector load failed: derived exception */
235
}
102
+ v7m_exception_taken(cpu, lr, true, true);
236
#elif defined(TARGET_PPC)
103
+ return;
237
- /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
104
+ }
238
- * to return an input NaN if we have one (ie c) rather than generating
105
239
- * a default NaN
106
/* Now we've done everything that might cause a derived exception
240
- */
107
* we can go ahead and activate whichever exception we're going to
241
-
242
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
243
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
244
*/
245
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
246
return 1;
247
}
248
#elif defined(TARGET_S390X)
249
- if (infzero) {
250
- return 3;
251
- }
252
-
253
if (is_snan(a_cls)) {
254
return 0;
255
} else if (is_snan(b_cls)) {
108
--
256
--
109
2.16.1
257
2.34.1
110
111
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
Make v7m_push_callee_stack() honour the MPU by using the
1
IEEE 758 does not define a fixed rule for which NaN to pick as the
2
new v7m_stack_write() function. We return a flag to indicate
2
result if both operands of a 3-operand fused multiply-add operation
3
whether the pushes failed, which we can then use in
3
are NaNs. As a result different architectures have ended up with
4
v7m_exception_taken() to cause us to handle the derived
4
different rules for propagating NaNs.
5
exception correctly.
5
6
QEMU currently hardcodes the NaN propagation logic into the binary
7
because pickNaNMulAdd() has an ifdef ladder for different targets.
8
We want to make the propagation rule instead be selectable at
9
runtime, because:
10
* this will let us have multiple targets in one QEMU binary
11
* the Arm FEAT_AFP architectural feature includes letting
12
the guest select a NaN propagation rule at runtime
13
14
In this commit we add an enum for the propagation rule, the field in
15
float_status, and the corresponding getters and setters. We change
16
pickNaNMulAdd to honour this, but because all targets still leave
17
this field at its default 0 value, the fallback logic will pick the
18
rule type with the old ifdef ladder.
19
20
It's valid not to set a propagation rule if default_nan_mode is
21
enabled, because in that case there's no need to pick a NaN; all the
22
callers of pickNaNMulAdd() catch this case and skip calling it.
6
23
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
26
Message-id: 20241202131347.498124-16-peter.maydell@linaro.org
10
Message-id: 1517324542-6607-6-git-send-email-peter.maydell@linaro.org
11
---
27
---
12
target/arm/helper.c | 64 ++++++++++++++++++++++++++++++++++++++++-------------
28
include/fpu/softfloat-helpers.h | 11 +++
13
1 file changed, 49 insertions(+), 15 deletions(-)
29
include/fpu/softfloat-types.h | 55 +++++++++++
14
30
fpu/softfloat-specialize.c.inc | 167 ++++++++------------------------
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
31
3 files changed, 107 insertions(+), 126 deletions(-)
32
33
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
16
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
35
--- a/include/fpu/softfloat-helpers.h
18
+++ b/target/arm/helper.c
36
+++ b/include/fpu/softfloat-helpers.h
19
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure)
37
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
20
return addr;
38
status->float_2nan_prop_rule = rule;
21
}
39
}
22
40
23
-static void v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
41
+static inline void set_float_3nan_prop_rule(Float3NaNPropRule rule,
24
+static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
42
+ float_status *status)
25
bool ignore_faults)
43
+{
44
+ status->float_3nan_prop_rule = rule;
45
+}
46
+
47
static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
float_status *status)
26
{
49
{
27
/* For v8M, push the callee-saves register part of the stack frame.
50
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
28
@@ -XXX,XX +XXX,XX @@ static void v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
51
return status->float_2nan_prop_rule;
29
* In the tailchaining case this may not be the current stack.
30
*/
31
CPUARMState *env = &cpu->env;
32
- CPUState *cs = CPU(cpu);
33
uint32_t *frame_sp_p;
34
uint32_t frameptr;
35
+ ARMMMUIdx mmu_idx;
36
+ bool stacked_ok;
37
38
if (dotailchain) {
39
- frame_sp_p = get_v7m_sp_ptr(env, true,
40
- lr & R_V7M_EXCRET_MODE_MASK,
41
+ bool mode = lr & R_V7M_EXCRET_MODE_MASK;
42
+ bool priv = !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_NPRIV_MASK) ||
43
+ !mode;
44
+
45
+ mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, M_REG_S, priv);
46
+ frame_sp_p = get_v7m_sp_ptr(env, M_REG_S, mode,
47
lr & R_V7M_EXCRET_SPSEL_MASK);
48
} else {
49
+ mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
50
frame_sp_p = &env->regs[13];
51
}
52
53
frameptr = *frame_sp_p - 0x28;
54
55
- stl_phys(cs->as, frameptr, 0xfefa125b);
56
- stl_phys(cs->as, frameptr + 0x8, env->regs[4]);
57
- stl_phys(cs->as, frameptr + 0xc, env->regs[5]);
58
- stl_phys(cs->as, frameptr + 0x10, env->regs[6]);
59
- stl_phys(cs->as, frameptr + 0x14, env->regs[7]);
60
- stl_phys(cs->as, frameptr + 0x18, env->regs[8]);
61
- stl_phys(cs->as, frameptr + 0x1c, env->regs[9]);
62
- stl_phys(cs->as, frameptr + 0x20, env->regs[10]);
63
- stl_phys(cs->as, frameptr + 0x24, env->regs[11]);
64
+ /* Write as much of the stack frame as we can. A write failure may
65
+ * cause us to pend a derived exception.
66
+ */
67
+ stacked_ok =
68
+ v7m_stack_write(cpu, frameptr, 0xfefa125b, mmu_idx, ignore_faults) &&
69
+ v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx,
70
+ ignore_faults) &&
71
+ v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx,
72
+ ignore_faults) &&
73
+ v7m_stack_write(cpu, frameptr + 0x10, env->regs[6], mmu_idx,
74
+ ignore_faults) &&
75
+ v7m_stack_write(cpu, frameptr + 0x14, env->regs[7], mmu_idx,
76
+ ignore_faults) &&
77
+ v7m_stack_write(cpu, frameptr + 0x18, env->regs[8], mmu_idx,
78
+ ignore_faults) &&
79
+ v7m_stack_write(cpu, frameptr + 0x1c, env->regs[9], mmu_idx,
80
+ ignore_faults) &&
81
+ v7m_stack_write(cpu, frameptr + 0x20, env->regs[10], mmu_idx,
82
+ ignore_faults) &&
83
+ v7m_stack_write(cpu, frameptr + 0x24, env->regs[11], mmu_idx,
84
+ ignore_faults);
85
86
+ /* Update SP regardless of whether any of the stack accesses failed.
87
+ * When we implement v8M stack limit checking then this attempt to
88
+ * update SP might also fail and result in a derived exception.
89
+ */
90
*frame_sp_p = frameptr;
91
+
92
+ return !stacked_ok;
93
}
52
}
94
53
95
static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
54
+static inline Float3NaNPropRule get_float_3nan_prop_rule(float_status *status)
96
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
55
+{
97
uint32_t addr;
56
+ return status->float_3nan_prop_rule;
98
bool targets_secure;
57
+}
99
int exc;
58
+
100
+ bool push_failed = false;
59
static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
101
60
{
102
armv7m_nvic_get_pending_irq_info(env->nvic, &exc, &targets_secure);
61
return status->float_infzeronan_rule;
103
62
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
104
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
63
index XXXXXXX..XXXXXXX 100644
105
*/
64
--- a/include/fpu/softfloat-types.h
106
if (lr & R_V7M_EXCRET_DCRS_MASK &&
65
+++ b/include/fpu/softfloat-types.h
107
!(dotailchain && (lr & R_V7M_EXCRET_ES_MASK))) {
66
@@ -XXX,XX +XXX,XX @@ this code that are retained.
108
- v7m_push_callee_stack(cpu, lr, dotailchain,
67
#ifndef SOFTFLOAT_TYPES_H
109
- ignore_stackfaults);
68
#define SOFTFLOAT_TYPES_H
110
+ push_failed = v7m_push_callee_stack(cpu, lr, dotailchain,
69
111
+ ignore_stackfaults);
70
+#include "hw/registerfields.h"
112
}
71
+
113
lr |= R_V7M_EXCRET_DCRS_MASK;
72
/*
114
}
73
* Software IEC/IEEE floating-point types.
115
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
74
*/
75
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
76
float_2nan_prop_x87,
77
} Float2NaNPropRule;
78
79
+/*
80
+ * 3-input NaN propagation rule, for fused multiply-add. Individual
81
+ * architectures have different rules for which input NaN is
82
+ * propagated to the output when there is more than one NaN on the
83
+ * input.
84
+ *
85
+ * If default_nan_mode is enabled then it is valid not to set a NaN
86
+ * propagation rule, because the softfloat code guarantees not to try
87
+ * to pick a NaN to propagate in default NaN mode. When not in
88
+ * default-NaN mode, it is an error for the target not to set the rule
89
+ * in float_status if it uses a muladd, and we will assert if we need
90
+ * to handle an input NaN and no rule was selected.
91
+ *
92
+ * The naming scheme for Float3NaNPropRule values is:
93
+ * float_3nan_prop_s_abc:
94
+ * = "Prefer SNaN over QNaN, then operand A over B over C"
95
+ * float_3nan_prop_abc:
96
+ * = "Prefer A over B over C regardless of SNaN vs QNAN"
97
+ *
98
+ * For QEMU, the multiply-add operation is A * B + C.
99
+ */
100
+
101
+/*
102
+ * We set the Float3NaNPropRule enum values up so we can select the
103
+ * right value in pickNaNMulAdd in a data driven way.
104
+ */
105
+FIELD(3NAN, 1ST, 0, 2) /* which operand is most preferred ? */
106
+FIELD(3NAN, 2ND, 2, 2) /* which operand is next most preferred ? */
107
+FIELD(3NAN, 3RD, 4, 2) /* which operand is least preferred ? */
108
+FIELD(3NAN, SNAN, 6, 1) /* do we prefer SNaN over QNaN ? */
109
+
110
+#define PROPRULE(X, Y, Z) \
111
+ ((X << R_3NAN_1ST_SHIFT) | (Y << R_3NAN_2ND_SHIFT) | (Z << R_3NAN_3RD_SHIFT))
112
+
113
+typedef enum __attribute__((__packed__)) {
114
+ float_3nan_prop_none = 0, /* No propagation rule specified */
115
+ float_3nan_prop_abc = PROPRULE(0, 1, 2),
116
+ float_3nan_prop_acb = PROPRULE(0, 2, 1),
117
+ float_3nan_prop_bac = PROPRULE(1, 0, 2),
118
+ float_3nan_prop_bca = PROPRULE(1, 2, 0),
119
+ float_3nan_prop_cab = PROPRULE(2, 0, 1),
120
+ float_3nan_prop_cba = PROPRULE(2, 1, 0),
121
+ float_3nan_prop_s_abc = float_3nan_prop_abc | R_3NAN_SNAN_MASK,
122
+ float_3nan_prop_s_acb = float_3nan_prop_acb | R_3NAN_SNAN_MASK,
123
+ float_3nan_prop_s_bac = float_3nan_prop_bac | R_3NAN_SNAN_MASK,
124
+ float_3nan_prop_s_bca = float_3nan_prop_bca | R_3NAN_SNAN_MASK,
125
+ float_3nan_prop_s_cab = float_3nan_prop_cab | R_3NAN_SNAN_MASK,
126
+ float_3nan_prop_s_cba = float_3nan_prop_cba | R_3NAN_SNAN_MASK,
127
+} Float3NaNPropRule;
128
+
129
+#undef PROPRULE
130
+
131
/*
132
* Rule for result of fused multiply-add 0 * Inf + NaN.
133
* This must be a NaN, but implementations differ on whether this
134
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
135
FloatRoundMode float_rounding_mode;
136
FloatX80RoundPrec floatx80_rounding_precision;
137
Float2NaNPropRule float_2nan_prop_rule;
138
+ Float3NaNPropRule float_3nan_prop_rule;
139
FloatInfZeroNaNRule float_infzeronan_rule;
140
bool tininess_before_rounding;
141
/* should denormalised results go to zero and set the inexact flag? */
142
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
143
index XXXXXXX..XXXXXXX 100644
144
--- a/fpu/softfloat-specialize.c.inc
145
+++ b/fpu/softfloat-specialize.c.inc
146
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
147
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
148
bool infzero, bool have_snan, float_status *status)
149
{
150
+ FloatClass cls[3] = { a_cls, b_cls, c_cls };
151
+ Float3NaNPropRule rule = status->float_3nan_prop_rule;
152
+ int which;
153
+
154
/*
155
* We guarantee not to require the target to tell us how to
156
* pick a NaN if we're always returning the default NaN.
157
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
116
}
158
}
117
}
159
}
118
160
119
+ if (push_failed && !ignore_stackfaults) {
161
+ if (rule == float_3nan_prop_none) {
120
+ /* Derived exception on callee-saves register stacking:
162
#if defined(TARGET_ARM)
121
+ * we might now want to take a different exception which
163
-
122
+ * targets a different security state, so try again from the top.
164
- /* This looks different from the ARM ARM pseudocode, because the ARM ARM
165
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
166
- */
167
- if (is_snan(c_cls)) {
168
- return 2;
169
- } else if (is_snan(a_cls)) {
170
- return 0;
171
- } else if (is_snan(b_cls)) {
172
- return 1;
173
- } else if (is_qnan(c_cls)) {
174
- return 2;
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
123
+ */
183
+ */
124
+ v7m_exception_taken(cpu, lr, true, true);
184
+ rule = float_3nan_prop_s_cab;
125
+ return;
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
126
+ }
321
+ }
127
+
322
+
128
addr = arm_v7m_load_vector(cpu, exc, targets_secure);
323
+ assert(rule != float_3nan_prop_none);
129
324
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
130
/* Now we've done everything that might cause a derived exception
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
/*----------------------------------------------------------------------------
131
--
340
--
132
2.16.1
341
2.34.1
133
134
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
1
The code where we added the TT instruction was accidentally
1
Set the Float3NaNPropRule explicitly for i386. We had no
2
missing a 'break', which meant that after generating the code
2
i386-specific behaviour in the old ifdef ladder, so we were using the
3
to execute the TT we would fall through to 'goto illegal_op'
3
default "prefer a then b then c" fallback; this is actually the
4
and generate code to take an UNDEF insn.
4
correct per-the-spec handling for i386.
5
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180206103941.13985-1-peter.maydell@linaro.org
8
Message-id: 20241202131347.498124-25-peter.maydell@linaro.org
9
---
9
---
10
target/arm/translate.c | 1 +
10
target/i386/tcg/fpu_helper.c | 1 +
11
1 file changed, 1 insertion(+)
11
1 file changed, 1 insertion(+)
12
12
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
13
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
15
--- a/target/i386/tcg/fpu_helper.c
16
+++ b/target/arm/translate.c
16
+++ b/target/i386/tcg/fpu_helper.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
17
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
18
tcg_temp_free_i32(addr);
18
* there are multiple input NaNs they are selected in the order a, b, c.
19
tcg_temp_free_i32(op);
19
*/
20
store_reg(s, rd, ttresp);
20
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
21
+ break;
21
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
22
}
22
}
23
goto illegal_op;
23
24
}
24
static inline uint8_t save_exception_flags(CPUX86State *env)
25
--
25
--
26
2.16.1
26
2.34.1
27
28
diff view generated by jsdifflib
1
Currently armv7m_nvic_acknowledge_irq() does three things:
1
Set the Float3NaNPropRule explicitly for HPPA, and remove the
2
* make the current highest priority pending interrupt active
2
ifdef from pickNaNMulAdd().
3
* return a bool indicating whether that interrupt is targeting
4
Secure or NonSecure state
5
* implicitly tell the caller which is the highest priority
6
pending interrupt by setting env->v7m.exception
7
3
8
We need to split these jobs, because v7m_exception_taken()
4
HPPA is the only target that was using the default branch of the
9
needs to know whether the pending interrupt targets Secure so
5
ifdef ladder (other targets either do not use muladd or set
10
it can choose to stack callee-saves registers or not, but it
6
default_nan_mode), so we can remove the ifdef fallback entirely now
11
must not make the interrupt active until after it has done
7
(allowing the "rule not set" case to fall into the default of the
12
that stacking, in case the stacking causes a derived exception.
8
switch statement and assert).
13
Similarly, it needs to know the number of the pending interrupt
14
so it can read the correct vector table entry before the
15
interrupt is made active, because vector table reads might
16
also cause a derived exception.
17
9
18
Create a new armv7m_nvic_get_pending_irq_info() function which simply
10
We add a TODO note that the HPPA rule is probably wrong; this is
19
returns information about the highest priority pending interrupt, and
11
not a behavioural change for this refactoring.
20
use it to rearrange the v7m_exception_taken() code so we don't
21
acknowledge the exception until we've done all the things which could
22
possibly cause a derived exception.
23
12
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20241202131347.498124-26-peter.maydell@linaro.org
27
Message-id: 1517324542-6607-3-git-send-email-peter.maydell@linaro.org
28
---
16
---
29
target/arm/cpu.h | 19 ++++++++++++++++---
17
target/hppa/fpu_helper.c | 8 ++++++++
30
hw/intc/armv7m_nvic.c | 30 +++++++++++++++++++++++-------
18
fpu/softfloat-specialize.c.inc | 4 ----
31
target/arm/helper.c | 16 ++++++++++++----
19
2 files changed, 8 insertions(+), 4 deletions(-)
32
hw/intc/trace-events | 3 ++-
33
4 files changed, 53 insertions(+), 15 deletions(-)
34
20
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
36
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.h
23
--- a/target/hppa/fpu_helper.c
38
+++ b/target/arm/cpu.h
24
+++ b/target/hppa/fpu_helper.c
39
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure);
25
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
40
* a different exception).
26
* HPPA does note implement a CPU reset method at all...
41
*/
27
*/
42
void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
28
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
43
+/**
29
+ /*
44
+ * armv7m_nvic_get_pending_irq_info: return highest priority pending
30
+ * TODO: The HPPA architecture reference only documents its NaN
45
+ * exception, and whether it targets Secure state
31
+ * propagation rule for 2-operand operations. Testing on real hardware
46
+ * @opaque: the NVIC
32
+ * might be necessary to confirm whether this order for muladd is correct.
47
+ * @pirq: set to pending exception number
33
+ * Not preferring the SNaN is almost certainly incorrect as it diverges
48
+ * @ptargets_secure: set to whether pending exception targets Secure
34
+ * from the documented rules for 2-operand operations.
49
+ *
35
+ */
50
+ * This function writes the number of the highest priority pending
36
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
51
+ * exception (the one which would be made active by
37
/* For inf * 0 + NaN, return the input NaN */
52
+ * armv7m_nvic_acknowledge_irq()) to @pirq, and sets @ptargets_secure
38
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
53
+ * to true if the current highest priority pending exception should
39
}
54
+ * be taken to Secure state, false for NS.
40
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
55
+ */
56
+void armv7m_nvic_get_pending_irq_info(void *opaque, int *pirq,
57
+ bool *ptargets_secure);
58
/**
59
* armv7m_nvic_acknowledge_irq: make highest priority pending exception active
60
* @opaque: the NVIC
61
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
62
* Move the current highest priority pending exception from the pending
63
* state to the active state, and update v7m.exception to indicate that
64
* it is the exception currently being handled.
65
- *
66
- * Returns: true if exception should be taken to Secure state, false for NS
67
*/
68
-bool armv7m_nvic_acknowledge_irq(void *opaque);
69
+void armv7m_nvic_acknowledge_irq(void *opaque);
70
/**
71
* armv7m_nvic_complete_irq: complete specified interrupt or exception
72
* @opaque: the NVIC
73
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
74
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/intc/armv7m_nvic.c
42
--- a/fpu/softfloat-specialize.c.inc
76
+++ b/hw/intc/armv7m_nvic.c
43
+++ b/fpu/softfloat-specialize.c.inc
77
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure)
44
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
78
}
79
80
/* Make pending IRQ active. */
81
-bool armv7m_nvic_acknowledge_irq(void *opaque)
82
+void armv7m_nvic_acknowledge_irq(void *opaque)
83
{
84
NVICState *s = (NVICState *)opaque;
85
CPUARMState *env = &s->cpu->env;
86
const int pending = s->vectpending;
87
const int running = nvic_exec_prio(s);
88
VecInfo *vec;
89
- bool targets_secure;
90
91
assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
92
93
if (s->vectpending_is_s_banked) {
94
vec = &s->sec_vectors[pending];
95
- targets_secure = true;
96
} else {
97
vec = &s->vectors[pending];
98
- targets_secure = !exc_is_banked(s->vectpending) &&
99
- exc_targets_secure(s, s->vectpending);
100
}
101
102
assert(vec->enabled);
103
@@ -XXX,XX +XXX,XX @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
104
105
assert(s->vectpending_prio < running);
106
107
- trace_nvic_acknowledge_irq(pending, s->vectpending_prio, targets_secure);
108
+ trace_nvic_acknowledge_irq(pending, s->vectpending_prio);
109
110
vec->active = 1;
111
vec->pending = 0;
112
@@ -XXX,XX +XXX,XX @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
113
write_v7m_exception(env, s->vectpending);
114
115
nvic_irq_update(s);
116
+}
117
+
118
+void armv7m_nvic_get_pending_irq_info(void *opaque,
119
+ int *pirq, bool *ptargets_secure)
120
+{
121
+ NVICState *s = (NVICState *)opaque;
122
+ const int pending = s->vectpending;
123
+ bool targets_secure;
124
+
125
+ assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
126
+
127
+ if (s->vectpending_is_s_banked) {
128
+ targets_secure = true;
129
+ } else {
130
+ targets_secure = !exc_is_banked(pending) &&
131
+ exc_targets_secure(s, pending);
132
+ }
133
+
134
+ trace_nvic_get_pending_irq_info(pending, targets_secure);
135
136
- return targets_secure;
137
+ *ptargets_secure = targets_secure;
138
+ *pirq = pending;
139
}
140
141
int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
142
diff --git a/target/arm/helper.c b/target/arm/helper.c
143
index XXXXXXX..XXXXXXX 100644
144
--- a/target/arm/helper.c
145
+++ b/target/arm/helper.c
146
@@ -XXX,XX +XXX,XX @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
147
}
148
}
149
150
-static uint32_t arm_v7m_load_vector(ARMCPU *cpu, bool targets_secure)
151
+static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure)
152
{
153
CPUState *cs = CPU(cpu);
154
CPUARMState *env = &cpu->env;
155
MemTxResult result;
156
- hwaddr vec = env->v7m.vecbase[targets_secure] + env->v7m.exception * 4;
157
+ hwaddr vec = env->v7m.vecbase[targets_secure] + exc * 4;
158
uint32_t addr;
159
160
addr = address_space_ldl(cs->as, vec,
161
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
162
CPUARMState *env = &cpu->env;
163
uint32_t addr;
164
bool targets_secure;
165
+ int exc;
166
167
- targets_secure = armv7m_nvic_acknowledge_irq(env->nvic);
168
+ armv7m_nvic_get_pending_irq_info(env->nvic, &exc, &targets_secure);
169
170
if (arm_feature(env, ARM_FEATURE_V8)) {
171
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
172
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
173
}
45
}
174
}
46
}
175
47
176
+ addr = arm_v7m_load_vector(cpu, exc, targets_secure);
48
- if (rule == float_3nan_prop_none) {
177
+
49
- rule = float_3nan_prop_abc;
178
+ /* Now we've done everything that might cause a derived exception
50
- }
179
+ * we can go ahead and activate whichever exception we're going to
51
-
180
+ * take (which might now be the derived exception).
52
assert(rule != float_3nan_prop_none);
181
+ */
53
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
182
+ armv7m_nvic_acknowledge_irq(env->nvic);
54
/* We have at least one SNaN input and should prefer it */
183
+
184
/* Switch to target security state -- must do this before writing SPSEL */
185
switch_v7m_security_state(env, targets_secure);
186
write_v7m_control_spsel(env, 0);
187
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
188
/* Clear IT bits */
189
env->condexec_bits = 0;
190
env->regs[14] = lr;
191
- addr = arm_v7m_load_vector(cpu, targets_secure);
192
env->regs[15] = addr & 0xfffffffe;
193
env->thumb = addr & 1;
194
}
195
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
196
index XXXXXXX..XXXXXXX 100644
197
--- a/hw/intc/trace-events
198
+++ b/hw/intc/trace-events
199
@@ -XXX,XX +XXX,XX @@ nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled"
200
nvic_set_pending(int irq, bool secure, bool derived, int en, int prio) "NVIC set pending irq %d secure-bank %d derived %d (enabled: %d priority %d)"
201
nvic_clear_pending(int irq, bool secure, int en, int prio) "NVIC clear pending irq %d secure-bank %d (enabled: %d priority %d)"
202
nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1"
203
-nvic_acknowledge_irq(int irq, int prio, bool targets_secure) "NVIC acknowledge IRQ: %d now active (prio %d targets_secure %d)"
204
+nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (prio %d)"
205
+nvic_get_pending_irq_info(int irq, bool secure) "NVIC next IRQ %d: targets_secure: %d"
206
nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)"
207
nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
208
nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
209
--
55
--
210
2.16.1
56
2.34.1
211
212
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
In the v8M architecture, if the process of taking an exception
1
In the helper functions flcmps and flcmpd we use a scratch float_status
2
results in a further exception this is called a derived exception
2
so that we don't change the CPU state if the comparison raises any
3
(for example, an MPU exception when writing the exception frame to
3
floating point exception flags. Instead of zero-initializing this
4
memory). If the derived exception happens while pushing the initial
4
scratch float_status, initialize it as a copy of env->fp_status. This
5
stack frame, we must ignore any subsequent possible exception
5
avoids the need to explicitly initialize settings like the NaN
6
pushing the callee-saves registers.
6
propagation rule or others we might add to softfloat in future.
7
7
8
In preparation for making the stack writes check for exceptions,
8
To do this we need to pass the CPU env pointer in to the helper.
9
add a return value from v7m_push_stack() and a new parameter to
10
v7m_exception_taken(), so that the former can tell the latter that
11
it needs to ignore failures to write to the stack. We also plumb
12
the argument through to v7m_push_callee_stack(), which is where
13
the code to ignore the failures will be.
14
15
(Note that the v8M ARM pseudocode structures this slightly differently:
16
derived exceptions cause the attempt to process the original
17
exception to be abandoned; then at the top level it calls
18
DerivedLateArrival to prioritize the derived exception and call
19
TakeException from there. We choose to let the NVIC do the prioritization
20
and continue forward with a call to TakeException which will then
21
take either the original or the derived exception. The effect is
22
the same, but this structure works better for QEMU because we don't
23
have a convenient top level place to do the abandon-and-retry logic.)
24
9
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 1517324542-6607-4-git-send-email-peter.maydell@linaro.org
12
Message-id: 20241202131347.498124-33-peter.maydell@linaro.org
28
---
13
---
29
target/arm/helper.c | 35 +++++++++++++++++++++++------------
14
target/sparc/helper.h | 4 ++--
30
1 file changed, 23 insertions(+), 12 deletions(-)
15
target/sparc/fop_helper.c | 8 ++++----
16
target/sparc/translate.c | 4 ++--
17
3 files changed, 8 insertions(+), 8 deletions(-)
31
18
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
33
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/helper.c
21
--- a/target/sparc/helper.h
35
+++ b/target/arm/helper.c
22
+++ b/target/sparc/helper.h
36
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure)
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
37
return addr;
24
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
25
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128)
26
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128)
27
-DEF_HELPER_FLAGS_2(flcmps, TCG_CALL_NO_RWG_SE, i32, f32, f32)
28
-DEF_HELPER_FLAGS_2(flcmpd, TCG_CALL_NO_RWG_SE, i32, f64, f64)
29
+DEF_HELPER_FLAGS_3(flcmps, TCG_CALL_NO_RWG_SE, i32, env, f32, f32)
30
+DEF_HELPER_FLAGS_3(flcmpd, TCG_CALL_NO_RWG_SE, i32, env, f64, f64)
31
DEF_HELPER_2(raise_exception, noreturn, env, int)
32
33
DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64)
34
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/sparc/fop_helper.c
37
+++ b/target/sparc/fop_helper.c
38
@@ -XXX,XX +XXX,XX @@ uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
39
return finish_fcmp(env, r, GETPC());
38
}
40
}
39
41
40
-static void v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain)
42
-uint32_t helper_flcmps(float32 src1, float32 src2)
41
+static void v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
43
+uint32_t helper_flcmps(CPUSPARCState *env, float32 src1, float32 src2)
42
+ bool ignore_faults)
43
{
44
{
44
/* For v8M, push the callee-saves register part of the stack frame.
45
/*
45
* Compare the v8M pseudocode PushCalleeStack().
46
* FLCMP never raises an exception nor modifies any FSR fields.
46
@@ -XXX,XX +XXX,XX @@ static void v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain)
47
* Perform the comparison with a dummy fp environment.
47
*frame_sp_p = frameptr;
48
*/
49
- float_status discard = { };
50
+ float_status discard = env->fp_status;
51
FloatRelation r;
52
53
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
54
@@ -XXX,XX +XXX,XX @@ uint32_t helper_flcmps(float32 src1, float32 src2)
55
g_assert_not_reached();
48
}
56
}
49
57
50
-static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
58
-uint32_t helper_flcmpd(float64 src1, float64 src2)
51
+static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
59
+uint32_t helper_flcmpd(CPUSPARCState *env, float64 src1, float64 src2)
52
+ bool ignore_stackfaults)
53
{
60
{
54
/* Do the "take the exception" parts of exception entry,
61
- float_status discard = { };
55
* but not the pushing of state to the stack. This is
62
+ float_status discard = env->fp_status;
56
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
63
FloatRelation r;
57
*/
64
58
if (lr & R_V7M_EXCRET_DCRS_MASK &&
65
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
59
!(dotailchain && (lr & R_V7M_EXCRET_ES_MASK))) {
66
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
60
- v7m_push_callee_stack(cpu, lr, dotailchain);
67
index XXXXXXX..XXXXXXX 100644
61
+ v7m_push_callee_stack(cpu, lr, dotailchain,
68
--- a/target/sparc/translate.c
62
+ ignore_stackfaults);
69
+++ b/target/sparc/translate.c
63
}
70
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a)
64
lr |= R_V7M_EXCRET_DCRS_MASK;
71
65
}
72
src1 = gen_load_fpr_F(dc, a->rs1);
66
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
73
src2 = gen_load_fpr_F(dc, a->rs2);
67
env->thumb = addr & 1;
74
- gen_helper_flcmps(cpu_fcc[a->cc], src1, src2);
75
+ gen_helper_flcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
76
return advance_pc(dc);
68
}
77
}
69
78
70
-static void v7m_push_stack(ARMCPU *cpu)
79
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
71
+static bool v7m_push_stack(ARMCPU *cpu)
80
72
{
81
src1 = gen_load_fpr_D(dc, a->rs1);
73
/* Do the "set up stack frame" part of exception entry,
82
src2 = gen_load_fpr_D(dc, a->rs2);
74
* similar to pseudocode PushStack().
83
- gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
75
+ * Return true if we generate a derived exception (and so
84
+ gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
76
+ * should ignore further stack faults trying to process
85
return advance_pc(dc);
77
+ * that derived exception.)
78
*/
79
CPUARMState *env = &cpu->env;
80
uint32_t xpsr = xpsr_read(env);
81
@@ -XXX,XX +XXX,XX @@ static void v7m_push_stack(ARMCPU *cpu)
82
v7m_push(env, env->regs[2]);
83
v7m_push(env, env->regs[1]);
84
v7m_push(env, env->regs[0]);
85
+
86
+ return false;
87
}
86
}
88
87
89
static void do_v7m_exception_exit(ARMCPU *cpu)
90
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
91
if (sfault) {
92
env->v7m.sfsr |= R_V7M_SFSR_INVER_MASK;
93
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
94
- v7m_exception_taken(cpu, excret, true);
95
+ v7m_exception_taken(cpu, excret, true, false);
96
qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
97
"stackframe: failed EXC_RETURN.ES validity check\n");
98
return;
99
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
100
*/
101
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
102
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
103
- v7m_exception_taken(cpu, excret, true);
104
+ v7m_exception_taken(cpu, excret, true, false);
105
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
106
"stackframe: failed exception return integrity check\n");
107
return;
108
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
109
/* Take a SecureFault on the current stack */
110
env->v7m.sfsr |= R_V7M_SFSR_INVIS_MASK;
111
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
112
- v7m_exception_taken(cpu, excret, true);
113
+ v7m_exception_taken(cpu, excret, true, false);
114
qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
115
"stackframe: failed exception return integrity "
116
"signature check\n");
117
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
118
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
119
env->v7m.secure);
120
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
121
- v7m_exception_taken(cpu, excret, true);
122
+ v7m_exception_taken(cpu, excret, true, false);
123
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
124
"stackframe: failed exception return integrity "
125
"check\n");
126
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
127
/* Take an INVPC UsageFault by pushing the stack again;
128
* we know we're v7M so this is never a Secure UsageFault.
129
*/
130
+ bool ignore_stackfaults;
131
+
132
assert(!arm_feature(env, ARM_FEATURE_V8));
133
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, false);
134
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVPC_MASK;
135
- v7m_push_stack(cpu);
136
- v7m_exception_taken(cpu, excret, false);
137
+ ignore_stackfaults = v7m_push_stack(cpu);
138
+ v7m_exception_taken(cpu, excret, false, ignore_stackfaults);
139
qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on new stackframe: "
140
"failed exception return integrity check\n");
141
return;
142
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
143
ARMCPU *cpu = ARM_CPU(cs);
144
CPUARMState *env = &cpu->env;
145
uint32_t lr;
146
+ bool ignore_stackfaults;
147
148
arm_log_exception(cs->exception_index);
149
150
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
151
lr |= R_V7M_EXCRET_MODE_MASK;
152
}
153
154
- v7m_push_stack(cpu);
155
- v7m_exception_taken(cpu, lr, false);
156
+ ignore_stackfaults = v7m_push_stack(cpu);
157
+ v7m_exception_taken(cpu, lr, false, ignore_stackfaults);
158
qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception);
159
}
160
161
--
88
--
162
2.16.1
89
2.34.1
163
164
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: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add minimal code needed to allow upstream Linux guest to boot.
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
5
Cc: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Cc: Jason Wang <jasowang@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
9
Cc: Michael S. Tsirkin <mst@redhat.com>
10
Cc: qemu-devel@nongnu.org
11
Cc: qemu-arm@nongnu.org
12
Cc: yurovsky@gmail.com
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
12
Message-id: 20241203203949.483774-2-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
14
---
18
include/hw/timer/imx_gpt.h | 1 +
15
target/arm/tcg/vec_helper.c | 20 +++++++-------------
19
hw/timer/imx_gpt.c | 25 +++++++++++++++++++++++++
16
1 file changed, 7 insertions(+), 13 deletions(-)
20
2 files changed, 26 insertions(+)
21
17
22
diff --git a/include/hw/timer/imx_gpt.h b/include/hw/timer/imx_gpt.h
18
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/timer/imx_gpt.h
20
--- a/target/arm/tcg/vec_helper.c
25
+++ b/include/hw/timer/imx_gpt.h
21
+++ b/target/arm/tcg/vec_helper.c
26
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp)
27
#define TYPE_IMX25_GPT "imx25.gpt"
23
* no effect on AArch32 instructions.
28
#define TYPE_IMX31_GPT "imx31.gpt"
24
*/
29
#define TYPE_IMX6_GPT "imx6.gpt"
25
bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF;
30
+#define TYPE_IMX7_GPT "imx7.gpt"
26
- *statusp = (float_status){
31
27
- .tininess_before_rounding = float_tininess_before_rounding,
32
#define TYPE_IMX_GPT TYPE_IMX25_GPT
28
- .float_rounding_mode = float_round_to_odd_inf,
33
29
- .flush_to_zero = true,
34
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
30
- .flush_inputs_to_zero = true,
35
index XXXXXXX..XXXXXXX 100644
31
- .default_nan_mode = true,
36
--- a/hw/timer/imx_gpt.c
32
- };
37
+++ b/hw/timer/imx_gpt.c
38
@@ -XXX,XX +XXX,XX @@ static const IMXClk imx6_gpt_clocks[] = {
39
CLK_HIGH, /* 111 reference clock */
40
};
41
42
+static const IMXClk imx7_gpt_clocks[] = {
43
+ CLK_NONE, /* 000 No clock source */
44
+ CLK_IPG, /* 001 ipg_clk, 532MHz*/
45
+ CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
46
+ CLK_EXT, /* 011 External clock */
47
+ CLK_32k, /* 100 ipg_clk_32k */
48
+ CLK_HIGH, /* 101 reference clock */
49
+ CLK_NONE, /* 110 not defined */
50
+ CLK_NONE, /* 111 not defined */
51
+};
52
+
33
+
53
static void imx_gpt_set_freq(IMXGPTState *s)
34
+ *statusp = env->vfp.fp_status;
54
{
35
+ set_default_nan_mode(true, statusp);
55
uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
36
56
@@ -XXX,XX +XXX,XX @@ static void imx6_gpt_init(Object *obj)
37
if (ebf) {
57
s->clocks = imx6_gpt_clocks;
38
- float_status *fpst = &env->vfp.fp_status;
39
- set_flush_to_zero(get_flush_to_zero(fpst), statusp);
40
- set_flush_inputs_to_zero(get_flush_inputs_to_zero(fpst), statusp);
41
- set_float_rounding_mode(get_float_rounding_mode(fpst), statusp);
42
-
43
/* EBF=1 needs to do a step with round-to-odd semantics */
44
*oddstatusp = *statusp;
45
set_float_rounding_mode(float_round_to_odd, oddstatusp);
46
+ } else {
47
+ set_flush_to_zero(true, statusp);
48
+ set_flush_inputs_to_zero(true, statusp);
49
+ set_float_rounding_mode(float_round_to_odd_inf, statusp);
50
}
51
-
52
return ebf;
58
}
53
}
59
54
60
+static void imx7_gpt_init(Object *obj)
61
+{
62
+ IMXGPTState *s = IMX_GPT(obj);
63
+
64
+ s->clocks = imx7_gpt_clocks;
65
+}
66
+
67
static const TypeInfo imx25_gpt_info = {
68
.name = TYPE_IMX25_GPT,
69
.parent = TYPE_SYS_BUS_DEVICE,
70
@@ -XXX,XX +XXX,XX @@ static const TypeInfo imx6_gpt_info = {
71
.instance_init = imx6_gpt_init,
72
};
73
74
+static const TypeInfo imx7_gpt_info = {
75
+ .name = TYPE_IMX7_GPT,
76
+ .parent = TYPE_IMX25_GPT,
77
+ .instance_init = imx7_gpt_init,
78
+};
79
+
80
static void imx_gpt_register_types(void)
81
{
82
type_register_static(&imx25_gpt_info);
83
type_register_static(&imx31_gpt_info);
84
type_register_static(&imx6_gpt_info);
85
+ type_register_static(&imx7_gpt_info);
86
}
87
88
type_init(imx_gpt_register_types)
89
--
55
--
90
2.16.1
56
2.34.1
91
57
92
58
diff view generated by jsdifflib
1
In order to support derived exceptions (exceptions generated in
1
Currently we hardcode the default NaN value in parts64_default_nan()
2
the course of trying to take an exception), we need to be able
2
using a compile-time ifdef ladder. This is awkward for two cases:
3
to handle prioritizing whether to take the original exception
3
* for single-QEMU-binary we can't hard-code target-specifics like this
4
or the derived exception.
4
* for Arm FEAT_AFP the default NaN value depends on FPCR.AH
5
(specifically the sign bit is different)
5
6
6
We do this by introducing a new function
7
Add a field to float_status to specify the default NaN value; fall
7
armv7m_nvic_set_pending_derived() which the exception-taking code in
8
back to the old ifdef behaviour if these are not set.
8
helper.c will call when a derived exception occurs. Derived
9
exceptions are dealt with mostly like normal pending exceptions, so
10
we share the implementation with the armv7m_nvic_set_pending()
11
function.
12
9
13
Note that the way we structure this is significantly different
10
The default NaN value is specified by setting a uint8_t to a
14
from the v8M Arm ARM pseudocode: that does all the prioritization
11
pattern corresponding to the sign and upper fraction parts of
15
logic in the DerivedLateArrival() function, whereas we choose to
12
the NaN; the lower bits of the fraction are set from bit 0 of
16
let the existing "identify highest priority exception" logic
13
the pattern.
17
do the prioritization for us. The effect is the same, though.
18
14
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 1517324542-6607-2-git-send-email-peter.maydell@linaro.org
17
Message-id: 20241202131347.498124-35-peter.maydell@linaro.org
22
---
18
---
23
target/arm/cpu.h | 13 ++++++++++
19
include/fpu/softfloat-helpers.h | 11 +++++++
24
hw/intc/armv7m_nvic.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++--
20
include/fpu/softfloat-types.h | 10 ++++++
25
hw/intc/trace-events | 2 +-
21
fpu/softfloat-specialize.c.inc | 55 ++++++++++++++++++++-------------
26
3 files changed, 80 insertions(+), 3 deletions(-)
22
3 files changed, 54 insertions(+), 22 deletions(-)
27
23
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
24
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
29
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
26
--- a/include/fpu/softfloat-helpers.h
31
+++ b/target/arm/cpu.h
27
+++ b/include/fpu/softfloat-helpers.h
32
@@ -XXX,XX +XXX,XX @@ static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
28
@@ -XXX,XX +XXX,XX @@ static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
33
* of architecturally banked exceptions.
29
status->float_infzeronan_rule = rule;
34
*/
35
void armv7m_nvic_set_pending(void *opaque, int irq, bool secure);
36
+/**
37
+ * armv7m_nvic_set_pending_derived: mark this derived exception as pending
38
+ * @opaque: the NVIC
39
+ * @irq: the exception number to mark pending
40
+ * @secure: false for non-banked exceptions or for the nonsecure
41
+ * version of a banked exception, true for the secure version of a banked
42
+ * exception.
43
+ *
44
+ * Similar to armv7m_nvic_set_pending(), but specifically for derived
45
+ * exceptions (exceptions generated in the course of trying to take
46
+ * a different exception).
47
+ */
48
+void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
49
/**
50
* armv7m_nvic_acknowledge_irq: make highest priority pending exception active
51
* @opaque: the NVIC
52
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/intc/armv7m_nvic.c
55
+++ b/hw/intc/armv7m_nvic.c
56
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_clear_pending(void *opaque, int irq, bool secure)
57
}
58
}
30
}
59
31
60
-void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
32
+static inline void set_float_default_nan_pattern(uint8_t dnan_pattern,
61
+static void do_armv7m_nvic_set_pending(void *opaque, int irq, bool secure,
33
+ float_status *status)
62
+ bool derived)
63
{
64
+ /* Pend an exception, including possibly escalating it to HardFault.
65
+ *
66
+ * This function handles both "normal" pending of interrupts and
67
+ * exceptions, and also derived exceptions (ones which occur as
68
+ * a result of trying to take some other exception).
69
+ *
70
+ * If derived == true, the caller guarantees that we are part way through
71
+ * trying to take an exception (but have not yet called
72
+ * armv7m_nvic_acknowledge_irq() to make it active), and so:
73
+ * - s->vectpending is the "original exception" we were trying to take
74
+ * - irq is the "derived exception"
75
+ * - nvic_exec_prio(s) gives the priority before exception entry
76
+ * Here we handle the prioritization logic which the pseudocode puts
77
+ * in the DerivedLateArrival() function.
78
+ */
79
+
80
NVICState *s = (NVICState *)opaque;
81
bool banked = exc_is_banked(irq);
82
VecInfo *vec;
83
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
84
85
vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
86
87
- trace_nvic_set_pending(irq, secure, vec->enabled, vec->prio);
88
+ trace_nvic_set_pending(irq, secure, derived, vec->enabled, vec->prio);
89
+
90
+ if (derived) {
91
+ /* Derived exceptions are always synchronous. */
92
+ assert(irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV);
93
+
94
+ if (irq == ARMV7M_EXCP_DEBUG &&
95
+ exc_group_prio(s, vec->prio, secure) >= nvic_exec_prio(s)) {
96
+ /* DebugMonitorFault, but its priority is lower than the
97
+ * preempted exception priority: just ignore it.
98
+ */
99
+ return;
100
+ }
101
+
102
+ if (irq == ARMV7M_EXCP_HARD && vec->prio >= s->vectpending_prio) {
103
+ /* If this is a terminal exception (one which means we cannot
104
+ * take the original exception, like a failure to read its
105
+ * vector table entry), then we must take the derived exception.
106
+ * If the derived exception can't take priority over the
107
+ * original exception, then we go into Lockup.
108
+ *
109
+ * For QEMU, we rely on the fact that a derived exception is
110
+ * terminal if and only if it's reported to us as HardFault,
111
+ * which saves having to have an extra argument is_terminal
112
+ * that we'd only use in one place.
113
+ */
114
+ cpu_abort(&s->cpu->parent_obj,
115
+ "Lockup: can't take terminal derived exception "
116
+ "(original exception priority %d)\n",
117
+ s->vectpending_prio);
118
+ }
119
+ /* We now continue with the same code as for a normal pending
120
+ * exception, which will cause us to pend the derived exception.
121
+ * We'll then take either the original or the derived exception
122
+ * based on which is higher priority by the usual mechanism
123
+ * for selecting the highest priority pending interrupt.
124
+ */
125
+ }
126
127
if (irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV) {
128
/* If a synchronous exception is pending then it may be
129
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
130
}
131
}
132
133
+void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
134
+{
34
+{
135
+ do_armv7m_nvic_set_pending(opaque, irq, secure, false);
35
+ status->default_nan_pattern = dnan_pattern;
136
+}
36
+}
137
+
37
+
138
+void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure)
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)
139
+{
46
+{
140
+ do_armv7m_nvic_set_pending(opaque, irq, secure, true);
47
+ return status->default_nan_pattern;
141
+}
48
+}
142
+
49
+
143
/* Make pending IRQ active. */
50
static inline bool get_flush_to_zero(float_status *status)
144
bool armv7m_nvic_acknowledge_irq(void *opaque)
145
{
51
{
146
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
52
return status->flush_to_zero;
53
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
147
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/intc/trace-events
55
--- a/include/fpu/softfloat-types.h
149
+++ b/hw/intc/trace-events
56
+++ b/include/fpu/softfloat-types.h
150
@@ -XXX,XX +XXX,XX @@ nvic_set_prio(int irq, bool secure, uint8_t prio) "NVIC set irq %d secure-bank %
57
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
151
nvic_irq_update(int vectpending, int pendprio, int exception_prio, int level) "NVIC vectpending %d pending prio %d exception_prio %d: setting irq line to %d"
58
/* should denormalised inputs go to zero and set the input_denormal flag? */
152
nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq %d to HardFault: insufficient priority %d >= %d"
59
bool flush_inputs_to_zero;
153
nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled"
60
bool default_nan_mode;
154
-nvic_set_pending(int irq, bool secure, int en, int prio) "NVIC set pending irq %d secure-bank %d (enabled: %d priority %d)"
61
+ /*
155
+nvic_set_pending(int irq, bool secure, bool derived, int en, int prio) "NVIC set pending irq %d secure-bank %d derived %d (enabled: %d priority %d)"
62
+ * The pattern to use for the default NaN. Here the high bit specifies
156
nvic_clear_pending(int irq, bool secure, int en, int prio) "NVIC clear pending irq %d secure-bank %d (enabled: %d priority %d)"
63
+ * the default NaN's sign bit, and bits 6..0 specify the high bits of the
157
nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1"
64
+ * fractional part. The low bits of the fractional part are copies of bit 0.
158
nvic_acknowledge_irq(int irq, int prio, bool targets_secure) "NVIC acknowledge IRQ: %d now active (prio %d targets_secure %d)"
65
+ * The exponent of the default NaN is (as for any NaN) always all 1s.
66
+ * Note that a value of 0 here is not a valid NaN. The target must set
67
+ * this to the correct non-zero value, or we will assert when trying to
68
+ * create a default NaN.
69
+ */
70
+ uint8_t default_nan_pattern;
71
/*
72
* The flags below are not used on all specializations and may
73
* constant fold away (see snan_bit_is_one()/no_signalling_nans() in
74
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
75
index XXXXXXX..XXXXXXX 100644
76
--- a/fpu/softfloat-specialize.c.inc
77
+++ b/fpu/softfloat-specialize.c.inc
78
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
79
{
80
bool sign = 0;
81
uint64_t frac;
82
+ uint8_t dnan_pattern = status->default_nan_pattern;
83
84
+ if (dnan_pattern == 0) {
85
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
86
- /* !snan_bit_is_one, set all bits */
87
- frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
88
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
89
+ /* Sign bit clear, all frac bits set */
90
+ dnan_pattern = 0b01111111;
91
+#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
92
|| defined(TARGET_MICROBLAZE)
93
- /* !snan_bit_is_one, set sign and msb */
94
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
95
- sign = 1;
96
+ /* Sign bit set, most significant frac bit set */
97
+ dnan_pattern = 0b11000000;
98
#elif defined(TARGET_HPPA)
99
- /* snan_bit_is_one, set msb-1. */
100
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
101
+ /* Sign bit clear, msb-1 frac bit set */
102
+ dnan_pattern = 0b00100000;
103
#elif defined(TARGET_HEXAGON)
104
- sign = 1;
105
- frac = ~0ULL;
106
+ /* Sign bit set, all frac bits set. */
107
+ dnan_pattern = 0b11111111;
108
#else
109
- /*
110
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
111
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
112
- * do not have floating-point.
113
- */
114
- if (snan_bit_is_one(status)) {
115
- /* set all bits other than msb */
116
- frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1;
117
- } else {
118
- /* set msb */
119
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
120
- }
121
+ /*
122
+ * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
123
+ * S390, SH4, TriCore, and Xtensa. Our other supported targets
124
+ * do not have floating-point.
125
+ */
126
+ if (snan_bit_is_one(status)) {
127
+ /* sign bit clear, set all frac bits other than msb */
128
+ dnan_pattern = 0b00111111;
129
+ } else {
130
+ /* sign bit clear, set frac msb */
131
+ dnan_pattern = 0b01000000;
132
+ }
133
#endif
134
+ }
135
+ assert(dnan_pattern != 0);
136
+
137
+ sign = dnan_pattern >> 7;
138
+ /*
139
+ * Place default_nan_pattern [6:0] into bits [62:56],
140
+ * and replecate bit [0] down into [55:0]
141
+ */
142
+ frac = deposit64(0, DECOMPOSED_BINARY_POINT - 7, 7, dnan_pattern);
143
+ frac = deposit64(frac, 0, DECOMPOSED_BINARY_POINT - 7, -(dnan_pattern & 1));
144
145
*p = (FloatParts64) {
146
.cls = float_class_qnan,
159
--
147
--
160
2.16.1
148
2.34.1
161
162
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
1
The memory writes done to push registers on the stack
1
Set the default NaN pattern explicitly for the arm target.
2
on exception entry in M profile CPUs are supposed to
2
This includes setting it for the old linux-user nwfpe emulation.
3
go via MPU permissions checks, which may cause us to
3
For nwfpe, our default doesn't match the real kernel, but we
4
take a derived exception instead of the original one of
4
avoid making a behaviour change in this commit.
5
the MPU lookup fails. We were implementing these as
6
always-succeeds direct writes to physical memory.
7
Rewrite v7m_push_stack() to do the necessary checks.
8
5
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 1517324542-6607-5-git-send-email-peter.maydell@linaro.org
8
Message-id: 20241202131347.498124-41-peter.maydell@linaro.org
12
---
9
---
13
target/arm/helper.c | 103 ++++++++++++++++++++++++++++++++++++++++++++--------
10
linux-user/arm/nwfpe/fpa11.c | 5 +++++
14
1 file changed, 87 insertions(+), 16 deletions(-)
11
target/arm/cpu.c | 2 ++
12
2 files changed, 7 insertions(+)
15
13
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
16
--- a/linux-user/arm/nwfpe/fpa11.c
19
+++ b/target/arm/helper.c
17
+++ b/linux-user/arm/nwfpe/fpa11.c
20
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
18
@@ -XXX,XX +XXX,XX @@ void resetFPA11(void)
21
return target_el;
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);
22
}
27
}
23
28
24
-static void v7m_push(CPUARMState *env, uint32_t val)
29
void SetRoundingMode(const unsigned int opcode)
25
+static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
26
+ ARMMMUIdx mmu_idx, bool ignfault)
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)
27
{
41
{
28
- CPUState *cs = CPU(arm_env_get_cpu(env));
42
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
29
+ CPUState *cs = CPU(cpu);
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
30
+ CPUARMState *env = &cpu->env;
44
set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
31
+ MemTxAttrs attrs = {};
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
32
+ MemTxResult txres;
46
+ set_float_default_nan_pattern(0b01000000, s);
33
+ target_ulong page_size;
34
+ hwaddr physaddr;
35
+ int prot;
36
+ ARMMMUFaultInfo fi;
37
+ bool secure = mmu_idx & ARM_MMU_IDX_M_S;
38
+ int exc;
39
+ bool exc_secure;
40
41
- env->regs[13] -= 4;
42
- stl_phys(cs->as, env->regs[13], val);
43
+ if (get_phys_addr(env, addr, MMU_DATA_STORE, mmu_idx, &physaddr,
44
+ &attrs, &prot, &page_size, &fi, NULL)) {
45
+ /* MPU/SAU lookup failed */
46
+ if (fi.type == ARMFault_QEMU_SFault) {
47
+ qemu_log_mask(CPU_LOG_INT,
48
+ "...SecureFault with SFSR.AUVIOL during stacking\n");
49
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
50
+ env->v7m.sfar = addr;
51
+ exc = ARMV7M_EXCP_SECURE;
52
+ exc_secure = false;
53
+ } else {
54
+ qemu_log_mask(CPU_LOG_INT, "...MemManageFault with CFSR.MSTKERR\n");
55
+ env->v7m.cfsr[secure] |= R_V7M_CFSR_MSTKERR_MASK;
56
+ exc = ARMV7M_EXCP_MEM;
57
+ exc_secure = secure;
58
+ }
59
+ goto pend_fault;
60
+ }
61
+ address_space_stl_le(arm_addressspace(cs, attrs), physaddr, value,
62
+ attrs, &txres);
63
+ if (txres != MEMTX_OK) {
64
+ /* BusFault trying to write the data */
65
+ qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.STKERR\n");
66
+ env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_STKERR_MASK;
67
+ exc = ARMV7M_EXCP_BUS;
68
+ exc_secure = false;
69
+ goto pend_fault;
70
+ }
71
+ return true;
72
+
73
+pend_fault:
74
+ /* By pending the exception at this point we are making
75
+ * the IMPDEF choice "overridden exceptions pended" (see the
76
+ * MergeExcInfo() pseudocode). The other choice would be to not
77
+ * pend them now and then make a choice about which to throw away
78
+ * later if we have two derived exceptions.
79
+ * The only case when we must not pend the exception but instead
80
+ * throw it away is if we are doing the push of the callee registers
81
+ * and we've already generated a derived exception. Even in this
82
+ * case we will still update the fault status registers.
83
+ */
84
+ if (!ignfault) {
85
+ armv7m_nvic_set_pending_derived(env->nvic, exc, exc_secure);
86
+ }
87
+ return false;
88
}
47
}
89
48
90
/* Return true if we're using the process stack pointer (not the MSP) */
49
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
91
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
92
* should ignore further stack faults trying to process
93
* that derived exception.)
94
*/
95
+ bool stacked_ok;
96
CPUARMState *env = &cpu->env;
97
uint32_t xpsr = xpsr_read(env);
98
+ uint32_t frameptr = env->regs[13];
99
+ ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
100
101
/* Align stack pointer if the guest wants that */
102
- if ((env->regs[13] & 4) &&
103
+ if ((frameptr & 4) &&
104
(env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKALIGN_MASK)) {
105
- env->regs[13] -= 4;
106
+ frameptr -= 4;
107
xpsr |= XPSR_SPREALIGN;
108
}
109
- /* Switch to the handler mode. */
110
- v7m_push(env, xpsr);
111
- v7m_push(env, env->regs[15]);
112
- v7m_push(env, env->regs[14]);
113
- v7m_push(env, env->regs[12]);
114
- v7m_push(env, env->regs[3]);
115
- v7m_push(env, env->regs[2]);
116
- v7m_push(env, env->regs[1]);
117
- v7m_push(env, env->regs[0]);
118
119
- return false;
120
+ frameptr -= 0x20;
121
+
122
+ /* Write as much of the stack frame as we can. If we fail a stack
123
+ * write this will result in a derived exception being pended
124
+ * (which may be taken in preference to the one we started with
125
+ * if it has higher priority).
126
+ */
127
+ stacked_ok =
128
+ v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, false) &&
129
+ v7m_stack_write(cpu, frameptr + 4, env->regs[1], mmu_idx, false) &&
130
+ v7m_stack_write(cpu, frameptr + 8, env->regs[2], mmu_idx, false) &&
131
+ v7m_stack_write(cpu, frameptr + 12, env->regs[3], mmu_idx, false) &&
132
+ v7m_stack_write(cpu, frameptr + 16, env->regs[12], mmu_idx, false) &&
133
+ v7m_stack_write(cpu, frameptr + 20, env->regs[14], mmu_idx, false) &&
134
+ v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
135
+ v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
136
+
137
+ /* Update SP regardless of whether any of the stack accesses failed.
138
+ * When we implement v8M stack limit checking then this attempt to
139
+ * update SP might also fail and result in a derived exception.
140
+ */
141
+ env->regs[13] = frameptr;
142
+
143
+ return !stacked_ok;
144
}
145
146
static void do_v7m_exception_exit(ARMCPU *cpu)
147
--
50
--
148
2.16.1
51
2.34.1
149
150
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
1
From: Christoffer Dall <christoffer.dall@linaro.org>
1
Set the default NaN pattern explicitly for ppc.
2
2
3
KVM doesn't support emulating a GICv3 in userspace, only GICv2. We
4
currently attempt this anyway, and as a result a KVM guest doesn't
5
receive interrupts and the user is left wondering why. Report an error
6
to the user if this particular combination is requested.
7
8
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20180201205307.30343-1-christoffer.dall@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-46-peter.maydell@linaro.org
12
---
6
---
13
target/arm/kvm_arm.h | 4 ++++
7
target/ppc/cpu_init.c | 4 ++++
14
1 file changed, 4 insertions(+)
8
1 file changed, 4 insertions(+)
15
9
16
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
10
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
17
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/kvm_arm.h
12
--- a/target/ppc/cpu_init.c
19
+++ b/target/arm/kvm_arm.h
13
+++ b/target/ppc/cpu_init.c
20
@@ -XXX,XX +XXX,XX @@ static inline const char *gicv3_class_name(void)
14
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
21
exit(1);
15
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
#endif
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
23
} else {
17
24
+ if (kvm_enabled()) {
18
+ /* Default NaN: sign bit clear, set frac msb */
25
+ error_report("Userspace GICv3 is not supported with KVM");
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
26
+ exit(1);
20
+ set_float_default_nan_pattern(0b01000000, &env->vec_status);
27
+ }
21
+
28
return "arm-gicv3";
22
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
29
}
23
ppc_spr_t *spr = &env->spr_cb[i];
30
}
24
31
--
25
--
32
2.16.1
26
2.34.1
33
34
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
1
The documentation for the generic loader claims that you can
1
Set the default NaN pattern explicitly for riscv.
2
set the PC for a CPU with an option of the form
3
-device loader,cpu-num=0,addr=0x10000004
4
5
However if you try this QEMU complains:
6
cpu_num must be specified when setting a program counter
7
8
This is because we were testing against 0 rather than CPU_NONE.
9
2
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 20241202131347.498124-53-peter.maydell@linaro.org
13
Message-id: 20180205150426.20542-1-peter.maydell@linaro.org
14
---
6
---
15
hw/core/generic-loader.c | 2 +-
7
target/riscv/cpu.c | 2 ++
16
1 file changed, 1 insertion(+), 1 deletion(-)
8
1 file changed, 2 insertions(+)
17
9
18
diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
10
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
19
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/core/generic-loader.c
12
--- a/target/riscv/cpu.c
21
+++ b/hw/core/generic-loader.c
13
+++ b/target/riscv/cpu.c
22
@@ -XXX,XX +XXX,XX @@ static void generic_loader_realize(DeviceState *dev, Error **errp)
14
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
23
error_setg(errp, "data can not be specified when setting a "
15
cs->exception_index = RISCV_EXCP_NONE;
24
"program counter");
16
env->load_res = -1;
25
return;
17
set_default_nan_mode(1, &env->fp_status);
26
- } else if (!s->cpu_num) {
18
+ /* Default NaN value: sign bit clear, frac msb set */
27
+ } else if (s->cpu_num == CPU_NONE) {
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
28
error_setg(errp, "cpu_num must be specified when setting a "
20
env->vill = true;
29
"program counter");
21
30
return;
22
#ifndef CONFIG_USER_ONLY
31
--
23
--
32
2.16.1
24
2.34.1
33
34
diff view generated by jsdifflib
1
Handle possible MPU faults, SAU faults or bus errors when
1
Set the default NaN pattern explicitly for tricore.
2
popping register state off the stack during exception return.
3
2
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 1517324542-6607-8-git-send-email-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-54-peter.maydell@linaro.org
7
---
6
---
8
target/arm/helper.c | 115 ++++++++++++++++++++++++++++++++++++++++++----------
7
target/tricore/helper.c | 2 ++
9
1 file changed, 94 insertions(+), 21 deletions(-)
8
1 file changed, 2 insertions(+)
10
9
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
10
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
12
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/helper.c
12
--- a/target/tricore/helper.c
14
+++ b/target/arm/helper.c
13
+++ b/target/tricore/helper.c
15
@@ -XXX,XX +XXX,XX @@ pend_fault:
14
@@ -XXX,XX +XXX,XX @@ void fpu_set_state(CPUTriCoreState *env)
16
return false;
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);
17
}
20
}
18
21
19
+static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr,
22
uint32_t psw_read(CPUTriCoreState *env)
20
+ ARMMMUIdx mmu_idx)
21
+{
22
+ CPUState *cs = CPU(cpu);
23
+ CPUARMState *env = &cpu->env;
24
+ MemTxAttrs attrs = {};
25
+ MemTxResult txres;
26
+ target_ulong page_size;
27
+ hwaddr physaddr;
28
+ int prot;
29
+ ARMMMUFaultInfo fi;
30
+ bool secure = mmu_idx & ARM_MMU_IDX_M_S;
31
+ int exc;
32
+ bool exc_secure;
33
+ uint32_t value;
34
+
35
+ if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr,
36
+ &attrs, &prot, &page_size, &fi, NULL)) {
37
+ /* MPU/SAU lookup failed */
38
+ if (fi.type == ARMFault_QEMU_SFault) {
39
+ qemu_log_mask(CPU_LOG_INT,
40
+ "...SecureFault with SFSR.AUVIOL during unstack\n");
41
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
42
+ env->v7m.sfar = addr;
43
+ exc = ARMV7M_EXCP_SECURE;
44
+ exc_secure = false;
45
+ } else {
46
+ qemu_log_mask(CPU_LOG_INT,
47
+ "...MemManageFault with CFSR.MUNSTKERR\n");
48
+ env->v7m.cfsr[secure] |= R_V7M_CFSR_MUNSTKERR_MASK;
49
+ exc = ARMV7M_EXCP_MEM;
50
+ exc_secure = secure;
51
+ }
52
+ goto pend_fault;
53
+ }
54
+
55
+ value = address_space_ldl(arm_addressspace(cs, attrs), physaddr,
56
+ attrs, &txres);
57
+ if (txres != MEMTX_OK) {
58
+ /* BusFault trying to read the data */
59
+ qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.UNSTKERR\n");
60
+ env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_UNSTKERR_MASK;
61
+ exc = ARMV7M_EXCP_BUS;
62
+ exc_secure = false;
63
+ goto pend_fault;
64
+ }
65
+
66
+ *dest = value;
67
+ return true;
68
+
69
+pend_fault:
70
+ /* By pending the exception at this point we are making
71
+ * the IMPDEF choice "overridden exceptions pended" (see the
72
+ * MergeExcInfo() pseudocode). The other choice would be to not
73
+ * pend them now and then make a choice about which to throw away
74
+ * later if we have two derived exceptions.
75
+ */
76
+ armv7m_nvic_set_pending(env->nvic, exc, exc_secure);
77
+ return false;
78
+}
79
+
80
/* Return true if we're using the process stack pointer (not the MSP) */
81
static bool v7m_using_psp(CPUARMState *env)
82
{
83
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
84
!return_to_handler,
85
return_to_sp_process);
86
uint32_t frameptr = *frame_sp_p;
87
+ bool pop_ok = true;
88
+ ARMMMUIdx mmu_idx;
89
+
90
+ mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, return_to_secure,
91
+ !return_to_handler);
92
93
if (!QEMU_IS_ALIGNED(frameptr, 8) &&
94
arm_feature(env, ARM_FEATURE_V8)) {
95
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
96
return;
97
}
98
99
- env->regs[4] = ldl_phys(cs->as, frameptr + 0x8);
100
- env->regs[5] = ldl_phys(cs->as, frameptr + 0xc);
101
- env->regs[6] = ldl_phys(cs->as, frameptr + 0x10);
102
- env->regs[7] = ldl_phys(cs->as, frameptr + 0x14);
103
- env->regs[8] = ldl_phys(cs->as, frameptr + 0x18);
104
- env->regs[9] = ldl_phys(cs->as, frameptr + 0x1c);
105
- env->regs[10] = ldl_phys(cs->as, frameptr + 0x20);
106
- env->regs[11] = ldl_phys(cs->as, frameptr + 0x24);
107
+ pop_ok =
108
+ v7m_stack_read(cpu, &env->regs[4], frameptr + 0x8, mmu_idx) &&
109
+ v7m_stack_read(cpu, &env->regs[4], frameptr + 0x8, mmu_idx) &&
110
+ v7m_stack_read(cpu, &env->regs[5], frameptr + 0xc, mmu_idx) &&
111
+ v7m_stack_read(cpu, &env->regs[6], frameptr + 0x10, mmu_idx) &&
112
+ v7m_stack_read(cpu, &env->regs[7], frameptr + 0x14, mmu_idx) &&
113
+ v7m_stack_read(cpu, &env->regs[8], frameptr + 0x18, mmu_idx) &&
114
+ v7m_stack_read(cpu, &env->regs[9], frameptr + 0x1c, mmu_idx) &&
115
+ v7m_stack_read(cpu, &env->regs[10], frameptr + 0x20, mmu_idx) &&
116
+ v7m_stack_read(cpu, &env->regs[11], frameptr + 0x24, mmu_idx);
117
118
frameptr += 0x28;
119
}
120
121
- /* Pop registers. TODO: make these accesses use the correct
122
- * attributes and address space (S/NS, priv/unpriv) and handle
123
- * memory transaction failures.
124
- */
125
- env->regs[0] = ldl_phys(cs->as, frameptr);
126
- env->regs[1] = ldl_phys(cs->as, frameptr + 0x4);
127
- env->regs[2] = ldl_phys(cs->as, frameptr + 0x8);
128
- env->regs[3] = ldl_phys(cs->as, frameptr + 0xc);
129
- env->regs[12] = ldl_phys(cs->as, frameptr + 0x10);
130
- env->regs[14] = ldl_phys(cs->as, frameptr + 0x14);
131
- env->regs[15] = ldl_phys(cs->as, frameptr + 0x18);
132
+ /* Pop registers */
133
+ pop_ok = pop_ok &&
134
+ v7m_stack_read(cpu, &env->regs[0], frameptr, mmu_idx) &&
135
+ v7m_stack_read(cpu, &env->regs[1], frameptr + 0x4, mmu_idx) &&
136
+ v7m_stack_read(cpu, &env->regs[2], frameptr + 0x8, mmu_idx) &&
137
+ v7m_stack_read(cpu, &env->regs[3], frameptr + 0xc, mmu_idx) &&
138
+ v7m_stack_read(cpu, &env->regs[12], frameptr + 0x10, mmu_idx) &&
139
+ v7m_stack_read(cpu, &env->regs[14], frameptr + 0x14, mmu_idx) &&
140
+ v7m_stack_read(cpu, &env->regs[15], frameptr + 0x18, mmu_idx) &&
141
+ v7m_stack_read(cpu, &xpsr, frameptr + 0x1c, mmu_idx);
142
+
143
+ if (!pop_ok) {
144
+ /* v7m_stack_read() pended a fault, so take it (as a tail
145
+ * chained exception on the same stack frame)
146
+ */
147
+ v7m_exception_taken(cpu, excret, true, false);
148
+ return;
149
+ }
150
151
/* Returning from an exception with a PC with bit 0 set is defined
152
* behaviour on v8M (bit 0 is ignored), but for v7M it was specified
153
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
154
}
155
}
156
157
- xpsr = ldl_phys(cs->as, frameptr + 0x1c);
158
-
159
if (arm_feature(env, ARM_FEATURE_V8)) {
160
/* For v8M we have to check whether the xPSR exception field
161
* matches the EXCRET value for return to handler/thread
162
--
23
--
163
2.16.1
24
2.34.1
164
165
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
Now that all our targets have bene converted to explicitly specify
2
their pattern for the default NaN value we can remove the remaining
3
fallback code in parts64_default_nan().
2
4
3
Add enough code to emulate i.MX2 watchdog IP block so it would be
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
possible to reboot the machine running Linux Guest.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241202131347.498124-55-peter.maydell@linaro.org
8
---
9
fpu/softfloat-specialize.c.inc | 14 --------------
10
1 file changed, 14 deletions(-)
5
11
6
Cc: Peter Maydell <peter.maydell@linaro.org>
12
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
7
Cc: Jason Wang <jasowang@redhat.com>
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
10
Cc: Michael S. Tsirkin <mst@redhat.com>
11
Cc: qemu-devel@nongnu.org
12
Cc: qemu-arm@nongnu.org
13
Cc: yurovsky@gmail.com
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
hw/misc/Makefile.objs | 1 +
20
include/hw/misc/imx2_wdt.h | 33 +++++++++++++++++
21
hw/misc/imx2_wdt.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++
22
3 files changed, 123 insertions(+)
23
create mode 100644 include/hw/misc/imx2_wdt.h
24
create mode 100644 hw/misc/imx2_wdt.c
25
26
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
27
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/misc/Makefile.objs
14
--- a/fpu/softfloat-specialize.c.inc
29
+++ b/hw/misc/Makefile.objs
15
+++ b/fpu/softfloat-specialize.c.inc
30
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IMX) += imx25_ccm.o
16
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
31
obj-$(CONFIG_IMX) += imx6_ccm.o
17
uint64_t frac;
32
obj-$(CONFIG_IMX) += imx6_src.o
18
uint8_t dnan_pattern = status->default_nan_pattern;
33
obj-$(CONFIG_IMX) += imx7_ccm.o
19
34
+obj-$(CONFIG_IMX) += imx2_wdt.o
20
- if (dnan_pattern == 0) {
35
obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
21
- /*
36
obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
22
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
37
obj-$(CONFIG_MAINSTONE) += mst_fpga.o
23
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
38
diff --git a/include/hw/misc/imx2_wdt.h b/include/hw/misc/imx2_wdt.h
24
- * do not have floating-point.
39
new file mode 100644
25
- */
40
index XXXXXXX..XXXXXXX
26
- if (snan_bit_is_one(status)) {
41
--- /dev/null
27
- /* sign bit clear, set all frac bits other than msb */
42
+++ b/include/hw/misc/imx2_wdt.h
28
- dnan_pattern = 0b00111111;
43
@@ -XXX,XX +XXX,XX @@
29
- } else {
44
+/*
30
- /* sign bit clear, set frac msb */
45
+ * Copyright (c) 2017, Impinj, Inc.
31
- dnan_pattern = 0b01000000;
46
+ *
32
- }
47
+ * i.MX2 Watchdog IP block
33
- }
48
+ *
34
assert(dnan_pattern != 0);
49
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
35
50
+ *
36
sign = dnan_pattern >> 7;
51
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
52
+ * See the COPYING file in the top-level directory.
53
+ */
54
+
55
+#ifndef IMX2_WDT_H
56
+#define IMX2_WDT_H
57
+
58
+#include "hw/sysbus.h"
59
+
60
+#define TYPE_IMX2_WDT "imx2.wdt"
61
+#define IMX2_WDT(obj) OBJECT_CHECK(IMX2WdtState, (obj), TYPE_IMX2_WDT)
62
+
63
+enum IMX2WdtRegisters {
64
+ IMX2_WDT_WCR = 0x0000,
65
+ IMX2_WDT_REG_NUM = 0x0008 / sizeof(uint16_t) + 1,
66
+};
67
+
68
+
69
+typedef struct IMX2WdtState {
70
+ /* <private> */
71
+ SysBusDevice parent_obj;
72
+
73
+ MemoryRegion mmio;
74
+} IMX2WdtState;
75
+
76
+#endif /* IMX7_SNVS_H */
77
diff --git a/hw/misc/imx2_wdt.c b/hw/misc/imx2_wdt.c
78
new file mode 100644
79
index XXXXXXX..XXXXXXX
80
--- /dev/null
81
+++ b/hw/misc/imx2_wdt.c
82
@@ -XXX,XX +XXX,XX @@
83
+/*
84
+ * Copyright (c) 2018, Impinj, Inc.
85
+ *
86
+ * i.MX2 Watchdog IP block
87
+ *
88
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
89
+ *
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
91
+ * See the COPYING file in the top-level directory.
92
+ */
93
+
94
+#include "qemu/osdep.h"
95
+#include "qemu/bitops.h"
96
+#include "sysemu/watchdog.h"
97
+
98
+#include "hw/misc/imx2_wdt.h"
99
+
100
+#define IMX2_WDT_WCR_WDA BIT(5) /* -> External Reset WDOG_B */
101
+#define IMX2_WDT_WCR_SRS BIT(4) /* -> Software Reset Signal */
102
+
103
+static uint64_t imx2_wdt_read(void *opaque, hwaddr addr,
104
+ unsigned int size)
105
+{
106
+ return 0;
107
+}
108
+
109
+static void imx2_wdt_write(void *opaque, hwaddr addr,
110
+ uint64_t value, unsigned int size)
111
+{
112
+ if (addr == IMX2_WDT_WCR &&
113
+ (value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) {
114
+ watchdog_perform_action();
115
+ }
116
+}
117
+
118
+static const MemoryRegionOps imx2_wdt_ops = {
119
+ .read = imx2_wdt_read,
120
+ .write = imx2_wdt_write,
121
+ .endianness = DEVICE_NATIVE_ENDIAN,
122
+ .impl = {
123
+ /*
124
+ * Our device would not work correctly if the guest was doing
125
+ * unaligned access. This might not be a limitation on the
126
+ * real device but in practice there is no reason for a guest
127
+ * to access this device unaligned.
128
+ */
129
+ .min_access_size = 4,
130
+ .max_access_size = 4,
131
+ .unaligned = false,
132
+ },
133
+};
134
+
135
+static void imx2_wdt_realize(DeviceState *dev, Error **errp)
136
+{
137
+ IMX2WdtState *s = IMX2_WDT(dev);
138
+
139
+ memory_region_init_io(&s->mmio, OBJECT(dev),
140
+ &imx2_wdt_ops, s,
141
+ TYPE_IMX2_WDT".mmio",
142
+ IMX2_WDT_REG_NUM * sizeof(uint16_t));
143
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
144
+}
145
+
146
+static void imx2_wdt_class_init(ObjectClass *klass, void *data)
147
+{
148
+ DeviceClass *dc = DEVICE_CLASS(klass);
149
+
150
+ dc->realize = imx2_wdt_realize;
151
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
152
+}
153
+
154
+static const TypeInfo imx2_wdt_info = {
155
+ .name = TYPE_IMX2_WDT,
156
+ .parent = TYPE_SYS_BUS_DEVICE,
157
+ .instance_size = sizeof(IMX2WdtState),
158
+ .class_init = imx2_wdt_class_init,
159
+};
160
+
161
+static WatchdogTimerModel model = {
162
+ .wdt_name = "imx2-watchdog",
163
+ .wdt_description = "i.MX2 Watchdog",
164
+};
165
+
166
+static void imx2_wdt_register_type(void)
167
+{
168
+ watchdog_add_model(&model);
169
+ type_register_static(&imx2_wdt_info);
170
+}
171
+type_init(imx2_wdt_register_type)
172
--
37
--
173
2.16.1
38
2.34.1
174
175
diff view generated by jsdifflib
1
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This implements emulation of the new SM3 instructions that have
3
Inline pickNaNMulAdd into its only caller. This makes
4
been added as an optional extension to the ARMv8 Crypto Extensions
4
one assert redundant with the immediately preceding IF.
5
in ARM v8.2.
6
5
7
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180207111729.15737-4-ard.biesheuvel@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/cpu.h | 1 +
12
fpu/softfloat-parts.c.inc | 41 +++++++++++++++++++++++++-
13
target/arm/helper.h | 4 ++
13
fpu/softfloat-specialize.c.inc | 54 ----------------------------------
14
target/arm/crypto_helper.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++
14
2 files changed, 40 insertions(+), 55 deletions(-)
15
target/arm/translate-a64.c | 88 ++++++++++++++++++++++++++++++++++++++++--
16
4 files changed, 186 insertions(+), 3 deletions(-)
17
15
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
18
--- a/fpu/softfloat-parts.c.inc
21
+++ b/target/arm/cpu.h
19
+++ b/fpu/softfloat-parts.c.inc
22
@@ -XXX,XX +XXX,XX @@ enum arm_features {
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
23
ARM_FEATURE_SVE, /* has Scalable Vector Extension */
21
}
24
ARM_FEATURE_V8_SHA512, /* implements SHA512 part of v8 Crypto Extensions */
22
25
ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
23
if (s->default_nan_mode) {
26
+ ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
24
+ /*
27
};
25
+ * We guarantee not to require the target to tell us how to
28
26
+ * pick a NaN if we're always returning the default NaN.
29
static inline int arm_feature(CPUARMState *env, int feature)
27
+ * But if we're not in default-NaN mode then the target must
30
diff --git a/target/arm/helper.h b/target/arm/helper.h
28
+ * specify.
31
index XXXXXXX..XXXXXXX 100644
29
+ */
32
--- a/target/arm/helper.h
30
which = 3;
33
+++ b/target/arm/helper.h
31
+ } else if (infzero) {
34
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(crypto_sha512h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
32
+ /*
35
DEF_HELPER_FLAGS_2(crypto_sha512su0, TCG_CALL_NO_RWG, void, ptr, ptr)
33
+ * Inf * 0 + NaN -- some implementations return the
36
DEF_HELPER_FLAGS_3(crypto_sha512su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
34
+ * default NaN here, and some return the input NaN.
37
35
+ */
38
+DEF_HELPER_FLAGS_5(crypto_sm3tt, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32, i32)
36
+ switch (s->float_infzeronan_rule) {
39
+DEF_HELPER_FLAGS_3(crypto_sm3partw1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
37
+ case float_infzeronan_dnan_never:
40
+DEF_HELPER_FLAGS_3(crypto_sm3partw2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
38
+ which = 2;
41
+
42
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
43
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
44
DEF_HELPER_2(dc_zva, void, env, i64)
45
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/crypto_helper.c
48
+++ b/target/arm/crypto_helper.c
49
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm)
50
rd[0] += s1_512(rn[0]) + rm[0];
51
rd[1] += s1_512(rn[1]) + rm[1];
52
}
53
+
54
+void HELPER(crypto_sm3partw1)(void *vd, void *vn, void *vm)
55
+{
56
+ uint64_t *rd = vd;
57
+ uint64_t *rn = vn;
58
+ uint64_t *rm = vm;
59
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
60
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
61
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
62
+ uint32_t t;
63
+
64
+ t = CR_ST_WORD(d, 0) ^ CR_ST_WORD(n, 0) ^ ror32(CR_ST_WORD(m, 1), 17);
65
+ CR_ST_WORD(d, 0) = t ^ ror32(t, 17) ^ ror32(t, 9);
66
+
67
+ t = CR_ST_WORD(d, 1) ^ CR_ST_WORD(n, 1) ^ ror32(CR_ST_WORD(m, 2), 17);
68
+ CR_ST_WORD(d, 1) = t ^ ror32(t, 17) ^ ror32(t, 9);
69
+
70
+ t = CR_ST_WORD(d, 2) ^ CR_ST_WORD(n, 2) ^ ror32(CR_ST_WORD(m, 3), 17);
71
+ CR_ST_WORD(d, 2) = t ^ ror32(t, 17) ^ ror32(t, 9);
72
+
73
+ t = CR_ST_WORD(d, 3) ^ CR_ST_WORD(n, 3) ^ ror32(CR_ST_WORD(d, 0), 17);
74
+ CR_ST_WORD(d, 3) = t ^ ror32(t, 17) ^ ror32(t, 9);
75
+
76
+ rd[0] = d.l[0];
77
+ rd[1] = d.l[1];
78
+}
79
+
80
+void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm)
81
+{
82
+ uint64_t *rd = vd;
83
+ uint64_t *rn = vn;
84
+ uint64_t *rm = vm;
85
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
86
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
87
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
88
+ uint32_t t = CR_ST_WORD(n, 0) ^ ror32(CR_ST_WORD(m, 0), 25);
89
+
90
+ CR_ST_WORD(d, 0) ^= t;
91
+ CR_ST_WORD(d, 1) ^= CR_ST_WORD(n, 1) ^ ror32(CR_ST_WORD(m, 1), 25);
92
+ CR_ST_WORD(d, 2) ^= CR_ST_WORD(n, 2) ^ ror32(CR_ST_WORD(m, 2), 25);
93
+ CR_ST_WORD(d, 3) ^= CR_ST_WORD(n, 3) ^ ror32(CR_ST_WORD(m, 3), 25) ^
94
+ ror32(t, 17) ^ ror32(t, 2) ^ ror32(t, 26);
95
+
96
+ rd[0] = d.l[0];
97
+ rd[1] = d.l[1];
98
+}
99
+
100
+void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2,
101
+ uint32_t opcode)
102
+{
103
+ uint64_t *rd = vd;
104
+ uint64_t *rn = vn;
105
+ uint64_t *rm = vm;
106
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
107
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
108
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
109
+ uint32_t t;
110
+
111
+ assert(imm2 < 4);
112
+
113
+ if (opcode == 0 || opcode == 2) {
114
+ /* SM3TT1A, SM3TT2A */
115
+ t = par(CR_ST_WORD(d, 3), CR_ST_WORD(d, 2), CR_ST_WORD(d, 1));
116
+ } else if (opcode == 1) {
117
+ /* SM3TT1B */
118
+ t = maj(CR_ST_WORD(d, 3), CR_ST_WORD(d, 2), CR_ST_WORD(d, 1));
119
+ } else if (opcode == 3) {
120
+ /* SM3TT2B */
121
+ t = cho(CR_ST_WORD(d, 3), CR_ST_WORD(d, 2), CR_ST_WORD(d, 1));
122
+ } else {
123
+ g_assert_not_reached();
124
+ }
125
+
126
+ t += CR_ST_WORD(d, 0) + CR_ST_WORD(m, imm2);
127
+
128
+ CR_ST_WORD(d, 0) = CR_ST_WORD(d, 1);
129
+
130
+ if (opcode < 2) {
131
+ /* SM3TT1A, SM3TT1B */
132
+ t += CR_ST_WORD(n, 3) ^ ror32(CR_ST_WORD(d, 3), 20);
133
+
134
+ CR_ST_WORD(d, 1) = ror32(CR_ST_WORD(d, 2), 23);
135
+ } else {
136
+ /* SM3TT2A, SM3TT2B */
137
+ t += CR_ST_WORD(n, 3);
138
+ t ^= rol32(t, 9) ^ rol32(t, 17);
139
+
140
+ CR_ST_WORD(d, 1) = ror32(CR_ST_WORD(d, 2), 13);
141
+ }
142
+
143
+ CR_ST_WORD(d, 2) = CR_ST_WORD(d, 3);
144
+ CR_ST_WORD(d, 3) = t;
145
+
146
+ rd[0] = d.l[0];
147
+ rd[1] = d.l[1];
148
+}
149
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
150
index XXXXXXX..XXXXXXX 100644
151
--- a/target/arm/translate-a64.c
152
+++ b/target/arm/translate-a64.c
153
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
154
break;
155
}
156
} else {
157
- unallocated_encoding(s);
158
- return;
159
+ switch (opcode) {
160
+ case 0: /* SM3PARTW1 */
161
+ feature = ARM_FEATURE_V8_SM3;
162
+ genfn = gen_helper_crypto_sm3partw1;
163
+ break;
39
+ break;
164
+ case 1: /* SM3PARTW2 */
40
+ case float_infzeronan_dnan_always:
165
+ feature = ARM_FEATURE_V8_SM3;
41
+ which = 3;
166
+ genfn = gen_helper_crypto_sm3partw2;
42
+ break;
43
+ case float_infzeronan_dnan_if_qnan:
44
+ which = is_qnan(c->cls) ? 3 : 2;
167
+ break;
45
+ break;
168
+ default:
46
+ default:
169
+ unallocated_encoding(s);
47
+ g_assert_not_reached();
170
+ return;
48
+ }
49
} else {
50
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
51
+ FloatClass cls[3] = { a->cls, b->cls, c->cls };
52
+ Float3NaNPropRule rule = s->float_3nan_prop_rule;
53
+
54
+ assert(rule != float_3nan_prop_none);
55
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
56
+ /* We have at least one SNaN input and should prefer it */
57
+ do {
58
+ which = rule & R_3NAN_1ST_MASK;
59
+ rule >>= R_3NAN_1ST_LENGTH;
60
+ } while (!is_snan(cls[which]));
61
+ } else {
62
+ do {
63
+ which = rule & R_3NAN_1ST_MASK;
64
+ rule >>= R_3NAN_1ST_LENGTH;
65
+ } while (!is_nan(cls[which]));
171
+ }
66
+ }
172
}
67
}
173
68
174
if (!arm_dc_feature(s, feature)) {
69
if (which == 3) {
175
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_four_reg(DisasContext *s, uint32_t insn)
70
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
176
case 1: /* BCAX */
71
index XXXXXXX..XXXXXXX 100644
177
feature = ARM_FEATURE_V8_SHA3;
72
--- a/fpu/softfloat-specialize.c.inc
178
break;
73
+++ b/fpu/softfloat-specialize.c.inc
179
+ case 2: /* SM3SS1 */
74
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
180
+ feature = ARM_FEATURE_V8_SM3;
181
+ break;
182
default:
183
unallocated_encoding(s);
184
return;
185
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_four_reg(DisasContext *s, uint32_t insn)
186
tcg_temp_free_i64(tcg_res[0]);
187
tcg_temp_free_i64(tcg_res[1]);
188
} else {
189
- g_assert_not_reached();
190
+ TCGv_i32 tcg_op1, tcg_op2, tcg_op3, tcg_res, tcg_zero;
191
+
192
+ tcg_op1 = tcg_temp_new_i32();
193
+ tcg_op2 = tcg_temp_new_i32();
194
+ tcg_op3 = tcg_temp_new_i32();
195
+ tcg_res = tcg_temp_new_i32();
196
+ tcg_zero = tcg_const_i32(0);
197
+
198
+ read_vec_element_i32(s, tcg_op1, rn, 3, MO_32);
199
+ read_vec_element_i32(s, tcg_op2, rm, 3, MO_32);
200
+ read_vec_element_i32(s, tcg_op3, ra, 3, MO_32);
201
+
202
+ tcg_gen_rotri_i32(tcg_res, tcg_op1, 20);
203
+ tcg_gen_add_i32(tcg_res, tcg_res, tcg_op2);
204
+ tcg_gen_add_i32(tcg_res, tcg_res, tcg_op3);
205
+ tcg_gen_rotri_i32(tcg_res, tcg_res, 25);
206
+
207
+ write_vec_element_i32(s, tcg_zero, rd, 0, MO_32);
208
+ write_vec_element_i32(s, tcg_zero, rd, 1, MO_32);
209
+ write_vec_element_i32(s, tcg_zero, rd, 2, MO_32);
210
+ write_vec_element_i32(s, tcg_res, rd, 3, MO_32);
211
+
212
+ tcg_temp_free_i32(tcg_op1);
213
+ tcg_temp_free_i32(tcg_op2);
214
+ tcg_temp_free_i32(tcg_op3);
215
+ tcg_temp_free_i32(tcg_res);
216
+ tcg_temp_free_i32(tcg_zero);
217
}
75
}
218
}
76
}
219
77
220
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_xar(DisasContext *s, uint32_t insn)
78
-/*----------------------------------------------------------------------------
221
tcg_temp_free_i64(tcg_res[1]);
79
-| Select which NaN to propagate for a three-input operation.
222
}
80
-| For the moment we assume that no CPU needs the 'larger significand'
223
81
-| information.
224
+/* Crypto three-reg imm2
82
-| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
225
+ * 31 21 20 16 15 14 13 12 11 10 9 5 4 0
83
-*----------------------------------------------------------------------------*/
226
+ * +-----------------------+------+-----+------+--------+------+------+
84
-static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
227
+ * | 1 1 0 0 1 1 1 0 0 1 0 | Rm | 1 0 | imm2 | opcode | Rn | Rd |
85
- bool infzero, bool have_snan, float_status *status)
228
+ * +-----------------------+------+-----+------+--------+------+------+
86
-{
229
+ */
87
- FloatClass cls[3] = { a_cls, b_cls, c_cls };
230
+static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
88
- Float3NaNPropRule rule = status->float_3nan_prop_rule;
231
+{
89
- int which;
232
+ int opcode = extract32(insn, 10, 2);
90
-
233
+ int imm2 = extract32(insn, 12, 2);
91
- /*
234
+ int rm = extract32(insn, 16, 5);
92
- * We guarantee not to require the target to tell us how to
235
+ int rn = extract32(insn, 5, 5);
93
- * pick a NaN if we're always returning the default NaN.
236
+ int rd = extract32(insn, 0, 5);
94
- * But if we're not in default-NaN mode then the target must
237
+ TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
95
- * specify.
238
+ TCGv_i32 tcg_imm2, tcg_opcode;
96
- */
239
+
97
- assert(!status->default_nan_mode);
240
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_SM3)) {
98
-
241
+ unallocated_encoding(s);
99
- if (infzero) {
242
+ return;
100
- /*
243
+ }
101
- * Inf * 0 + NaN -- some implementations return the default NaN here,
244
+
102
- * and some return the input NaN.
245
+ if (!fp_access_check(s)) {
103
- */
246
+ return;
104
- switch (status->float_infzeronan_rule) {
247
+ }
105
- case float_infzeronan_dnan_never:
248
+
106
- return 2;
249
+ tcg_rd_ptr = vec_full_reg_ptr(s, rd);
107
- case float_infzeronan_dnan_always:
250
+ tcg_rn_ptr = vec_full_reg_ptr(s, rn);
108
- return 3;
251
+ tcg_rm_ptr = vec_full_reg_ptr(s, rm);
109
- case float_infzeronan_dnan_if_qnan:
252
+ tcg_imm2 = tcg_const_i32(imm2);
110
- return is_qnan(c_cls) ? 3 : 2;
253
+ tcg_opcode = tcg_const_i32(opcode);
111
- default:
254
+
112
- g_assert_not_reached();
255
+ gen_helper_crypto_sm3tt(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr, tcg_imm2,
113
- }
256
+ tcg_opcode);
114
- }
257
+
115
-
258
+ tcg_temp_free_ptr(tcg_rd_ptr);
116
- assert(rule != float_3nan_prop_none);
259
+ tcg_temp_free_ptr(tcg_rn_ptr);
117
- if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
260
+ tcg_temp_free_ptr(tcg_rm_ptr);
118
- /* We have at least one SNaN input and should prefer it */
261
+ tcg_temp_free_i32(tcg_imm2);
119
- do {
262
+ tcg_temp_free_i32(tcg_opcode);
120
- which = rule & R_3NAN_1ST_MASK;
263
+}
121
- rule >>= R_3NAN_1ST_LENGTH;
264
+
122
- } while (!is_snan(cls[which]));
265
/* C3.6 Data processing - SIMD, inc Crypto
123
- } else {
266
*
124
- do {
267
* As the decode gets a little complex we are using a table based
125
- which = rule & R_3NAN_1ST_MASK;
268
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
126
- rule >>= R_3NAN_1ST_LENGTH;
269
{ 0xcec08000, 0xfffff000, disas_crypto_two_reg_sha512 },
127
- } while (!is_nan(cls[which]));
270
{ 0xce000000, 0xff808000, disas_crypto_four_reg },
128
- }
271
{ 0xce800000, 0xffe00000, disas_crypto_xar },
129
- return which;
272
+ { 0xce408000, 0xffe0c000, disas_crypto_three_reg_imm2 },
130
-}
273
{ 0x00000000, 0x00000000, NULL }
131
-
274
};
132
/*----------------------------------------------------------------------------
275
133
| Returns 1 if the double-precision floating-point value `a' is a quiet
134
| NaN; otherwise returns 0.
276
--
135
--
277
2.16.1
136
2.34.1
278
137
279
138
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add minimal code needed to allow upstream Linux guest to boot.
3
Remove "3" as a special case for which and simply
4
branch to return the desired value.
4
5
5
Cc: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Cc: Jason Wang <jasowang@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20241203203949.483774-4-richard.henderson@linaro.org
8
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
9
Cc: Michael S. Tsirkin <mst@redhat.com>
10
Cc: qemu-devel@nongnu.org
11
Cc: qemu-arm@nongnu.org
12
Cc: yurovsky@gmail.com
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
10
---
17
hw/misc/Makefile.objs | 1 +
11
fpu/softfloat-parts.c.inc | 20 ++++++++++----------
18
include/hw/misc/imx7_ccm.h | 139 +++++++++++++++++++++++
12
1 file changed, 10 insertions(+), 10 deletions(-)
19
hw/misc/imx7_ccm.c | 277 +++++++++++++++++++++++++++++++++++++++++++++
20
3 files changed, 417 insertions(+)
21
create mode 100644 include/hw/misc/imx7_ccm.h
22
create mode 100644 hw/misc/imx7_ccm.c
23
13
24
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
25
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/misc/Makefile.objs
16
--- a/fpu/softfloat-parts.c.inc
27
+++ b/hw/misc/Makefile.objs
17
+++ b/fpu/softfloat-parts.c.inc
28
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_IMX) += imx31_ccm.o
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
29
obj-$(CONFIG_IMX) += imx25_ccm.o
19
* But if we're not in default-NaN mode then the target must
30
obj-$(CONFIG_IMX) += imx6_ccm.o
20
* specify.
31
obj-$(CONFIG_IMX) += imx6_src.o
21
*/
32
+obj-$(CONFIG_IMX) += imx7_ccm.o
22
- which = 3;
33
obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
23
+ goto default_nan;
34
obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
24
} else if (infzero) {
35
obj-$(CONFIG_MAINSTONE) += mst_fpga.o
25
/*
36
diff --git a/include/hw/misc/imx7_ccm.h b/include/hw/misc/imx7_ccm.h
26
* Inf * 0 + NaN -- some implementations return the
37
new file mode 100644
27
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
38
index XXXXXXX..XXXXXXX
28
*/
39
--- /dev/null
29
switch (s->float_infzeronan_rule) {
40
+++ b/include/hw/misc/imx7_ccm.h
30
case float_infzeronan_dnan_never:
41
@@ -XXX,XX +XXX,XX @@
31
- which = 2;
42
+/*
32
break;
43
+ * Copyright (c) 2017, Impinj, Inc.
33
case float_infzeronan_dnan_always:
44
+ *
34
- which = 3;
45
+ * i.MX7 CCM, PMU and ANALOG IP blocks emulation code
35
- break;
46
+ *
36
+ goto default_nan;
47
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
37
case float_infzeronan_dnan_if_qnan:
48
+ *
38
- which = is_qnan(c->cls) ? 3 : 2;
49
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
39
+ if (is_qnan(c->cls)) {
50
+ * See the COPYING file in the top-level directory.
40
+ goto default_nan;
51
+ */
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;
52
+
66
+
53
+#ifndef IMX7_CCM_H
67
+ default_nan:
54
+#define IMX7_CCM_H
68
+ parts_default_nan(a, s);
55
+
69
+ return a;
56
+#include "hw/misc/imx_ccm.h"
70
}
57
+#include "qemu/bitops.h"
71
58
+
72
/*
59
+enum IMX7AnalogRegisters {
60
+ ANALOG_PLL_ARM,
61
+ ANALOG_PLL_ARM_SET,
62
+ ANALOG_PLL_ARM_CLR,
63
+ ANALOG_PLL_ARM_TOG,
64
+ ANALOG_PLL_DDR,
65
+ ANALOG_PLL_DDR_SET,
66
+ ANALOG_PLL_DDR_CLR,
67
+ ANALOG_PLL_DDR_TOG,
68
+ ANALOG_PLL_DDR_SS,
69
+ ANALOG_PLL_DDR_SS_SET,
70
+ ANALOG_PLL_DDR_SS_CLR,
71
+ ANALOG_PLL_DDR_SS_TOG,
72
+ ANALOG_PLL_DDR_NUM,
73
+ ANALOG_PLL_DDR_NUM_SET,
74
+ ANALOG_PLL_DDR_NUM_CLR,
75
+ ANALOG_PLL_DDR_NUM_TOG,
76
+ ANALOG_PLL_DDR_DENOM,
77
+ ANALOG_PLL_DDR_DENOM_SET,
78
+ ANALOG_PLL_DDR_DENOM_CLR,
79
+ ANALOG_PLL_DDR_DENOM_TOG,
80
+ ANALOG_PLL_480,
81
+ ANALOG_PLL_480_SET,
82
+ ANALOG_PLL_480_CLR,
83
+ ANALOG_PLL_480_TOG,
84
+ ANALOG_PLL_480A,
85
+ ANALOG_PLL_480A_SET,
86
+ ANALOG_PLL_480A_CLR,
87
+ ANALOG_PLL_480A_TOG,
88
+ ANALOG_PLL_480B,
89
+ ANALOG_PLL_480B_SET,
90
+ ANALOG_PLL_480B_CLR,
91
+ ANALOG_PLL_480B_TOG,
92
+ ANALOG_PLL_ENET,
93
+ ANALOG_PLL_ENET_SET,
94
+ ANALOG_PLL_ENET_CLR,
95
+ ANALOG_PLL_ENET_TOG,
96
+ ANALOG_PLL_AUDIO,
97
+ ANALOG_PLL_AUDIO_SET,
98
+ ANALOG_PLL_AUDIO_CLR,
99
+ ANALOG_PLL_AUDIO_TOG,
100
+ ANALOG_PLL_AUDIO_SS,
101
+ ANALOG_PLL_AUDIO_SS_SET,
102
+ ANALOG_PLL_AUDIO_SS_CLR,
103
+ ANALOG_PLL_AUDIO_SS_TOG,
104
+ ANALOG_PLL_AUDIO_NUM,
105
+ ANALOG_PLL_AUDIO_NUM_SET,
106
+ ANALOG_PLL_AUDIO_NUM_CLR,
107
+ ANALOG_PLL_AUDIO_NUM_TOG,
108
+ ANALOG_PLL_AUDIO_DENOM,
109
+ ANALOG_PLL_AUDIO_DENOM_SET,
110
+ ANALOG_PLL_AUDIO_DENOM_CLR,
111
+ ANALOG_PLL_AUDIO_DENOM_TOG,
112
+ ANALOG_PLL_VIDEO,
113
+ ANALOG_PLL_VIDEO_SET,
114
+ ANALOG_PLL_VIDEO_CLR,
115
+ ANALOG_PLL_VIDEO_TOG,
116
+ ANALOG_PLL_VIDEO_SS,
117
+ ANALOG_PLL_VIDEO_SS_SET,
118
+ ANALOG_PLL_VIDEO_SS_CLR,
119
+ ANALOG_PLL_VIDEO_SS_TOG,
120
+ ANALOG_PLL_VIDEO_NUM,
121
+ ANALOG_PLL_VIDEO_NUM_SET,
122
+ ANALOG_PLL_VIDEO_NUM_CLR,
123
+ ANALOG_PLL_VIDEO_NUM_TOG,
124
+ ANALOG_PLL_VIDEO_DENOM,
125
+ ANALOG_PLL_VIDEO_DENOM_SET,
126
+ ANALOG_PLL_VIDEO_DENOM_CLR,
127
+ ANALOG_PLL_VIDEO_DENOM_TOG,
128
+ ANALOG_PLL_MISC0,
129
+ ANALOG_PLL_MISC0_SET,
130
+ ANALOG_PLL_MISC0_CLR,
131
+ ANALOG_PLL_MISC0_TOG,
132
+
133
+ ANALOG_DIGPROG = 0x800 / sizeof(uint32_t),
134
+ ANALOG_MAX,
135
+
136
+ ANALOG_PLL_LOCK = BIT(31)
137
+};
138
+
139
+enum IMX7CCMRegisters {
140
+ CCM_MAX = 0xBE00 / sizeof(uint32_t) + 1,
141
+};
142
+
143
+enum IMX7PMURegisters {
144
+ PMU_MAX = 0x140 / sizeof(uint32_t),
145
+};
146
+
147
+#define TYPE_IMX7_CCM "imx7.ccm"
148
+#define IMX7_CCM(obj) OBJECT_CHECK(IMX7CCMState, (obj), TYPE_IMX7_CCM)
149
+
150
+typedef struct IMX7CCMState {
151
+ /* <private> */
152
+ IMXCCMState parent_obj;
153
+
154
+ /* <public> */
155
+ MemoryRegion iomem;
156
+
157
+ uint32_t ccm[CCM_MAX];
158
+} IMX7CCMState;
159
+
160
+
161
+#define TYPE_IMX7_ANALOG "imx7.analog"
162
+#define IMX7_ANALOG(obj) OBJECT_CHECK(IMX7AnalogState, (obj), TYPE_IMX7_ANALOG)
163
+
164
+typedef struct IMX7AnalogState {
165
+ /* <private> */
166
+ IMXCCMState parent_obj;
167
+
168
+ /* <public> */
169
+ struct {
170
+ MemoryRegion container;
171
+ MemoryRegion analog;
172
+ MemoryRegion digprog;
173
+ MemoryRegion pmu;
174
+ } mmio;
175
+
176
+ uint32_t analog[ANALOG_MAX];
177
+ uint32_t pmu[PMU_MAX];
178
+} IMX7AnalogState;
179
+
180
+#endif /* IMX7_CCM_H */
181
diff --git a/hw/misc/imx7_ccm.c b/hw/misc/imx7_ccm.c
182
new file mode 100644
183
index XXXXXXX..XXXXXXX
184
--- /dev/null
185
+++ b/hw/misc/imx7_ccm.c
186
@@ -XXX,XX +XXX,XX @@
187
+/*
188
+ * Copyright (c) 2018, Impinj, Inc.
189
+ *
190
+ * i.MX7 CCM, PMU and ANALOG IP blocks emulation code
191
+ *
192
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
193
+ *
194
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
195
+ * See the COPYING file in the top-level directory.
196
+ */
197
+
198
+#include "qemu/osdep.h"
199
+#include "qemu/log.h"
200
+
201
+#include "hw/misc/imx7_ccm.h"
202
+
203
+static void imx7_analog_reset(DeviceState *dev)
204
+{
205
+ IMX7AnalogState *s = IMX7_ANALOG(dev);
206
+
207
+ memset(s->pmu, 0, sizeof(s->pmu));
208
+ memset(s->analog, 0, sizeof(s->analog));
209
+
210
+ s->analog[ANALOG_PLL_ARM] = 0x00002042;
211
+ s->analog[ANALOG_PLL_DDR] = 0x0060302c;
212
+ s->analog[ANALOG_PLL_DDR_SS] = 0x00000000;
213
+ s->analog[ANALOG_PLL_DDR_NUM] = 0x06aaac4d;
214
+ s->analog[ANALOG_PLL_DDR_DENOM] = 0x100003ec;
215
+ s->analog[ANALOG_PLL_480] = 0x00002000;
216
+ s->analog[ANALOG_PLL_480A] = 0x52605a56;
217
+ s->analog[ANALOG_PLL_480B] = 0x52525216;
218
+ s->analog[ANALOG_PLL_ENET] = 0x00001fc0;
219
+ s->analog[ANALOG_PLL_AUDIO] = 0x0001301b;
220
+ s->analog[ANALOG_PLL_AUDIO_SS] = 0x00000000;
221
+ s->analog[ANALOG_PLL_AUDIO_NUM] = 0x05f5e100;
222
+ s->analog[ANALOG_PLL_AUDIO_DENOM] = 0x2964619c;
223
+ s->analog[ANALOG_PLL_VIDEO] = 0x0008201b;
224
+ s->analog[ANALOG_PLL_VIDEO_SS] = 0x00000000;
225
+ s->analog[ANALOG_PLL_VIDEO_NUM] = 0x0000f699;
226
+ s->analog[ANALOG_PLL_VIDEO_DENOM] = 0x000f4240;
227
+ s->analog[ANALOG_PLL_MISC0] = 0x00000000;
228
+
229
+ /* all PLLs need to be locked */
230
+ s->analog[ANALOG_PLL_ARM] |= ANALOG_PLL_LOCK;
231
+ s->analog[ANALOG_PLL_DDR] |= ANALOG_PLL_LOCK;
232
+ s->analog[ANALOG_PLL_480] |= ANALOG_PLL_LOCK;
233
+ s->analog[ANALOG_PLL_480A] |= ANALOG_PLL_LOCK;
234
+ s->analog[ANALOG_PLL_480B] |= ANALOG_PLL_LOCK;
235
+ s->analog[ANALOG_PLL_ENET] |= ANALOG_PLL_LOCK;
236
+ s->analog[ANALOG_PLL_AUDIO] |= ANALOG_PLL_LOCK;
237
+ s->analog[ANALOG_PLL_VIDEO] |= ANALOG_PLL_LOCK;
238
+ s->analog[ANALOG_PLL_MISC0] |= ANALOG_PLL_LOCK;
239
+
240
+ /*
241
+ * Since I couldn't find any info about this in the reference
242
+ * manual the value of this register is based strictly on matching
243
+ * what Linux kernel expects it to be.
244
+ */
245
+ s->analog[ANALOG_DIGPROG] = 0x720000;
246
+ /*
247
+ * Set revision to be 1.0 (Arbitrary choice, no particular
248
+ * reason).
249
+ */
250
+ s->analog[ANALOG_DIGPROG] |= 0x000010;
251
+}
252
+
253
+static void imx7_ccm_reset(DeviceState *dev)
254
+{
255
+ IMX7CCMState *s = IMX7_CCM(dev);
256
+
257
+ memset(s->ccm, 0, sizeof(s->ccm));
258
+}
259
+
260
+#define CCM_INDEX(offset) (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t))
261
+#define CCM_BITOP(offset) ((offset) & (hwaddr)0xF)
262
+
263
+enum {
264
+ CCM_BITOP_NONE = 0x00,
265
+ CCM_BITOP_SET = 0x04,
266
+ CCM_BITOP_CLR = 0x08,
267
+ CCM_BITOP_TOG = 0x0C,
268
+};
269
+
270
+static uint64_t imx7_set_clr_tog_read(void *opaque, hwaddr offset,
271
+ unsigned size)
272
+{
273
+ const uint32_t *mmio = opaque;
274
+
275
+ return mmio[CCM_INDEX(offset)];
276
+}
277
+
278
+static void imx7_set_clr_tog_write(void *opaque, hwaddr offset,
279
+ uint64_t value, unsigned size)
280
+{
281
+ const uint8_t bitop = CCM_BITOP(offset);
282
+ const uint32_t index = CCM_INDEX(offset);
283
+ uint32_t *mmio = opaque;
284
+
285
+ switch (bitop) {
286
+ case CCM_BITOP_NONE:
287
+ mmio[index] = value;
288
+ break;
289
+ case CCM_BITOP_SET:
290
+ mmio[index] |= value;
291
+ break;
292
+ case CCM_BITOP_CLR:
293
+ mmio[index] &= ~value;
294
+ break;
295
+ case CCM_BITOP_TOG:
296
+ mmio[index] ^= value;
297
+ break;
298
+ };
299
+}
300
+
301
+static const struct MemoryRegionOps imx7_set_clr_tog_ops = {
302
+ .read = imx7_set_clr_tog_read,
303
+ .write = imx7_set_clr_tog_write,
304
+ .endianness = DEVICE_NATIVE_ENDIAN,
305
+ .impl = {
306
+ /*
307
+ * Our device would not work correctly if the guest was doing
308
+ * unaligned access. This might not be a limitation on the real
309
+ * device but in practice there is no reason for a guest to access
310
+ * this device unaligned.
311
+ */
312
+ .min_access_size = 4,
313
+ .max_access_size = 4,
314
+ .unaligned = false,
315
+ },
316
+};
317
+
318
+static const struct MemoryRegionOps imx7_digprog_ops = {
319
+ .read = imx7_set_clr_tog_read,
320
+ .endianness = DEVICE_NATIVE_ENDIAN,
321
+ .impl = {
322
+ .min_access_size = 4,
323
+ .max_access_size = 4,
324
+ .unaligned = false,
325
+ },
326
+};
327
+
328
+static void imx7_ccm_init(Object *obj)
329
+{
330
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
331
+ IMX7CCMState *s = IMX7_CCM(obj);
332
+
333
+ memory_region_init_io(&s->iomem,
334
+ obj,
335
+ &imx7_set_clr_tog_ops,
336
+ s->ccm,
337
+ TYPE_IMX7_CCM ".ccm",
338
+ sizeof(s->ccm));
339
+
340
+ sysbus_init_mmio(sd, &s->iomem);
341
+}
342
+
343
+static void imx7_analog_init(Object *obj)
344
+{
345
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
346
+ IMX7AnalogState *s = IMX7_ANALOG(obj);
347
+
348
+ memory_region_init(&s->mmio.container, obj, TYPE_IMX7_ANALOG,
349
+ 0x10000);
350
+
351
+ memory_region_init_io(&s->mmio.analog,
352
+ obj,
353
+ &imx7_set_clr_tog_ops,
354
+ s->analog,
355
+ TYPE_IMX7_ANALOG,
356
+ sizeof(s->analog));
357
+
358
+ memory_region_add_subregion(&s->mmio.container,
359
+ 0x60, &s->mmio.analog);
360
+
361
+ memory_region_init_io(&s->mmio.pmu,
362
+ obj,
363
+ &imx7_set_clr_tog_ops,
364
+ s->pmu,
365
+ TYPE_IMX7_ANALOG ".pmu",
366
+ sizeof(s->pmu));
367
+
368
+ memory_region_add_subregion(&s->mmio.container,
369
+ 0x200, &s->mmio.pmu);
370
+
371
+ memory_region_init_io(&s->mmio.digprog,
372
+ obj,
373
+ &imx7_digprog_ops,
374
+ &s->analog[ANALOG_DIGPROG],
375
+ TYPE_IMX7_ANALOG ".digprog",
376
+ sizeof(uint32_t));
377
+
378
+ memory_region_add_subregion_overlap(&s->mmio.container,
379
+ 0x800, &s->mmio.digprog, 10);
380
+
381
+
382
+ sysbus_init_mmio(sd, &s->mmio.container);
383
+}
384
+
385
+static const VMStateDescription vmstate_imx7_ccm = {
386
+ .name = TYPE_IMX7_CCM,
387
+ .version_id = 1,
388
+ .minimum_version_id = 1,
389
+ .fields = (VMStateField[]) {
390
+ VMSTATE_UINT32_ARRAY(ccm, IMX7CCMState, CCM_MAX),
391
+ VMSTATE_END_OF_LIST()
392
+ },
393
+};
394
+
395
+static uint32_t imx7_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
396
+{
397
+ /*
398
+ * This function is "consumed" by GPT emulation code, however on
399
+ * i.MX7 each GPT block can have their own clock root. This means
400
+ * that this functions needs somehow to know requester's identity
401
+ * and the way to pass it: be it via additional IMXClk constants
402
+ * or by adding another argument to this method needs to be
403
+ * figured out
404
+ */
405
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Not implemented\n",
406
+ TYPE_IMX7_CCM, __func__);
407
+ return 0;
408
+}
409
+
410
+static void imx7_ccm_class_init(ObjectClass *klass, void *data)
411
+{
412
+ DeviceClass *dc = DEVICE_CLASS(klass);
413
+ IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
414
+
415
+ dc->reset = imx7_ccm_reset;
416
+ dc->vmsd = &vmstate_imx7_ccm;
417
+ dc->desc = "i.MX7 Clock Control Module";
418
+
419
+ ccm->get_clock_frequency = imx7_ccm_get_clock_frequency;
420
+}
421
+
422
+static const TypeInfo imx7_ccm_info = {
423
+ .name = TYPE_IMX7_CCM,
424
+ .parent = TYPE_IMX_CCM,
425
+ .instance_size = sizeof(IMX7CCMState),
426
+ .instance_init = imx7_ccm_init,
427
+ .class_init = imx7_ccm_class_init,
428
+};
429
+
430
+static const VMStateDescription vmstate_imx7_analog = {
431
+ .name = TYPE_IMX7_ANALOG,
432
+ .version_id = 1,
433
+ .minimum_version_id = 1,
434
+ .fields = (VMStateField[]) {
435
+ VMSTATE_UINT32_ARRAY(analog, IMX7AnalogState, ANALOG_MAX),
436
+ VMSTATE_UINT32_ARRAY(pmu, IMX7AnalogState, PMU_MAX),
437
+ VMSTATE_END_OF_LIST()
438
+ },
439
+};
440
+
441
+static void imx7_analog_class_init(ObjectClass *klass, void *data)
442
+{
443
+ DeviceClass *dc = DEVICE_CLASS(klass);
444
+
445
+ dc->reset = imx7_analog_reset;
446
+ dc->vmsd = &vmstate_imx7_analog;
447
+ dc->desc = "i.MX7 Analog Module";
448
+}
449
+
450
+static const TypeInfo imx7_analog_info = {
451
+ .name = TYPE_IMX7_ANALOG,
452
+ .parent = TYPE_SYS_BUS_DEVICE,
453
+ .instance_size = sizeof(IMX7AnalogState),
454
+ .instance_init = imx7_analog_init,
455
+ .class_init = imx7_analog_class_init,
456
+};
457
+
458
+static void imx7_ccm_register_type(void)
459
+{
460
+ type_register_static(&imx7_ccm_info);
461
+ type_register_static(&imx7_analog_info);
462
+}
463
+type_init(imx7_ccm_register_type)
464
--
73
--
465
2.16.1
74
2.34.1
466
75
467
76
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Convert i.MX6 to use TYPE_IMX_USDHC since that's what real HW comes
3
Assign the pointer return value to 'a' directly,
4
with.
4
rather than going through an intermediary index.
5
5
6
Cc: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Cc: Jason Wang <jasowang@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20241203203949.483774-5-richard.henderson@linaro.org
9
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
10
Cc: Michael S. Tsirkin <mst@redhat.com>
11
Cc: qemu-devel@nongnu.org
12
Cc: qemu-arm@nongnu.org
13
Cc: yurovsky@gmail.com
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
10
---
18
hw/arm/fsl-imx6.c | 2 +-
11
fpu/softfloat-parts.c.inc | 32 ++++++++++----------------------
19
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 10 insertions(+), 22 deletions(-)
20
13
21
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/fsl-imx6.c
16
--- a/fpu/softfloat-parts.c.inc
24
+++ b/hw/arm/fsl-imx6.c
17
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6_init(Object *obj)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
FloatPartsN *c, float_status *s,
20
int ab_mask, int abc_mask)
21
{
22
- int which;
23
bool infzero = (ab_mask == float_cmask_infzero);
24
bool have_snan = (abc_mask & float_cmask_snan);
25
+ FloatPartsN *ret;
26
27
if (unlikely(have_snan)) {
28
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
30
default:
31
g_assert_not_reached();
32
}
33
- which = 2;
34
+ ret = c;
35
} else {
36
- FloatClass cls[3] = { a->cls, b->cls, c->cls };
37
+ FloatPartsN *val[3] = { a, b, c };
38
Float3NaNPropRule rule = s->float_3nan_prop_rule;
39
40
assert(rule != float_3nan_prop_none);
41
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
42
/* We have at least one SNaN input and should prefer it */
43
do {
44
- which = rule & R_3NAN_1ST_MASK;
45
+ ret = val[rule & R_3NAN_1ST_MASK];
46
rule >>= R_3NAN_1ST_LENGTH;
47
- } while (!is_snan(cls[which]));
48
+ } while (!is_snan(ret->cls));
49
} else {
50
do {
51
- which = rule & R_3NAN_1ST_MASK;
52
+ ret = val[rule & R_3NAN_1ST_MASK];
53
rule >>= R_3NAN_1ST_LENGTH;
54
- } while (!is_nan(cls[which]));
55
+ } while (!is_nan(ret->cls));
56
}
26
}
57
}
27
58
28
for (i = 0; i < FSL_IMX6_NUM_ESDHCS; i++) {
59
- switch (which) {
29
- object_initialize(&s->esdhc[i], sizeof(s->esdhc[i]), TYPE_SYSBUS_SDHCI);
60
- case 0:
30
+ object_initialize(&s->esdhc[i], sizeof(s->esdhc[i]), TYPE_IMX_USDHC);
61
- break;
31
qdev_set_parent_bus(DEVICE(&s->esdhc[i]), sysbus_get_default());
62
- case 1:
32
snprintf(name, NAME_SIZE, "sdhc%d", i + 1);
63
- a = b;
33
object_property_add_child(obj, name, OBJECT(&s->esdhc[i]), NULL);
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);
34
--
81
--
35
2.16.1
82
2.34.1
36
83
37
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
Save the high parts of the Zregs and all of the Pregs.
3
While all indices into val[] should be in [0-2], the mask
4
The ZCR_ELx registers are migrated via the CP mechanism.
4
applied is two bits. To help static analysis see there is
5
no possibility of read beyond the end of the array, pad the
6
array to 4 entries, with the final being (implicitly) NULL.
5
7
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20241203203949.483774-6-richard.henderson@linaro.org
9
Message-id: 20180123035349.24538-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
target/arm/machine.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++
13
fpu/softfloat-parts.c.inc | 2 +-
13
1 file changed, 53 insertions(+)
14
1 file changed, 1 insertion(+), 1 deletion(-)
14
15
15
diff --git a/target/arm/machine.c b/target/arm/machine.c
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/machine.c
18
--- a/fpu/softfloat-parts.c.inc
18
+++ b/target/arm/machine.c
19
+++ b/fpu/softfloat-parts.c.inc
19
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_iwmmxt = {
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
20
}
21
}
21
};
22
ret = c;
22
23
} else {
23
+#ifdef TARGET_AARCH64
24
- FloatPartsN *val[3] = { a, b, c };
24
+/* The expression ARM_MAX_VQ - 2 is 0 for pure AArch32 build,
25
+ FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
25
+ * and ARMPredicateReg is actively empty. This triggers errors
26
Float3NaNPropRule rule = s->float_3nan_prop_rule;
26
+ * in the expansion of the VMSTATE macros.
27
27
+ */
28
assert(rule != float_3nan_prop_none);
28
+
29
+static bool sve_needed(void *opaque)
30
+{
31
+ ARMCPU *cpu = opaque;
32
+ CPUARMState *env = &cpu->env;
33
+
34
+ return arm_feature(env, ARM_FEATURE_SVE);
35
+}
36
+
37
+/* The first two words of each Zreg is stored in VFP state. */
38
+static const VMStateDescription vmstate_zreg_hi_reg = {
39
+ .name = "cpu/sve/zreg_hi",
40
+ .version_id = 1,
41
+ .minimum_version_id = 1,
42
+ .fields = (VMStateField[]) {
43
+ VMSTATE_UINT64_SUB_ARRAY(d, ARMVectorReg, 2, ARM_MAX_VQ - 2),
44
+ VMSTATE_END_OF_LIST()
45
+ }
46
+};
47
+
48
+static const VMStateDescription vmstate_preg_reg = {
49
+ .name = "cpu/sve/preg",
50
+ .version_id = 1,
51
+ .minimum_version_id = 1,
52
+ .fields = (VMStateField[]) {
53
+ VMSTATE_UINT64_ARRAY(p, ARMPredicateReg, 2 * ARM_MAX_VQ / 8),
54
+ VMSTATE_END_OF_LIST()
55
+ }
56
+};
57
+
58
+static const VMStateDescription vmstate_sve = {
59
+ .name = "cpu/sve",
60
+ .version_id = 1,
61
+ .minimum_version_id = 1,
62
+ .needed = sve_needed,
63
+ .fields = (VMStateField[]) {
64
+ VMSTATE_STRUCT_ARRAY(env.vfp.zregs, ARMCPU, 32, 0,
65
+ vmstate_zreg_hi_reg, ARMVectorReg),
66
+ VMSTATE_STRUCT_ARRAY(env.vfp.pregs, ARMCPU, 17, 0,
67
+ vmstate_preg_reg, ARMPredicateReg),
68
+ VMSTATE_END_OF_LIST()
69
+ }
70
+};
71
+#endif /* AARCH64 */
72
+
73
static bool m_needed(void *opaque)
74
{
75
ARMCPU *cpu = opaque;
76
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_arm_cpu = {
77
&vmstate_pmsav7,
78
&vmstate_pmsav8,
79
&vmstate_m_security,
80
+#ifdef TARGET_AARCH64
81
+ &vmstate_sve,
82
+#endif
83
NULL
84
}
85
};
86
--
29
--
87
2.16.1
30
2.34.1
88
31
89
32
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Define ZCR_EL[1-3].
3
This function is part of the public interface and
4
is not "specialized" to any target in any way.
4
5
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180123035349.24538-5-richard.henderson@linaro.org
8
Message-id: 20241203203949.483774-7-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
target/arm/cpu.h | 5 ++
11
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++++++++
11
target/arm/helper.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++
12
fpu/softfloat-specialize.c.inc | 52 ----------------------------------
12
2 files changed, 136 insertions(+)
13
2 files changed, 52 insertions(+), 52 deletions(-)
13
14
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
--- a/fpu/softfloat.c
17
+++ b/target/arm/cpu.h
18
+++ b/fpu/softfloat.c
18
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
19
*/
20
*zExpPtr = 1 - shiftCount;
20
float_status fp_status;
21
}
21
float_status standard_fp_status;
22
23
+/*----------------------------------------------------------------------------
24
+| Takes two extended double-precision floating-point values `a' and `b', one
25
+| of which is a NaN, and returns the appropriate NaN result. If either `a' or
26
+| `b' is a signaling NaN, the invalid exception is raised.
27
+*----------------------------------------------------------------------------*/
22
+
28
+
23
+ /* ZCR_EL[1-3] */
29
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
24
+ uint64_t zcr_el[4];
25
} vfp;
26
uint64_t exclusive_addr;
27
uint64_t exclusive_val;
28
@@ -XXX,XX +XXX,XX @@ void pmccntr_sync(CPUARMState *env);
29
#define CPTR_TCPAC (1U << 31)
30
#define CPTR_TTA (1U << 20)
31
#define CPTR_TFP (1U << 10)
32
+#define CPTR_TZ (1U << 8) /* CPTR_EL2 */
33
+#define CPTR_EZ (1U << 8) /* CPTR_EL3 */
34
35
#define MDCR_EPMAD (1U << 21)
36
#define MDCR_EDAD (1U << 20)
37
diff --git a/target/arm/helper.c b/target/arm/helper.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/helper.c
40
+++ b/target/arm/helper.c
41
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
42
REGINFO_SENTINEL
43
};
44
45
+/* Return the exception level to which SVE-disabled exceptions should
46
+ * be taken, or 0 if SVE is enabled.
47
+ */
48
+static int sve_exception_el(CPUARMState *env)
49
+{
30
+{
50
+#ifndef CONFIG_USER_ONLY
31
+ bool aIsLargerSignificand;
51
+ unsigned current_el = arm_current_el(env);
32
+ FloatClass a_cls, b_cls;
52
+
33
+
53
+ /* The CPACR.ZEN controls traps to EL1:
34
+ /* This is not complete, but is good enough for pickNaN. */
54
+ * 0, 2 : trap EL0 and EL1 accesses
35
+ a_cls = (!floatx80_is_any_nan(a)
55
+ * 1 : trap only EL0 accesses
36
+ ? float_class_normal
56
+ * 3 : trap no accesses
37
+ : floatx80_is_signaling_nan(a, status)
57
+ */
38
+ ? float_class_snan
58
+ switch (extract32(env->cp15.cpacr_el1, 16, 2)) {
39
+ : float_class_qnan);
59
+ default:
40
+ b_cls = (!floatx80_is_any_nan(b)
60
+ if (current_el <= 1) {
41
+ ? float_class_normal
61
+ /* Trap to PL1, which might be EL1 or EL3 */
42
+ : floatx80_is_signaling_nan(b, status)
62
+ if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
43
+ ? float_class_snan
63
+ return 3;
44
+ : float_class_qnan);
64
+ }
45
+
65
+ return 1;
46
+ if (is_snan(a_cls) || is_snan(b_cls)) {
66
+ }
47
+ float_raise(float_flag_invalid, status);
67
+ break;
68
+ case 1:
69
+ if (current_el == 0) {
70
+ return 1;
71
+ }
72
+ break;
73
+ case 3:
74
+ break;
75
+ }
48
+ }
76
+
49
+
77
+ /* Similarly for CPACR.FPEN, after having checked ZEN. */
50
+ if (status->default_nan_mode) {
78
+ switch (extract32(env->cp15.cpacr_el1, 20, 2)) {
51
+ return floatx80_default_nan(status);
79
+ default:
80
+ if (current_el <= 1) {
81
+ if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
82
+ return 3;
83
+ }
84
+ return 1;
85
+ }
86
+ break;
87
+ case 1:
88
+ if (current_el == 0) {
89
+ return 1;
90
+ }
91
+ break;
92
+ case 3:
93
+ break;
94
+ }
52
+ }
95
+
53
+
96
+ /* CPTR_EL2. Check both TZ and TFP. */
54
+ if (a.low < b.low) {
97
+ if (current_el <= 2
55
+ aIsLargerSignificand = 0;
98
+ && (env->cp15.cptr_el[2] & (CPTR_TFP | CPTR_TZ))
56
+ } else if (b.low < a.low) {
99
+ && !arm_is_secure_below_el3(env)) {
57
+ aIsLargerSignificand = 1;
100
+ return 2;
58
+ } else {
59
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
101
+ }
60
+ }
102
+
61
+
103
+ /* CPTR_EL3. Check both EZ and TFP. */
62
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
104
+ if (!(env->cp15.cptr_el[3] & CPTR_EZ)
63
+ if (is_snan(b_cls)) {
105
+ || (env->cp15.cptr_el[3] & CPTR_TFP)) {
64
+ return floatx80_silence_nan(b, status);
106
+ return 3;
65
+ }
66
+ return b;
67
+ } else {
68
+ if (is_snan(a_cls)) {
69
+ return floatx80_silence_nan(a, status);
70
+ }
71
+ return a;
107
+ }
72
+ }
108
+#endif
109
+ return 0;
110
+}
73
+}
111
+
74
+
112
+static CPAccessResult zcr_access(CPUARMState *env, const ARMCPRegInfo *ri,
75
/*----------------------------------------------------------------------------
113
+ bool isread)
76
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
114
+{
77
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
115
+ switch (sve_exception_el(env)) {
78
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
116
+ case 3:
79
index XXXXXXX..XXXXXXX 100644
117
+ return CP_ACCESS_TRAP_EL3;
80
--- a/fpu/softfloat-specialize.c.inc
118
+ case 2:
81
+++ b/fpu/softfloat-specialize.c.inc
119
+ return CP_ACCESS_TRAP_EL2;
82
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
120
+ case 1:
83
return a;
121
+ return CP_ACCESS_TRAP;
122
+ }
123
+ return CP_ACCESS_OK;
124
+}
125
+
126
+static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
127
+ uint64_t value)
128
+{
129
+ /* Bits other than [3:0] are RAZ/WI. */
130
+ raw_write(env, ri, value & 0xf);
131
+}
132
+
133
+static const ARMCPRegInfo zcr_el1_reginfo = {
134
+ .name = "ZCR_EL1", .state = ARM_CP_STATE_AA64,
135
+ .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0,
136
+ .access = PL1_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
137
+ .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]),
138
+ .writefn = zcr_write, .raw_writefn = raw_write
139
+};
140
+
141
+static const ARMCPRegInfo zcr_el2_reginfo = {
142
+ .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
143
+ .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
144
+ .access = PL2_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
145
+ .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]),
146
+ .writefn = zcr_write, .raw_writefn = raw_write
147
+};
148
+
149
+static const ARMCPRegInfo zcr_no_el2_reginfo = {
150
+ .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
151
+ .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
152
+ .access = PL2_RW, .type = ARM_CP_64BIT,
153
+ .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore
154
+};
155
+
156
+static const ARMCPRegInfo zcr_el3_reginfo = {
157
+ .name = "ZCR_EL3", .state = ARM_CP_STATE_AA64,
158
+ .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0,
159
+ .access = PL3_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT,
160
+ .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]),
161
+ .writefn = zcr_write, .raw_writefn = raw_write
162
+};
163
+
164
void hw_watchpoint_update(ARMCPU *cpu, int n)
165
{
166
CPUARMState *env = &cpu->env;
167
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
168
}
169
define_one_arm_cp_reg(cpu, &sctlr);
170
}
171
+
172
+ if (arm_feature(env, ARM_FEATURE_SVE)) {
173
+ define_one_arm_cp_reg(cpu, &zcr_el1_reginfo);
174
+ if (arm_feature(env, ARM_FEATURE_EL2)) {
175
+ define_one_arm_cp_reg(cpu, &zcr_el2_reginfo);
176
+ } else {
177
+ define_one_arm_cp_reg(cpu, &zcr_no_el2_reginfo);
178
+ }
179
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
180
+ define_one_arm_cp_reg(cpu, &zcr_el3_reginfo);
181
+ }
182
+ }
183
}
84
}
184
85
185
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
86
-/*----------------------------------------------------------------------------
87
-| Takes two extended double-precision floating-point values `a' and `b', one
88
-| of which is a NaN, and returns the appropriate NaN result. If either `a' or
89
-| `b' is a signaling NaN, the invalid exception is raised.
90
-*----------------------------------------------------------------------------*/
91
-
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.
186
--
141
--
187
2.16.1
142
2.34.1
188
189
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Unpacking and repacking the parts may be slightly more work
4
than we did before, but we get to reuse more code. For a
5
code path handling exceptional values, this is an improvement.
6
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 20241203203949.483774-8-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 20180123035349.24538-3-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
11
---
9
target/arm/cpu.h | 12 ++++++++++++
12
fpu/softfloat.c | 43 +++++--------------------------------------
10
1 file changed, 12 insertions(+)
13
1 file changed, 5 insertions(+), 38 deletions(-)
11
14
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.h
17
--- a/fpu/softfloat.c
15
+++ b/target/arm/cpu.h
18
+++ b/fpu/softfloat.c
16
@@ -XXX,XX +XXX,XX @@ typedef struct ARMVectorReg {
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
17
uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16);
20
18
} ARMVectorReg;
21
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
19
22
{
20
+/* In AArch32 mode, predicate registers do not exist at all. */
23
- bool aIsLargerSignificand;
21
+#ifdef TARGET_AARCH64
24
- FloatClass a_cls, b_cls;
22
+typedef struct ARMPredicateReg {
25
+ FloatParts128 pa, pb, *pr;
23
+ uint64_t p[2 * ARM_MAX_VQ / 8] QEMU_ALIGNED(16);
26
24
+} ARMPredicateReg;
27
- /* This is not complete, but is good enough for pickNaN. */
25
+#endif
28
- a_cls = (!floatx80_is_any_nan(a)
26
+
29
- ? float_class_normal
27
30
- : floatx80_is_signaling_nan(a, status)
28
typedef struct CPUARMState {
31
- ? float_class_snan
29
/* Regs for current mode. */
32
- : float_class_qnan);
30
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
33
- b_cls = (!floatx80_is_any_nan(b)
31
struct {
34
- ? float_class_normal
32
ARMVectorReg zregs[32];
35
- : floatx80_is_signaling_nan(b, status)
33
36
- ? float_class_snan
34
+#ifdef TARGET_AARCH64
37
- : float_class_qnan);
35
+ /* Store FFR as pregs[16] to make it easier to treat as any other. */
38
-
36
+ ARMPredicateReg pregs[17];
39
- if (is_snan(a_cls) || is_snan(b_cls)) {
37
+#endif
40
- float_raise(float_flag_invalid, status);
38
+
41
- }
39
uint32_t xregs[16];
42
-
40
/* We store these fpcsr fields separately for convenience. */
43
- if (status->default_nan_mode) {
41
int vec_len;
44
+ if (!floatx80_unpack_canonical(&pa, a, status) ||
45
+ !floatx80_unpack_canonical(&pb, b, status)) {
46
return floatx80_default_nan(status);
47
}
48
49
- if (a.low < b.low) {
50
- aIsLargerSignificand = 0;
51
- } else if (b.low < a.low) {
52
- aIsLargerSignificand = 1;
53
- } else {
54
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
55
- }
56
-
57
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
58
- if (is_snan(b_cls)) {
59
- return floatx80_silence_nan(b, status);
60
- }
61
- return b;
62
- } else {
63
- if (is_snan(a_cls)) {
64
- return floatx80_silence_nan(a, status);
65
- }
66
- return a;
67
- }
68
+ pr = parts_pick_nan(&pa, &pb, status);
69
+ return floatx80_round_pack_canonical(pr, status);
70
}
71
72
/*----------------------------------------------------------------------------
42
--
73
--
43
2.16.1
74
2.34.1
44
45
diff view generated by jsdifflib
1
From: Andrey Smirnov <andrew.smirnov@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Move virt's PSCI DT fixup code to arm/boot.c and set this fixup to
3
Inline pickNaN into its only caller. This makes one assert
4
happen automatically for every board that doesn't mark "psci-conduit"
4
redundant with the immediately preceding IF.
5
as disabled. This way emulated boards other than "virt" that rely on
5
6
PSIC for SMP could benefit from that code.
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Cc: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-9-richard.henderson@linaro.org
9
Cc: Jason Wang <jasowang@redhat.com>
10
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Cc: Marcel Apfelbaum <marcel.apfelbaum@zoho.com>
12
Cc: Michael S. Tsirkin <mst@redhat.com>
13
Cc: qemu-devel@nongnu.org
14
Cc: qemu-arm@nongnu.org
15
Cc: yurovsky@gmail.com
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
10
---
21
hw/arm/boot.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11
fpu/softfloat-parts.c.inc | 82 +++++++++++++++++++++++++----
22
hw/arm/virt.c | 61 -------------------------------------------------------
12
fpu/softfloat-specialize.c.inc | 96 ----------------------------------
23
2 files changed, 65 insertions(+), 61 deletions(-)
13
2 files changed, 73 insertions(+), 105 deletions(-)
24
14
25
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
15
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/boot.c
17
--- a/fpu/softfloat-parts.c.inc
28
+++ b/hw/arm/boot.c
18
+++ b/fpu/softfloat-parts.c.inc
29
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args_old(const struct arm_boot_info *info)
19
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
20
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
21
float_status *s)
22
{
23
+ int cmp, which;
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)
30
}
122
}
31
}
123
}
32
124
33
+static void fdt_add_psci_node(void *fdt)
125
-/*----------------------------------------------------------------------------
34
+{
126
-| Select which NaN to propagate for a two-input operation.
35
+ uint32_t cpu_suspend_fn;
127
-| IEEE754 doesn't specify all the details of this, so the
36
+ uint32_t cpu_off_fn;
128
-| algorithm is target-specific.
37
+ uint32_t cpu_on_fn;
129
-| The routine is passed various bits of information about the
38
+ uint32_t migrate_fn;
130
-| two NaNs and should return 0 to select NaN a and 1 for NaN b.
39
+ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
131
-| Note that signalling NaNs are always squashed to quiet NaNs
40
+ const char *psci_method;
132
-| by the caller, by calling floatXX_silence_nan() before
41
+ int64_t psci_conduit;
133
-| returning them.
42
+
134
-|
43
+ psci_conduit = object_property_get_int(OBJECT(armcpu),
135
-| aIsLargerSignificand is only valid if both a and b are NaNs
44
+ "psci-conduit",
136
-| of some kind, and is true if a has the larger significand,
45
+ &error_abort);
137
-| or if both a and b have the same significand but a is
46
+ switch (psci_conduit) {
138
-| positive but b is negative. It is only needed for the x87
47
+ case QEMU_PSCI_CONDUIT_DISABLED:
139
-| tie-break rule.
48
+ return;
140
-*----------------------------------------------------------------------------*/
49
+ case QEMU_PSCI_CONDUIT_HVC:
141
-
50
+ psci_method = "hvc";
142
-static int pickNaN(FloatClass a_cls, FloatClass b_cls,
51
+ break;
143
- bool aIsLargerSignificand, float_status *status)
52
+ case QEMU_PSCI_CONDUIT_SMC:
53
+ psci_method = "smc";
54
+ break;
55
+ default:
56
+ g_assert_not_reached();
57
+ }
58
+
59
+ qemu_fdt_add_subnode(fdt, "/psci");
60
+ if (armcpu->psci_version == 2) {
61
+ const char comp[] = "arm,psci-0.2\0arm,psci";
62
+ qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
63
+
64
+ cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF;
65
+ if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) {
66
+ cpu_suspend_fn = QEMU_PSCI_0_2_FN64_CPU_SUSPEND;
67
+ cpu_on_fn = QEMU_PSCI_0_2_FN64_CPU_ON;
68
+ migrate_fn = QEMU_PSCI_0_2_FN64_MIGRATE;
69
+ } else {
70
+ cpu_suspend_fn = QEMU_PSCI_0_2_FN_CPU_SUSPEND;
71
+ cpu_on_fn = QEMU_PSCI_0_2_FN_CPU_ON;
72
+ migrate_fn = QEMU_PSCI_0_2_FN_MIGRATE;
73
+ }
74
+ } else {
75
+ qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci");
76
+
77
+ cpu_suspend_fn = QEMU_PSCI_0_1_FN_CPU_SUSPEND;
78
+ cpu_off_fn = QEMU_PSCI_0_1_FN_CPU_OFF;
79
+ cpu_on_fn = QEMU_PSCI_0_1_FN_CPU_ON;
80
+ migrate_fn = QEMU_PSCI_0_1_FN_MIGRATE;
81
+ }
82
+
83
+ /* We adopt the PSCI spec's nomenclature, and use 'conduit' to refer
84
+ * to the instruction that should be used to invoke PSCI functions.
85
+ * However, the device tree binding uses 'method' instead, so that is
86
+ * what we should use here.
87
+ */
88
+ qemu_fdt_setprop_string(fdt, "/psci", "method", psci_method);
89
+
90
+ qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend", cpu_suspend_fn);
91
+ qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", cpu_off_fn);
92
+ qemu_fdt_setprop_cell(fdt, "/psci", "cpu_on", cpu_on_fn);
93
+ qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
94
+}
95
+
96
/**
97
* load_dtb() - load a device tree binary image into memory
98
* @addr: the address to load the image at
99
@@ -XXX,XX +XXX,XX @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
100
}
101
}
102
103
+ fdt_add_psci_node(fdt);
104
+
105
if (binfo->modify_dtb) {
106
binfo->modify_dtb(binfo, fdt);
107
}
108
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/hw/arm/virt.c
111
+++ b/hw/arm/virt.c
112
@@ -XXX,XX +XXX,XX @@ static void create_fdt(VirtMachineState *vms)
113
}
114
}
115
116
-static void fdt_add_psci_node(const VirtMachineState *vms)
117
-{
144
-{
118
- uint32_t cpu_suspend_fn;
145
- /*
119
- uint32_t cpu_off_fn;
146
- * We guarantee not to require the target to tell us how to
120
- uint32_t cpu_on_fn;
147
- * pick a NaN if we're always returning the default NaN.
121
- uint32_t migrate_fn;
148
- * But if we're not in default-NaN mode then the target must
122
- void *fdt = vms->fdt;
149
- * specify via set_float_2nan_prop_rule().
123
- ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
150
- */
124
- const char *psci_method;
151
- assert(!status->default_nan_mode);
125
-
152
-
126
- switch (vms->psci_conduit) {
153
- switch (status->float_2nan_prop_rule) {
127
- case QEMU_PSCI_CONDUIT_DISABLED:
154
- case float_2nan_prop_s_ab:
128
- return;
155
- if (is_snan(a_cls)) {
129
- case QEMU_PSCI_CONDUIT_HVC:
156
- return 0;
130
- psci_method = "hvc";
157
- } else if (is_snan(b_cls)) {
131
- break;
158
- return 1;
132
- case QEMU_PSCI_CONDUIT_SMC:
159
- } else if (is_qnan(a_cls)) {
133
- psci_method = "smc";
160
- return 0;
134
- break;
161
- } else {
162
- return 1;
163
- }
164
- break;
165
- case float_2nan_prop_s_ba:
166
- if (is_snan(b_cls)) {
167
- return 1;
168
- } else if (is_snan(a_cls)) {
169
- return 0;
170
- } else if (is_qnan(b_cls)) {
171
- return 1;
172
- } else {
173
- return 0;
174
- }
175
- break;
176
- case float_2nan_prop_ab:
177
- if (is_nan(a_cls)) {
178
- return 0;
179
- } else {
180
- return 1;
181
- }
182
- break;
183
- case float_2nan_prop_ba:
184
- if (is_nan(b_cls)) {
185
- return 1;
186
- } else {
187
- return 0;
188
- }
189
- break;
190
- case float_2nan_prop_x87:
191
- /*
192
- * This implements x87 NaN propagation rules:
193
- * SNaN + QNaN => return the QNaN
194
- * two SNaNs => return the one with the larger significand, silenced
195
- * two QNaNs => return the one with the larger significand
196
- * SNaN and a non-NaN => return the SNaN, silenced
197
- * QNaN and a non-NaN => return the QNaN
198
- *
199
- * If we get down to comparing significands and they are the same,
200
- * return the NaN with the positive sign bit (if any).
201
- */
202
- if (is_snan(a_cls)) {
203
- if (is_snan(b_cls)) {
204
- return aIsLargerSignificand ? 0 : 1;
205
- }
206
- return is_qnan(b_cls) ? 1 : 0;
207
- } else if (is_qnan(a_cls)) {
208
- if (is_snan(b_cls) || !is_qnan(b_cls)) {
209
- return 0;
210
- } else {
211
- return aIsLargerSignificand ? 0 : 1;
212
- }
213
- } else {
214
- return 1;
215
- }
135
- default:
216
- default:
136
- g_assert_not_reached();
217
- g_assert_not_reached();
137
- }
218
- }
138
-
139
- qemu_fdt_add_subnode(fdt, "/psci");
140
- if (armcpu->psci_version == 2) {
141
- const char comp[] = "arm,psci-0.2\0arm,psci";
142
- qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
143
-
144
- cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF;
145
- if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) {
146
- cpu_suspend_fn = QEMU_PSCI_0_2_FN64_CPU_SUSPEND;
147
- cpu_on_fn = QEMU_PSCI_0_2_FN64_CPU_ON;
148
- migrate_fn = QEMU_PSCI_0_2_FN64_MIGRATE;
149
- } else {
150
- cpu_suspend_fn = QEMU_PSCI_0_2_FN_CPU_SUSPEND;
151
- cpu_on_fn = QEMU_PSCI_0_2_FN_CPU_ON;
152
- migrate_fn = QEMU_PSCI_0_2_FN_MIGRATE;
153
- }
154
- } else {
155
- qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci");
156
-
157
- cpu_suspend_fn = QEMU_PSCI_0_1_FN_CPU_SUSPEND;
158
- cpu_off_fn = QEMU_PSCI_0_1_FN_CPU_OFF;
159
- cpu_on_fn = QEMU_PSCI_0_1_FN_CPU_ON;
160
- migrate_fn = QEMU_PSCI_0_1_FN_MIGRATE;
161
- }
162
-
163
- /* We adopt the PSCI spec's nomenclature, and use 'conduit' to refer
164
- * to the instruction that should be used to invoke PSCI functions.
165
- * However, the device tree binding uses 'method' instead, so that is
166
- * what we should use here.
167
- */
168
- qemu_fdt_setprop_string(fdt, "/psci", "method", psci_method);
169
-
170
- qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend", cpu_suspend_fn);
171
- qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", cpu_off_fn);
172
- qemu_fdt_setprop_cell(fdt, "/psci", "cpu_on", cpu_on_fn);
173
- qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
174
-}
219
-}
175
-
220
-
176
static void fdt_add_timer_nodes(const VirtMachineState *vms)
221
/*----------------------------------------------------------------------------
177
{
222
| Returns 1 if the double-precision floating-point value `a' is a quiet
178
/* On real hardware these interrupts are level-triggered.
223
| NaN; otherwise returns 0.
179
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
180
}
181
fdt_add_timer_nodes(vms);
182
fdt_add_cpu_nodes(vms);
183
- fdt_add_psci_node(vms);
184
185
memory_region_allocate_system_memory(ram, NULL, "mach-virt.ram",
186
machine->ram_size);
187
--
224
--
188
2.16.1
225
2.34.1
189
226
190
227
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Change vfp.regs as a uint64_t to vfp.zregs as an ARMVectorReg.
3
Remember if there was an SNaN, and use that to simplify
4
The previous patches have made the change in representation
4
float_2nan_prop_s_{ab,ba} to only the snan component.
5
relatively painless.
5
Then, fall through to the corresponding
6
float_2nan_prop_{ab,ba} case to handle any remaining
7
nans, which must be quiet.
6
8
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20180123035349.24538-2-richard.henderson@linaro.org
11
Message-id: 20241203203949.483774-10-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
---
13
target/arm/cpu.h | 59 +++++++++++++++++++++++++++++++---------------
14
fpu/softfloat-parts.c.inc | 32 ++++++++++++--------------------
14
target/arm/machine.c | 35 ++++++++++++++++++++++++++-
15
1 file changed, 12 insertions(+), 20 deletions(-)
15
target/arm/translate-a64.c | 8 +++----
16
target/arm/translate.c | 7 +++---
17
4 files changed, 81 insertions(+), 28 deletions(-)
18
16
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.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/target/arm/cpu.h
19
--- a/fpu/softfloat-parts.c.inc
22
+++ b/target/arm/cpu.h
20
+++ b/fpu/softfloat-parts.c.inc
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
21
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
24
uint32_t base_mask;
22
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
25
} TCR;
23
float_status *s)
26
27
+/* Define a maximum sized vector register.
28
+ * For 32-bit, this is a 128-bit NEON/AdvSIMD register.
29
+ * For 64-bit, this is a 2048-bit SVE register.
30
+ *
31
+ * Note that the mapping between S, D, and Q views of the register bank
32
+ * differs between AArch64 and AArch32.
33
+ * In AArch32:
34
+ * Qn = regs[n].d[1]:regs[n].d[0]
35
+ * Dn = regs[n / 2].d[n & 1]
36
+ * Sn = regs[n / 4].d[n % 4 / 2],
37
+ * bits 31..0 for even n, and bits 63..32 for odd n
38
+ * (and regs[16] to regs[31] are inaccessible)
39
+ * In AArch64:
40
+ * Zn = regs[n].d[*]
41
+ * Qn = regs[n].d[1]:regs[n].d[0]
42
+ * Dn = regs[n].d[0]
43
+ * Sn = regs[n].d[0] bits 31..0
44
+ *
45
+ * This corresponds to the architecturally defined mapping between
46
+ * the two execution states, and means we do not need to explicitly
47
+ * map these registers when changing states.
48
+ *
49
+ * Align the data for use with TCG host vector operations.
50
+ */
51
+
52
+#ifdef TARGET_AARCH64
53
+# define ARM_MAX_VQ 16
54
+#else
55
+# define ARM_MAX_VQ 1
56
+#endif
57
+
58
+typedef struct ARMVectorReg {
59
+ uint64_t d[2 * ARM_MAX_VQ] QEMU_ALIGNED(16);
60
+} ARMVectorReg;
61
+
62
+
63
typedef struct CPUARMState {
64
/* Regs for current mode. */
65
uint32_t regs[16];
66
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
67
68
/* VFP coprocessor state. */
69
struct {
70
- /* VFP/Neon register state. Note that the mapping between S, D and Q
71
- * views of the register bank differs between AArch64 and AArch32:
72
- * In AArch32:
73
- * Qn = regs[2n+1]:regs[2n]
74
- * Dn = regs[n]
75
- * Sn = regs[n/2] bits 31..0 for even n, and bits 63..32 for odd n
76
- * (and regs[32] to regs[63] are inaccessible)
77
- * In AArch64:
78
- * Qn = regs[2n+1]:regs[2n]
79
- * Dn = regs[2n]
80
- * Sn = regs[2n] bits 31..0
81
- * This corresponds to the architecturally defined mapping between
82
- * the two execution states, and means we do not need to explicitly
83
- * map these registers when changing states.
84
- */
85
- uint64_t regs[64] QEMU_ALIGNED(16);
86
+ ARMVectorReg zregs[32];
87
88
uint32_t xregs[16];
89
/* We store these fpcsr fields separately for convenience. */
90
@@ -XXX,XX +XXX,XX @@ static inline void *arm_get_el_change_hook_opaque(ARMCPU *cpu)
91
*/
92
static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno)
93
{
24
{
94
- return &env->vfp.regs[regno];
25
+ bool have_snan = false;
95
+ return &env->vfp.zregs[regno >> 1].d[regno & 1];
26
int cmp, which;
96
}
27
97
28
if (is_snan(a->cls) || is_snan(b->cls)) {
98
/**
29
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
99
@@ -XXX,XX +XXX,XX @@ static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno)
30
+ have_snan = true;
100
*/
101
static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno)
102
{
103
- return &env->vfp.regs[2 * regno];
104
+ return &env->vfp.zregs[regno].d[0];
105
}
106
107
/**
108
@@ -XXX,XX +XXX,XX @@ static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno)
109
*/
110
static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno)
111
{
112
- return &env->vfp.regs[2 * regno];
113
+ return &env->vfp.zregs[regno].d[0];
114
}
115
116
#endif
117
diff --git a/target/arm/machine.c b/target/arm/machine.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/target/arm/machine.c
120
+++ b/target/arm/machine.c
121
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_vfp = {
122
.minimum_version_id = 3,
123
.needed = vfp_needed,
124
.fields = (VMStateField[]) {
125
- VMSTATE_UINT64_ARRAY(env.vfp.regs, ARMCPU, 64),
126
+ /* For compatibility, store Qn out of Zn here. */
127
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[0].d, ARMCPU, 0, 2),
128
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[1].d, ARMCPU, 0, 2),
129
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[2].d, ARMCPU, 0, 2),
130
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[3].d, ARMCPU, 0, 2),
131
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[4].d, ARMCPU, 0, 2),
132
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[5].d, ARMCPU, 0, 2),
133
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[6].d, ARMCPU, 0, 2),
134
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[7].d, ARMCPU, 0, 2),
135
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[8].d, ARMCPU, 0, 2),
136
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[9].d, ARMCPU, 0, 2),
137
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[10].d, ARMCPU, 0, 2),
138
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[11].d, ARMCPU, 0, 2),
139
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[12].d, ARMCPU, 0, 2),
140
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[13].d, ARMCPU, 0, 2),
141
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[14].d, ARMCPU, 0, 2),
142
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[15].d, ARMCPU, 0, 2),
143
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[16].d, ARMCPU, 0, 2),
144
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[17].d, ARMCPU, 0, 2),
145
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[18].d, ARMCPU, 0, 2),
146
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[19].d, ARMCPU, 0, 2),
147
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[20].d, ARMCPU, 0, 2),
148
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[21].d, ARMCPU, 0, 2),
149
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[22].d, ARMCPU, 0, 2),
150
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[23].d, ARMCPU, 0, 2),
151
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[24].d, ARMCPU, 0, 2),
152
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[25].d, ARMCPU, 0, 2),
153
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[26].d, ARMCPU, 0, 2),
154
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[27].d, ARMCPU, 0, 2),
155
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[28].d, ARMCPU, 0, 2),
156
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[29].d, ARMCPU, 0, 2),
157
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[30].d, ARMCPU, 0, 2),
158
+ VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[31].d, ARMCPU, 0, 2),
159
+
160
/* The xregs array is a little awkward because element 1 (FPSCR)
161
* requires a specific accessor, so we have to split it up in
162
* the vmstate:
163
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/target/arm/translate-a64.c
166
+++ b/target/arm/translate-a64.c
167
@@ -XXX,XX +XXX,XX @@ static inline int vec_reg_offset(DisasContext *s, int regno,
168
{
169
int offs = 0;
170
#ifdef HOST_WORDS_BIGENDIAN
171
- /* This is complicated slightly because vfp.regs[2n] is
172
- * still the low half and vfp.regs[2n+1] the high half
173
+ /* This is complicated slightly because vfp.zregs[n].d[0] is
174
+ * still the low half and vfp.zregs[n].d[1] the high half
175
* of the 128 bit vector, even on big endian systems.
176
* Calculate the offset assuming a fully bigendian 128 bits,
177
* then XOR to account for the order of the two 64 bit halves.
178
@@ -XXX,XX +XXX,XX @@ static inline int vec_reg_offset(DisasContext *s, int regno,
179
#else
180
offs += element * (1 << size);
181
#endif
182
- offs += offsetof(CPUARMState, vfp.regs[regno * 2]);
183
+ offs += offsetof(CPUARMState, vfp.zregs[regno]);
184
assert_fp_access_checked(s);
185
return offs;
186
}
187
@@ -XXX,XX +XXX,XX @@ static inline int vec_reg_offset(DisasContext *s, int regno,
188
static inline int vec_full_reg_offset(DisasContext *s, int regno)
189
{
190
assert_fp_access_checked(s);
191
- return offsetof(CPUARMState, vfp.regs[regno * 2]);
192
+ return offsetof(CPUARMState, vfp.zregs[regno]);
193
}
194
195
/* Return a newly allocated pointer to the vector register. */
196
diff --git a/target/arm/translate.c b/target/arm/translate.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/target/arm/translate.c
199
+++ b/target/arm/translate.c
200
@@ -XXX,XX +XXX,XX @@ static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
201
}
31
}
202
}
32
203
33
if (s->default_nan_mode) {
204
-static inline long
34
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
205
-vfp_reg_offset (int dp, int reg)
35
206
+static inline long vfp_reg_offset(bool dp, unsigned reg)
36
switch (s->float_2nan_prop_rule) {
207
{
37
case float_2nan_prop_s_ab:
208
if (dp) {
38
- if (is_snan(a->cls)) {
209
- return offsetof(CPUARMState, vfp.regs[reg]);
39
- which = 0;
210
+ return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
40
- } else if (is_snan(b->cls)) {
211
} else {
41
- which = 1;
212
- long ofs = offsetof(CPUARMState, vfp.regs[reg >> 1]);
42
- } else if (is_qnan(a->cls)) {
213
+ long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
43
- which = 0;
214
if (reg & 1) {
44
- } else {
215
ofs += offsetof(CPU_DoubleU, l.upper);
45
- which = 1;
216
} else {
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;
217
--
75
--
218
2.16.1
76
2.34.1
219
220
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add both SVE exception state and vector length.
3
Move the fractional comparison to the end of the
4
float_2nan_prop_x87 case. This is not required for
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.
4
8
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180123035349.24538-6-richard.henderson@linaro.org
11
Message-id: 20241203203949.483774-11-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
target/arm/cpu.h | 8 ++++++++
14
fpu/softfloat-parts.c.inc | 19 +++++++++----------
11
target/arm/translate.h | 2 ++
15
1 file changed, 9 insertions(+), 10 deletions(-)
12
target/arm/helper.c | 25 ++++++++++++++++++++++++-
13
target/arm/translate-a64.c | 2 ++
14
4 files changed, 36 insertions(+), 1 deletion(-)
15
16
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
--- a/fpu/softfloat-parts.c.inc
19
+++ b/target/arm/cpu.h
20
+++ b/fpu/softfloat-parts.c.inc
20
@@ -XXX,XX +XXX,XX @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
21
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
21
#define ARM_TBFLAG_TBI0_MASK (0x1ull << ARM_TBFLAG_TBI0_SHIFT)
22
return a;
22
#define ARM_TBFLAG_TBI1_SHIFT 1 /* TBI1 for EL0/1 */
23
}
23
#define ARM_TBFLAG_TBI1_MASK (0x1ull << ARM_TBFLAG_TBI1_SHIFT)
24
24
+#define ARM_TBFLAG_SVEEXC_EL_SHIFT 2
25
- cmp = frac_cmp(a, b);
25
+#define ARM_TBFLAG_SVEEXC_EL_MASK (0x3 << ARM_TBFLAG_SVEEXC_EL_SHIFT)
26
- if (cmp == 0) {
26
+#define ARM_TBFLAG_ZCR_LEN_SHIFT 4
27
- cmp = a->sign < b->sign;
27
+#define ARM_TBFLAG_ZCR_LEN_MASK (0xf << ARM_TBFLAG_ZCR_LEN_SHIFT)
28
- }
28
29
-
29
/* some convenience accessor macros */
30
switch (s->float_2nan_prop_rule) {
30
#define ARM_TBFLAG_AARCH64_STATE(F) \
31
case float_2nan_prop_s_ab:
31
@@ -XXX,XX +XXX,XX @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
32
if (have_snan) {
32
(((F) & ARM_TBFLAG_TBI0_MASK) >> ARM_TBFLAG_TBI0_SHIFT)
33
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
33
#define ARM_TBFLAG_TBI1(F) \
34
* return the NaN with the positive sign bit (if any).
34
(((F) & ARM_TBFLAG_TBI1_MASK) >> ARM_TBFLAG_TBI1_SHIFT)
35
*/
35
+#define ARM_TBFLAG_SVEEXC_EL(F) \
36
if (is_snan(a->cls)) {
36
+ (((F) & ARM_TBFLAG_SVEEXC_EL_MASK) >> ARM_TBFLAG_SVEEXC_EL_SHIFT)
37
- if (is_snan(b->cls)) {
37
+#define ARM_TBFLAG_ZCR_LEN(F) \
38
- which = cmp > 0 ? 0 : 1;
38
+ (((F) & ARM_TBFLAG_ZCR_LEN_MASK) >> ARM_TBFLAG_ZCR_LEN_SHIFT)
39
- } else {
39
40
+ if (!is_snan(b->cls)) {
40
static inline bool bswap_code(bool sctlr_b)
41
which = is_qnan(b->cls) ? 1 : 0;
41
{
42
+ break;
42
diff --git a/target/arm/translate.h b/target/arm/translate.h
43
}
43
index XXXXXXX..XXXXXXX 100644
44
} else if (is_qnan(a->cls)) {
44
--- a/target/arm/translate.h
45
if (is_snan(b->cls) || !is_qnan(b->cls)) {
45
+++ b/target/arm/translate.h
46
which = 0;
46
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
47
- } else {
47
bool tbi1; /* TBI1 for EL0/1, not used for EL2/3 */
48
- which = cmp > 0 ? 0 : 1;
48
bool ns; /* Use non-secure CPREG bank on access */
49
+ break;
49
int fp_excp_el; /* FP exception EL or 0 if enabled */
50
}
50
+ int sve_excp_el; /* SVE exception EL or 0 if enabled */
51
} else {
51
+ int sve_len; /* SVE vector length in bytes */
52
which = 1;
52
/* Flag indicating that exceptions from secure mode are routed to EL3. */
53
+ break;
53
bool secure_routed_to_el3;
54
}
54
bool vfp_enabled; /* FP enabled via FPSCR.EN */
55
+ cmp = frac_cmp(a, b);
55
diff --git a/target/arm/helper.c b/target/arm/helper.c
56
+ if (cmp == 0) {
56
index XXXXXXX..XXXXXXX 100644
57
+ cmp = a->sign < b->sign;
57
--- a/target/arm/helper.c
58
+++ b/target/arm/helper.c
59
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
60
target_ulong *cs_base, uint32_t *pflags)
61
{
62
ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
63
+ int fp_el = fp_exception_el(env);
64
uint32_t flags;
65
66
if (is_a64(env)) {
67
+ int sve_el = sve_exception_el(env);
68
+ uint32_t zcr_len;
69
+
70
*pc = env->pc;
71
flags = ARM_TBFLAG_AARCH64_STATE_MASK;
72
/* Get control bits for tagged addresses */
73
flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
74
flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
75
+ flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT;
76
+
77
+ /* If SVE is disabled, but FP is enabled,
78
+ then the effective len is 0. */
79
+ if (sve_el != 0 && fp_el == 0) {
80
+ zcr_len = 0;
81
+ } else {
82
+ int current_el = arm_current_el(env);
83
+
84
+ zcr_len = env->vfp.zcr_el[current_el <= 1 ? 1 : current_el];
85
+ zcr_len &= 0xf;
86
+ if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
87
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
88
+ }
89
+ if (current_el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
90
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
91
+ }
92
+ }
58
+ }
93
+ flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT;
59
+ which = cmp > 0 ? 0 : 1;
94
} else {
60
break;
95
*pc = env->regs[15];
61
default:
96
flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
62
g_assert_not_reached();
97
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
98
if (arm_cpu_data_is_big_endian(env)) {
99
flags |= ARM_TBFLAG_BE_DATA_MASK;
100
}
101
- flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
102
+ flags |= fp_el << ARM_TBFLAG_FPEXC_EL_SHIFT;
103
104
if (arm_v7m_is_handler_mode(env)) {
105
flags |= ARM_TBFLAG_HANDLER_MASK;
106
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/target/arm/translate-a64.c
109
+++ b/target/arm/translate-a64.c
110
@@ -XXX,XX +XXX,XX @@ static int aarch64_tr_init_disas_context(DisasContextBase *dcbase,
111
dc->user = (dc->current_el == 0);
112
#endif
113
dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
114
+ dc->sve_excp_el = ARM_TBFLAG_SVEEXC_EL(dc->base.tb->flags);
115
+ dc->sve_len = (ARM_TBFLAG_ZCR_LEN(dc->base.tb->flags) + 1) * 16;
116
dc->vec_len = 0;
117
dc->vec_stride = 0;
118
dc->cp_regs = arm_cpu->cp_regs;
119
--
63
--
120
2.16.1
64
2.34.1
121
122
diff view generated by jsdifflib
1
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This implements emulation of the new SHA-3 instructions that have
3
Replace the "index" selecting between A and B with a result variable
4
been added as an optional extensions to the ARMv8 Crypto Extensions
4
of the proper type. This improves clarity within the function.
5
in ARM v8.2.
6
5
7
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180207111729.15737-3-ard.biesheuvel@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-12-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/cpu.h | 1 +
11
fpu/softfloat-parts.c.inc | 28 +++++++++++++---------------
13
target/arm/translate-a64.c | 148 +++++++++++++++++++++++++++++++++++++++++++--
12
1 file changed, 13 insertions(+), 15 deletions(-)
14
2 files changed, 145 insertions(+), 4 deletions(-)
15
13
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
16
--- a/fpu/softfloat-parts.c.inc
19
+++ b/target/arm/cpu.h
17
+++ b/fpu/softfloat-parts.c.inc
20
@@ -XXX,XX +XXX,XX @@ enum arm_features {
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
21
ARM_FEATURE_JAZELLE, /* has (trivial) Jazelle implementation */
19
float_status *s)
22
ARM_FEATURE_SVE, /* has Scalable Vector Extension */
20
{
23
ARM_FEATURE_V8_SHA512, /* implements SHA512 part of v8 Crypto Extensions */
21
bool have_snan = false;
24
+ ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
22
- int cmp, which;
25
};
23
+ FloatPartsN *ret;
26
24
+ int cmp;
27
static inline int arm_feature(CPUARMState *env, int feature)
25
28
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
26
if (is_snan(a->cls) || is_snan(b->cls)) {
29
index XXXXXXX..XXXXXXX 100644
27
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
30
--- a/target/arm/translate-a64.c
28
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
31
+++ b/target/arm/translate-a64.c
29
switch (s->float_2nan_prop_rule) {
32
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
30
case float_2nan_prop_s_ab:
33
feature = ARM_FEATURE_V8_SHA512;
31
if (have_snan) {
34
genfn = gen_helper_crypto_sha512su1;
32
- which = is_snan(a->cls) ? 0 : 1;
33
+ ret = is_snan(a->cls) ? a : b;
35
break;
34
break;
36
- default:
37
- unallocated_encoding(s);
38
- return;
39
+ case 3: /* RAX1 */
40
+ feature = ARM_FEATURE_V8_SHA3;
41
+ genfn = NULL;
42
+ break;
43
}
35
}
44
} else {
36
/* fall through */
45
unallocated_encoding(s);
37
case float_2nan_prop_ab:
46
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
38
- which = is_nan(a->cls) ? 0 : 1;
47
tcg_temp_free_ptr(tcg_rn_ptr);
39
+ ret = is_nan(a->cls) ? a : b;
48
tcg_temp_free_ptr(tcg_rm_ptr);
40
break;
49
} else {
41
case float_2nan_prop_s_ba:
50
- g_assert_not_reached();
42
if (have_snan) {
51
+ TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
43
- which = is_snan(b->cls) ? 1 : 0;
52
+ int pass;
44
+ ret = is_snan(b->cls) ? b : a;
53
+
45
break;
54
+ tcg_op1 = tcg_temp_new_i64();
46
}
55
+ tcg_op2 = tcg_temp_new_i64();
47
/* fall through */
56
+ tcg_res[0] = tcg_temp_new_i64();
48
case float_2nan_prop_ba:
57
+ tcg_res[1] = tcg_temp_new_i64();
49
- which = is_nan(b->cls) ? 1 : 0;
58
+
50
+ ret = is_nan(b->cls) ? b : a;
59
+ for (pass = 0; pass < 2; pass++) {
51
break;
60
+ read_vec_element(s, tcg_op1, rn, pass, MO_64);
52
case float_2nan_prop_x87:
61
+ read_vec_element(s, tcg_op2, rm, pass, MO_64);
53
/*
62
+
54
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
63
+ tcg_gen_rotli_i64(tcg_res[pass], tcg_op2, 1);
55
*/
64
+ tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
56
if (is_snan(a->cls)) {
65
+ }
57
if (!is_snan(b->cls)) {
66
+ write_vec_element(s, tcg_res[0], rd, 0, MO_64);
58
- which = is_qnan(b->cls) ? 1 : 0;
67
+ write_vec_element(s, tcg_res[1], rd, 1, MO_64);
59
+ ret = is_qnan(b->cls) ? b : a;
68
+
60
break;
69
+ tcg_temp_free_i64(tcg_op1);
61
}
70
+ tcg_temp_free_i64(tcg_op2);
62
} else if (is_qnan(a->cls)) {
71
+ tcg_temp_free_i64(tcg_res[0]);
63
if (is_snan(b->cls) || !is_qnan(b->cls)) {
72
+ tcg_temp_free_i64(tcg_res[1]);
64
- which = 0;
65
+ ret = a;
66
break;
67
}
68
} else {
69
- which = 1;
70
+ ret = b;
71
break;
72
}
73
cmp = frac_cmp(a, b);
74
if (cmp == 0) {
75
cmp = a->sign < b->sign;
76
}
77
- which = cmp > 0 ? 0 : 1;
78
+ ret = cmp > 0 ? a : b;
79
break;
80
default:
81
g_assert_not_reached();
73
}
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;
74
}
94
}
75
95
76
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
96
static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
77
tcg_temp_free_ptr(tcg_rn_ptr);
78
}
79
80
+/* Crypto four-register
81
+ * 31 23 22 21 20 16 15 14 10 9 5 4 0
82
+ * +-------------------+-----+------+---+------+------+------+
83
+ * | 1 1 0 0 1 1 1 0 0 | Op0 | Rm | 0 | Ra | Rn | Rd |
84
+ * +-------------------+-----+------+---+------+------+------+
85
+ */
86
+static void disas_crypto_four_reg(DisasContext *s, uint32_t insn)
87
+{
88
+ int op0 = extract32(insn, 21, 2);
89
+ int rm = extract32(insn, 16, 5);
90
+ int ra = extract32(insn, 10, 5);
91
+ int rn = extract32(insn, 5, 5);
92
+ int rd = extract32(insn, 0, 5);
93
+ int feature;
94
+
95
+ switch (op0) {
96
+ case 0: /* EOR3 */
97
+ case 1: /* BCAX */
98
+ feature = ARM_FEATURE_V8_SHA3;
99
+ break;
100
+ default:
101
+ unallocated_encoding(s);
102
+ return;
103
+ }
104
+
105
+ if (!arm_dc_feature(s, feature)) {
106
+ unallocated_encoding(s);
107
+ return;
108
+ }
109
+
110
+ if (!fp_access_check(s)) {
111
+ return;
112
+ }
113
+
114
+ if (op0 < 2) {
115
+ TCGv_i64 tcg_op1, tcg_op2, tcg_op3, tcg_res[2];
116
+ int pass;
117
+
118
+ tcg_op1 = tcg_temp_new_i64();
119
+ tcg_op2 = tcg_temp_new_i64();
120
+ tcg_op3 = tcg_temp_new_i64();
121
+ tcg_res[0] = tcg_temp_new_i64();
122
+ tcg_res[1] = tcg_temp_new_i64();
123
+
124
+ for (pass = 0; pass < 2; pass++) {
125
+ read_vec_element(s, tcg_op1, rn, pass, MO_64);
126
+ read_vec_element(s, tcg_op2, rm, pass, MO_64);
127
+ read_vec_element(s, tcg_op3, ra, pass, MO_64);
128
+
129
+ if (op0 == 0) {
130
+ /* EOR3 */
131
+ tcg_gen_xor_i64(tcg_res[pass], tcg_op2, tcg_op3);
132
+ } else {
133
+ /* BCAX */
134
+ tcg_gen_andc_i64(tcg_res[pass], tcg_op2, tcg_op3);
135
+ }
136
+ tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
137
+ }
138
+ write_vec_element(s, tcg_res[0], rd, 0, MO_64);
139
+ write_vec_element(s, tcg_res[1], rd, 1, MO_64);
140
+
141
+ tcg_temp_free_i64(tcg_op1);
142
+ tcg_temp_free_i64(tcg_op2);
143
+ tcg_temp_free_i64(tcg_op3);
144
+ tcg_temp_free_i64(tcg_res[0]);
145
+ tcg_temp_free_i64(tcg_res[1]);
146
+ } else {
147
+ g_assert_not_reached();
148
+ }
149
+}
150
+
151
+/* Crypto XAR
152
+ * 31 21 20 16 15 10 9 5 4 0
153
+ * +-----------------------+------+--------+------+------+
154
+ * | 1 1 0 0 1 1 1 0 1 0 0 | Rm | imm6 | Rn | Rd |
155
+ * +-----------------------+------+--------+------+------+
156
+ */
157
+static void disas_crypto_xar(DisasContext *s, uint32_t insn)
158
+{
159
+ int rm = extract32(insn, 16, 5);
160
+ int imm6 = extract32(insn, 10, 6);
161
+ int rn = extract32(insn, 5, 5);
162
+ int rd = extract32(insn, 0, 5);
163
+ TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
164
+ int pass;
165
+
166
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA3)) {
167
+ unallocated_encoding(s);
168
+ return;
169
+ }
170
+
171
+ if (!fp_access_check(s)) {
172
+ return;
173
+ }
174
+
175
+ tcg_op1 = tcg_temp_new_i64();
176
+ tcg_op2 = tcg_temp_new_i64();
177
+ tcg_res[0] = tcg_temp_new_i64();
178
+ tcg_res[1] = tcg_temp_new_i64();
179
+
180
+ for (pass = 0; pass < 2; pass++) {
181
+ read_vec_element(s, tcg_op1, rn, pass, MO_64);
182
+ read_vec_element(s, tcg_op2, rm, pass, MO_64);
183
+
184
+ tcg_gen_xor_i64(tcg_res[pass], tcg_op1, tcg_op2);
185
+ tcg_gen_rotri_i64(tcg_res[pass], tcg_res[pass], imm6);
186
+ }
187
+ write_vec_element(s, tcg_res[0], rd, 0, MO_64);
188
+ write_vec_element(s, tcg_res[1], rd, 1, MO_64);
189
+
190
+ tcg_temp_free_i64(tcg_op1);
191
+ tcg_temp_free_i64(tcg_op2);
192
+ tcg_temp_free_i64(tcg_res[0]);
193
+ tcg_temp_free_i64(tcg_res[1]);
194
+}
195
+
196
/* C3.6 Data processing - SIMD, inc Crypto
197
*
198
* As the decode gets a little complex we are using a table based
199
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
200
{ 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha },
201
{ 0xce608000, 0xffe0b000, disas_crypto_three_reg_sha512 },
202
{ 0xcec08000, 0xfffff000, disas_crypto_two_reg_sha512 },
203
+ { 0xce000000, 0xff808000, disas_crypto_four_reg },
204
+ { 0xce800000, 0xffe00000, disas_crypto_xar },
205
{ 0x00000000, 0x00000000, NULL }
206
};
207
208
--
97
--
209
2.16.1
98
2.34.1
210
99
211
100
diff view generated by jsdifflib
1
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
Add support for the new ARMv8.2 SHA-3, SM3, SM4 and SHA-512 instructions to
3
I'm migrating to Qualcomm's new open source email infrastructure, so
4
AArch64 user mode emulation.
4
update my email address, and update the mailmap to match.
5
5
6
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
6
Signed-off-by: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
7
Message-id: 20180207111729.15737-6-ard.biesheuvel@linaro.org
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20241205114047.1125842-1-leif.lindholm@oss.qualcomm.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
linux-user/elfload.c | 19 +++++++++++++++++++
14
MAINTAINERS | 2 +-
12
target/arm/cpu64.c | 4 ++++
15
.mailmap | 5 +++--
13
2 files changed, 23 insertions(+)
16
2 files changed, 4 insertions(+), 3 deletions(-)
14
17
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
18
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
20
--- a/MAINTAINERS
18
+++ b/linux-user/elfload.c
21
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ enum {
22
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
20
ARM_HWCAP_A64_SHA1 = 1 << 5,
23
SBSA-REF
21
ARM_HWCAP_A64_SHA2 = 1 << 6,
24
M: Radoslaw Biernacki <rad@semihalf.com>
22
ARM_HWCAP_A64_CRC32 = 1 << 7,
25
M: Peter Maydell <peter.maydell@linaro.org>
23
+ ARM_HWCAP_A64_ATOMICS = 1 << 8,
26
-R: Leif Lindholm <quic_llindhol@quicinc.com>
24
+ ARM_HWCAP_A64_FPHP = 1 << 9,
27
+R: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
25
+ ARM_HWCAP_A64_ASIMDHP = 1 << 10,
28
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
26
+ ARM_HWCAP_A64_CPUID = 1 << 11,
29
L: qemu-arm@nongnu.org
27
+ ARM_HWCAP_A64_ASIMDRDM = 1 << 12,
30
S: Maintained
28
+ ARM_HWCAP_A64_JSCVT = 1 << 13,
31
diff --git a/.mailmap b/.mailmap
29
+ ARM_HWCAP_A64_FCMA = 1 << 14,
30
+ ARM_HWCAP_A64_LRCPC = 1 << 15,
31
+ ARM_HWCAP_A64_DCPOP = 1 << 16,
32
+ ARM_HWCAP_A64_SHA3 = 1 << 17,
33
+ ARM_HWCAP_A64_SM3 = 1 << 18,
34
+ ARM_HWCAP_A64_SM4 = 1 << 19,
35
+ ARM_HWCAP_A64_ASIMDDP = 1 << 20,
36
+ ARM_HWCAP_A64_SHA512 = 1 << 21,
37
+ ARM_HWCAP_A64_SVE = 1 << 22,
38
};
39
40
#define ELF_HWCAP get_elf_hwcap()
41
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
42
GET_FEATURE(ARM_FEATURE_V8_SHA1, ARM_HWCAP_A64_SHA1);
43
GET_FEATURE(ARM_FEATURE_V8_SHA256, ARM_HWCAP_A64_SHA2);
44
GET_FEATURE(ARM_FEATURE_CRC, ARM_HWCAP_A64_CRC32);
45
+ GET_FEATURE(ARM_FEATURE_V8_SHA3, ARM_HWCAP_A64_SHA3);
46
+ GET_FEATURE(ARM_FEATURE_V8_SM3, ARM_HWCAP_A64_SM3);
47
+ GET_FEATURE(ARM_FEATURE_V8_SM4, ARM_HWCAP_A64_SM4);
48
+ GET_FEATURE(ARM_FEATURE_V8_SHA512, ARM_HWCAP_A64_SHA512);
49
#undef GET_FEATURE
50
51
return hwcaps;
52
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
53
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/cpu64.c
33
--- a/.mailmap
55
+++ b/target/arm/cpu64.c
34
+++ b/.mailmap
56
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
35
@@ -XXX,XX +XXX,XX @@ Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
57
set_feature(&cpu->env, ARM_FEATURE_V8_AES);
36
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
58
set_feature(&cpu->env, ARM_FEATURE_V8_SHA1);
37
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
59
set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
38
Juan Quintela <quintela@trasno.org> <quintela@redhat.com>
60
+ set_feature(&cpu->env, ARM_FEATURE_V8_SHA512);
39
-Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
61
+ set_feature(&cpu->env, ARM_FEATURE_V8_SHA3);
40
-Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
62
+ set_feature(&cpu->env, ARM_FEATURE_V8_SM3);
41
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <quic_llindhol@quicinc.com>
63
+ set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
42
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif.lindholm@linaro.org>
64
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
43
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif@nuviainc.com>
65
set_feature(&cpu->env, ARM_FEATURE_CRC);
44
Luc Michel <luc@lmichel.fr> <luc.michel@git.antfield.fr>
66
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
45
Luc Michel <luc@lmichel.fr> <luc.michel@greensocs.com>
46
Luc Michel <luc@lmichel.fr> <lmichel@kalray.eu>
67
--
47
--
68
2.16.1
48
2.34.1
69
49
70
50
diff view generated by jsdifflib
1
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
1
From: Vikram Garhwal <vikram.garhwal@bytedance.com>
2
2
3
This implements emulation of the new SM4 instructions that have
3
Previously, maintainer role was paused due to inactive email id. Commit id:
4
been added as an optional extension to the ARMv8 Crypto Extensions
4
c009d715721861984c4987bcc78b7ee183e86d75.
5
in ARM v8.2.
6
5
7
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
6
Signed-off-by: Vikram Garhwal <vikram.garhwal@bytedance.com>
8
Message-id: 20180207111729.15737-5-ard.biesheuvel@linaro.org
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241204184205.12952-1-vikram.garhwal@bytedance.com
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/cpu.h | 1 +
11
MAINTAINERS | 2 ++
13
target/arm/helper.h | 3 ++
12
1 file changed, 2 insertions(+)
14
target/arm/crypto_helper.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++
15
target/arm/translate-a64.c | 8 ++++
16
4 files changed, 103 insertions(+)
17
13
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/MAINTAINERS b/MAINTAINERS
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
16
--- a/MAINTAINERS
21
+++ b/target/arm/cpu.h
17
+++ b/MAINTAINERS
22
@@ -XXX,XX +XXX,XX @@ enum arm_features {
18
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-sb16-test.c
23
ARM_FEATURE_V8_SHA512, /* implements SHA512 part of v8 Crypto Extensions */
19
24
ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
20
Xilinx CAN
25
ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
21
M: Francisco Iglesias <francisco.iglesias@amd.com>
26
+ ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
22
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
27
};
23
S: Maintained
28
24
F: hw/net/can/xlnx-*
29
static inline int arm_feature(CPUARMState *env, int feature)
25
F: include/hw/net/xlnx-*
30
diff --git a/target/arm/helper.h b/target/arm/helper.h
26
@@ -XXX,XX +XXX,XX @@ F: include/hw/rx/
31
index XXXXXXX..XXXXXXX 100644
27
CAN bus subsystem and hardware
32
--- a/target/arm/helper.h
28
M: Pavel Pisa <pisa@cmp.felk.cvut.cz>
33
+++ b/target/arm/helper.h
29
M: Francisco Iglesias <francisco.iglesias@amd.com>
34
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(crypto_sm3tt, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32, i32)
30
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
35
DEF_HELPER_FLAGS_3(crypto_sm3partw1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
31
S: Maintained
36
DEF_HELPER_FLAGS_3(crypto_sm3partw2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
32
W: https://canbus.pages.fel.cvut.cz/
37
33
F: net/can/*
38
+DEF_HELPER_FLAGS_2(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr)
39
+DEF_HELPER_FLAGS_3(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
40
+
41
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
42
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
43
DEF_HELPER_2(dc_zva, void, env, i64)
44
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/crypto_helper.c
47
+++ b/target/arm/crypto_helper.c
48
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2,
49
rd[0] = d.l[0];
50
rd[1] = d.l[1];
51
}
52
+
53
+static uint8_t const sm4_sbox[] = {
54
+ 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
55
+ 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
56
+ 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
57
+ 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
58
+ 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
59
+ 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
60
+ 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
61
+ 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
62
+ 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
63
+ 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
64
+ 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
65
+ 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
66
+ 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
67
+ 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
68
+ 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
69
+ 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
70
+ 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
71
+ 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
72
+ 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
73
+ 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
74
+ 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
75
+ 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
76
+ 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
77
+ 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
78
+ 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
79
+ 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
80
+ 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
81
+ 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
82
+ 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
83
+ 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
84
+ 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
85
+ 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,
86
+};
87
+
88
+void HELPER(crypto_sm4e)(void *vd, void *vn)
89
+{
90
+ uint64_t *rd = vd;
91
+ uint64_t *rn = vn;
92
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
93
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
94
+ uint32_t t, i;
95
+
96
+ for (i = 0; i < 4; i++) {
97
+ t = CR_ST_WORD(d, (i + 1) % 4) ^
98
+ CR_ST_WORD(d, (i + 2) % 4) ^
99
+ CR_ST_WORD(d, (i + 3) % 4) ^
100
+ CR_ST_WORD(n, i);
101
+
102
+ t = sm4_sbox[t & 0xff] |
103
+ sm4_sbox[(t >> 8) & 0xff] << 8 |
104
+ sm4_sbox[(t >> 16) & 0xff] << 16 |
105
+ sm4_sbox[(t >> 24) & 0xff] << 24;
106
+
107
+ CR_ST_WORD(d, i) ^= t ^ rol32(t, 2) ^ rol32(t, 10) ^ rol32(t, 18) ^
108
+ rol32(t, 24);
109
+ }
110
+
111
+ rd[0] = d.l[0];
112
+ rd[1] = d.l[1];
113
+}
114
+
115
+void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm)
116
+{
117
+ uint64_t *rd = vd;
118
+ uint64_t *rn = vn;
119
+ uint64_t *rm = vm;
120
+ union CRYPTO_STATE d;
121
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
122
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
123
+ uint32_t t, i;
124
+
125
+ d = n;
126
+ for (i = 0; i < 4; i++) {
127
+ t = CR_ST_WORD(d, (i + 1) % 4) ^
128
+ CR_ST_WORD(d, (i + 2) % 4) ^
129
+ CR_ST_WORD(d, (i + 3) % 4) ^
130
+ CR_ST_WORD(m, i);
131
+
132
+ t = sm4_sbox[t & 0xff] |
133
+ sm4_sbox[(t >> 8) & 0xff] << 8 |
134
+ sm4_sbox[(t >> 16) & 0xff] << 16 |
135
+ sm4_sbox[(t >> 24) & 0xff] << 24;
136
+
137
+ CR_ST_WORD(d, i) ^= t ^ rol32(t, 13) ^ rol32(t, 23);
138
+ }
139
+
140
+ rd[0] = d.l[0];
141
+ rd[1] = d.l[1];
142
+}
143
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/target/arm/translate-a64.c
146
+++ b/target/arm/translate-a64.c
147
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
148
feature = ARM_FEATURE_V8_SM3;
149
genfn = gen_helper_crypto_sm3partw2;
150
break;
151
+ case 2: /* SM4EKEY */
152
+ feature = ARM_FEATURE_V8_SM4;
153
+ genfn = gen_helper_crypto_sm4ekey;
154
+ break;
155
default:
156
unallocated_encoding(s);
157
return;
158
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
159
feature = ARM_FEATURE_V8_SHA512;
160
genfn = gen_helper_crypto_sha512su0;
161
break;
162
+ case 1: /* SM4E */
163
+ feature = ARM_FEATURE_V8_SM4;
164
+ genfn = gen_helper_crypto_sm4e;
165
+ break;
166
default:
167
unallocated_encoding(s);
168
return;
169
--
34
--
170
2.16.1
35
2.34.1
171
172
diff view generated by jsdifflib