1
The following changes since commit 4c41341af76cfc85b5a6c0f87de4838672ab9f89:
1
First arm pullreq of the cycle; this is mostly my softfloat NaN
2
handling series. (Lots more in my to-review queue, but I don't
3
like pullreqs growing too close to a hundred patches at a time :-))
2
4
3
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20201020' into staging (2020-10-20 11:20:36 +0100)
5
thanks
6
-- PMM
7
8
The following changes since commit 97f2796a3736ed37a1b85dc1c76a6c45b829dd17:
9
10
Open 10.0 development tree (2024-12-10 17:41:17 +0000)
4
11
5
are available in the Git repository at:
12
are available in the Git repository at:
6
13
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201020
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20241211
8
15
9
for you to fetch changes up to 6358890cb939192f6169fdf7664d903bf9b1d338:
16
for you to fetch changes up to 1abe28d519239eea5cf9620bb13149423e5665f8:
10
17
11
tests/tcg/aarch64: Add bti smoke tests (2020-10-20 16:12:02 +0100)
18
MAINTAINERS: Add correct email address for Vikram Garhwal (2024-12-11 15:31:09 +0000)
12
19
13
----------------------------------------------------------------
20
----------------------------------------------------------------
14
target-arm queue:
21
target-arm queue:
15
* Fix AArch32 SMLAD incorrect setting of Q bit
22
* hw/net/lan9118: Extract PHY model, reuse with imx_fec, fix bugs
16
* AArch32 VCVT fixed-point to float is always round-to-nearest
23
* fpu: Make muladd NaN handling runtime-selected, not compile-time
17
* strongarm: Fix 'time to transmit a char' unit comment
24
* fpu: Make default NaN pattern runtime-selected, not compile-time
18
* Restrict APEI tables generation to the 'virt' machine
25
* fpu: Minor NaN-related cleanups
19
* bcm2835: minor code cleanups
26
* MAINTAINERS: email address updates
20
* correctly flush TLBs when TBI is enabled
21
* tests/qtest: Add npcm7xx timer test
22
* loads-stores.rst: add footnote that clarifies GETPC usage
23
* Fix reported EL for mte_check_fail
24
* Ignore HCR_EL2.ATA when {E2H,TGE} != 11
25
* microbit_i2c: Fix coredump when dump-vmstate
26
* nseries: Fix loading kernel image on n8x0 machines
27
* Implement v8.1M low-overhead-loops
28
* linux-user: Support AArch64 BTI
29
27
30
----------------------------------------------------------------
28
----------------------------------------------------------------
31
Emanuele Giuseppe Esposito (1):
29
Bernhard Beschow (5):
32
loads-stores.rst: add footnote that clarifies GETPC usage
30
hw/net/lan9118: Extract lan9118_phy
31
hw/net/lan9118_phy: Reuse in imx_fec and consolidate implementations
32
hw/net/lan9118_phy: Fix off-by-one error in MII_ANLPAR register
33
hw/net/lan9118_phy: Reuse MII constants
34
hw/net/lan9118_phy: Add missing 100 mbps full duplex advertisement
33
35
34
Havard Skinnemoen (1):
36
Leif Lindholm (1):
35
tests/qtest: Add npcm7xx timer test
37
MAINTAINERS: update email address for Leif Lindholm
36
38
37
Peng Liang (1):
39
Peter Maydell (54):
38
microbit_i2c: Fix coredump when dump-vmstate
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
39
94
40
Peter Maydell (12):
95
Richard Henderson (11):
41
target/arm: Fix SMLAD incorrect setting of Q bit
96
target/arm: Copy entire float_status in is_ebf
42
target/arm: AArch32 VCVT fixed-point to float is always round-to-nearest
97
softfloat: Inline pickNaNMulAdd
43
decodetree: Fix codegen for non-overlapping group inside overlapping group
98
softfloat: Use goto for default nan case in pick_nan_muladd
44
target/arm: Implement v8.1M NOCP handling
99
softfloat: Remove which from parts_pick_nan_muladd
45
target/arm: Implement v8.1M conditional-select insns
100
softfloat: Pad array size in pick_nan_muladd
46
target/arm: Make the t32 insn[25:23]=111 group non-overlapping
101
softfloat: Move propagateFloatx80NaN to softfloat.c
47
target/arm: Don't allow BLX imm for M-profile
102
softfloat: Use parts_pick_nan in propagateFloatx80NaN
48
target/arm: Implement v8.1M branch-future insns (as NOPs)
103
softfloat: Inline pickNaN
49
target/arm: Implement v8.1M low-overhead-loop instructions
104
softfloat: Share code between parts_pick_nan cases
50
target/arm: Fix has_vfp/has_neon ID reg squashing for M-profile
105
softfloat: Sink frac_cmp in parts_pick_nan until needed
51
target/arm: Allow M-profile CPUs with FP16 to set FPSCR.FP16
106
softfloat: Replace WHICH with RET in parts_pick_nan
52
target/arm: Implement FPSCR.LTPSIZE for M-profile LOB extension
53
107
54
Philippe Mathieu-Daudé (10):
108
Vikram Garhwal (1):
55
hw/arm/strongarm: Fix 'time to transmit a char' unit comment
109
MAINTAINERS: Add correct email address for Vikram Garhwal
56
hw/arm: Restrict APEI tables generation to the 'virt' machine
57
hw/timer/bcm2835: Introduce BCM2835_SYSTIMER_COUNT definition
58
hw/timer/bcm2835: Rename variable holding CTRL_STATUS register
59
hw/timer/bcm2835: Support the timer COMPARE registers
60
hw/arm/bcm2835_peripherals: Correctly wire the SYS_timer IRQs
61
hw/intc/bcm2835_ic: Trace GPU/CPU IRQ handlers
62
hw/intc/bcm2836_control: Use IRQ definitions instead of magic numbers
63
hw/arm/nseries: Fix loading kernel image on n8x0 machines
64
linux-user/elfload: Avoid leaking interp_name using GLib memory API
65
110
66
Richard Henderson (16):
111
MAINTAINERS | 4 +-
67
accel/tcg: Add tlb_flush_page_bits_by_mmuidx*
112
include/fpu/softfloat-helpers.h | 38 +++-
68
target/arm: Use tlb_flush_page_bits_by_mmuidx*
113
include/fpu/softfloat-types.h | 89 +++++++-
69
target/arm: Remove redundant mmu_idx lookup
114
include/hw/net/imx_fec.h | 9 +-
70
target/arm: Fix reported EL for mte_check_fail
115
include/hw/net/lan9118_phy.h | 37 ++++
71
target/arm: Ignore HCR_EL2.ATA when {E2H,TGE} != 11
116
include/hw/net/mii.h | 6 +
72
linux-user/aarch64: Reset btype for signals
117
target/mips/fpu_helper.h | 20 ++
73
linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI
118
target/sparc/helper.h | 4 +-
74
include/elf: Add defines related to GNU property notes for AArch64
119
fpu/softfloat.c | 19 ++
75
linux-user/elfload: Fix coding style in load_elf_image
120
hw/net/imx_fec.c | 146 ++------------
76
linux-user/elfload: Adjust iteration over phdr
121
hw/net/lan9118.c | 137 ++-----------
77
linux-user/elfload: Move PT_INTERP detection to first loop
122
hw/net/lan9118_phy.c | 222 ++++++++++++++++++++
78
linux-user/elfload: Use Error for load_elf_image
123
linux-user/arm/nwfpe/fpa11.c | 5 +
79
linux-user/elfload: Use Error for load_elf_interp
124
target/alpha/cpu.c | 2 +
80
linux-user/elfload: Parse NT_GNU_PROPERTY_TYPE_0 notes
125
target/arm/cpu.c | 10 +
81
linux-user/elfload: Parse GNU_PROPERTY_AARCH64_FEATURE_1_AND
126
target/arm/tcg/vec_helper.c | 20 +-
82
tests/tcg/aarch64: Add bti smoke tests
127
target/hexagon/cpu.c | 2 +
83
128
target/hppa/fpu_helper.c | 12 ++
84
docs/devel/loads-stores.rst | 8 +-
129
target/i386/tcg/fpu_helper.c | 12 ++
85
default-configs/devices/arm-softmmu.mak | 1 -
130
target/loongarch/tcg/fpu_helper.c | 14 +-
86
include/elf.h | 22 ++
131
target/m68k/cpu.c | 14 +-
87
include/exec/cpu-all.h | 2 +
132
target/m68k/fpu_helper.c | 6 +-
88
include/exec/exec-all.h | 36 ++
133
target/m68k/helper.c | 6 +-
89
include/hw/timer/bcm2835_systmr.h | 17 +-
134
target/microblaze/cpu.c | 2 +
90
linux-user/qemu.h | 4 +
135
target/mips/msa.c | 10 +
91
linux-user/syscall_defs.h | 4 +
136
target/openrisc/cpu.c | 2 +
92
target/arm/cpu.h | 13 +
137
target/ppc/cpu_init.c | 19 ++
93
target/arm/helper.h | 13 +
138
target/ppc/fpu_helper.c | 3 +-
94
target/arm/internals.h | 9 +-
139
target/riscv/cpu.c | 2 +
95
target/arm/m-nocp.decode | 10 +-
140
target/rx/cpu.c | 2 +
96
target/arm/t32.decode | 50 ++-
141
target/s390x/cpu.c | 5 +
97
accel/tcg/cputlb.c | 275 +++++++++++++++-
142
target/sh4/cpu.c | 2 +
98
hw/arm/bcm2835_peripherals.c | 13 +-
143
target/sparc/cpu.c | 6 +
99
hw/arm/nseries.c | 1 +
144
target/sparc/fop_helper.c | 8 +-
100
hw/arm/strongarm.c | 2 +-
145
target/sparc/translate.c | 4 +-
101
hw/i2c/microbit_i2c.c | 1 +
146
target/tricore/helper.c | 2 +
102
hw/intc/bcm2835_ic.c | 4 +-
147
target/xtensa/cpu.c | 4 +
103
hw/intc/bcm2836_control.c | 8 +-
148
target/xtensa/fpu_helper.c | 3 +-
104
hw/timer/bcm2835_systmr.c | 57 ++--
149
tests/fp/fp-bench.c | 7 +
105
linux-user/aarch64/signal.c | 10 +-
150
tests/fp/fp-test-log2.c | 1 +
106
linux-user/elfload.c | 326 ++++++++++++++----
151
tests/fp/fp-test.c | 7 +
107
linux-user/mmap.c | 16 +
152
fpu/softfloat-parts.c.inc | 152 +++++++++++---
108
target/arm/cpu.c | 38 ++-
153
fpu/softfloat-specialize.c.inc | 412 ++------------------------------------
109
target/arm/helper.c | 55 +++-
154
.mailmap | 5 +-
110
target/arm/mte_helper.c | 13 +-
155
hw/net/Kconfig | 5 +
111
target/arm/translate-a64.c | 6 +-
156
hw/net/meson.build | 1 +
112
target/arm/translate.c | 239 +++++++++++++-
157
hw/net/trace-events | 10 +-
113
target/arm/vfp_helper.c | 76 +++--
158
47 files changed, 778 insertions(+), 730 deletions(-)
114
tests/qtest/npcm7xx_timer-test.c | 562 ++++++++++++++++++++++++++++++++
159
create mode 100644 include/hw/net/lan9118_phy.h
115
tests/tcg/aarch64/bti-1.c | 62 ++++
160
create mode 100644 hw/net/lan9118_phy.c
116
tests/tcg/aarch64/bti-2.c | 108 ++++++
117
tests/tcg/aarch64/bti-crt.inc.c | 51 +++
118
hw/arm/Kconfig | 1 +
119
hw/intc/trace-events | 4 +
120
hw/timer/trace-events | 6 +-
121
scripts/decodetree.py | 2 +-
122
target/arm/translate-vfp.c.inc | 41 ++-
123
tests/qtest/meson.build | 1 +
124
tests/tcg/aarch64/Makefile.target | 10 +
125
tests/tcg/configure.sh | 4 +
126
42 files changed, 1973 insertions(+), 208 deletions(-)
127
create mode 100644 tests/qtest/npcm7xx_timer-test.c
128
create mode 100644 tests/tcg/aarch64/bti-1.c
129
create mode 100644 tests/tcg/aarch64/bti-2.c
130
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
131
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
The note test requires gcc 10 for -mbranch-protection=standard.
3
A very similar implementation of the same device exists in imx_fec. Prepare for
4
The mmap test uses PROT_BTI and does not require special compiler support.
4
a common implementation by extracting a device model into its own files.
5
5
6
Acked-by: Alex Bennée <alex.bennee@linaro.org>
6
Some migration state has been moved into the new device model which breaks
7
migration compatibility for the following machines:
8
* smdkc210
9
* realview-*
10
* vexpress-*
11
* kzm
12
* mps2-*
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>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20241102125724.532843-2-shentey@gmail.com
9
Message-id: 20201016184207.786698-13-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
22
---
12
tests/tcg/aarch64/bti-1.c | 62 +++++++++++++++++
23
include/hw/net/lan9118_phy.h | 37 ++++++++
13
tests/tcg/aarch64/bti-2.c | 108 ++++++++++++++++++++++++++++++
24
hw/net/lan9118.c | 137 +++++-----------------------
14
tests/tcg/aarch64/bti-crt.inc.c | 51 ++++++++++++++
25
hw/net/lan9118_phy.c | 169 +++++++++++++++++++++++++++++++++++
15
tests/tcg/aarch64/Makefile.target | 10 +++
26
hw/net/Kconfig | 4 +
16
tests/tcg/configure.sh | 4 ++
27
hw/net/meson.build | 1 +
17
5 files changed, 235 insertions(+)
28
5 files changed, 233 insertions(+), 115 deletions(-)
18
create mode 100644 tests/tcg/aarch64/bti-1.c
29
create mode 100644 include/hw/net/lan9118_phy.h
19
create mode 100644 tests/tcg/aarch64/bti-2.c
30
create mode 100644 hw/net/lan9118_phy.c
20
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
21
31
22
diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c
32
diff --git a/include/hw/net/lan9118_phy.h b/include/hw/net/lan9118_phy.h
23
new file mode 100644
33
new file mode 100644
24
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
25
--- /dev/null
35
--- /dev/null
26
+++ b/tests/tcg/aarch64/bti-1.c
36
+++ b/include/hw/net/lan9118_phy.h
27
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
28
+/*
38
+/*
29
+ * Branch target identification, basic notskip cases.
39
+ * SMSC LAN9118 PHY emulation
40
+ *
41
+ * Copyright (c) 2009 CodeSourcery, LLC.
42
+ * Written by Paul Brook
43
+ *
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
45
+ * See the COPYING file in the top-level directory.
30
+ */
46
+ */
31
+
47
+
32
+#include "bti-crt.inc.c"
48
+#ifndef HW_NET_LAN9118_PHY_H
33
+
49
+#define HW_NET_LAN9118_PHY_H
34
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
50
+
35
+{
51
+#include "qom/object.h"
36
+ uc->uc_mcontext.pc += 8;
52
+#include "hw/sysbus.h"
37
+ uc->uc_mcontext.pstate = 1;
53
+
38
+}
54
+#define TYPE_LAN9118_PHY "lan9118-phy"
39
+
55
+OBJECT_DECLARE_SIMPLE_TYPE(Lan9118PhyState, LAN9118_PHY)
40
+#define NOP "nop"
56
+
41
+#define BTI_N "hint #32"
57
+typedef struct Lan9118PhyState {
42
+#define BTI_C "hint #34"
58
+ SysBusDevice parent_obj;
43
+#define BTI_J "hint #36"
59
+
44
+#define BTI_JC "hint #38"
60
+ uint16_t status;
45
+
61
+ uint16_t control;
46
+#define BTYPE_1(DEST) \
62
+ uint16_t advertise;
47
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \
63
+ uint16_t ints;
48
+ : "=r"(skipped) : : "x16")
64
+ uint16_t int_mask;
49
+
65
+ qemu_irq irq;
50
+#define BTYPE_2(DEST) \
66
+ bool link_down;
51
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \
67
+} Lan9118PhyState;
52
+ : "=r"(skipped) : : "x16", "x30")
68
+
53
+
69
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down);
54
+#define BTYPE_3(DEST) \
70
+void lan9118_phy_reset(Lan9118PhyState *s);
55
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \
71
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg);
56
+ : "=r"(skipped) : : "x15")
72
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val);
57
+
73
+
58
+#define TEST(WHICH, DEST, EXPECT) \
74
+#endif
59
+ do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0)
75
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
60
+
76
index XXXXXXX..XXXXXXX 100644
61
+
77
--- a/hw/net/lan9118.c
62
+int main()
78
+++ b/hw/net/lan9118.c
63
+{
79
@@ -XXX,XX +XXX,XX @@
64
+ int fail = 0;
80
#include "net/net.h"
65
+ int skipped;
81
#include "net/eth.h"
66
+
82
#include "hw/irq.h"
67
+ /* Signal-like with SA_SIGINFO. */
83
+#include "hw/net/lan9118_phy.h"
68
+ signal_info(SIGILL, skip2_sigill);
84
#include "hw/net/lan9118.h"
69
+
85
#include "hw/ptimer.h"
70
+ TEST(BTYPE_1, NOP, 1);
86
#include "hw/qdev-properties.h"
71
+ TEST(BTYPE_1, BTI_N, 1);
87
@@ -XXX,XX +XXX,XX @@ do { printf("lan9118: " fmt , ## __VA_ARGS__); } while (0)
72
+ TEST(BTYPE_1, BTI_C, 0);
88
#define MAC_CR_RXEN 0x00000004
73
+ TEST(BTYPE_1, BTI_J, 0);
89
#define MAC_CR_RESERVED 0x7f404213
74
+ TEST(BTYPE_1, BTI_JC, 0);
90
75
+
91
-#define PHY_INT_ENERGYON 0x80
76
+ TEST(BTYPE_2, NOP, 1);
92
-#define PHY_INT_AUTONEG_COMPLETE 0x40
77
+ TEST(BTYPE_2, BTI_N, 1);
93
-#define PHY_INT_FAULT 0x20
78
+ TEST(BTYPE_2, BTI_C, 0);
94
-#define PHY_INT_DOWN 0x10
79
+ TEST(BTYPE_2, BTI_J, 1);
95
-#define PHY_INT_AUTONEG_LP 0x08
80
+ TEST(BTYPE_2, BTI_JC, 0);
96
-#define PHY_INT_PARFAULT 0x04
81
+
97
-#define PHY_INT_AUTONEG_PAGE 0x02
82
+ TEST(BTYPE_3, NOP, 1);
98
-
83
+ TEST(BTYPE_3, BTI_N, 1);
99
#define GPT_TIMER_EN 0x20000000
84
+ TEST(BTYPE_3, BTI_C, 1);
100
85
+ TEST(BTYPE_3, BTI_J, 0);
101
/*
86
+ TEST(BTYPE_3, BTI_JC, 0);
102
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
87
+
103
uint32_t mac_mii_data;
88
+ return fail;
104
uint32_t mac_flow;
89
+}
105
90
diff --git a/tests/tcg/aarch64/bti-2.c b/tests/tcg/aarch64/bti-2.c
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
91
new file mode 100644
312
new file mode 100644
92
index XXXXXXX..XXXXXXX
313
index XXXXXXX..XXXXXXX
93
--- /dev/null
314
--- /dev/null
94
+++ b/tests/tcg/aarch64/bti-2.c
315
+++ b/hw/net/lan9118_phy.c
95
@@ -XXX,XX +XXX,XX @@
316
@@ -XXX,XX +XXX,XX @@
96
+/*
317
+/*
97
+ * Branch target identification, basic notskip cases.
318
+ * SMSC LAN9118 PHY emulation
319
+ *
320
+ * Copyright (c) 2009 CodeSourcery, LLC.
321
+ * Written by Paul Brook
322
+ *
323
+ * This code is licensed under the GNU GPL v2
324
+ *
325
+ * Contributions after 2012-01-13 are licensed under the terms of the
326
+ * GNU GPL, version 2 or (at your option) any later version.
98
+ */
327
+ */
99
+
328
+
100
+#include <stdio.h>
329
+#include "qemu/osdep.h"
101
+#include <signal.h>
330
+#include "hw/net/lan9118_phy.h"
102
+#include <string.h>
331
+#include "hw/irq.h"
103
+#include <unistd.h>
332
+#include "hw/resettable.h"
104
+#include <sys/mman.h>
333
+#include "migration/vmstate.h"
105
+
334
+#include "qemu/log.h"
106
+#ifndef PROT_BTI
335
+
107
+#define PROT_BTI 0x10
336
+#define PHY_INT_ENERGYON (1 << 7)
108
+#endif
337
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
109
+
338
+#define PHY_INT_FAULT (1 << 5)
110
+static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
339
+#define PHY_INT_DOWN (1 << 4)
111
+{
340
+#define PHY_INT_AUTONEG_LP (1 << 3)
112
+ ucontext_t *uc = vuc;
341
+#define PHY_INT_PARFAULT (1 << 2)
113
+ uc->uc_mcontext.pc += 8;
342
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
114
+ uc->uc_mcontext.pstate = 1;
343
+
115
+}
344
+static void lan9118_phy_update_irq(Lan9118PhyState *s)
116
+
345
+{
117
+#define NOP "nop"
346
+ qemu_set_irq(s->irq, !!(s->ints & s->int_mask));
118
+#define BTI_N "hint #32"
347
+}
119
+#define BTI_C "hint #34"
348
+
120
+#define BTI_J "hint #36"
349
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
121
+#define BTI_JC "hint #38"
350
+{
122
+
351
+ uint16_t val;
123
+#define BTYPE_1(DEST) \
352
+
124
+ "mov x1, #1\n\t" \
353
+ switch (reg) {
125
+ "adr x16, 1f\n\t" \
354
+ case 0: /* Basic Control */
126
+ "br x16\n" \
355
+ return s->control;
127
+"1: " DEST "\n\t" \
356
+ case 1: /* Basic Status */
128
+ "mov x1, #0"
357
+ return s->status;
129
+
358
+ case 2: /* ID1 */
130
+#define BTYPE_2(DEST) \
359
+ return 0x0007;
131
+ "mov x1, #1\n\t" \
360
+ case 3: /* ID2 */
132
+ "adr x16, 1f\n\t" \
361
+ return 0xc0d1;
133
+ "blr x16\n" \
362
+ case 4: /* Auto-neg advertisement */
134
+"1: " DEST "\n\t" \
363
+ return s->advertise;
135
+ "mov x1, #0"
364
+ case 5: /* Auto-neg Link Partner Ability */
136
+
365
+ return 0x0f71;
137
+#define BTYPE_3(DEST) \
366
+ case 6: /* Auto-neg Expansion */
138
+ "mov x1, #1\n\t" \
139
+ "adr x15, 1f\n\t" \
140
+ "br x15\n" \
141
+"1: " DEST "\n\t" \
142
+ "mov x1, #0"
143
+
144
+#define TEST(WHICH, DEST, EXPECT) \
145
+ WHICH(DEST) "\n" \
146
+ ".if " #EXPECT "\n\t" \
147
+ "eor x1, x1," #EXPECT "\n" \
148
+ ".endif\n\t" \
149
+ "add x0, x0, x1\n\t"
150
+
151
+extern char test_begin[], test_end[];
152
+
153
+asm("\n"
154
+"test_begin:\n\t"
155
+ BTI_C "\n\t"
156
+ "mov x2, x30\n\t"
157
+ "mov x0, #0\n\t"
158
+
159
+ TEST(BTYPE_1, NOP, 1)
160
+ TEST(BTYPE_1, BTI_N, 1)
161
+ TEST(BTYPE_1, BTI_C, 0)
162
+ TEST(BTYPE_1, BTI_J, 0)
163
+ TEST(BTYPE_1, BTI_JC, 0)
164
+
165
+ TEST(BTYPE_2, NOP, 1)
166
+ TEST(BTYPE_2, BTI_N, 1)
167
+ TEST(BTYPE_2, BTI_C, 0)
168
+ TEST(BTYPE_2, BTI_J, 1)
169
+ TEST(BTYPE_2, BTI_JC, 0)
170
+
171
+ TEST(BTYPE_3, NOP, 1)
172
+ TEST(BTYPE_3, BTI_N, 1)
173
+ TEST(BTYPE_3, BTI_C, 1)
174
+ TEST(BTYPE_3, BTI_J, 0)
175
+ TEST(BTYPE_3, BTI_JC, 0)
176
+
177
+ "ret x2\n"
178
+"test_end:"
179
+);
180
+
181
+int main()
182
+{
183
+ struct sigaction sa;
184
+
185
+ void *p = mmap(0, getpagesize(),
186
+ PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
187
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
188
+ if (p == MAP_FAILED) {
189
+ perror("mmap");
190
+ return 1;
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;
191
+ }
380
+ }
192
+
381
+}
193
+ memset(&sa, 0, sizeof(sa));
382
+
194
+ sa.sa_sigaction = skip2_sigill;
383
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
195
+ sa.sa_flags = SA_SIGINFO;
384
+{
196
+ if (sigaction(SIGILL, &sa, NULL) < 0) {
385
+ switch (reg) {
197
+ perror("sigaction");
386
+ case 0: /* Basic Control */
198
+ return 1;
387
+ if (val & 0x8000) {
388
+ lan9118_phy_reset(s);
389
+ break;
390
+ }
391
+ s->control = val & 0x7980;
392
+ /* Complete autonegotiation immediately. */
393
+ if (val & 0x1000) {
394
+ s->status |= 0x0020;
395
+ }
396
+ break;
397
+ case 4: /* Auto-neg advertisement */
398
+ s->advertise = (val & 0x2d7f) | 0x80;
399
+ break;
400
+ /* TODO 17, 18, 27, 31 */
401
+ case 30: /* Interrupt mask */
402
+ s->int_mask = val & 0xff;
403
+ lan9118_phy_update_irq(s);
404
+ break;
405
+ default:
406
+ qemu_log_mask(LOG_GUEST_ERROR,
407
+ "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
199
+ }
408
+ }
200
+
409
+}
201
+ memcpy(p, test_begin, test_end - test_begin);
410
+
202
+ return ((int (*)(void))p)();
411
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
203
+}
412
+{
204
diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c
413
+ s->link_down = link_down;
205
new file mode 100644
414
+
206
index XXXXXXX..XXXXXXX
415
+ /* Autonegotiation status mirrors link status. */
207
--- /dev/null
416
+ if (link_down) {
208
+++ b/tests/tcg/aarch64/bti-crt.inc.c
417
+ s->status &= ~0x0024;
209
@@ -XXX,XX +XXX,XX @@
418
+ s->ints |= PHY_INT_DOWN;
210
+/*
419
+ } else {
211
+ * Minimal user-environment for testing BTI.
420
+ s->status |= 0x0024;
212
+ *
421
+ s->ints |= PHY_INT_ENERGYON;
213
+ * Normal libc is not (yet) built with BTI support enabled,
422
+ s->ints |= PHY_INT_AUTONEG_COMPLETE;
214
+ * and so could generate a BTI TRAP before ever reaching main.
423
+ }
215
+ */
424
+ lan9118_phy_update_irq(s);
216
+
425
+}
217
+#include <stdlib.h>
426
+
218
+#include <signal.h>
427
+void lan9118_phy_reset(Lan9118PhyState *s)
219
+#include <ucontext.h>
428
+{
220
+#include <asm/unistd.h>
429
+ s->control = 0x3000;
221
+
430
+ s->status = 0x7809;
222
+int main(void);
431
+ s->advertise = 0x01e1;
223
+
432
+ s->int_mask = 0;
224
+void _start(void)
433
+ s->ints = 0;
225
+{
434
+ lan9118_phy_update_link(s, s->link_down);
226
+ exit(main());
435
+}
227
+}
436
+
228
+
437
+static void lan9118_phy_reset_hold(Object *obj, ResetType type)
229
+void exit(int ret)
438
+{
230
+{
439
+ Lan9118PhyState *s = LAN9118_PHY(obj);
231
+ register int x0 __asm__("x0") = ret;
440
+
232
+ register int x8 __asm__("x8") = __NR_exit;
441
+ lan9118_phy_reset(s);
233
+
442
+}
234
+ asm volatile("svc #0" : : "r"(x0), "r"(x8));
443
+
235
+ __builtin_unreachable();
444
+static void lan9118_phy_init(Object *obj)
236
+}
445
+{
237
+
446
+ Lan9118PhyState *s = LAN9118_PHY(obj);
238
+/*
447
+
239
+ * Irritatingly, the user API struct sigaction does not match the
448
+ qdev_init_gpio_out(DEVICE(s), &s->irq, 1);
240
+ * kernel API struct sigaction. So for simplicity, isolate the
449
+}
241
+ * kernel ABI here, and make this act like signal.
450
+
242
+ */
451
+static const VMStateDescription vmstate_lan9118_phy = {
243
+void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *))
452
+ .name = "lan9118-phy",
244
+{
453
+ .version_id = 1,
245
+ struct kernel_sigaction {
454
+ .minimum_version_id = 1,
246
+ void (*handler)(int, siginfo_t *, ucontext_t *);
455
+ .fields = (const VMStateField[]) {
247
+ unsigned long flags;
456
+ VMSTATE_UINT16(control, Lan9118PhyState),
248
+ unsigned long restorer;
457
+ VMSTATE_UINT16(status, Lan9118PhyState),
249
+ unsigned long mask;
458
+ VMSTATE_UINT16(advertise, Lan9118PhyState),
250
+ } sa = { fn, SA_SIGINFO, 0, 0 };
459
+ VMSTATE_UINT16(ints, Lan9118PhyState),
251
+
460
+ VMSTATE_UINT16(int_mask, Lan9118PhyState),
252
+ register int x0 __asm__("x0") = sig;
461
+ VMSTATE_BOOL(link_down, Lan9118PhyState),
253
+ register void *x1 __asm__("x1") = &sa;
462
+ VMSTATE_END_OF_LIST()
254
+ register void *x2 __asm__("x2") = 0;
463
+ }
255
+ register int x3 __asm__("x3") = sizeof(unsigned long);
464
+};
256
+ register int x8 __asm__("x8") = __NR_rt_sigaction;
465
+
257
+
466
+static void lan9118_phy_class_init(ObjectClass *klass, void *data)
258
+ asm volatile("svc #0"
467
+{
259
+ : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
468
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
260
+}
469
+ DeviceClass *dc = DEVICE_CLASS(klass);
261
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
470
+
471
+ rc->phases.hold = lan9118_phy_reset_hold;
472
+ dc->vmsd = &vmstate_lan9118_phy;
473
+}
474
+
475
+static const TypeInfo types[] = {
476
+ {
477
+ .name = TYPE_LAN9118_PHY,
478
+ .parent = TYPE_SYS_BUS_DEVICE,
479
+ .instance_size = sizeof(Lan9118PhyState),
480
+ .instance_init = lan9118_phy_init,
481
+ .class_init = lan9118_phy_class_init,
482
+ }
483
+};
484
+
485
+DEFINE_TYPES(types)
486
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
262
index XXXXXXX..XXXXXXX 100644
487
index XXXXXXX..XXXXXXX 100644
263
--- a/tests/tcg/aarch64/Makefile.target
488
--- a/hw/net/Kconfig
264
+++ b/tests/tcg/aarch64/Makefile.target
489
+++ b/hw/net/Kconfig
265
@@ -XXX,XX +XXX,XX @@ run-pauth-%: QEMU_OPTS += -cpu max
490
@@ -XXX,XX +XXX,XX @@ config VMXNET3_PCI
266
run-plugin-pauth-%: QEMU_OPTS += -cpu max
491
config SMC91C111
267
endif
492
bool
268
493
269
+# BTI Tests
494
+config LAN9118_PHY
270
+# bti-1 tests the elf notes, so we require special compiler support.
495
+ bool
271
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),)
496
+
272
+AARCH64_TESTS += bti-1
497
config LAN9118
273
+bti-1: CFLAGS += -mbranch-protection=standard
498
bool
274
+bti-1: LDFLAGS += -nostdlib
499
+ select LAN9118_PHY
275
+endif
500
select PTIMER
276
+# bti-2 tests PROT_BTI, so no special compiler support required.
501
277
+AARCH64_TESTS += bti-2
502
config NE2000_ISA
278
+
503
diff --git a/hw/net/meson.build b/hw/net/meson.build
279
# Semihosting smoke test for linux-user
504
index XXXXXXX..XXXXXXX 100644
280
AARCH64_TESTS += semihosting
505
--- a/hw/net/meson.build
281
run-semihosting: semihosting
506
+++ b/hw/net/meson.build
282
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
507
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('vmxnet3.c'))
283
index XXXXXXX..XXXXXXX 100755
508
284
--- a/tests/tcg/configure.sh
509
system_ss.add(when: 'CONFIG_SMC91C111', if_true: files('smc91c111.c'))
285
+++ b/tests/tcg/configure.sh
510
system_ss.add(when: 'CONFIG_LAN9118', if_true: files('lan9118.c'))
286
@@ -XXX,XX +XXX,XX @@ for target in $target_list; do
511
+system_ss.add(when: 'CONFIG_LAN9118_PHY', if_true: files('lan9118_phy.c'))
287
-march=armv8.3-a -o $TMPE $TMPC; then
512
system_ss.add(when: 'CONFIG_NE2000_ISA', if_true: files('ne2000-isa.c'))
288
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
513
system_ss.add(when: 'CONFIG_OPENCORES_ETH', if_true: files('opencores_eth.c'))
289
fi
514
system_ss.add(when: 'CONFIG_XGMAC', if_true: files('xgmac.c'))
290
+ if do_compiler "$target_compiler" $target_compiler_cflags \
291
+ -mbranch-protection=standard -o $TMPE $TMPC; then
292
+ echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak
293
+ fi
294
;;
295
esac
296
297
--
515
--
298
2.20.1
516
2.34.1
299
300
diff view generated by jsdifflib
1
From: Peng Liang <liangpeng10@huawei.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
VMStateDescription.fields should be end with VMSTATE_END_OF_LIST().
3
imx_fec models the same PHY as lan9118_phy. The code is almost the same with
4
However, microbit_i2c_vmstate doesn't follow it. Let's change it.
4
imx_fec having more logging and tracing. Merge these improvements into
5
lan9118_phy and reuse in imx_fec to fix the code duplication.
5
6
6
Fixes: 9d68bf564e ("arm: Stub out NRF51 TWI magnetometer/accelerometer detection")
7
Some migration state how resides in the new device model which breaks migration
7
Reported-by: Euler Robot <euler.robot@huawei.com>
8
compatibility for the following machines:
8
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
9
* imx25-pdk
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
* sabrelite
10
Message-id: 20201019093401.2993833-1-liangpeng10@huawei.com
11
* mcimx7d-sabre
12
* mcimx6ul-evk
13
14
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
15
Tested-by: Guenter Roeck <linux@roeck-us.net>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Message-id: 20241102125724.532843-3-shentey@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
19
---
13
hw/i2c/microbit_i2c.c | 1 +
20
include/hw/net/imx_fec.h | 9 ++-
14
1 file changed, 1 insertion(+)
21
hw/net/imx_fec.c | 146 ++++-----------------------------------
22
hw/net/lan9118_phy.c | 82 ++++++++++++++++------
23
hw/net/Kconfig | 1 +
24
hw/net/trace-events | 10 +--
25
5 files changed, 85 insertions(+), 163 deletions(-)
15
26
16
diff --git a/hw/i2c/microbit_i2c.c b/hw/i2c/microbit_i2c.c
27
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
17
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/i2c/microbit_i2c.c
29
--- a/include/hw/net/imx_fec.h
19
+++ b/hw/i2c/microbit_i2c.c
30
+++ b/include/hw/net/imx_fec.h
20
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription microbit_i2c_vmstate = {
31
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC)
21
.fields = (VMStateField[]) {
32
#define TYPE_IMX_ENET "imx.enet"
22
VMSTATE_UINT32_ARRAY(regs, MicrobitI2CState, MICROBIT_I2C_NREGS),
33
23
VMSTATE_UINT32(read_idx, MicrobitI2CState),
34
#include "hw/sysbus.h"
24
+ VMSTATE_END_OF_LIST()
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 = {
25
},
79
},
26
};
80
};
27
81
82
-#define PHY_INT_ENERGYON (1 << 7)
83
-#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
84
-#define PHY_INT_FAULT (1 << 5)
85
-#define PHY_INT_DOWN (1 << 4)
86
-#define PHY_INT_AUTONEG_LP (1 << 3)
87
-#define PHY_INT_PARFAULT (1 << 2)
88
-#define PHY_INT_AUTONEG_PAGE (1 << 1)
89
-
90
static void imx_eth_update(IMXFECState *s);
91
92
/*
93
@@ -XXX,XX +XXX,XX @@ static void imx_eth_update(IMXFECState *s);
94
* For now we don't handle any GPIO/interrupt line, so the OS will
95
* have to poll for the PHY status.
96
*/
97
-static void imx_phy_update_irq(IMXFECState *s)
98
+static void imx_phy_update_irq(void *opaque, int n, int level)
99
{
100
- imx_eth_update(s);
101
-}
102
-
103
-static void imx_phy_update_link(IMXFECState *s)
104
-{
105
- /* Autonegotiation status mirrors link status. */
106
- if (qemu_get_queue(s->nic)->link_down) {
107
- trace_imx_phy_update_link("down");
108
- s->phy_status &= ~0x0024;
109
- s->phy_int |= PHY_INT_DOWN;
110
- } else {
111
- trace_imx_phy_update_link("up");
112
- s->phy_status |= 0x0024;
113
- s->phy_int |= PHY_INT_ENERGYON;
114
- s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
115
- }
116
- imx_phy_update_irq(s);
117
+ imx_eth_update(opaque);
118
}
119
120
static void imx_eth_set_link(NetClientState *nc)
121
{
122
- imx_phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
123
-}
124
-
125
-static void imx_phy_reset(IMXFECState *s)
126
-{
127
- trace_imx_phy_reset();
128
-
129
- s->phy_status = 0x7809;
130
- s->phy_control = 0x3000;
131
- s->phy_advertise = 0x01e1;
132
- s->phy_int_mask = 0;
133
- s->phy_int = 0;
134
- imx_phy_update_link(s);
135
+ lan9118_phy_update_link(&IMX_FEC(qemu_get_nic_opaque(nc))->mii,
136
+ nc->link_down);
137
}
138
139
static uint32_t imx_phy_read(IMXFECState *s, int reg)
140
{
141
- uint32_t val;
142
uint32_t phy = reg / 32;
143
144
if (!s->phy_connected) {
145
@@ -XXX,XX +XXX,XX @@ static uint32_t imx_phy_read(IMXFECState *s, int reg)
146
147
reg %= 32;
148
149
- switch (reg) {
150
- case 0: /* Basic Control */
151
- val = s->phy_control;
152
- break;
153
- case 1: /* Basic Status */
154
- val = s->phy_status;
155
- break;
156
- case 2: /* ID1 */
157
- val = 0x0007;
158
- break;
159
- case 3: /* ID2 */
160
- val = 0xc0d1;
161
- break;
162
- case 4: /* Auto-neg advertisement */
163
- val = s->phy_advertise;
164
- break;
165
- case 5: /* Auto-neg Link Partner Ability */
166
- val = 0x0f71;
167
- break;
168
- case 6: /* Auto-neg Expansion */
169
- val = 1;
170
- break;
171
- case 29: /* Interrupt source. */
172
- val = s->phy_int;
173
- s->phy_int = 0;
174
- imx_phy_update_irq(s);
175
- break;
176
- case 30: /* Interrupt mask */
177
- val = s->phy_int_mask;
178
- break;
179
- case 17:
180
- case 18:
181
- case 27:
182
- case 31:
183
- qemu_log_mask(LOG_UNIMP, "[%s.phy]%s: reg %d not implemented\n",
184
- TYPE_IMX_FEC, __func__, reg);
185
- val = 0;
186
- break;
187
- default:
188
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
189
- TYPE_IMX_FEC, __func__, reg);
190
- val = 0;
191
- break;
192
- }
193
-
194
- trace_imx_phy_read(val, phy, reg);
195
-
196
- return val;
197
+ return lan9118_phy_read(&s->mii, reg);
198
}
199
200
static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
201
@@ -XXX,XX +XXX,XX @@ static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
202
203
reg %= 32;
204
205
- trace_imx_phy_write(val, phy, reg);
206
-
207
- switch (reg) {
208
- case 0: /* Basic Control */
209
- if (val & 0x8000) {
210
- imx_phy_reset(s);
211
- } else {
212
- s->phy_control = val & 0x7980;
213
- /* Complete autonegotiation immediately. */
214
- if (val & 0x1000) {
215
- s->phy_status |= 0x0020;
216
- }
217
- }
218
- break;
219
- case 4: /* Auto-neg advertisement */
220
- s->phy_advertise = (val & 0x2d7f) | 0x80;
221
- break;
222
- case 30: /* Interrupt mask */
223
- s->phy_int_mask = val & 0xff;
224
- imx_phy_update_irq(s);
225
- break;
226
- case 17:
227
- case 18:
228
- case 27:
229
- case 31:
230
- qemu_log_mask(LOG_UNIMP, "[%s.phy)%s: reg %d not implemented\n",
231
- TYPE_IMX_FEC, __func__, reg);
232
- break;
233
- default:
234
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
235
- TYPE_IMX_FEC, __func__, reg);
236
- break;
237
- }
238
+ lan9118_phy_write(&s->mii, reg, val);
239
}
240
241
static void imx_fec_read_bd(IMXFECBufDesc *bd, dma_addr_t addr)
242
@@ -XXX,XX +XXX,XX @@ static void imx_eth_reset(DeviceState *d)
243
244
s->rx_descriptor = 0;
245
memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor));
246
-
247
- /* We also reset the PHY */
248
- imx_phy_reset(s);
249
}
250
251
static uint32_t imx_default_read(IMXFECState *s, uint32_t index)
252
@@ -XXX,XX +XXX,XX @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
253
sysbus_init_irq(sbd, &s->irq[0]);
254
sysbus_init_irq(sbd, &s->irq[1]);
255
256
+ qemu_init_irq(&s->mii_irq, imx_phy_update_irq, s, 0);
257
+ object_initialize_child(OBJECT(s), "mii", &s->mii, TYPE_LAN9118_PHY);
258
+ if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->mii), errp)) {
259
+ return;
260
+ }
261
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
262
+
263
qemu_macaddr_default_if_unset(&s->conf.macaddr);
264
265
s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
266
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
267
index XXXXXXX..XXXXXXX 100644
268
--- a/hw/net/lan9118_phy.c
269
+++ b/hw/net/lan9118_phy.c
270
@@ -XXX,XX +XXX,XX @@
271
* Copyright (c) 2009 CodeSourcery, LLC.
272
* Written by Paul Brook
273
*
274
+ * Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
275
+ *
276
* This code is licensed under the GNU GPL v2
277
*
278
* Contributions after 2012-01-13 are licensed under the terms of the
279
@@ -XXX,XX +XXX,XX @@
280
#include "hw/resettable.h"
281
#include "migration/vmstate.h"
282
#include "qemu/log.h"
283
+#include "trace.h"
284
285
#define PHY_INT_ENERGYON (1 << 7)
286
#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
287
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
288
289
switch (reg) {
290
case 0: /* Basic Control */
291
- return s->control;
292
+ val = s->control;
293
+ break;
294
case 1: /* Basic Status */
295
- return s->status;
296
+ val = s->status;
297
+ break;
298
case 2: /* ID1 */
299
- return 0x0007;
300
+ val = 0x0007;
301
+ break;
302
case 3: /* ID2 */
303
- return 0xc0d1;
304
+ val = 0xc0d1;
305
+ break;
306
case 4: /* Auto-neg advertisement */
307
- return s->advertise;
308
+ val = s->advertise;
309
+ break;
310
case 5: /* Auto-neg Link Partner Ability */
311
- return 0x0f71;
312
+ val = 0x0f71;
313
+ break;
314
case 6: /* Auto-neg Expansion */
315
- return 1;
316
- /* TODO 17, 18, 27, 29, 30, 31 */
317
+ val = 1;
318
+ break;
319
case 29: /* Interrupt source. */
320
val = s->ints;
321
s->ints = 0;
322
lan9118_phy_update_irq(s);
323
- return val;
324
+ break;
325
case 30: /* Interrupt mask */
326
- return s->int_mask;
327
+ val = s->int_mask;
328
+ break;
329
+ case 17:
330
+ case 18:
331
+ case 27:
332
+ case 31:
333
+ qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
334
+ __func__, reg);
335
+ val = 0;
336
+ break;
337
default:
338
- qemu_log_mask(LOG_GUEST_ERROR,
339
- "lan9118_phy_read: PHY read reg %d\n", reg);
340
- return 0;
341
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
342
+ __func__, reg);
343
+ val = 0;
344
+ break;
345
}
346
+
347
+ trace_lan9118_phy_read(val, reg);
348
+
349
+ return val;
350
}
351
352
void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
353
{
354
+ trace_lan9118_phy_write(val, reg);
355
+
356
switch (reg) {
357
case 0: /* Basic Control */
358
if (val & 0x8000) {
359
lan9118_phy_reset(s);
360
- break;
361
- }
362
- s->control = val & 0x7980;
363
- /* Complete autonegotiation immediately. */
364
- if (val & 0x1000) {
365
- s->status |= 0x0020;
366
+ } else {
367
+ s->control = val & 0x7980;
368
+ /* Complete autonegotiation immediately. */
369
+ if (val & 0x1000) {
370
+ s->status |= 0x0020;
371
+ }
372
}
373
break;
374
case 4: /* Auto-neg advertisement */
375
s->advertise = (val & 0x2d7f) | 0x80;
376
break;
377
- /* TODO 17, 18, 27, 31 */
378
case 30: /* Interrupt mask */
379
s->int_mask = val & 0xff;
380
lan9118_phy_update_irq(s);
381
break;
382
+ case 17:
383
+ case 18:
384
+ case 27:
385
+ case 31:
386
+ qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
387
+ __func__, reg);
388
+ break;
389
default:
390
- qemu_log_mask(LOG_GUEST_ERROR,
391
- "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
392
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
393
+ __func__, reg);
394
+ break;
395
}
396
}
397
398
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
399
400
/* Autonegotiation status mirrors link status. */
401
if (link_down) {
402
+ trace_lan9118_phy_update_link("down");
403
s->status &= ~0x0024;
404
s->ints |= PHY_INT_DOWN;
405
} else {
406
+ trace_lan9118_phy_update_link("up");
407
s->status |= 0x0024;
408
s->ints |= PHY_INT_ENERGYON;
409
s->ints |= PHY_INT_AUTONEG_COMPLETE;
410
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
411
412
void lan9118_phy_reset(Lan9118PhyState *s)
413
{
414
+ trace_lan9118_phy_reset();
415
+
416
s->control = 0x3000;
417
s->status = 0x7809;
418
s->advertise = 0x01e1;
419
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118_phy = {
420
.version_id = 1,
421
.minimum_version_id = 1,
422
.fields = (const VMStateField[]) {
423
- VMSTATE_UINT16(control, Lan9118PhyState),
424
VMSTATE_UINT16(status, Lan9118PhyState),
425
+ VMSTATE_UINT16(control, Lan9118PhyState),
426
VMSTATE_UINT16(advertise, Lan9118PhyState),
427
VMSTATE_UINT16(ints, Lan9118PhyState),
428
VMSTATE_UINT16(int_mask, Lan9118PhyState),
429
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
430
index XXXXXXX..XXXXXXX 100644
431
--- a/hw/net/Kconfig
432
+++ b/hw/net/Kconfig
433
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_SUN8I_EMAC
434
435
config IMX_FEC
436
bool
437
+ select LAN9118_PHY
438
439
config CADENCE
440
bool
441
diff --git a/hw/net/trace-events b/hw/net/trace-events
442
index XXXXXXX..XXXXXXX 100644
443
--- a/hw/net/trace-events
444
+++ b/hw/net/trace-events
445
@@ -XXX,XX +XXX,XX @@ allwinner_sun8i_emac_set_link(bool active) "Set link: active=%u"
446
allwinner_sun8i_emac_read(uint64_t offset, uint64_t val) "MMIO read: offset=0x%" PRIx64 " value=0x%" PRIx64
447
allwinner_sun8i_emac_write(uint64_t offset, uint64_t val) "MMIO write: offset=0x%" PRIx64 " value=0x%" PRIx64
448
449
+# lan9118_phy.c
450
+lan9118_phy_read(uint16_t val, int reg) "[0x%02x] -> 0x%04" PRIx16
451
+lan9118_phy_write(uint16_t val, int reg) "[0x%02x] <- 0x%04" PRIx16
452
+lan9118_phy_update_link(const char *s) "%s"
453
+lan9118_phy_reset(void) ""
454
+
455
# lance.c
456
lance_mem_readw(uint64_t addr, uint32_t ret) "addr=0x%"PRIx64"val=0x%04x"
457
lance_mem_writew(uint64_t addr, uint32_t val) "addr=0x%"PRIx64"val=0x%04x"
458
@@ -XXX,XX +XXX,XX @@ i82596_set_multicast(uint16_t count) "Added %d multicast entries"
459
i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION"
460
461
# imx_fec.c
462
-imx_phy_read(uint32_t val, int phy, int reg) "0x%04"PRIx32" <= phy[%d].reg[%d]"
463
imx_phy_read_num(int phy, int configured) "read request from unconfigured phy %d (configured %d)"
464
-imx_phy_write(uint32_t val, int phy, int reg) "0x%04"PRIx32" => phy[%d].reg[%d]"
465
imx_phy_write_num(int phy, int configured) "write request to unconfigured phy %d (configured %d)"
466
-imx_phy_update_link(const char *s) "%s"
467
-imx_phy_reset(void) ""
468
imx_fec_read_bd(uint64_t addr, int flags, int len, int data) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x"
469
imx_enet_read_bd(uint64_t addr, int flags, int len, int data, int options, int status) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x option 0x%04x status 0x%04x"
470
imx_eth_tx_bd_busy(void) "tx_bd ran out of descriptors to transmit"
28
--
471
--
29
2.20.1
472
2.34.1
30
31
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
The time to transmit a char is expressed in nanoseconds, not in ticks.
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
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Fixes: 2a424990170b "LAN9118 emulation"
6
Message-id: 20201014213601.205222-1-f4bug@amsat.org
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Tested-by: Guenter Roeck <linux@roeck-us.net>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20241102125724.532843-4-shentey@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
12
---
10
hw/arm/strongarm.c | 2 +-
13
hw/net/lan9118_phy.c | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
12
15
13
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/strongarm.c
18
--- a/hw/net/lan9118_phy.c
16
+++ b/hw/arm/strongarm.c
19
+++ b/hw/net/lan9118_phy.c
17
@@ -XXX,XX +XXX,XX @@ struct StrongARMUARTState {
20
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
18
uint8_t rx_start;
21
val = s->advertise;
19
uint8_t rx_len;
22
break;
20
23
case 5: /* Auto-neg Link Partner Ability */
21
- uint64_t char_transmit_time; /* time to transmit a char in ticks*/
24
- val = 0x0f71;
22
+ uint64_t char_transmit_time; /* time to transmit a char in nanoseconds */
25
+ val = 0x0fe1;
23
bool wait_break_end;
26
break;
24
QEMUTimer *rx_timeout_timer;
27
case 6: /* Auto-neg Expansion */
25
QEMUTimer *tx_timer;
28
val = 1;
26
--
29
--
27
2.20.1
30
2.34.1
28
29
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
The kernel sets btype for the signal handler as if for a call.
3
Prefer named constants over magic values for better readability.
4
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
7
Message-id: 20201016184207.786698-2-richard.henderson@linaro.org
7
Tested-by: Guenter Roeck <linux@roeck-us.net>
8
Message-id: 20241102125724.532843-5-shentey@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
linux-user/aarch64/signal.c | 10 ++++++++--
11
include/hw/net/mii.h | 6 +++++
11
1 file changed, 8 insertions(+), 2 deletions(-)
12
hw/net/lan9118_phy.c | 63 ++++++++++++++++++++++++++++----------------
13
2 files changed, 46 insertions(+), 23 deletions(-)
12
14
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
15
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/signal.c
17
--- a/include/hw/net/mii.h
16
+++ b/linux-user/aarch64/signal.c
18
+++ b/include/hw/net/mii.h
17
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
19
@@ -XXX,XX +XXX,XX @@
18
+ offsetof(struct target_rt_frame_record, tramp);
20
#define MII_BMSR_JABBER (1 << 1) /* Jabber detected */
21
#define MII_BMSR_EXTCAP (1 << 0) /* Ext-reg capability */
22
23
+#define MII_ANAR_RFAULT (1 << 13) /* Say we can detect faults */
24
#define MII_ANAR_PAUSE_ASYM (1 << 11) /* Try for asymmetric pause */
25
#define MII_ANAR_PAUSE (1 << 10) /* Try for pause */
26
#define MII_ANAR_TXFD (1 << 8)
27
@@ -XXX,XX +XXX,XX @@
28
#define MII_ANAR_10FD (1 << 6)
29
#define MII_ANAR_10 (1 << 5)
30
#define MII_ANAR_CSMACD (1 << 0)
31
+#define MII_ANAR_SELECT (0x001f) /* Selector bits */
32
33
#define MII_ANLPAR_ACK (1 << 14)
34
#define MII_ANLPAR_PAUSEASY (1 << 11) /* can pause asymmetrically */
35
@@ -XXX,XX +XXX,XX @@
36
#define RTL8201CP_PHYID1 0x0000
37
#define RTL8201CP_PHYID2 0x8201
38
39
+/* SMSC LAN9118 */
40
+#define SMSCLAN9118_PHYID1 0x0007
41
+#define SMSCLAN9118_PHYID2 0xc0d1
42
+
43
/* RealTek 8211E */
44
#define RTL8211E_PHYID1 0x001c
45
#define RTL8211E_PHYID2 0xc915
46
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/net/lan9118_phy.c
49
+++ b/hw/net/lan9118_phy.c
50
@@ -XXX,XX +XXX,XX @@
51
52
#include "qemu/osdep.h"
53
#include "hw/net/lan9118_phy.h"
54
+#include "hw/net/mii.h"
55
#include "hw/irq.h"
56
#include "hw/resettable.h"
57
#include "migration/vmstate.h"
58
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
59
uint16_t val;
60
61
switch (reg) {
62
- case 0: /* Basic Control */
63
+ case MII_BMCR:
64
val = s->control;
65
break;
66
- case 1: /* Basic Status */
67
+ case MII_BMSR:
68
val = s->status;
69
break;
70
- case 2: /* ID1 */
71
- val = 0x0007;
72
+ case MII_PHYID1:
73
+ val = SMSCLAN9118_PHYID1;
74
break;
75
- case 3: /* ID2 */
76
- val = 0xc0d1;
77
+ case MII_PHYID2:
78
+ val = SMSCLAN9118_PHYID2;
79
break;
80
- case 4: /* Auto-neg advertisement */
81
+ case MII_ANAR:
82
val = s->advertise;
83
break;
84
- case 5: /* Auto-neg Link Partner Ability */
85
- val = 0x0fe1;
86
+ case MII_ANLPAR:
87
+ val = MII_ANLPAR_PAUSEASY | MII_ANLPAR_PAUSE | MII_ANLPAR_T4 |
88
+ MII_ANLPAR_TXFD | MII_ANLPAR_TX | MII_ANLPAR_10FD |
89
+ MII_ANLPAR_10 | MII_ANLPAR_CSMACD;
90
break;
91
- case 6: /* Auto-neg Expansion */
92
- val = 1;
93
+ case MII_ANER:
94
+ val = MII_ANER_NWAY;
95
break;
96
case 29: /* Interrupt source. */
97
val = s->ints;
98
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
99
trace_lan9118_phy_write(val, reg);
100
101
switch (reg) {
102
- case 0: /* Basic Control */
103
- if (val & 0x8000) {
104
+ case MII_BMCR:
105
+ if (val & MII_BMCR_RESET) {
106
lan9118_phy_reset(s);
107
} else {
108
- s->control = val & 0x7980;
109
+ s->control = val & (MII_BMCR_LOOPBACK | MII_BMCR_SPEED100 |
110
+ MII_BMCR_AUTOEN | MII_BMCR_PDOWN | MII_BMCR_FD |
111
+ MII_BMCR_CTST);
112
/* Complete autonegotiation immediately. */
113
- if (val & 0x1000) {
114
- s->status |= 0x0020;
115
+ if (val & MII_BMCR_AUTOEN) {
116
+ s->status |= MII_BMSR_AN_COMP;
117
}
118
}
119
break;
120
- case 4: /* Auto-neg advertisement */
121
- s->advertise = (val & 0x2d7f) | 0x80;
122
+ case MII_ANAR:
123
+ s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
124
+ MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
125
+ MII_ANAR_SELECT))
126
+ | MII_ANAR_TX;
127
break;
128
case 30: /* Interrupt mask */
129
s->int_mask = val & 0xff;
130
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
131
/* Autonegotiation status mirrors link status. */
132
if (link_down) {
133
trace_lan9118_phy_update_link("down");
134
- s->status &= ~0x0024;
135
+ s->status &= ~(MII_BMSR_AN_COMP | MII_BMSR_LINK_ST);
136
s->ints |= PHY_INT_DOWN;
137
} else {
138
trace_lan9118_phy_update_link("up");
139
- s->status |= 0x0024;
140
+ s->status |= MII_BMSR_AN_COMP | MII_BMSR_LINK_ST;
141
s->ints |= PHY_INT_ENERGYON;
142
s->ints |= PHY_INT_AUTONEG_COMPLETE;
19
}
143
}
20
env->xregs[0] = usig;
144
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_reset(Lan9118PhyState *s)
21
- env->xregs[31] = frame_addr;
145
{
22
env->xregs[29] = frame_addr + fr_ofs;
146
trace_lan9118_phy_reset();
23
- env->pc = ka->_sa_handler;
147
24
env->xregs[30] = return_addr;
148
- s->control = 0x3000;
25
+ env->xregs[31] = frame_addr;
149
- s->status = 0x7809;
26
+ env->pc = ka->_sa_handler;
150
- s->advertise = 0x01e1;
27
+
151
+ s->control = MII_BMCR_AUTOEN | MII_BMCR_SPEED100;
28
+ /* Invoke the signal handler as if by indirect call. */
152
+ s->status = MII_BMSR_100TX_FD
29
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
153
+ | MII_BMSR_100TX_HD
30
+ env->btype = 2;
154
+ | MII_BMSR_10T_FD
31
+ }
155
+ | MII_BMSR_10T_HD
32
+
156
+ | MII_BMSR_AUTONEG
33
if (info) {
157
+ | MII_BMSR_EXTCAP;
34
tswap_siginfo(&frame->info, info);
158
+ s->advertise = MII_ANAR_TXFD
35
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
159
+ | MII_ANAR_TX
160
+ | MII_ANAR_10FD
161
+ | MII_ANAR_10
162
+ | MII_ANAR_CSMACD;
163
s->int_mask = 0;
164
s->ints = 0;
165
lan9118_phy_update_link(s, s->link_down);
36
--
166
--
37
2.20.1
167
2.34.1
38
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
These are all of the defines required to parse
3
The real device advertises this mode and the device model already advertises
4
GNU_PROPERTY_AARCH64_FEATURE_1_AND, copied from binutils.
4
100 mbps half duplex and 10 mbps full+half duplex. So advertise this mode to
5
Other missing defines related to other GNU program headers
5
make the model more realistic.
6
and notes are elided for now.
7
6
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
10
Message-id: 20201016184207.786698-4-richard.henderson@linaro.org
9
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
Message-id: 20241102125724.532843-6-shentey@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
12
---
13
include/elf.h | 22 ++++++++++++++++++++++
13
hw/net/lan9118_phy.c | 4 ++--
14
1 file changed, 22 insertions(+)
14
1 file changed, 2 insertions(+), 2 deletions(-)
15
15
16
diff --git a/include/elf.h b/include/elf.h
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/elf.h
18
--- a/hw/net/lan9118_phy.c
19
+++ b/include/elf.h
19
+++ b/hw/net/lan9118_phy.c
20
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
20
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
21
#define PT_NOTE 4
21
break;
22
#define PT_SHLIB 5
22
case MII_ANAR:
23
#define PT_PHDR 6
23
s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
24
+#define PT_LOOS 0x60000000
24
- MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
25
+#define PT_HIOS 0x6fffffff
25
- MII_ANAR_SELECT))
26
#define PT_LOPROC 0x70000000
26
+ MII_ANAR_PAUSE | MII_ANAR_TXFD | MII_ANAR_10FD |
27
#define PT_HIPROC 0x7fffffff
27
+ MII_ANAR_10 | MII_ANAR_SELECT))
28
28
| MII_ANAR_TX;
29
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
29
break;
30
+
30
case 30: /* Interrupt mask */
31
#define PT_MIPS_REGINFO 0x70000000
32
#define PT_MIPS_RTPROC 0x70000001
33
#define PT_MIPS_OPTIONS 0x70000002
34
@@ -XXX,XX +XXX,XX @@ typedef struct elf64_shdr {
35
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
36
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension regs */
37
38
+/* Defined note types for GNU systems. */
39
+
40
+#define NT_GNU_PROPERTY_TYPE_0 5 /* Program property */
41
+
42
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
43
+
44
+#define GNU_PROPERTY_STACK_SIZE 1
45
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
46
+
47
+#define GNU_PROPERTY_LOPROC 0xc0000000
48
+#define GNU_PROPERTY_HIPROC 0xdfffffff
49
+#define GNU_PROPERTY_LOUSER 0xe0000000
50
+#define GNU_PROPERTY_HIUSER 0xffffffff
51
+
52
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
53
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1u << 0)
54
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1u << 1)
55
+
56
/*
57
* Physical entry point into the kernel.
58
*
59
--
31
--
60
2.20.1
32
2.34.1
61
62
diff view generated by jsdifflib
New patch
1
For IEEE fused multiply-add, the (0 * inf) + NaN case should raise
2
Invalid for the multiplication of 0 by infinity. Currently we handle
3
this in the per-architecture ifdef ladder in pickNaNMulAdd().
4
However, since this isn't really architecture specific we can hoist
5
it up to the generic code.
1
6
7
For the cases where the infzero test in pickNaNMulAdd was
8
returning 2, we can delete the check entirely and allow the
9
code to fall into the normal pick-a-NaN handling, because this
10
will return 2 anyway (input 'c' being the only NaN in this case).
11
For the cases where infzero was returning 3 to indicate "return
12
the default NaN", we must retain that "return 3".
13
14
For Arm, this looks like it might be a behaviour change because we
15
used to set float_flag_invalid | float_flag_invalid_imz only if C is
16
a quiet NaN. However, it is not, because Arm target code never looks
17
at float_flag_invalid_imz, and for the (0 * inf) + SNaN case we
18
already raised float_flag_invalid via the "abc_mask &
19
float_cmask_snan" check in pick_nan_muladd.
20
21
For any target architecture using the "default implementation" at the
22
bottom of the ifdef, this is a behaviour change but will be fixing a
23
bug (where we failed to raise the Invalid exception for (0 * inf +
24
QNaN). The architectures using the default case are:
25
* hppa
26
* i386
27
* sh4
28
* tricore
29
30
The x86, Tricore and SH4 CPU architecture manuals are clear that this
31
should have raised Invalid; HPPA is a bit vaguer but still seems
32
clear enough.
33
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
36
Message-id: 20241202131347.498124-2-peter.maydell@linaro.org
37
---
38
fpu/softfloat-parts.c.inc | 13 +++++++------
39
fpu/softfloat-specialize.c.inc | 29 +----------------------------
40
2 files changed, 8 insertions(+), 34 deletions(-)
41
42
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
43
index XXXXXXX..XXXXXXX 100644
44
--- a/fpu/softfloat-parts.c.inc
45
+++ b/fpu/softfloat-parts.c.inc
46
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
47
int ab_mask, int abc_mask)
48
{
49
int which;
50
+ bool infzero = (ab_mask == float_cmask_infzero);
51
52
if (unlikely(abc_mask & float_cmask_snan)) {
53
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
54
}
55
56
- which = pickNaNMulAdd(a->cls, b->cls, c->cls,
57
- ab_mask == float_cmask_infzero, s);
58
+ if (infzero) {
59
+ /* This is (0 * inf) + NaN or (inf * 0) + NaN */
60
+ float_raise(float_flag_invalid | float_flag_invalid_imz, s);
61
+ }
62
+
63
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
64
65
if (s->default_nan_mode || which == 3) {
66
- /*
67
- * Note that this check is after pickNaNMulAdd so that function
68
- * has an opportunity to set the Invalid flag for infzero.
69
- */
70
parts_default_nan(a, s);
71
return a;
72
}
73
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
74
index XXXXXXX..XXXXXXX 100644
75
--- a/fpu/softfloat-specialize.c.inc
76
+++ b/fpu/softfloat-specialize.c.inc
77
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
78
* the default NaN
79
*/
80
if (infzero && is_qnan(c_cls)) {
81
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
82
return 3;
83
}
84
85
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
86
* case sets InvalidOp and returns the default NaN
87
*/
88
if (infzero) {
89
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
90
return 3;
91
}
92
/* Prefer sNaN over qNaN, in the a, b, c order. */
93
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
94
* For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
95
* case sets InvalidOp and returns the input value 'c'
96
*/
97
- if (infzero) {
98
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
99
- return 2;
100
- }
101
/* Prefer sNaN over qNaN, in the c, a, b order. */
102
if (is_snan(c_cls)) {
103
return 2;
104
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
105
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
106
* case sets InvalidOp and returns the input value 'c'
107
*/
108
- if (infzero) {
109
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
110
- return 2;
111
- }
112
+
113
/* Prefer sNaN over qNaN, in the c, a, b order. */
114
if (is_snan(c_cls)) {
115
return 2;
116
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
117
* to return an input NaN if we have one (ie c) rather than generating
118
* a default NaN
119
*/
120
- if (infzero) {
121
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
122
- return 2;
123
- }
124
125
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
126
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
127
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
128
return 1;
129
}
130
#elif defined(TARGET_RISCV)
131
- /* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
132
- if (infzero) {
133
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
134
- }
135
return 3; /* default NaN */
136
#elif defined(TARGET_S390X)
137
if (infzero) {
138
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
139
return 3;
140
}
141
142
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
143
return 2;
144
}
145
#elif defined(TARGET_SPARC)
146
- /* For (inf,0,nan) return c. */
147
- if (infzero) {
148
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
149
- return 2;
150
- }
151
/* Prefer SNaN over QNaN, order C, B, A. */
152
if (is_snan(c_cls)) {
153
return 2;
154
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
155
* For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
156
* an input NaN if we have one (ie c).
157
*/
158
- if (infzero) {
159
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
160
- return 2;
161
- }
162
if (status->use_first_nan) {
163
if (is_nan(a_cls)) {
164
return 0;
165
--
166
2.34.1
diff view generated by jsdifflib
New patch
1
If the target sets default_nan_mode then we're always going to return
2
the default NaN, and pickNaNMulAdd() no longer has any side effects.
3
For consistency with pickNaN(), check for default_nan_mode before
4
calling pickNaNMulAdd().
1
5
6
When we convert pickNaNMulAdd() to allow runtime selection of the NaN
7
propagation rule, this means we won't have to make the targets which
8
use default_nan_mode also set a propagation rule.
9
10
Since RiscV always uses default_nan_mode, this allows us to remove
11
its ifdef case from pickNaNMulAdd().
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20241202131347.498124-3-peter.maydell@linaro.org
16
---
17
fpu/softfloat-parts.c.inc | 8 ++++++--
18
fpu/softfloat-specialize.c.inc | 9 +++++++--
19
2 files changed, 13 insertions(+), 4 deletions(-)
20
21
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
22
index XXXXXXX..XXXXXXX 100644
23
--- a/fpu/softfloat-parts.c.inc
24
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
26
float_raise(float_flag_invalid | float_flag_invalid_imz, s);
27
}
28
29
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
30
+ if (s->default_nan_mode) {
31
+ which = 3;
32
+ } else {
33
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
34
+ }
35
36
- if (s->default_nan_mode || which == 3) {
37
+ if (which == 3) {
38
parts_default_nan(a, s);
39
return a;
40
}
41
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
42
index XXXXXXX..XXXXXXX 100644
43
--- a/fpu/softfloat-specialize.c.inc
44
+++ b/fpu/softfloat-specialize.c.inc
45
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
46
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
47
bool infzero, float_status *status)
48
{
49
+ /*
50
+ * We guarantee not to require the target to tell us how to
51
+ * pick a NaN if we're always returning the default NaN.
52
+ * But if we're not in default-NaN mode then the target must
53
+ * specify.
54
+ */
55
+ assert(!status->default_nan_mode);
56
#if defined(TARGET_ARM)
57
/* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
58
* the default NaN
59
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
60
} else {
61
return 1;
62
}
63
-#elif defined(TARGET_RISCV)
64
- return 3; /* default NaN */
65
#elif defined(TARGET_S390X)
66
if (infzero) {
67
return 3;
68
--
69
2.34.1
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
IEEE 758 does not define a fixed rule for what NaN to return in
2
2
the case of a fused multiply-add of inf * 0 + NaN. Different
3
This test exercises the various modes of the npcm7xx timer. In
3
architectures thus do different things:
4
particular, it triggers the bug found by the fuzzer, as reported here:
4
* some return the default NaN
5
5
* some return the input NaN
6
https://lists.gnu.org/archive/html/qemu-devel/2020-09/msg02992.html
6
* Arm returns the default NaN if the input NaN is quiet,
7
7
and the input NaN if it is signalling
8
It also found several other bugs, especially related to interrupt
8
9
handling.
9
We want to make this logic be runtime selected rather than
10
10
hardcoded into the binary, because:
11
The test exercises all the timers in all the timer modules, which
11
* this will let us have multiple targets in one QEMU binary
12
expands to 180 test cases in total.
12
* the Arm FEAT_AFP architectural feature includes letting
13
13
the guest select a NaN propagation rule at runtime
14
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
14
15
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
15
In this commit we add an enum for the propagation rule, the field in
16
Message-id: 20201008232154.94221-2-hskinnemoen@google.com
16
float_status, and the corresponding getters and setters. We change
17
pickNaNMulAdd to honour this, but because all targets still leave
18
this field at its default 0 value, the fallback logic will pick the
19
rule type with the old ifdef ladder.
20
21
Note that four architectures both use the muladd softfloat functions
22
and did not have a branch of the ifdef ladder to specify their
23
behaviour (and so were ending up with the "default" case, probably
24
wrongly): i386, HPPA, SH4 and Tricore. SH4 and Tricore both set
25
default_nan_mode, and so will never get into pickNaNMulAdd(). For
26
HPPA and i386 we retain the same behaviour as the old default-case,
27
which is to not ever return the default NaN. This might not be
28
correct but it is not a behaviour change.
29
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
32
Message-id: 20241202131347.498124-4-peter.maydell@linaro.org
18
---
33
---
19
tests/qtest/npcm7xx_timer-test.c | 562 +++++++++++++++++++++++++++++++
34
include/fpu/softfloat-helpers.h | 11 ++++
20
tests/qtest/meson.build | 1 +
35
include/fpu/softfloat-types.h | 23 +++++++++
21
2 files changed, 563 insertions(+)
36
fpu/softfloat-specialize.c.inc | 91 ++++++++++++++++++++++-----------
22
create mode 100644 tests/qtest/npcm7xx_timer-test.c
37
3 files changed, 95 insertions(+), 30 deletions(-)
23
38
24
diff --git a/tests/qtest/npcm7xx_timer-test.c b/tests/qtest/npcm7xx_timer-test.c
39
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
25
new file mode 100644
40
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX
41
--- a/include/fpu/softfloat-helpers.h
27
--- /dev/null
42
+++ b/include/fpu/softfloat-helpers.h
28
+++ b/tests/qtest/npcm7xx_timer-test.c
43
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
29
@@ -XXX,XX +XXX,XX @@
44
status->float_2nan_prop_rule = rule;
45
}
46
47
+static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
+ float_status *status)
49
+{
50
+ status->float_infzeronan_rule = rule;
51
+}
52
+
53
static inline void set_flush_to_zero(bool val, float_status *status)
54
{
55
status->flush_to_zero = val;
56
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
57
return status->float_2nan_prop_rule;
58
}
59
60
+static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
61
+{
62
+ return status->float_infzeronan_rule;
63
+}
64
+
65
static inline bool get_flush_to_zero(float_status *status)
66
{
67
return status->flush_to_zero;
68
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
69
index XXXXXXX..XXXXXXX 100644
70
--- a/include/fpu/softfloat-types.h
71
+++ b/include/fpu/softfloat-types.h
72
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
73
float_2nan_prop_x87,
74
} Float2NaNPropRule;
75
30
+/*
76
+/*
31
+ * QTest testcase for the Nuvoton NPCM7xx Timer
77
+ * Rule for result of fused multiply-add 0 * Inf + NaN.
78
+ * This must be a NaN, but implementations differ on whether this
79
+ * is the input NaN or the default NaN.
32
+ *
80
+ *
33
+ * Copyright 2020 Google LLC
81
+ * You don't need to set this if default_nan_mode is enabled.
34
+ *
82
+ * When not in default-NaN mode, it is an error for the target
35
+ * This program is free software; you can redistribute it and/or modify it
83
+ * not to set the rule in float_status if it uses muladd, and we
36
+ * under the terms of the GNU General Public License as published by the
84
+ * will assert if we need to handle an input NaN and no rule was
37
+ * Free Software Foundation; either version 2 of the License, or
85
+ * selected.
38
+ * (at your option) any later version.
39
+ *
40
+ * This program is distributed in the hope that it will be useful, but WITHOUT
41
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
42
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
43
+ * for more details.
44
+ */
86
+ */
45
+
87
+typedef enum __attribute__((__packed__)) {
46
+#include "qemu/osdep.h"
88
+ /* No propagation rule specified */
47
+#include "qemu/timer.h"
89
+ float_infzeronan_none = 0,
48
+#include "libqtest-single.h"
90
+ /* Result is never the default NaN (so always the input NaN) */
49
+
91
+ float_infzeronan_dnan_never,
50
+#define TIM_REF_HZ (25000000)
92
+ /* Result is always the default NaN */
51
+
93
+ float_infzeronan_dnan_always,
52
+/* Bits in TCSRx */
94
+ /* Result is the default NaN if the input NaN is quiet */
53
+#define CEN BIT(30)
95
+ float_infzeronan_dnan_if_qnan,
54
+#define IE BIT(29)
96
+} FloatInfZeroNaNRule;
55
+#define MODE_ONESHOT (0 << 27)
97
+
56
+#define MODE_PERIODIC (1 << 27)
98
/*
57
+#define CRST BIT(26)
99
* Floating Point Status. Individual architectures may maintain
58
+#define CACT BIT(25)
100
* several versions of float_status for different functions. The
59
+#define PRESCALE(x) (x)
101
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
60
+
102
FloatRoundMode float_rounding_mode;
61
+/* Registers shared between all timers in a module. */
103
FloatX80RoundPrec floatx80_rounding_precision;
62
+#define TISR 0x18
104
Float2NaNPropRule float_2nan_prop_rule;
63
+#define WTCR 0x1c
105
+ FloatInfZeroNaNRule float_infzeronan_rule;
64
+# define WTCLK(x) ((x) << 10)
106
bool tininess_before_rounding;
65
+
107
/* should denormalised results go to zero and set the inexact flag? */
66
+/* Power-on default; used to re-initialize timers before each test. */
108
bool flush_to_zero;
67
+#define TCSR_DEFAULT PRESCALE(5)
109
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
68
+
110
index XXXXXXX..XXXXXXX 100644
69
+/* Register offsets for a timer within a timer block. */
111
--- a/fpu/softfloat-specialize.c.inc
70
+typedef struct Timer {
112
+++ b/fpu/softfloat-specialize.c.inc
71
+ unsigned int tcsr_offset;
113
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
72
+ unsigned int ticr_offset;
114
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
73
+ unsigned int tdr_offset;
115
bool infzero, float_status *status)
74
+} Timer;
116
{
75
+
117
+ FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
76
+/* A timer block containing 5 timers. */
118
+
77
+typedef struct TimerBlock {
119
/*
78
+ int irq_base;
120
* We guarantee not to require the target to tell us how to
79
+ uint64_t base_addr;
121
* pick a NaN if we're always returning the default NaN.
80
+} TimerBlock;
122
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
81
+
123
* specify.
82
+/* Testdata for testing a particular timer within a timer block. */
124
*/
83
+typedef struct TestData {
125
assert(!status->default_nan_mode);
84
+ const TimerBlock *tim;
126
+
85
+ const Timer *timer;
127
+ if (rule == float_infzeronan_none) {
86
+} TestData;
128
+ /*
87
+
129
+ * Temporarily fall back to ifdef ladder
88
+const TimerBlock timer_block[] = {
130
+ */
89
+ {
131
#if defined(TARGET_ARM)
90
+ .irq_base = 32,
132
- /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
91
+ .base_addr = 0xf0008000,
133
- * the default NaN
92
+ },
134
- */
93
+ {
135
- if (infzero && is_qnan(c_cls)) {
94
+ .irq_base = 37,
136
- return 3;
95
+ .base_addr = 0xf0009000,
137
+ /*
96
+ },
138
+ * For ARM, the (inf,zero,qnan) case returns the default NaN,
97
+ {
139
+ * but (inf,zero,snan) returns the input NaN.
98
+ .irq_base = 42,
140
+ */
99
+ .base_addr = 0xf000a000,
141
+ rule = float_infzeronan_dnan_if_qnan;
100
+ },
142
+#elif defined(TARGET_MIPS)
101
+};
143
+ if (snan_bit_is_one(status)) {
102
+
144
+ /*
103
+const Timer timer[] = {
145
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
104
+ {
146
+ * case sets InvalidOp and returns the default NaN
105
+ .tcsr_offset = 0x00,
147
+ */
106
+ .ticr_offset = 0x08,
148
+ rule = float_infzeronan_dnan_always;
107
+ .tdr_offset = 0x10,
149
+ } else {
108
+ }, {
150
+ /*
109
+ .tcsr_offset = 0x04,
151
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
110
+ .ticr_offset = 0x0c,
152
+ * case sets InvalidOp and returns the input value 'c'
111
+ .tdr_offset = 0x14,
153
+ */
112
+ }, {
154
+ rule = float_infzeronan_dnan_never;
113
+ .tcsr_offset = 0x20,
114
+ .ticr_offset = 0x28,
115
+ .tdr_offset = 0x30,
116
+ }, {
117
+ .tcsr_offset = 0x24,
118
+ .ticr_offset = 0x2c,
119
+ .tdr_offset = 0x34,
120
+ }, {
121
+ .tcsr_offset = 0x40,
122
+ .ticr_offset = 0x48,
123
+ .tdr_offset = 0x50,
124
+ },
125
+};
126
+
127
+/* Returns the index of the timer block. */
128
+static int tim_index(const TimerBlock *tim)
129
+{
130
+ ptrdiff_t diff = tim - timer_block;
131
+
132
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer_block));
133
+
134
+ return diff;
135
+}
136
+
137
+/* Returns the index of a timer within a timer block. */
138
+static int timer_index(const Timer *t)
139
+{
140
+ ptrdiff_t diff = t - timer;
141
+
142
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer));
143
+
144
+ return diff;
145
+}
146
+
147
+/* Returns the irq line for a given timer. */
148
+static int tim_timer_irq(const TestData *td)
149
+{
150
+ return td->tim->irq_base + timer_index(td->timer);
151
+}
152
+
153
+/* Register read/write accessors. */
154
+
155
+static void tim_write(const TestData *td,
156
+ unsigned int offset, uint32_t value)
157
+{
158
+ writel(td->tim->base_addr + offset, value);
159
+}
160
+
161
+static uint32_t tim_read(const TestData *td, unsigned int offset)
162
+{
163
+ return readl(td->tim->base_addr + offset);
164
+}
165
+
166
+static void tim_write_tcsr(const TestData *td, uint32_t value)
167
+{
168
+ tim_write(td, td->timer->tcsr_offset, value);
169
+}
170
+
171
+static uint32_t tim_read_tcsr(const TestData *td)
172
+{
173
+ return tim_read(td, td->timer->tcsr_offset);
174
+}
175
+
176
+static void tim_write_ticr(const TestData *td, uint32_t value)
177
+{
178
+ tim_write(td, td->timer->ticr_offset, value);
179
+}
180
+
181
+static uint32_t tim_read_ticr(const TestData *td)
182
+{
183
+ return tim_read(td, td->timer->ticr_offset);
184
+}
185
+
186
+static uint32_t tim_read_tdr(const TestData *td)
187
+{
188
+ return tim_read(td, td->timer->tdr_offset);
189
+}
190
+
191
+/* Returns the number of nanoseconds to count the given number of cycles. */
192
+static int64_t tim_calculate_step(uint32_t count, uint32_t prescale)
193
+{
194
+ return (1000000000LL / TIM_REF_HZ) * count * (prescale + 1);
195
+}
196
+
197
+/* Returns a bitmask corresponding to the timer under test. */
198
+static uint32_t tim_timer_bit(const TestData *td)
199
+{
200
+ return BIT(timer_index(td->timer));
201
+}
202
+
203
+/* Resets all timers to power-on defaults. */
204
+static void tim_reset(const TestData *td)
205
+{
206
+ int i, j;
207
+
208
+ /* Reset all the timers, in case a previous test left a timer running. */
209
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
210
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
211
+ writel(timer_block[i].base_addr + timer[j].tcsr_offset,
212
+ CRST | TCSR_DEFAULT);
213
+ }
155
+ }
214
+ writel(timer_block[i].base_addr + TISR, -1);
156
+#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
215
+ }
157
+ defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
216
+}
158
+ defined(TARGET_I386) || defined(TARGET_LOONGARCH)
217
+
159
+ /*
218
+/* Verifies the reset state of a timer. */
160
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
219
+static void test_reset(gconstpointer test_data)
161
+ * case sets InvalidOp and returns the input value 'c'
220
+{
162
+ */
221
+ const TestData *td = test_data;
163
+ /*
222
+
164
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
223
+ tim_reset(td);
165
+ * to return an input NaN if we have one (ie c) rather than generating
224
+
166
+ * a default NaN
225
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
167
+ */
226
+ g_assert_cmphex(tim_read_ticr(td), ==, 0);
168
+ rule = float_infzeronan_dnan_never;
227
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
169
+#elif defined(TARGET_S390X)
228
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
170
+ rule = float_infzeronan_dnan_always;
229
+ g_assert_cmphex(tim_read(td, WTCR), ==, WTCLK(1));
171
+#endif
230
+}
172
}
231
+
173
232
+/* Verifies that CRST wins if both CEN and CRST are set. */
174
+ if (infzero) {
233
+static void test_reset_overrides_enable(gconstpointer test_data)
175
+ /*
234
+{
176
+ * Inf * 0 + NaN -- some implementations return the default NaN here,
235
+ const TestData *td = test_data;
177
+ * and some return the input NaN.
236
+
178
+ */
237
+ tim_reset(td);
179
+ switch (rule) {
238
+
180
+ case float_infzeronan_dnan_never:
239
+ /* CRST should force CEN to 0 */
181
+ return 2;
240
+ tim_write_tcsr(td, CEN | CRST | TCSR_DEFAULT);
182
+ case float_infzeronan_dnan_always:
241
+
183
+ return 3;
242
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
184
+ case float_infzeronan_dnan_if_qnan:
243
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
185
+ return is_qnan(c_cls) ? 3 : 2;
244
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
186
+ default:
245
+}
187
+ g_assert_not_reached();
246
+
247
+/* Verifies the behavior when CEN is set and then cleared. */
248
+static void test_oneshot_enable_then_disable(gconstpointer test_data)
249
+{
250
+ const TestData *td = test_data;
251
+
252
+ tim_reset(td);
253
+
254
+ /* Enable the timer with zero initial count, then disable it again. */
255
+ tim_write_tcsr(td, CEN | TCSR_DEFAULT);
256
+ tim_write_tcsr(td, TCSR_DEFAULT);
257
+
258
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
259
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
260
+ /* Timer interrupt flag should be set, but interrupts are not enabled. */
261
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
262
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
263
+}
264
+
265
+/* Verifies that a one-shot timer fires when expected with prescaler 5. */
266
+static void test_oneshot_ps5(gconstpointer test_data)
267
+{
268
+ const TestData *td = test_data;
269
+ unsigned int count = 256;
270
+ unsigned int ps = 5;
271
+
272
+ tim_reset(td);
273
+
274
+ tim_write_ticr(td, count);
275
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
276
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
277
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
278
+
279
+ clock_step(tim_calculate_step(count, ps) - 1);
280
+
281
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
282
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
283
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
284
+
285
+ clock_step(1);
286
+
287
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
288
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
289
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
290
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
291
+
292
+ /* Clear the interrupt flag. */
293
+ tim_write(td, TISR, tim_timer_bit(td));
294
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
295
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
296
+
297
+ /* Verify that this isn't a periodic timer. */
298
+ clock_step(2 * tim_calculate_step(count, ps));
299
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
300
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
301
+}
302
+
303
+/* Verifies that a one-shot timer fires when expected with prescaler 0. */
304
+static void test_oneshot_ps0(gconstpointer test_data)
305
+{
306
+ const TestData *td = test_data;
307
+ unsigned int count = 1;
308
+ unsigned int ps = 0;
309
+
310
+ tim_reset(td);
311
+
312
+ tim_write_ticr(td, count);
313
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
314
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
315
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
316
+
317
+ clock_step(tim_calculate_step(count, ps) - 1);
318
+
319
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
320
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
321
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
322
+
323
+ clock_step(1);
324
+
325
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
326
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
327
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
328
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
329
+}
330
+
331
+/* Verifies that a one-shot timer fires when expected with highest prescaler. */
332
+static void test_oneshot_ps255(gconstpointer test_data)
333
+{
334
+ const TestData *td = test_data;
335
+ unsigned int count = (1U << 24) - 1;
336
+ unsigned int ps = 255;
337
+
338
+ tim_reset(td);
339
+
340
+ tim_write_ticr(td, count);
341
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
342
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
343
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
344
+
345
+ clock_step(tim_calculate_step(count, ps) - 1);
346
+
347
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
348
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
349
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
350
+
351
+ clock_step(1);
352
+
353
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
354
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
355
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
356
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
357
+}
358
+
359
+/* Verifies that a oneshot timer fires an interrupt when expected. */
360
+static void test_oneshot_interrupt(gconstpointer test_data)
361
+{
362
+ const TestData *td = test_data;
363
+ unsigned int count = 256;
364
+ unsigned int ps = 7;
365
+
366
+ tim_reset(td);
367
+
368
+ tim_write_ticr(td, count);
369
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
370
+
371
+ clock_step_next();
372
+
373
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
374
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
375
+}
376
+
377
+/*
378
+ * Verifies that the timer can be paused and later resumed, and it still fires
379
+ * at the right moment.
380
+ */
381
+static void test_pause_resume(gconstpointer test_data)
382
+{
383
+ const TestData *td = test_data;
384
+ unsigned int count = 256;
385
+ unsigned int ps = 1;
386
+
387
+ tim_reset(td);
388
+
389
+ tim_write_ticr(td, count);
390
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
391
+
392
+ /* Pause the timer halfway to expiration. */
393
+ clock_step(tim_calculate_step(count / 2, ps));
394
+ tim_write_tcsr(td, IE | MODE_ONESHOT | PRESCALE(ps));
395
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
396
+
397
+ /* Counter should not advance during the following step. */
398
+ clock_step(2 * tim_calculate_step(count, ps));
399
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
400
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
401
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
402
+
403
+ /* Resume the timer and run _almost_ to expiration. */
404
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
405
+ clock_step(tim_calculate_step(count / 2, ps) - 1);
406
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
407
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
408
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
409
+
410
+ /* Now, run the rest of the way and verify that the interrupt fires. */
411
+ clock_step(1);
412
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
413
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
414
+}
415
+
416
+/* Verifies that the prescaler can be changed while the timer is runnin. */
417
+static void test_prescaler_change(gconstpointer test_data)
418
+{
419
+ const TestData *td = test_data;
420
+ unsigned int count = 256;
421
+ unsigned int ps = 5;
422
+
423
+ tim_reset(td);
424
+
425
+ tim_write_ticr(td, count);
426
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
427
+
428
+ /* Run a quarter of the way, and change the prescaler. */
429
+ clock_step(tim_calculate_step(count / 4, ps));
430
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
431
+ ps = 2;
432
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
433
+ /* The counter must not change. */
434
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
435
+
436
+ /* Run another quarter of the way, and change the prescaler again. */
437
+ clock_step(tim_calculate_step(count / 4, ps));
438
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
439
+ ps = 8;
440
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
441
+ /* The counter must not change. */
442
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
443
+
444
+ /* Run another quarter of the way, and change the prescaler again. */
445
+ clock_step(tim_calculate_step(count / 4, ps));
446
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
447
+ ps = 0;
448
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
449
+ /* The counter must not change. */
450
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
451
+
452
+ /* Run almost to expiration, and verify the timer didn't fire yet. */
453
+ clock_step(tim_calculate_step(count / 4, ps) - 1);
454
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
455
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
456
+
457
+ /* Now, run the rest of the way and verify that the timer fires. */
458
+ clock_step(1);
459
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
460
+}
461
+
462
+/* Verifies that a periodic timer automatically restarts after expiration. */
463
+static void test_periodic_no_interrupt(gconstpointer test_data)
464
+{
465
+ const TestData *td = test_data;
466
+ unsigned int count = 2;
467
+ unsigned int ps = 3;
468
+ int i;
469
+
470
+ tim_reset(td);
471
+
472
+ tim_write_ticr(td, count);
473
+ tim_write_tcsr(td, CEN | MODE_PERIODIC | PRESCALE(ps));
474
+
475
+ for (i = 0; i < 4; i++) {
476
+ clock_step_next();
477
+
478
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
479
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
480
+
481
+ tim_write(td, TISR, tim_timer_bit(td));
482
+
483
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
484
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
485
+ }
486
+}
487
+
488
+/* Verifies that a periodict timer fires an interrupt every time it expires. */
489
+static void test_periodic_interrupt(gconstpointer test_data)
490
+{
491
+ const TestData *td = test_data;
492
+ unsigned int count = 65535;
493
+ unsigned int ps = 2;
494
+ int i;
495
+
496
+ tim_reset(td);
497
+
498
+ tim_write_ticr(td, count);
499
+ tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps));
500
+
501
+ for (i = 0; i < 4; i++) {
502
+ clock_step_next();
503
+
504
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
505
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
506
+
507
+ tim_write(td, TISR, tim_timer_bit(td));
508
+
509
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
510
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
511
+ }
512
+}
513
+
514
+/*
515
+ * Verifies that the timer behaves correctly when disabled right before and
516
+ * exactly when it's supposed to expire.
517
+ */
518
+static void test_disable_on_expiration(gconstpointer test_data)
519
+{
520
+ const TestData *td = test_data;
521
+ unsigned int count = 8;
522
+ unsigned int ps = 255;
523
+
524
+ tim_reset(td);
525
+
526
+ tim_write_ticr(td, count);
527
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
528
+
529
+ clock_step(tim_calculate_step(count, ps) - 1);
530
+
531
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
532
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
533
+ clock_step(1);
534
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
535
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
536
+}
537
+
538
+/*
539
+ * Constructs a name that includes the timer block, timer and testcase name,
540
+ * and adds the test to the test suite.
541
+ */
542
+static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
543
+{
544
+ g_autofree char *full_name;
545
+
546
+ full_name = g_strdup_printf("npcm7xx_timer/tim[%d]/timer[%d]/%s",
547
+ tim_index(td->tim), timer_index(td->timer),
548
+ name);
549
+ qtest_add_data_func(full_name, td, fn);
550
+}
551
+
552
+/* Convenience macro for adding a test with a predictable function name. */
553
+#define add_test(name, td) tim_add_test(#name, td, test_##name)
554
+
555
+int main(int argc, char **argv)
556
+{
557
+ TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)];
558
+ int ret;
559
+ int i, j;
560
+
561
+ g_test_init(&argc, &argv, NULL);
562
+ g_test_set_nonfatal_assertions();
563
+
564
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
565
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
566
+ TestData *td = &testdata[i * ARRAY_SIZE(timer) + j];
567
+ td->tim = &timer_block[i];
568
+ td->timer = &timer[j];
569
+
570
+ add_test(reset, td);
571
+ add_test(reset_overrides_enable, td);
572
+ add_test(oneshot_enable_then_disable, td);
573
+ add_test(oneshot_ps5, td);
574
+ add_test(oneshot_ps0, td);
575
+ add_test(oneshot_ps255, td);
576
+ add_test(oneshot_interrupt, td);
577
+ add_test(pause_resume, td);
578
+ add_test(prescaler_change, td);
579
+ add_test(periodic_no_interrupt, td);
580
+ add_test(periodic_interrupt, td);
581
+ add_test(disable_on_expiration, td);
582
+ }
188
+ }
583
+ }
189
+ }
584
+
190
+
585
+ qtest_start("-machine npcm750-evb");
191
+#if defined(TARGET_ARM)
586
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
192
+
587
+ ret = g_test_run();
193
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
588
+ qtest_end();
194
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
589
+
195
*/
590
+ return ret;
196
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
591
+}
197
}
592
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
198
#elif defined(TARGET_MIPS)
593
index XXXXXXX..XXXXXXX 100644
199
if (snan_bit_is_one(status)) {
594
--- a/tests/qtest/meson.build
200
- /*
595
+++ b/tests/qtest/meson.build
201
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
596
@@ -XXX,XX +XXX,XX @@ qtests_arm = \
202
- * case sets InvalidOp and returns the default NaN
597
['arm-cpu-features',
203
- */
598
'microbit-test',
204
- if (infzero) {
599
'm25p80-test',
205
- return 3;
600
+ 'npcm7xx_timer-test',
206
- }
601
'test-arm-mptimer',
207
/* Prefer sNaN over qNaN, in the a, b, c order. */
602
'boot-serial-test',
208
if (is_snan(a_cls)) {
603
'hexloader-test']
209
return 0;
210
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
211
return 2;
212
}
213
} else {
214
- /*
215
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
216
- * case sets InvalidOp and returns the input value 'c'
217
- */
218
/* Prefer sNaN over qNaN, in the c, a, b order. */
219
if (is_snan(c_cls)) {
220
return 2;
221
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
222
}
223
}
224
#elif defined(TARGET_LOONGARCH64)
225
- /*
226
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
227
- * case sets InvalidOp and returns the input value 'c'
228
- */
229
-
230
/* Prefer sNaN over qNaN, in the c, a, b order. */
231
if (is_snan(c_cls)) {
232
return 2;
233
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
234
return 1;
235
}
236
#elif defined(TARGET_PPC)
237
- /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
238
- * to return an input NaN if we have one (ie c) rather than generating
239
- * a default NaN
240
- */
241
-
242
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
243
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
244
*/
245
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
246
return 1;
247
}
248
#elif defined(TARGET_S390X)
249
- if (infzero) {
250
- return 3;
251
- }
252
-
253
if (is_snan(a_cls)) {
254
return 0;
255
} else if (is_snan(b_cls)) {
604
--
256
--
605
2.20.1
257
2.34.1
606
607
diff view generated by jsdifflib
1
The BLX immediate insn in the Thumb encoding always performs
1
Explicitly set a rule in the softfloat tests for the inf-zero-nan
2
a switch from Thumb to Arm state. This would be totally useless
2
muladd special case. In meson.build we put -DTARGET_ARM in fpcflags,
3
in M-profile which has no Arm decoder, and so the instruction
3
and so we should select here the Arm rule of
4
does not exist at all there. Make the encoding UNDEF for M-profile.
4
float_infzeronan_dnan_if_qnan.
5
6
(This part of the encoding space is used for the branch-future
7
and low-overhead-loop insns in v8.1M.)
8
5
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20201019151301.2046-6-peter.maydell@linaro.org
8
Message-id: 20241202131347.498124-5-peter.maydell@linaro.org
12
---
9
---
13
target/arm/translate.c | 8 ++++++++
10
tests/fp/fp-bench.c | 5 +++++
14
1 file changed, 8 insertions(+)
11
tests/fp/fp-test.c | 5 +++++
12
2 files changed, 10 insertions(+)
15
13
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
16
--- a/tests/fp/fp-bench.c
19
+++ b/target/arm/translate.c
17
+++ b/tests/fp/fp-bench.c
20
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
18
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
21
{
19
{
22
TCGv_i32 tmp;
20
bench_func_t f;
23
21
24
+ /*
22
+ /*
25
+ * BLX <imm> would be useless on M-profile; the encoding space
23
+ * These implementation-defined choices for various things IEEE
26
+ * is used for other insns from v8.1M onward, and UNDEFs before that.
24
+ * doesn't specify match those used by the Arm architecture.
27
+ */
25
+ */
28
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
29
+ return false;
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
30
+ }
28
31
+
29
f = bench_funcs[operation][precision];
32
/* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
30
g_assert(f);
33
if (s->thumb && (a->imm & 2)) {
31
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
34
return false;
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;
35
--
48
--
36
2.20.1
49
2.34.1
37
38
diff view generated by jsdifflib
1
If the M-profile low-overhead-branch extension is implemented, FPSCR
1
Set the FloatInfZeroNaNRule explicitly for the Arm target,
2
bits [18:16] are a new field LTPSIZE. If MVE is not implemented
2
so we can remove the ifdef from pickNaNMulAdd().
3
(currently always true for us) then this field always reads as 4 and
4
ignores writes.
5
6
These bits used to be the vector-length field for the old
7
short-vector extension, so we need to take care that they are not
8
misinterpreted as setting vec_len. We do this with a rearrangement
9
of the vfp_set_fpscr() code that deals with vec_len, vec_stride
10
and also the QC bit; this obviates the need for the M-profile
11
only masking step that we used to have at the start of the function.
12
13
We provide a new field in CPUState for LTPSIZE, even though this
14
will always be 4, in preparation for MVE, so we don't have to
15
come back later and split it out of the vfp.xregs[FPSCR] value.
16
(This state struct field will be saved and restored as part of
17
the FPSCR value via the vmstate_fpscr in machine.c.)
18
3
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20201019151301.2046-11-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-6-peter.maydell@linaro.org
22
---
7
---
23
target/arm/cpu.h | 1 +
8
target/arm/cpu.c | 3 +++
24
target/arm/cpu.c | 9 +++++++++
9
fpu/softfloat-specialize.c.inc | 8 +-------
25
target/arm/vfp_helper.c | 6 ++++++
10
2 files changed, 4 insertions(+), 7 deletions(-)
26
3 files changed, 16 insertions(+)
27
11
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
31
+++ b/target/arm/cpu.h
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
33
uint32_t fpdscr[M_REG_NUM_BANKS];
34
uint32_t cpacr[M_REG_NUM_BANKS];
35
uint32_t nsacr;
36
+ int ltpsize;
37
} v7m;
38
39
/* Information associated with an exception about to be taken:
40
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
41
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/cpu.c
14
--- a/target/arm/cpu.c
43
+++ b/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
44
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
45
uint8_t *rom;
17
* * tininess-before-rounding
46
uint32_t vecbase;
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
47
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
48
+ if (cpu_isar_feature(aa32_lob, cpu)) {
20
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
49
+ /*
21
+ * and the input NaN if it is signalling
50
+ * LTPSIZE is constant 4 if MVE not implemented, and resets
22
*/
51
+ * to an UNKNOWN value if MVE is implemented. We choose to
23
static void arm_set_default_fp_behaviours(float_status *s)
52
+ * always reset to 4.
24
{
53
+ */
25
set_float_detect_tininess(float_tininess_before_rounding, s);
54
+ env->v7m.ltpsize = 4;
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
55
+ }
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
56
+
28
}
57
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
29
58
env->v7m.secure = true;
30
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
59
} else {
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
60
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
61
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/vfp_helper.c
33
--- a/fpu/softfloat-specialize.c.inc
63
+++ b/target/arm/vfp_helper.c
34
+++ b/fpu/softfloat-specialize.c.inc
64
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
65
| (env->vfp.vec_len << 16)
36
/*
66
| (env->vfp.vec_stride << 20);
37
* Temporarily fall back to ifdef ladder
67
38
*/
68
+ /*
39
-#if defined(TARGET_ARM)
69
+ * M-profile LTPSIZE overlaps A-profile Stride; whichever of the
40
- /*
70
+ * two is not applicable to this CPU will always be zero.
41
- * For ARM, the (inf,zero,qnan) case returns the default NaN,
71
+ */
42
- * but (inf,zero,snan) returns the input NaN.
72
+ fpscr |= env->v7m.ltpsize << 16;
43
- */
73
+
44
- rule = float_infzeronan_dnan_if_qnan;
74
fpscr |= vfp_get_fpscr_from_host(env);
45
-#elif defined(TARGET_MIPS)
75
46
+#if defined(TARGET_MIPS)
76
i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
47
if (snan_bit_is_one(status)) {
48
/*
49
* For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
77
--
50
--
78
2.20.1
51
2.34.1
79
80
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Set the FloatInfZeroNaNRule explicitly for s390, so we
2
can remove the ifdef from pickNaNMulAdd().
2
3
3
The reporting in AArch64.TagCheckFail only depends on PSTATE.EL,
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
and not the AccType of the operation. There are two guest
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
visible problems that affect LDTR and STTR because of this:
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(-)
6
11
7
(1) Selecting TCF0 vs TCF1 to decide on reporting,
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
8
(2) Report "data abort same el" not "data abort lower el".
9
10
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
13
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Message-id: 20201008162155.161886-3-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/mte_helper.c | 10 +++-------
18
1 file changed, 3 insertions(+), 7 deletions(-)
19
20
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/mte_helper.c
14
--- a/target/s390x/cpu.c
23
+++ b/target/arm/mte_helper.c
15
+++ b/target/s390x/cpu.c
24
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
25
reg_el = regime_el(env, arm_mmu_idx);
17
set_float_detect_tininess(float_tininess_before_rounding,
26
sctlr = env->cp15.sctlr_el[reg_el];
18
&env->fpu_status);
27
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
28
- switch (arm_mmu_idx) {
20
+ set_float_infzeronan_rule(float_infzeronan_dnan_always,
29
- case ARMMMUIdx_E10_0:
21
+ &env->fpu_status);
30
- case ARMMMUIdx_E20_0:
22
/* fall through */
31
- el = 0;
23
case RESET_TYPE_S390_CPU_NORMAL:
32
+ el = arm_current_el(env);
24
env->psw.mask &= ~PSW_MASK_RI;
33
+ if (el == 0) {
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
34
tcf = extract64(sctlr, 38, 2);
26
index XXXXXXX..XXXXXXX 100644
35
- break;
27
--- a/fpu/softfloat-specialize.c.inc
36
- default:
28
+++ b/fpu/softfloat-specialize.c.inc
37
- el = reg_el;
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
38
+ } else {
30
* a default NaN
39
tcf = extract64(sctlr, 40, 2);
31
*/
32
rule = float_infzeronan_dnan_never;
33
-#elif defined(TARGET_S390X)
34
- rule = float_infzeronan_dnan_always;
35
#endif
40
}
36
}
41
37
42
--
38
--
43
2.20.1
39
2.34.1
44
45
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the PPC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-8-peter.maydell@linaro.org
7
---
8
target/ppc/cpu_init.c | 7 +++++++
9
fpu/softfloat-specialize.c.inc | 7 +------
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
15
+++ b/target/ppc/cpu_init.c
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
21
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
22
+ * to return an input NaN if we have one (ie c) rather than generating
23
+ * a default NaN
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
27
28
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
29
ppc_spr_t *spr = &env->spr_cb[i];
30
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
index XXXXXXX..XXXXXXX 100644
32
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
*/
36
rule = float_infzeronan_dnan_never;
37
}
38
-#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
39
+#elif defined(TARGET_SPARC) || \
40
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
41
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
42
/*
43
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
44
* case sets InvalidOp and returns the input value 'c'
45
*/
46
- /*
47
- * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
48
- * to return an input NaN if we have one (ie c) rather than generating
49
- * a default NaN
50
- */
51
rule = float_infzeronan_dnan_never;
52
#endif
53
}
54
--
55
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the MIPS target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-9-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 9 +++++++++
9
target/mips/msa.c | 4 ++++
10
fpu/softfloat-specialize.c.inc | 16 +---------------
11
3 files changed, 14 insertions(+), 15 deletions(-)
12
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_flush_mode(CPUMIPSState *env)
18
static inline void restore_snan_bit_mode(CPUMIPSState *env)
19
{
20
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
21
+ FloatInfZeroNaNRule izn_rule;
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
set_snan_bit_is_one(!nan2008, &env->active_fpu.fp_status);
28
set_default_nan_mode(!nan2008, &env->active_fpu.fp_status);
29
+ /*
30
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
31
+ * case sets InvalidOp and returns the default NaN.
32
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
33
+ * case sets InvalidOp and returns the input value 'c'.
34
+ */
35
+ izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
36
+ set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
37
}
38
39
static inline void restore_fp_status(CPUMIPSState *env)
40
diff --git a/target/mips/msa.c b/target/mips/msa.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/mips/msa.c
43
+++ b/target/mips/msa.c
44
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
45
46
/* set proper signanling bit meaning ("1" means "quiet") */
47
set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
48
+
49
+ /* Inf * 0 + NaN returns the input NaN */
50
+ set_float_infzeronan_rule(float_infzeronan_dnan_never,
51
+ &env->active_tc.msa_fp_status);
52
}
53
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
54
index XXXXXXX..XXXXXXX 100644
55
--- a/fpu/softfloat-specialize.c.inc
56
+++ b/fpu/softfloat-specialize.c.inc
57
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
58
/*
59
* Temporarily fall back to ifdef ladder
60
*/
61
-#if defined(TARGET_MIPS)
62
- if (snan_bit_is_one(status)) {
63
- /*
64
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
65
- * case sets InvalidOp and returns the default NaN
66
- */
67
- rule = float_infzeronan_dnan_always;
68
- } else {
69
- /*
70
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
71
- * case sets InvalidOp and returns the input value 'c'
72
- */
73
- rule = float_infzeronan_dnan_never;
74
- }
75
-#elif defined(TARGET_SPARC) || \
76
+#if defined(TARGET_SPARC) || \
77
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
78
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
79
/*
80
--
81
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the SPARC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-10-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 +--
10
2 files changed, 3 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
23
cpu_exec_realizefn(cs, &local_err);
24
if (local_err != NULL) {
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_SPARC) || \
34
- defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
35
+#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
36
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
37
/*
38
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the xtensa target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-11-peter.maydell@linaro.org
7
---
8
target/xtensa/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 +-
10
2 files changed, 3 insertions(+), 1 deletion(-)
11
12
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/xtensa/cpu.c
15
+++ b/target/xtensa/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
17
reset_mmu(env);
18
cs->halted = env->runstall;
19
#endif
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
set_no_signaling_nans(!dfpu, &env->fp_status);
23
xtensa_use_first_nan(env, !dfpu);
24
}
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
34
+#if defined(TARGET_HPPA) || \
35
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
36
/*
37
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the x86 target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-12-peter.maydell@linaro.org
6
---
7
target/i386/tcg/fpu_helper.c | 7 +++++++
8
fpu/softfloat-specialize.c.inc | 2 +-
9
2 files changed, 8 insertions(+), 1 deletion(-)
10
11
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/i386/tcg/fpu_helper.c
14
+++ b/target/i386/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->mmx_status);
18
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->sse_status);
19
+ /*
20
+ * Only SSE has multiply-add instructions. In the SDM Section 14.5.2
21
+ * "Fused-Multiply-ADD (FMA) Numeric Behavior" the NaN handling is
22
+ * specified -- for 0 * inf + NaN the input NaN is selected, and if
23
+ * there are multiple input NaNs they are selected in the order a, b, c.
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
26
}
27
28
static inline uint8_t save_exception_flags(CPUX86State *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
34
* Temporarily fall back to ifdef ladder
35
*/
36
#if defined(TARGET_HPPA) || \
37
- defined(TARGET_I386) || defined(TARGET_LOONGARCH)
38
+ defined(TARGET_LOONGARCH)
39
/*
40
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
41
* case sets InvalidOp and returns the input value 'c'
42
--
43
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the loongarch target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-13-peter.maydell@linaro.org
6
---
7
target/loongarch/tcg/fpu_helper.c | 5 +++++
8
fpu/softfloat-specialize.c.inc | 7 +------
9
2 files changed, 6 insertions(+), 6 deletions(-)
10
11
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/loongarch/tcg/fpu_helper.c
14
+++ b/target/loongarch/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
16
&env->fp_status);
17
set_flush_to_zero(0, &env->fp_status);
18
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
19
+ /*
20
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
21
+ * case sets InvalidOp and returns the input value 'c'
22
+ */
23
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
}
25
26
int ieee_ex_to_loongarch(int xcpt)
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
index XXXXXXX..XXXXXXX 100644
29
--- a/fpu/softfloat-specialize.c.inc
30
+++ b/fpu/softfloat-specialize.c.inc
31
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
32
/*
33
* Temporarily fall back to ifdef ladder
34
*/
35
-#if defined(TARGET_HPPA) || \
36
- defined(TARGET_LOONGARCH)
37
- /*
38
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
- * case sets InvalidOp and returns the input value 'c'
40
- */
41
+#if defined(TARGET_HPPA)
42
rule = float_infzeronan_dnan_never;
43
#endif
44
}
45
--
46
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the HPPA target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
As this is the last target to be converted to explicitly setting
5
the rule, we can remove the fallback code in pickNaNMulAdd()
6
entirely.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241202131347.498124-14-peter.maydell@linaro.org
11
---
12
target/hppa/fpu_helper.c | 2 ++
13
fpu/softfloat-specialize.c.inc | 13 +------------
14
2 files changed, 3 insertions(+), 12 deletions(-)
15
16
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/hppa/fpu_helper.c
19
+++ b/target/hppa/fpu_helper.c
20
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
21
* HPPA does note implement a CPU reset method at all...
22
*/
23
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
24
+ /* For inf * 0 + NaN, return the input NaN */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
}
27
28
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
34
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
bool infzero, float_status *status)
36
{
37
- FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
38
-
39
/*
40
* We guarantee not to require the target to tell us how to
41
* pick a NaN if we're always returning the default NaN.
42
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
43
*/
44
assert(!status->default_nan_mode);
45
46
- if (rule == float_infzeronan_none) {
47
- /*
48
- * Temporarily fall back to ifdef ladder
49
- */
50
-#if defined(TARGET_HPPA)
51
- rule = float_infzeronan_dnan_never;
52
-#endif
53
- }
54
-
55
if (infzero) {
56
/*
57
* Inf * 0 + NaN -- some implementations return the default NaN here,
58
* and some return the input NaN.
59
*/
60
- switch (rule) {
61
+ switch (status->float_infzeronan_rule) {
62
case float_infzeronan_dnan_never:
63
return 2;
64
case float_infzeronan_dnan_always:
65
--
66
2.34.1
diff view generated by jsdifflib
1
From v8.1M, disabled-coprocessor handling changes slightly:
1
The new implementation of pickNaNMulAdd() will find it convenient
2
* coprocessors 8, 9, 14 and 15 are also governed by the
2
to know whether at least one of the three arguments to the muladd
3
cp10 enable bit, like cp11
3
was a signaling NaN. We already calculate that in the caller,
4
* an extra range of instruction patterns is considered
4
so pass it in as a new bool have_snan.
5
to be inside the coprocessor space
6
7
We previously marked these up with TODO comments; implement the
8
correct behaviour.
9
10
Unfortunately there is no ID register field which indicates this
11
behaviour. We could in theory test an unrelated ID register which
12
indicates guaranteed-to-be-in-v8.1M behaviour like ID_ISAR0.CmpBranch
13
>= 3 (low-overhead-loops), but it seems better to simply define a new
14
ARM_FEATURE_V8_1M feature flag and use it for this and other
15
new-in-v8.1M behaviour that isn't identifiable from the ID registers.
16
5
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20201019151301.2046-3-peter.maydell@linaro.org
8
Message-id: 20241202131347.498124-15-peter.maydell@linaro.org
20
---
9
---
21
target/arm/cpu.h | 1 +
10
fpu/softfloat-parts.c.inc | 5 +++--
22
target/arm/m-nocp.decode | 10 ++++++----
11
fpu/softfloat-specialize.c.inc | 2 +-
23
target/arm/translate-vfp.c.inc | 17 +++++++++++++++--
12
2 files changed, 4 insertions(+), 3 deletions(-)
24
3 files changed, 22 insertions(+), 6 deletions(-)
25
13
26
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
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.h
16
--- a/fpu/softfloat-parts.c.inc
29
+++ b/target/arm/cpu.h
17
+++ b/fpu/softfloat-parts.c.inc
30
@@ -XXX,XX +XXX,XX @@ enum arm_features {
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
31
ARM_FEATURE_VBAR, /* has cp15 VBAR */
19
{
32
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
20
int which;
33
ARM_FEATURE_M_MAIN, /* M profile Main Extension */
21
bool infzero = (ab_mask == float_cmask_infzero);
34
+ ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
22
+ bool have_snan = (abc_mask & float_cmask_snan);
35
};
23
36
24
- if (unlikely(abc_mask & float_cmask_snan)) {
37
static inline int arm_feature(CPUARMState *env, int feature)
25
+ if (unlikely(have_snan)) {
38
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
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
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/m-nocp.decode
40
--- a/fpu/softfloat-specialize.c.inc
41
+++ b/target/arm/m-nocp.decode
41
+++ b/fpu/softfloat-specialize.c.inc
42
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
43
# If the coprocessor is not present or disabled then we will generate
43
| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
44
# the NOCP exception; otherwise we let the insn through to the main decode.
44
*----------------------------------------------------------------------------*/
45
45
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
46
+&nocp cp
46
- bool infzero, float_status *status)
47
+
47
+ bool infzero, bool have_snan, float_status *status)
48
{
49
# Special cases which do not take an early NOCP: VLLDM and VLSTM
50
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
51
# TODO: VSCCLRM (new in v8.1M) is similar:
52
#VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
53
54
- NOCP 111- 1110 ---- ---- ---- cp:4 ---- ----
55
- NOCP 111- 110- ---- ---- ---- cp:4 ---- ----
56
- # TODO: From v8.1M onwards we will also want this range to NOCP
57
- #NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- cp=10
58
+ NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
59
+ NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
60
+ # From v8.1M onwards this range will also NOCP:
61
+ NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- &nocp cp=10
62
}
63
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate-vfp.c.inc
66
+++ b/target/arm/translate-vfp.c.inc
67
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
68
return true;
69
}
70
71
-static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
72
+static bool trans_NOCP(DisasContext *s, arg_nocp *a)
73
{
48
{
74
/*
49
/*
75
* Handle M-profile early check for disabled coprocessor:
50
* We guarantee not to require the target to tell us how to
76
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
77
if (a->cp == 11) {
78
a->cp = 10;
79
}
80
- /* TODO: in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
81
+ if (arm_dc_feature(s, ARM_FEATURE_V8_1M) &&
82
+ (a->cp == 8 || a->cp == 9 || a->cp == 14 || a->cp == 15)) {
83
+ /* in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
84
+ a->cp = 10;
85
+ }
86
87
if (a->cp != 10) {
88
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
89
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
90
return false;
91
}
92
93
+static bool trans_NOCP_8_1(DisasContext *s, arg_nocp *a)
94
+{
95
+ /* This range needs a coprocessor check for v8.1M and later only */
96
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
97
+ return false;
98
+ }
99
+ return trans_NOCP(s, a);
100
+}
101
+
102
static bool trans_VINS(DisasContext *s, arg_VINS *a)
103
{
104
TCGv_i32 rd, rm;
105
--
51
--
106
2.20.1
52
2.34.1
107
108
diff view generated by jsdifflib
1
v8.1M implements a new 'branch future' feature, which is a
1
IEEE 758 does not define a fixed rule for which NaN to pick as the
2
set of instructions that request the CPU to perform a branch
2
result if both operands of a 3-operand fused multiply-add operation
3
"in the future", when it reaches a particular execution address.
3
are NaNs. As a result different architectures have ended up with
4
In hardware, the expected implementation is that the information
4
different rules for propagating NaNs.
5
about the branch location and destination is cached and then
5
6
acted upon when execution reaches the specified address.
6
QEMU currently hardcodes the NaN propagation logic into the binary
7
However the architecture permits an implementation to discard
7
because pickNaNMulAdd() has an ifdef ladder for different targets.
8
this cached information at any point, and so guest code must
8
We want to make the propagation rule instead be selectable at
9
always include a normal branch insn at the branch point as
9
runtime, because:
10
a fallback. In particular, an implementation is specifically
10
* this will let us have multiple targets in one QEMU binary
11
permitted to treat all BF insns as NOPs (which is equivalent
11
* the Arm FEAT_AFP architectural feature includes letting
12
to discarding the cached information immediately).
12
the guest select a NaN propagation rule at runtime
13
13
14
For QEMU, implementing this caching of branch information
14
In this commit we add an enum for the propagation rule, the field in
15
would be complicated and would not improve the speed of
15
float_status, and the corresponding getters and setters. We change
16
execution at all, so we make the IMPDEF choice to implement
16
pickNaNMulAdd to honour this, but because all targets still leave
17
all BF insns as NOPs.
17
this field at its default 0 value, the fallback logic will pick the
18
18
rule type with the old ifdef ladder.
19
20
It's valid not to set a propagation rule if default_nan_mode is
21
enabled, because in that case there's no need to pick a NaN; all the
22
callers of pickNaNMulAdd() catch this case and skip calling it.
23
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Message-id: 20241202131347.498124-16-peter.maydell@linaro.org
21
Message-id: 20201019151301.2046-7-peter.maydell@linaro.org
22
---
27
---
23
target/arm/cpu.h | 6 ++++++
28
include/fpu/softfloat-helpers.h | 11 +++
24
target/arm/t32.decode | 13 ++++++++++++-
29
include/fpu/softfloat-types.h | 55 +++++++++++
25
target/arm/translate.c | 20 ++++++++++++++++++++
30
fpu/softfloat-specialize.c.inc | 167 ++++++++------------------------
26
3 files changed, 38 insertions(+), 1 deletion(-)
31
3 files changed, 107 insertions(+), 126 deletions(-)
27
32
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
33
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
29
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
35
--- a/include/fpu/softfloat-helpers.h
31
+++ b/target/arm/cpu.h
36
+++ b/include/fpu/softfloat-helpers.h
32
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
37
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
33
return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1;
38
status->float_2nan_prop_rule = rule;
34
}
39
}
35
40
36
+static inline bool isar_feature_aa32_lob(const ARMISARegisters *id)
41
+static inline void set_float_3nan_prop_rule(Float3NaNPropRule rule,
42
+ float_status *status)
37
+{
43
+{
38
+ /* (M-profile) low-overhead loops and branch future */
44
+ status->float_3nan_prop_rule = rule;
39
+ return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3;
40
+}
45
+}
41
+
46
+
42
static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
47
static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
float_status *status)
43
{
49
{
44
return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0;
50
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
45
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
51
return status->float_2nan_prop_rule;
52
}
53
54
+static inline Float3NaNPropRule get_float_3nan_prop_rule(float_status *status)
55
+{
56
+ return status->float_3nan_prop_rule;
57
+}
58
+
59
static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
60
{
61
return status->float_infzeronan_rule;
62
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
46
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/t32.decode
64
--- a/include/fpu/softfloat-types.h
48
+++ b/target/arm/t32.decode
65
+++ b/include/fpu/softfloat-types.h
49
@@ -XXX,XX +XXX,XX @@ MRC 1110 1110 ... 1 .... .... .... ... 1 .... @mcr
66
@@ -XXX,XX +XXX,XX @@ this code that are retained.
50
67
#ifndef SOFTFLOAT_TYPES_H
51
B 1111 0. .......... 10.1 ............ @branch24
68
#define SOFTFLOAT_TYPES_H
52
BL 1111 0. .......... 11.1 ............ @branch24
69
53
-BLX_i 1111 0. .......... 11.0 ............ @branch24
70
+#include "hw/registerfields.h"
54
+{
71
+
55
+ # BLX_i is non-M-profile only
72
/*
56
+ BLX_i 1111 0. .......... 11.0 ............ @branch24
73
* Software IEC/IEEE floating-point types.
57
+ # M-profile only: loop and branch insns
74
*/
58
+ [
75
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
59
+ # All these BF insns have boff != 0b0000; we NOP them all
76
float_2nan_prop_x87,
60
+ BF 1111 0 boff:4 ------- 1100 - ---------- 1 # BFL
77
} Float2NaNPropRule;
61
+ BF 1111 0 boff:4 0 ------ 1110 - ---------- 1 # BFCSEL
78
62
+ BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
79
+/*
63
+ BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
80
+ * 3-input NaN propagation rule, for fused multiply-add. Individual
64
+ ]
81
+ * architectures have different rules for which input NaN is
65
+}
82
+ * propagated to the output when there is more than one NaN on the
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
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
67
index XXXXXXX..XXXXXXX 100644
143
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate.c
144
--- a/fpu/softfloat-specialize.c.inc
69
+++ b/target/arm/translate.c
145
+++ b/fpu/softfloat-specialize.c.inc
70
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
146
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
71
return true;
147
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
148
bool infzero, bool have_snan, float_status *status)
149
{
150
+ FloatClass cls[3] = { a_cls, b_cls, c_cls };
151
+ Float3NaNPropRule rule = status->float_3nan_prop_rule;
152
+ int which;
153
+
154
/*
155
* We guarantee not to require the target to tell us how to
156
* pick a NaN if we're always returning the default NaN.
157
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
158
}
159
}
160
161
+ if (rule == float_3nan_prop_none) {
162
#if defined(TARGET_ARM)
163
-
164
- /* This looks different from the ARM ARM pseudocode, because the ARM ARM
165
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
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
183
+ */
184
+ rule = float_3nan_prop_s_cab;
185
#elif defined(TARGET_MIPS)
186
- if (snan_bit_is_one(status)) {
187
- /* Prefer sNaN over qNaN, in the a, b, c order. */
188
- if (is_snan(a_cls)) {
189
- return 0;
190
- } else if (is_snan(b_cls)) {
191
- return 1;
192
- } else if (is_snan(c_cls)) {
193
- return 2;
194
- } else if (is_qnan(a_cls)) {
195
- return 0;
196
- } else if (is_qnan(b_cls)) {
197
- return 1;
198
+ if (snan_bit_is_one(status)) {
199
+ rule = float_3nan_prop_s_abc;
200
} else {
201
- return 2;
202
+ rule = float_3nan_prop_s_cab;
203
}
204
- } else {
205
- /* Prefer sNaN over qNaN, in the c, a, b order. */
206
- if (is_snan(c_cls)) {
207
- return 2;
208
- } else if (is_snan(a_cls)) {
209
- return 0;
210
- } else if (is_snan(b_cls)) {
211
- return 1;
212
- } else if (is_qnan(c_cls)) {
213
- return 2;
214
- } else if (is_qnan(a_cls)) {
215
- return 0;
216
- } else {
217
- return 1;
218
- }
219
- }
220
#elif defined(TARGET_LOONGARCH64)
221
- /* Prefer sNaN over qNaN, in the c, a, b order. */
222
- if (is_snan(c_cls)) {
223
- return 2;
224
- } else if (is_snan(a_cls)) {
225
- return 0;
226
- } else if (is_snan(b_cls)) {
227
- return 1;
228
- } else if (is_qnan(c_cls)) {
229
- return 2;
230
- } else if (is_qnan(a_cls)) {
231
- return 0;
232
- } else {
233
- return 1;
234
- }
235
+ rule = float_3nan_prop_s_cab;
236
#elif defined(TARGET_PPC)
237
- /* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
238
- * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
239
- */
240
- if (is_nan(a_cls)) {
241
- return 0;
242
- } else if (is_nan(c_cls)) {
243
- return 2;
244
- } else {
245
- return 1;
246
- }
247
+ /*
248
+ * If fRA is a NaN return it; otherwise if fRB is a NaN return it;
249
+ * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
250
+ */
251
+ rule = float_3nan_prop_acb;
252
#elif defined(TARGET_S390X)
253
- if (is_snan(a_cls)) {
254
- return 0;
255
- } else if (is_snan(b_cls)) {
256
- return 1;
257
- } else if (is_snan(c_cls)) {
258
- return 2;
259
- } else if (is_qnan(a_cls)) {
260
- return 0;
261
- } else if (is_qnan(b_cls)) {
262
- return 1;
263
- } else {
264
- return 2;
265
- }
266
+ rule = float_3nan_prop_s_abc;
267
#elif defined(TARGET_SPARC)
268
- /* Prefer SNaN over QNaN, order C, B, A. */
269
- if (is_snan(c_cls)) {
270
- return 2;
271
- } else if (is_snan(b_cls)) {
272
- return 1;
273
- } else if (is_snan(a_cls)) {
274
- return 0;
275
- } else if (is_qnan(c_cls)) {
276
- return 2;
277
- } else if (is_qnan(b_cls)) {
278
- return 1;
279
- } else {
280
- return 0;
281
- }
282
+ rule = float_3nan_prop_s_cba;
283
#elif defined(TARGET_XTENSA)
284
- /*
285
- * For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
286
- * an input NaN if we have one (ie c).
287
- */
288
- if (status->use_first_nan) {
289
- if (is_nan(a_cls)) {
290
- return 0;
291
- } else if (is_nan(b_cls)) {
292
- return 1;
293
+ if (status->use_first_nan) {
294
+ rule = float_3nan_prop_abc;
295
} else {
296
- return 2;
297
+ rule = float_3nan_prop_cba;
298
}
299
- } else {
300
- if (is_nan(c_cls)) {
301
- return 2;
302
- } else if (is_nan(b_cls)) {
303
- return 1;
304
- } else {
305
- return 0;
306
- }
307
- }
308
#else
309
- /* A default implementation: prefer a to b to c.
310
- * This is unlikely to actually match any real implementation.
311
- */
312
- if (is_nan(a_cls)) {
313
- return 0;
314
- } else if (is_nan(b_cls)) {
315
- return 1;
316
- } else {
317
- return 2;
318
- }
319
+ rule = float_3nan_prop_abc;
320
#endif
321
+ }
322
+
323
+ assert(rule != float_3nan_prop_none);
324
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
325
+ /* We have at least one SNaN input and should prefer it */
326
+ do {
327
+ which = rule & R_3NAN_1ST_MASK;
328
+ rule >>= R_3NAN_1ST_LENGTH;
329
+ } while (!is_snan(cls[which]));
330
+ } else {
331
+ do {
332
+ which = rule & R_3NAN_1ST_MASK;
333
+ rule >>= R_3NAN_1ST_LENGTH;
334
+ } while (!is_nan(cls[which]));
335
+ }
336
+ return which;
72
}
337
}
73
338
74
+static bool trans_BF(DisasContext *s, arg_BF *a)
339
/*----------------------------------------------------------------------------
75
+{
76
+ /*
77
+ * M-profile branch future insns. The architecture permits an
78
+ * implementation to implement these as NOPs (equivalent to
79
+ * discarding the LO_BRANCH_INFO cache immediately), and we
80
+ * take that IMPDEF option because for QEMU a "real" implementation
81
+ * would be complicated and wouldn't execute any faster.
82
+ */
83
+ if (!dc_isar_feature(aa32_lob, s)) {
84
+ return false;
85
+ }
86
+ if (a->boff == 0) {
87
+ /* SEE "Related encodings" (loop insns) */
88
+ return false;
89
+ }
90
+ /* Handle as NOP */
91
+ return true;
92
+}
93
+
94
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
95
{
96
TCGv_i32 addr, tmp;
97
--
340
--
98
2.20.1
341
2.34.1
99
100
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
1
In arm_cpu_realizefn(), if the CPU has VFP or Neon disabled then we
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
squash the ID register fields so that we don't advertise it to the
2
ifdef from pickNaNMulAdd().
3
guest. This code was written for A-profile and needs some tweaks to
4
work correctly on M-profile:
5
3
6
* A-profile only fields should not be zeroed on M-profile:
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
- MVFR0.FPSHVEC,FPTRAP
8
- MVFR1.SIMDLS,SIMDINT,SIMDSP,SIMDHP
9
- MVFR2.SIMDMISC
10
* M-profile only fields should be zeroed on M-profile:
11
- MVFR1.FP16
12
13
In particular, because MVFR1.SIMDHP on A-profile is the same field as
14
MVFR1.FP16 on M-profile this code was incorrectly disabling FP16
15
support on an M-profile CPU (where has_neon is always false). This
16
isn't a visible bug yet because we don't have any M-profile CPUs with
17
FP16 support, but the change is necessary before we introduce any.
18
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 20241202131347.498124-18-peter.maydell@linaro.org
21
Message-id: 20201019151301.2046-9-peter.maydell@linaro.org
22
---
7
---
23
target/arm/cpu.c | 29 ++++++++++++++++++-----------
8
target/arm/cpu.c | 5 +++++
24
1 file changed, 18 insertions(+), 11 deletions(-)
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 6 insertions(+), 7 deletions(-)
25
11
26
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
27
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.c
14
--- a/target/arm/cpu.c
29
+++ b/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
30
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
31
u = cpu->isar.mvfr0;
17
* * tininess-before-rounding
32
u = FIELD_DP32(u, MVFR0, FPSP, 0);
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
33
u = FIELD_DP32(u, MVFR0, FPDP, 0);
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
34
- u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
20
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
35
u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0);
21
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
36
u = FIELD_DP32(u, MVFR0, FPSQRT, 0);
22
+ * but note that for QEMU muladd is a * b + c, whereas for
37
- u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
23
+ * the pseudocode function the arguments are in the order c, a, b.
38
u = FIELD_DP32(u, MVFR0, FPROUND, 0);
24
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
25
* and the input NaN if it is signalling
40
+ u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
26
*/
41
+ u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
27
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
42
+ }
28
{
43
cpu->isar.mvfr0 = u;
29
set_float_detect_tininess(float_tininess_before_rounding, s);
44
30
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
45
u = cpu->isar.mvfr1;
31
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
46
u = FIELD_DP32(u, MVFR1, FPFTZ, 0);
32
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
47
u = FIELD_DP32(u, MVFR1, FPDNAN, 0);
33
}
48
u = FIELD_DP32(u, MVFR1, FPHP, 0);
34
49
+ if (arm_feature(env, ARM_FEATURE_M)) {
35
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
50
+ u = FIELD_DP32(u, MVFR1, FP16, 0);
36
index XXXXXXX..XXXXXXX 100644
51
+ }
37
--- a/fpu/softfloat-specialize.c.inc
52
cpu->isar.mvfr1 = u;
38
+++ b/fpu/softfloat-specialize.c.inc
53
39
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
54
u = cpu->isar.mvfr2;
55
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
56
u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
57
cpu->isar.id_isar6 = u;
58
59
- u = cpu->isar.mvfr1;
60
- u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
61
- u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
62
- u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
63
- u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
64
- cpu->isar.mvfr1 = u;
65
+ if (!arm_feature(env, ARM_FEATURE_M)) {
66
+ u = cpu->isar.mvfr1;
67
+ u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
68
+ u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
69
+ u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
70
+ u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
71
+ cpu->isar.mvfr1 = u;
72
73
- u = cpu->isar.mvfr2;
74
- u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
75
- cpu->isar.mvfr2 = u;
76
+ u = cpu->isar.mvfr2;
77
+ u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
78
+ cpu->isar.mvfr2 = u;
79
+ }
80
}
40
}
81
41
82
if (!cpu->has_neon && !cpu->has_vfp) {
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 {
83
--
54
--
84
2.20.1
55
2.34.1
85
86
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for loongarch, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-19-peter.maydell@linaro.org
7
---
8
target/loongarch/tcg/fpu_helper.c | 1 +
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 1 insertion(+), 2 deletions(-)
11
12
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/loongarch/tcg/fpu_helper.c
15
+++ b/target/loongarch/tcg/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
17
* case sets InvalidOp and returns the input value 'c'
18
*/
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
21
}
22
23
int ieee_ex_to_loongarch(int xcpt)
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
29
} else {
30
rule = float_3nan_prop_s_cab;
31
}
32
-#elif defined(TARGET_LOONGARCH64)
33
- rule = float_3nan_prop_s_cab;
34
#elif defined(TARGET_PPC)
35
/*
36
* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for PPC, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-20-peter.maydell@linaro.org
7
---
8
target/ppc/cpu_init.c | 8 ++++++++
9
fpu/softfloat-specialize.c.inc | 6 ------
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
15
+++ b/target/ppc/cpu_init.c
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
21
+ * NaN propagation for fused multiply-add:
22
+ * if fRA is a NaN return it; otherwise if fRB is a NaN return it;
23
+ * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
24
+ * whereas QEMU labels the operands as (a * b) + c.
25
+ */
26
+ set_float_3nan_prop_rule(float_3nan_prop_acb, &env->fp_status);
27
+ set_float_3nan_prop_rule(float_3nan_prop_acb, &env->vec_status);
28
/*
29
* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
30
* to return an input NaN if we have one (ie c) rather than generating
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
} else {
37
rule = float_3nan_prop_s_cab;
38
}
39
-#elif defined(TARGET_PPC)
40
- /*
41
- * If fRA is a NaN return it; otherwise if fRB is a NaN return it;
42
- * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
43
- */
44
- rule = float_3nan_prop_acb;
45
#elif defined(TARGET_S390X)
46
rule = float_3nan_prop_s_abc;
47
#elif defined(TARGET_SPARC)
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for s390x, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-21-peter.maydell@linaro.org
7
---
8
target/s390x/cpu.c | 1 +
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 1 insertion(+), 2 deletions(-)
11
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/s390x/cpu.c
15
+++ b/target/s390x/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
17
set_float_detect_tininess(float_tininess_before_rounding,
18
&env->fpu_status);
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
20
+ set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
21
set_float_infzeronan_rule(float_infzeronan_dnan_always,
22
&env->fpu_status);
23
/* fall through */
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
29
} else {
30
rule = float_3nan_prop_s_cab;
31
}
32
-#elif defined(TARGET_S390X)
33
- rule = float_3nan_prop_s_abc;
34
#elif defined(TARGET_SPARC)
35
rule = float_3nan_prop_s_cba;
36
#elif defined(TARGET_XTENSA)
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for SPARC, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-22-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For fused-multiply add, prefer SNaN over QNaN, then C->B->A */
21
+ set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
22
/* For inf * 0 + NaN, return the input NaN */
23
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
} else {
31
rule = float_3nan_prop_s_cab;
32
}
33
-#elif defined(TARGET_SPARC)
34
- rule = float_3nan_prop_s_cba;
35
#elif defined(TARGET_XTENSA)
36
if (status->use_first_nan) {
37
rule = float_3nan_prop_abc;
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-23-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 4 ++++
9
target/mips/msa.c | 3 +++
10
fpu/softfloat-specialize.c.inc | 8 +-------
11
3 files changed, 8 insertions(+), 7 deletions(-)
12
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
18
{
19
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
20
FloatInfZeroNaNRule izn_rule;
21
+ Float3NaNPropRule nan3_rule;
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
28
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
29
+ nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
30
+ set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
31
+
32
}
33
34
static inline void restore_fp_status(CPUMIPSState *env)
35
diff --git a/target/mips/msa.c b/target/mips/msa.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/mips/msa.c
38
+++ b/target/mips/msa.c
39
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
40
set_float_2nan_prop_rule(float_2nan_prop_s_ab,
41
&env->active_tc.msa_fp_status);
42
43
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab,
44
+ &env->active_tc.msa_fp_status);
45
+
46
/* clear float_status exception flags */
47
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
48
49
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
50
index XXXXXXX..XXXXXXX 100644
51
--- a/fpu/softfloat-specialize.c.inc
52
+++ b/fpu/softfloat-specialize.c.inc
53
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
54
}
55
56
if (rule == float_3nan_prop_none) {
57
-#if defined(TARGET_MIPS)
58
- if (snan_bit_is_one(status)) {
59
- rule = float_3nan_prop_s_abc;
60
- } else {
61
- rule = float_3nan_prop_s_cab;
62
- }
63
-#elif defined(TARGET_XTENSA)
64
+#if defined(TARGET_XTENSA)
65
if (status->use_first_nan) {
66
rule = float_3nan_prop_abc;
67
} else {
68
--
69
2.34.1
diff view generated by jsdifflib
1
M-profile CPUs with half-precision floating point support should
1
Set the Float3NaNPropRule explicitly for xtensa, and remove the
2
be able to write to FPSCR.FZ16, but an M-profile specific masking
2
ifdef from pickNaNMulAdd().
3
of the value at the top of vfp_set_fpscr() currently prevents that.
4
This is not yet an active bug because we have no M-profile
5
FP16 CPUs, but needs to be fixed before we can add any.
6
7
The bits that the masking is effectively preventing from being
8
set are the A-profile only short-vector Len and Stride fields,
9
plus the Neon QC bit. Rearrange the order of the function so
10
that those fields are handled earlier and only under a suitable
11
guard; this allows us to drop the M-profile specific masking,
12
making FZ16 writeable.
13
14
This change also makes the QC bit correctly RAZ/WI for older
15
no-Neon A-profile cores.
16
17
This refactoring also paves the way for the low-overhead-branch
18
LTPSIZE field, which uses some of the bits that are used for
19
A-profile Stride and Len.
20
3
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20201019151301.2046-10-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-24-peter.maydell@linaro.org
24
---
7
---
25
target/arm/vfp_helper.c | 47 ++++++++++++++++++++++++-----------------
8
target/xtensa/fpu_helper.c | 2 ++
26
1 file changed, 28 insertions(+), 19 deletions(-)
9
fpu/softfloat-specialize.c.inc | 8 --------
10
2 files changed, 2 insertions(+), 8 deletions(-)
27
11
28
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
12
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
29
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/vfp_helper.c
14
--- a/target/xtensa/fpu_helper.c
31
+++ b/target/arm/vfp_helper.c
15
+++ b/target/xtensa/fpu_helper.c
32
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
16
@@ -XXX,XX +XXX,XX @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
33
val &= ~FPCR_FZ16;
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,
34
}
30
}
35
31
36
- if (arm_feature(env, ARM_FEATURE_M)) {
32
if (rule == float_3nan_prop_none) {
37
+ vfp_set_fpscr_to_host(env, val);
33
-#if defined(TARGET_XTENSA)
38
+
34
- if (status->use_first_nan) {
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
35
- rule = float_3nan_prop_abc;
40
/*
36
- } else {
41
- * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
37
- rule = float_3nan_prop_cba;
42
- * and also for the trapped-exception-handling bits IxE.
38
- }
43
+ * Short-vector length and stride; on M-profile these bits
39
-#else
44
+ * are used for different purposes.
40
rule = float_3nan_prop_abc;
45
+ * We can't make this conditional be "if MVFR0.FPShVec != 0",
41
-#endif
46
+ * because in v7A no-short-vector-support cores still had to
47
+ * allow Stride/Len to be written with the only effect that
48
+ * some insns are required to UNDEF if the guest sets them.
49
+ *
50
+ * TODO: if M-profile MVE implemented, set LTPSIZE.
51
*/
52
- val &= 0xf7c0009f;
53
+ env->vfp.vec_len = extract32(val, 16, 3);
54
+ env->vfp.vec_stride = extract32(val, 20, 2);
55
}
42
}
56
43
57
- vfp_set_fpscr_to_host(env, val);
44
assert(rule != float_3nan_prop_none);
58
+ if (arm_feature(env, ARM_FEATURE_NEON)) {
59
+ /*
60
+ * The bit we set within fpscr_q is arbitrary; the register as a
61
+ * whole being zero/non-zero is what counts.
62
+ * TODO: M-profile MVE also has a QC bit.
63
+ */
64
+ env->vfp.qc[0] = val & FPCR_QC;
65
+ env->vfp.qc[1] = 0;
66
+ env->vfp.qc[2] = 0;
67
+ env->vfp.qc[3] = 0;
68
+ }
69
70
/*
71
* We don't implement trapped exception handling, so the
72
* trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
73
*
74
- * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
75
- * (which are stored in fp_status), and the other RES0 bits
76
- * in between, then we clear all of the low 16 bits.
77
+ * The exception flags IOC|DZC|OFC|UFC|IXC|IDC are stored in
78
+ * fp_status; QC, Len and Stride are stored separately earlier.
79
+ * Clear out all of those and the RES0 bits: only NZCV, AHP, DN,
80
+ * FZ, RMode and FZ16 are kept in vfp.xregs[FPSCR].
81
*/
82
env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
83
- env->vfp.vec_len = (val >> 16) & 7;
84
- env->vfp.vec_stride = (val >> 20) & 3;
85
-
86
- /*
87
- * The bit we set within fpscr_q is arbitrary; the register as a
88
- * whole being zero/non-zero is what counts.
89
- */
90
- env->vfp.qc[0] = val & FPCR_QC;
91
- env->vfp.qc[1] = 0;
92
- env->vfp.qc[2] = 0;
93
- env->vfp.qc[3] = 0;
94
}
95
96
void vfp_set_fpscr(CPUARMState *env, uint32_t val)
97
--
45
--
98
2.20.1
46
2.34.1
99
100
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Set the Float3NaNPropRule explicitly for i386. We had no
2
i386-specific behaviour in the old ifdef ladder, so we were using the
3
default "prefer a then b then c" fallback; this is actually the
4
correct per-the-spec handling for i386.
2
5
3
Commit 7998beb9c2e removed the ram_size initialization in the
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
arm_boot_info structure, however it is used by arm_load_kernel().
5
6
Initialize the field to fix:
7
8
$ qemu-system-arm -M n800 -append 'console=ttyS1' \
9
-kernel meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0
10
qemu-system-arm: kernel 'meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0' is too large to fit in RAM (kernel size 1964608, RAM size 0)
11
12
Noticed while running the test introduced in commit 050a82f0c5b
13
("tests/acceptance: Add a test for the N800 and N810 arm machines").
14
15
Fixes: 7998beb9c2e ("arm/nseries: use memdev for RAM")
16
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Tested-by: Thomas Huth <thuth@redhat.com>
8
Message-id: 20241202131347.498124-25-peter.maydell@linaro.org
19
Message-id: 20201019095148.1602119-1-f4bug@amsat.org
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
9
---
22
hw/arm/nseries.c | 1 +
10
target/i386/tcg/fpu_helper.c | 1 +
23
1 file changed, 1 insertion(+)
11
1 file changed, 1 insertion(+)
24
12
25
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
13
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
26
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/nseries.c
15
--- a/target/i386/tcg/fpu_helper.c
28
+++ b/hw/arm/nseries.c
16
+++ b/target/i386/tcg/fpu_helper.c
29
@@ -XXX,XX +XXX,XX @@ static void n8x0_init(MachineState *machine,
17
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
30
g_free(sz);
18
* there are multiple input NaNs they are selected in the order a, b, c.
31
exit(EXIT_FAILURE);
19
*/
32
}
20
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
33
+ binfo->ram_size = machine->ram_size;
21
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
34
22
}
35
memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE,
23
36
machine->ram);
24
static inline uint8_t save_exception_flags(CPUX86State *env)
37
--
25
--
38
2.20.1
26
2.34.1
39
40
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Set the Float3NaNPropRule explicitly for HPPA, and remove the
2
ifdef from pickNaNMulAdd().
2
3
3
Fix an unlikely memory leak in load_elf_image().
4
HPPA is the only target that was using the default branch of the
5
ifdef ladder (other targets either do not use muladd or set
6
default_nan_mode), so we can remove the ifdef fallback entirely now
7
(allowing the "rule not set" case to fall into the default of the
8
switch statement and assert).
4
9
5
Fixes: bf858897b7 ("linux-user: Re-use load_elf_image for the main binary.")
10
We add a TODO note that the HPPA rule is probably wrong; this is
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
not a behavioural change for this refactoring.
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
8
Message-id: 20201016184207.786698-5-richard.henderson@linaro.org
9
Message-Id: <20201003174944.1972444-1-f4bug@amsat.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20241202131347.498124-26-peter.maydell@linaro.org
13
---
16
---
14
linux-user/elfload.c | 8 ++++----
17
target/hppa/fpu_helper.c | 8 ++++++++
15
1 file changed, 4 insertions(+), 4 deletions(-)
18
fpu/softfloat-specialize.c.inc | 4 ----
19
2 files changed, 8 insertions(+), 4 deletions(-)
16
20
17
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
21
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
18
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
19
--- a/linux-user/elfload.c
23
--- a/target/hppa/fpu_helper.c
20
+++ b/linux-user/elfload.c
24
+++ b/target/hppa/fpu_helper.c
21
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
25
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
22
info->brk = vaddr_em;
26
* HPPA does note implement a CPU reset method at all...
23
}
27
*/
24
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
28
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
25
- char *interp_name;
29
+ /*
26
+ g_autofree char *interp_name = NULL;
30
+ * TODO: The HPPA architecture reference only documents its NaN
27
31
+ * propagation rule for 2-operand operations. Testing on real hardware
28
if (*pinterp_name) {
32
+ * might be necessary to confirm whether this order for muladd is correct.
29
errmsg = "Multiple PT_INTERP entries";
33
+ * Not preferring the SNaN is almost certainly incorrect as it diverges
30
goto exit_errmsg;
34
+ * from the documented rules for 2-operand operations.
31
}
35
+ */
32
- interp_name = malloc(eppnt->p_filesz);
36
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
33
+ interp_name = g_malloc(eppnt->p_filesz);
37
/* For inf * 0 + NaN, return the input NaN */
34
if (!interp_name) {
38
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
35
goto exit_perror;
39
}
36
}
40
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
37
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
41
index XXXXXXX..XXXXXXX 100644
38
errmsg = "Invalid PT_INTERP entry";
42
--- a/fpu/softfloat-specialize.c.inc
39
goto exit_errmsg;
43
+++ b/fpu/softfloat-specialize.c.inc
40
}
44
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
41
- *pinterp_name = interp_name;
45
}
42
+ *pinterp_name = g_steal_pointer(&interp_name);
43
#ifdef TARGET_MIPS
44
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
45
Mips_elf_abiflags_v0 abiflags;
46
@@ -XXX,XX +XXX,XX @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
47
if (elf_interpreter) {
48
info->load_bias = interp_info.load_bias;
49
info->entry = interp_info.entry;
50
- free(elf_interpreter);
51
+ g_free(elf_interpreter);
52
}
46
}
53
47
54
#ifdef USE_ELF_CORE_DUMP
48
- if (rule == float_3nan_prop_none) {
49
- rule = float_3nan_prop_abc;
50
- }
51
-
52
assert(rule != float_3nan_prop_none);
53
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
54
/* We have at least one SNaN input and should prefer it */
55
--
55
--
56
2.20.1
56
2.34.1
57
58
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
1
From: Richard Henderson <richard.henderson@linaro.org>
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.
2
4
3
Transform the prot bit to a qemu internal page bit, and save
5
floatx80 is used only by:
4
it in the page tables.
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)
5
13
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
The floatx80 default NaN as currently implemented is:
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
m68k: sign = 0, exp = 1...1, int = 1, frac = 1....1
8
Message-id: 20201016184207.786698-3-richard.henderson@linaro.org
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
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
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
10
---
40
---
11
include/exec/cpu-all.h | 2 ++
41
fpu/softfloat-specialize.c.inc | 20 ++++++++++----------
12
linux-user/syscall_defs.h | 4 ++++
42
1 file changed, 10 insertions(+), 10 deletions(-)
13
target/arm/cpu.h | 5 +++++
14
linux-user/mmap.c | 16 ++++++++++++++++
15
target/arm/translate-a64.c | 6 +++---
16
5 files changed, 30 insertions(+), 3 deletions(-)
17
43
18
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
44
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
19
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
20
--- a/include/exec/cpu-all.h
46
--- a/fpu/softfloat-specialize.c.inc
21
+++ b/include/exec/cpu-all.h
47
+++ b/fpu/softfloat-specialize.c.inc
22
@@ -XXX,XX +XXX,XX @@ extern intptr_t qemu_host_page_mask;
48
@@ -XXX,XX +XXX,XX @@ static void parts128_silence_nan(FloatParts128 *p, float_status *status)
23
/* FIXME: Code that sets/uses this is broken and needs to go away. */
49
floatx80 floatx80_default_nan(float_status *status)
24
#define PAGE_RESERVED 0x0020
50
{
25
#endif
51
floatx80 r;
26
+/* Target-specific bits that will be used via page_get_flags(). */
27
+#define PAGE_TARGET_1 0x0080
28
29
#if defined(CONFIG_USER_ONLY)
30
void page_dump(FILE *f);
31
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/linux-user/syscall_defs.h
34
+++ b/linux-user/syscall_defs.h
35
@@ -XXX,XX +XXX,XX @@ struct target_winsize {
36
#define TARGET_PROT_SEM 0x08
37
#endif
38
39
+#ifdef TARGET_AARCH64
40
+#define TARGET_PROT_BTI 0x10
41
+#endif
42
+
43
/* Common */
44
#define TARGET_MAP_SHARED    0x01        /* Share changes */
45
#define TARGET_MAP_PRIVATE    0x02        /* Changes are private */
46
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu.h
49
+++ b/target/arm/cpu.h
50
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
51
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
52
#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
53
54
+/*
55
+ * AArch64 usage of the PAGE_TARGET_* bits for linux-user.
56
+ */
57
+#define PAGE_BTI PAGE_TARGET_1
58
+
59
/*
60
* Naming convention for isar_feature functions:
61
* Functions which test 32-bit ID registers should have _aa32_ in
62
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/linux-user/mmap.c
65
+++ b/linux-user/mmap.c
66
@@ -XXX,XX +XXX,XX @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
67
*host_prot = (prot & (PROT_READ | PROT_WRITE))
68
| (prot & PROT_EXEC ? PROT_READ : 0);
69
70
+#ifdef TARGET_AARCH64
71
+ /*
52
+ /*
72
+ * The PROT_BTI bit is only accepted if the cpu supports the feature.
53
+ * Extrapolate from the choices made by parts64_default_nan to fill
73
+ * Since this is the unusual case, don't bother checking unless
54
+ * in the floatx80 format. We assume that floatx80's explicit
74
+ * the bit has been requested. If set and valid, record the bit
55
+ * integer bit is always set (this is true for i386 and m68k,
75
+ * within QEMU's page_flags.
56
+ * which are the only real users of this format).
76
+ */
57
+ */
77
+ if (prot & TARGET_PROT_BTI) {
58
+ FloatParts64 p64;
78
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
59
+ parts64_default_nan(&p64, status);
79
+ if (cpu_isar_feature(aa64_bti, cpu)) {
60
80
+ valid |= TARGET_PROT_BTI;
61
- /* None of the targets that have snan_bit_is_one use floatx80. */
81
+ page_flags |= PAGE_BTI;
62
- assert(!snan_bit_is_one(status));
82
+ }
63
-#if defined(TARGET_M68K)
83
+ }
64
- r.low = UINT64_C(0xFFFFFFFFFFFFFFFF);
84
+#endif
65
- r.high = 0x7FFF;
85
+
66
-#else
86
return prot & ~valid ? 0 : page_flags;
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;
87
}
74
}
88
75
89
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/translate-a64.c
92
+++ b/target/arm/translate-a64.c
93
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
94
*/
95
static bool is_guarded_page(CPUARMState *env, DisasContext *s)
96
{
97
-#ifdef CONFIG_USER_ONLY
98
- return false; /* FIXME */
99
-#else
100
uint64_t addr = s->base.pc_first;
101
+#ifdef CONFIG_USER_ONLY
102
+ return page_get_flags(addr) & PAGE_BTI;
103
+#else
104
int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
105
unsigned int index = tlb_index(env, mmu_idx, addr);
106
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
107
--
76
--
108
2.20.1
77
2.34.1
109
110
diff view generated by jsdifflib
New patch
1
In target/loongarch's helper_fclass_s() and helper_fclass_d() we pass
2
a zero-initialized float_status struct to float32_is_quiet_nan() and
3
float64_is_quiet_nan(), with the cryptic comment "for
4
snan_bit_is_one".
1
5
6
This pattern appears to have been copied from target/riscv, where it
7
is used because the functions there do not have ready access to the
8
CPU state struct. The comment presumably refers to the fact that the
9
main reason the is_quiet_nan() functions want the float_state is
10
because they want to know about the snan_bit_is_one config.
11
12
In the loongarch helpers, though, we have the CPU state struct
13
to hand. Use the usual env->fp_status here. This avoids our needing
14
to track that we need to update the initializer of the local
15
float_status structs when the core softfloat code adds new
16
options for targets to configure their behaviour.
17
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20241202131347.498124-30-peter.maydell@linaro.org
21
---
22
target/loongarch/tcg/fpu_helper.c | 6 ++----
23
1 file changed, 2 insertions(+), 4 deletions(-)
24
25
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/loongarch/tcg/fpu_helper.c
28
+++ b/target/loongarch/tcg/fpu_helper.c
29
@@ -XXX,XX +XXX,XX @@ uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj)
30
} else if (float32_is_zero_or_denormal(f)) {
31
return sign ? 1 << 4 : 1 << 8;
32
} else if (float32_is_any_nan(f)) {
33
- float_status s = { }; /* for snan_bit_is_one */
34
- return float32_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
35
+ return float32_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0;
36
} else {
37
return sign ? 1 << 3 : 1 << 7;
38
}
39
@@ -XXX,XX +XXX,XX @@ uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj)
40
} else if (float64_is_zero_or_denormal(f)) {
41
return sign ? 1 << 4 : 1 << 8;
42
} else if (float64_is_any_nan(f)) {
43
- float_status s = { }; /* for snan_bit_is_one */
44
- return float64_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
45
+ return float64_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0;
46
} else {
47
return sign ? 1 << 3 : 1 << 7;
48
}
49
--
50
2.34.1
diff view generated by jsdifflib
New patch
1
In the frem helper, we have a local float_status because we want to
2
execute the floatx80_div() with a custom rounding mode. Instead of
3
zero-initializing the local float_status and then having to set it up
4
with the m68k standard behaviour (including the NaN propagation rule
5
and copying the rounding precision from env->fp_status), initialize
6
it as a complete copy of env->fp_status. This will avoid our having
7
to add new code in this function for every new config knob we add
8
to fp_status.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-31-peter.maydell@linaro.org
13
---
14
target/m68k/fpu_helper.c | 6 ++----
15
1 file changed, 2 insertions(+), 4 deletions(-)
16
17
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/m68k/fpu_helper.c
20
+++ b/target/m68k/fpu_helper.c
21
@@ -XXX,XX +XXX,XX @@ void HELPER(frem)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
22
23
fp_rem = floatx80_rem(val1->d, val0->d, &env->fp_status);
24
if (!floatx80_is_any_nan(fp_rem)) {
25
- float_status fp_status = { };
26
+ /* Use local temporary fp_status to set different rounding mode */
27
+ float_status fp_status = env->fp_status;
28
uint32_t quotient;
29
int sign;
30
31
/* Calculate quotient directly using round to nearest mode */
32
- set_float_2nan_prop_rule(float_2nan_prop_ab, &fp_status);
33
set_float_rounding_mode(float_round_nearest_even, &fp_status);
34
- set_floatx80_rounding_precision(
35
- get_floatx80_rounding_precision(&env->fp_status), &fp_status);
36
fp_quot.d = floatx80_div(val1->d, val0->d, &fp_status);
37
38
sign = extractFloatx80Sign(fp_quot.d);
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
In cf_fpu_gdb_get_reg() and cf_fpu_gdb_set_reg() we do the conversion
2
from float64 to floatx80 using a scratch float_status, because we
3
don't want the conversion to affect the CPU's floating point exception
4
status. Currently we use a zero-initialized float_status. This will
5
get steadily more awkward as we add config knobs to float_status
6
that the target must initialize. Avoid having to add any of that
7
configuration here by instead initializing our local float_status
8
from the env->fp_status.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-32-peter.maydell@linaro.org
13
---
14
target/m68k/helper.c | 6 ++++--
15
1 file changed, 4 insertions(+), 2 deletions(-)
16
17
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/m68k/helper.c
20
+++ b/target/m68k/helper.c
21
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_get_reg(CPUState *cs, GByteArray *mem_buf, int n)
22
CPUM68KState *env = &cpu->env;
23
24
if (n < 8) {
25
- float_status s = {};
26
+ /* Use scratch float_status so any exceptions don't change CPU state */
27
+ float_status s = env->fp_status;
28
return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
29
}
30
switch (n) {
31
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n)
32
CPUM68KState *env = &cpu->env;
33
34
if (n < 8) {
35
- float_status s = {};
36
+ /* Use scratch float_status so any exceptions don't change CPU state */
37
+ float_status s = env->fp_status;
38
env->fregs[n].d = float64_to_floatx80(ldq_be_p(mem_buf), &s);
39
return 8;
40
}
41
--
42
2.34.1
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
In the helper functions flcmps and flcmpd we use a scratch float_status
2
so that we don't change the CPU state if the comparison raises any
3
floating point exception flags. Instead of zero-initializing this
4
scratch float_status, initialize it as a copy of env->fp_status. This
5
avoids the need to explicitly initialize settings like the NaN
6
propagation rule or others we might add to softfloat in future.
2
7
3
The IRQ values are defined few lines earlier, use them instead of
8
To do this we need to pass the CPU env pointer in to the helper.
4
the magic numbers.
5
9
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201017180731.1165871-3-f4bug@amsat.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-33-peter.maydell@linaro.org
10
---
13
---
11
hw/intc/bcm2836_control.c | 8 ++++----
14
target/sparc/helper.h | 4 ++--
12
1 file changed, 4 insertions(+), 4 deletions(-)
15
target/sparc/fop_helper.c | 8 ++++----
16
target/sparc/translate.c | 4 ++--
17
3 files changed, 8 insertions(+), 8 deletions(-)
13
18
14
diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c
19
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2836_control.c
21
--- a/target/sparc/helper.h
17
+++ b/hw/intc/bcm2836_control.c
22
+++ b/target/sparc/helper.h
18
@@ -XXX,XX +XXX,XX @@ static void bcm2836_control_set_local_irq(void *opaque, int core, int local_irq,
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
19
24
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
20
static void bcm2836_control_set_local_irq0(void *opaque, int core, int level)
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());
40
}
41
42
-uint32_t helper_flcmps(float32 src1, float32 src2)
43
+uint32_t helper_flcmps(CPUSPARCState *env, float32 src1, float32 src2)
21
{
44
{
22
- bcm2836_control_set_local_irq(opaque, core, 0, level);
45
/*
23
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPSIRQ, level);
46
* FLCMP never raises an exception nor modifies any FSR fields.
47
* Perform the comparison with a dummy fp environment.
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();
24
}
56
}
25
57
26
static void bcm2836_control_set_local_irq1(void *opaque, int core, int level)
58
-uint32_t helper_flcmpd(float64 src1, float64 src2)
59
+uint32_t helper_flcmpd(CPUSPARCState *env, float64 src1, float64 src2)
27
{
60
{
28
- bcm2836_control_set_local_irq(opaque, core, 1, level);
61
- float_status discard = { };
29
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPNSIRQ, level);
62
+ float_status discard = env->fp_status;
63
FloatRelation r;
64
65
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
66
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/sparc/translate.c
69
+++ b/target/sparc/translate.c
70
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a)
71
72
src1 = gen_load_fpr_F(dc, a->rs1);
73
src2 = gen_load_fpr_F(dc, a->rs2);
74
- gen_helper_flcmps(cpu_fcc[a->cc], src1, src2);
75
+ gen_helper_flcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
76
return advance_pc(dc);
30
}
77
}
31
78
32
static void bcm2836_control_set_local_irq2(void *opaque, int core, int level)
79
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
33
{
80
34
- bcm2836_control_set_local_irq(opaque, core, 2, level);
81
src1 = gen_load_fpr_D(dc, a->rs1);
35
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTHPIRQ, level);
82
src2 = gen_load_fpr_D(dc, a->rs2);
83
- gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
84
+ gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
85
return advance_pc(dc);
36
}
86
}
37
87
38
static void bcm2836_control_set_local_irq3(void *opaque, int core, int level)
39
{
40
- bcm2836_control_set_local_irq(opaque, core, 3, level);
41
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTVIRQ, level);
42
}
43
44
static void bcm2836_control_set_gpu_irq(void *opaque, int irq, int level)
45
--
88
--
46
2.20.1
89
2.34.1
47
48
diff view generated by jsdifflib
New patch
1
In the helper_compute_fprf functions, we pass a dummy float_status
2
in to the is_signaling_nan() function. This is unnecessary, because
3
we have convenient access to the CPU env pointer here and that
4
is already set up with the correct values for the snan_bit_is_one
5
and no_signaling_nans config settings. is_signaling_nan() doesn't
6
ever update the fp_status with any exception flags, so there is
7
no reason not to use env->fp_status here.
1
8
9
Use env->fp_status instead of the dummy fp_status.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20241202131347.498124-34-peter.maydell@linaro.org
14
---
15
target/ppc/fpu_helper.c | 3 +--
16
1 file changed, 1 insertion(+), 2 deletions(-)
17
18
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/ppc/fpu_helper.c
21
+++ b/target/ppc/fpu_helper.c
22
@@ -XXX,XX +XXX,XX @@ void helper_compute_fprf_##tp(CPUPPCState *env, tp arg) \
23
} else if (tp##_is_infinity(arg)) { \
24
fprf = neg ? 0x09 << FPSCR_FPRF : 0x05 << FPSCR_FPRF; \
25
} else { \
26
- float_status dummy = { }; /* snan_bit_is_one = 0 */ \
27
- if (tp##_is_signaling_nan(arg, &dummy)) { \
28
+ if (tp##_is_signaling_nan(arg, &env->fp_status)) { \
29
fprf = 0x00 << FPSCR_FPRF; \
30
} else { \
31
fprf = 0x11 << FPSCR_FPRF; \
32
--
33
2.34.1
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This is a bit clearer than open-coding some of this
3
Now that float_status has a bunch of fp parameters,
4
with a bare c string.
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.
5
8
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20201016184207.786698-9-richard.henderson@linaro.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20241203203949.483774-2-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
14
---
11
linux-user/elfload.c | 37 ++++++++++++++++++++-----------------
15
target/arm/tcg/vec_helper.c | 20 +++++++-------------
12
1 file changed, 20 insertions(+), 17 deletions(-)
16
1 file changed, 7 insertions(+), 13 deletions(-)
13
17
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
18
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
20
--- a/target/arm/tcg/vec_helper.c
17
+++ b/linux-user/elfload.c
21
+++ b/target/arm/tcg/vec_helper.c
18
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp)
19
#include "qemu/guest-random.h"
23
* no effect on AArch32 instructions.
20
#include "qemu/units.h"
24
*/
21
#include "qemu/selfmap.h"
25
bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF;
22
+#include "qapi/error.h"
26
- *statusp = (float_status){
23
27
- .tininess_before_rounding = float_tininess_before_rounding,
24
#ifdef _ARCH_PPC64
28
- .float_rounding_mode = float_round_to_odd_inf,
25
#undef ARCH_DLINFO
29
- .flush_to_zero = true,
26
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
30
- .flush_inputs_to_zero = true,
27
struct elf_phdr *phdr;
31
- .default_nan_mode = true,
28
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
32
- };
29
int i, retval;
33
+
30
- const char *errmsg;
34
+ *statusp = env->vfp.fp_status;
31
+ Error *err = NULL;
35
+ set_default_nan_mode(true, statusp);
32
36
33
/* First of all, some simple consistency checks */
37
if (ebf) {
34
- errmsg = "Invalid ELF image for this architecture";
38
- float_status *fpst = &env->vfp.fp_status;
35
if (!elf_check_ident(ehdr)) {
39
- set_flush_to_zero(get_flush_to_zero(fpst), statusp);
36
+ error_setg(&err, "Invalid ELF image for this architecture");
40
- set_flush_inputs_to_zero(get_flush_inputs_to_zero(fpst), statusp);
37
goto exit_errmsg;
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);
38
}
50
}
39
bswap_ehdr(ehdr);
51
-
40
if (!elf_check_ehdr(ehdr)) {
52
return ebf;
41
+ error_setg(&err, "Invalid ELF image for this architecture");
42
goto exit_errmsg;
43
}
44
45
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
46
g_autofree char *interp_name = NULL;
47
48
if (*pinterp_name) {
49
- errmsg = "Multiple PT_INTERP entries";
50
+ error_setg(&err, "Multiple PT_INTERP entries");
51
goto exit_errmsg;
52
}
53
+
54
interp_name = g_malloc(eppnt->p_filesz);
55
- if (!interp_name) {
56
- goto exit_perror;
57
- }
58
59
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
60
memcpy(interp_name, bprm_buf + eppnt->p_offset,
61
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
62
retval = pread(image_fd, interp_name, eppnt->p_filesz,
63
eppnt->p_offset);
64
if (retval != eppnt->p_filesz) {
65
- goto exit_perror;
66
+ goto exit_read;
67
}
68
}
69
if (interp_name[eppnt->p_filesz - 1] != 0) {
70
- errmsg = "Invalid PT_INTERP entry";
71
+ error_setg(&err, "Invalid PT_INTERP entry");
72
goto exit_errmsg;
73
}
74
*pinterp_name = g_steal_pointer(&interp_name);
75
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
76
(ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
77
-1, 0);
78
if (load_addr == -1) {
79
- goto exit_perror;
80
+ goto exit_mmap;
81
}
82
load_bias = load_addr - loaddr;
83
84
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
85
image_fd, eppnt->p_offset - vaddr_po);
86
87
if (error == -1) {
88
- goto exit_perror;
89
+ goto exit_mmap;
90
}
91
}
92
93
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
94
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
95
Mips_elf_abiflags_v0 abiflags;
96
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
97
- errmsg = "Invalid PT_MIPS_ABIFLAGS entry";
98
+ error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
99
goto exit_errmsg;
100
}
101
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
102
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
103
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
104
eppnt->p_offset);
105
if (retval != sizeof(Mips_elf_abiflags_v0)) {
106
- goto exit_perror;
107
+ goto exit_read;
108
}
109
}
110
bswap_mips_abiflags(&abiflags);
111
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
112
113
exit_read:
114
if (retval >= 0) {
115
- errmsg = "Incomplete read of file header";
116
- goto exit_errmsg;
117
+ error_setg(&err, "Incomplete read of file header");
118
+ } else {
119
+ error_setg_errno(&err, errno, "Error reading file header");
120
}
121
- exit_perror:
122
- errmsg = strerror(errno);
123
+ goto exit_errmsg;
124
+ exit_mmap:
125
+ error_setg_errno(&err, errno, "Error mapping file");
126
+ goto exit_errmsg;
127
exit_errmsg:
128
- fprintf(stderr, "%s: %s\n", image_name, errmsg);
129
+ error_reportf_err(err, "%s: ", image_name);
130
exit(-1);
131
}
53
}
132
54
133
--
55
--
134
2.20.1
56
2.34.1
135
57
136
58
diff view generated by jsdifflib
1
v8.1M's "low-overhead-loop" extension has three instructions
1
Currently we hardcode the default NaN value in parts64_default_nan()
2
for looping:
2
using a compile-time ifdef ladder. This is awkward for two cases:
3
* DLS (start of a do-loop)
3
* for single-QEMU-binary we can't hard-code target-specifics like this
4
* WLS (start of a while-loop)
4
* for Arm FEAT_AFP the default NaN value depends on FPCR.AH
5
* LE (end of a loop)
5
(specifically the sign bit is different)
6
6
7
The loop-start instructions are both simple operations to start a
7
Add a field to float_status to specify the default NaN value; fall
8
loop whose iteration count (if any) is in LR. The loop-end
8
back to the old ifdef behaviour if these are not set.
9
instruction handles "decrement iteration count and jump back to loop
10
start"; it also caches the information about the branch back to the
11
start of the loop to improve performance of the branch on subsequent
12
iterations.
13
9
14
As with the branch-future instructions, the architecture permits an
10
The default NaN value is specified by setting a uint8_t to a
15
implementation to discard the LO_BRANCH_INFO cache at any time, and
11
pattern corresponding to the sign and upper fraction parts of
16
QEMU takes the IMPDEF option to never set it in the first place
12
the NaN; the lower bits of the fraction are set from bit 0 of
17
(equivalent to discarding it immediately), because for us a "real"
13
the pattern.
18
implementation would be unnecessary complexity.
19
20
(This implementation only provides the simple looping constructs; the
21
vector extension MVE (Helium) adds some extra variants to handle
22
looping across vectors. We'll add those later when we implement
23
MVE.)
24
14
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20201019151301.2046-8-peter.maydell@linaro.org
17
Message-id: 20241202131347.498124-35-peter.maydell@linaro.org
28
---
18
---
29
target/arm/t32.decode | 8 ++++
19
include/fpu/softfloat-helpers.h | 11 +++++++
30
target/arm/translate.c | 93 +++++++++++++++++++++++++++++++++++++++++-
20
include/fpu/softfloat-types.h | 10 ++++++
31
2 files changed, 99 insertions(+), 2 deletions(-)
21
fpu/softfloat-specialize.c.inc | 55 ++++++++++++++++++++-------------
22
3 files changed, 54 insertions(+), 22 deletions(-)
32
23
33
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
24
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
34
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/t32.decode
26
--- a/include/fpu/softfloat-helpers.h
36
+++ b/target/arm/t32.decode
27
+++ b/include/fpu/softfloat-helpers.h
37
@@ -XXX,XX +XXX,XX @@ BL 1111 0. .......... 11.1 ............ @branch24
28
@@ -XXX,XX +XXX,XX @@ static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
38
BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
29
status->float_infzeronan_rule = rule;
39
BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
40
]
41
+ [
42
+ # LE and WLS immediate
43
+ %lob_imm 1:10 11:1 !function=times_2
44
+
45
+ DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001
46
+ WLS 1111 0 0000 100 rn:4 1100 . .......... 1 imm=%lob_imm
47
+ LE 1111 0 0000 0 f:1 0 1111 1100 . .......... 1 imm=%lob_imm
48
+ ]
49
}
30
}
50
diff --git a/target/arm/translate.c b/target/arm/translate.c
31
51
index XXXXXXX..XXXXXXX 100644
32
+static inline void set_float_default_nan_pattern(uint8_t dnan_pattern,
52
--- a/target/arm/translate.c
33
+ float_status *status)
53
+++ b/target/arm/translate.c
54
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
55
s->base.is_jmp = DISAS_NORETURN;
56
}
57
58
-static inline void gen_jmp (DisasContext *s, uint32_t dest)
59
+/* Jump, specifying which TB number to use if we gen_goto_tb() */
60
+static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
61
{
62
if (unlikely(is_singlestepping(s))) {
63
/* An indirect jump so that we still trigger the debug exception. */
64
gen_set_pc_im(s, dest);
65
s->base.is_jmp = DISAS_JUMP;
66
} else {
67
- gen_goto_tb(s, 0, dest);
68
+ gen_goto_tb(s, tbno, dest);
69
}
70
}
71
72
+static inline void gen_jmp(DisasContext *s, uint32_t dest)
73
+{
34
+{
74
+ gen_jmp_tb(s, dest, 0);
35
+ status->default_nan_pattern = dnan_pattern;
75
+}
36
+}
76
+
37
+
77
static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
38
static inline void set_flush_to_zero(bool val, float_status *status)
78
{
39
{
79
if (x)
40
status->flush_to_zero = val;
80
@@ -XXX,XX +XXX,XX @@ static bool trans_BF(DisasContext *s, arg_BF *a)
41
@@ -XXX,XX +XXX,XX @@ static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status
81
return true;
42
return status->float_infzeronan_rule;
82
}
43
}
83
44
84
+static bool trans_DLS(DisasContext *s, arg_DLS *a)
45
+static inline uint8_t get_float_default_nan_pattern(float_status *status)
85
+{
46
+{
86
+ /* M-profile low-overhead loop start */
47
+ return status->default_nan_pattern;
87
+ TCGv_i32 tmp;
88
+
89
+ if (!dc_isar_feature(aa32_lob, s)) {
90
+ return false;
91
+ }
92
+ if (a->rn == 13 || a->rn == 15) {
93
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
94
+ return false;
95
+ }
96
+
97
+ /* Not a while loop, no tail predication: just set LR to the count */
98
+ tmp = load_reg(s, a->rn);
99
+ store_reg(s, 14, tmp);
100
+ return true;
101
+}
48
+}
102
+
49
+
103
+static bool trans_WLS(DisasContext *s, arg_WLS *a)
50
static inline bool get_flush_to_zero(float_status *status)
104
+{
51
{
105
+ /* M-profile low-overhead while-loop start */
52
return status->flush_to_zero;
106
+ TCGv_i32 tmp;
53
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
107
+ TCGLabel *nextlabel;
54
index XXXXXXX..XXXXXXX 100644
55
--- a/include/fpu/softfloat-types.h
56
+++ b/include/fpu/softfloat-types.h
57
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
58
/* should denormalised inputs go to zero and set the input_denormal flag? */
59
bool flush_inputs_to_zero;
60
bool default_nan_mode;
61
+ /*
62
+ * The pattern to use for the default NaN. Here the high bit specifies
63
+ * the default NaN's sign bit, and bits 6..0 specify the high bits of the
64
+ * fractional part. The low bits of the fractional part are copies of bit 0.
65
+ * The exponent of the default NaN is (as for any NaN) always all 1s.
66
+ * Note that a value of 0 here is not a valid NaN. The target must set
67
+ * this to the correct non-zero value, or we will assert when trying to
68
+ * create a default NaN.
69
+ */
70
+ uint8_t default_nan_pattern;
71
/*
72
* The flags below are not used on all specializations and may
73
* constant fold away (see snan_bit_is_one()/no_signalling_nans() in
74
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
75
index XXXXXXX..XXXXXXX 100644
76
--- a/fpu/softfloat-specialize.c.inc
77
+++ b/fpu/softfloat-specialize.c.inc
78
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
79
{
80
bool sign = 0;
81
uint64_t frac;
82
+ uint8_t dnan_pattern = status->default_nan_pattern;
83
84
+ if (dnan_pattern == 0) {
85
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
86
- /* !snan_bit_is_one, set all bits */
87
- frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
88
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
89
+ /* Sign bit clear, all frac bits set */
90
+ dnan_pattern = 0b01111111;
91
+#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
92
|| defined(TARGET_MICROBLAZE)
93
- /* !snan_bit_is_one, set sign and msb */
94
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
95
- sign = 1;
96
+ /* Sign bit set, most significant frac bit set */
97
+ dnan_pattern = 0b11000000;
98
#elif defined(TARGET_HPPA)
99
- /* snan_bit_is_one, set msb-1. */
100
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
101
+ /* Sign bit clear, msb-1 frac bit set */
102
+ dnan_pattern = 0b00100000;
103
#elif defined(TARGET_HEXAGON)
104
- sign = 1;
105
- frac = ~0ULL;
106
+ /* Sign bit set, all frac bits set. */
107
+ dnan_pattern = 0b11111111;
108
#else
109
- /*
110
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
111
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
112
- * do not have floating-point.
113
- */
114
- if (snan_bit_is_one(status)) {
115
- /* set all bits other than msb */
116
- frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1;
117
- } else {
118
- /* set msb */
119
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
120
- }
121
+ /*
122
+ * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
123
+ * S390, SH4, TriCore, and Xtensa. Our other supported targets
124
+ * do not have floating-point.
125
+ */
126
+ if (snan_bit_is_one(status)) {
127
+ /* sign bit clear, set all frac bits other than msb */
128
+ dnan_pattern = 0b00111111;
129
+ } else {
130
+ /* sign bit clear, set frac msb */
131
+ dnan_pattern = 0b01000000;
132
+ }
133
#endif
134
+ }
135
+ assert(dnan_pattern != 0);
108
+
136
+
109
+ if (!dc_isar_feature(aa32_lob, s)) {
137
+ sign = dnan_pattern >> 7;
110
+ return false;
111
+ }
112
+ if (a->rn == 13 || a->rn == 15) {
113
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
114
+ return false;
115
+ }
116
+ if (s->condexec_mask) {
117
+ /*
118
+ * WLS in an IT block is CONSTRAINED UNPREDICTABLE;
119
+ * we choose to UNDEF, because otherwise our use of
120
+ * gen_goto_tb(1) would clash with the use of TB exit 1
121
+ * in the dc->condjmp condition-failed codepath in
122
+ * arm_tr_tb_stop() and we'd get an assertion.
123
+ */
124
+ return false;
125
+ }
126
+ nextlabel = gen_new_label();
127
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel);
128
+ tmp = load_reg(s, a->rn);
129
+ store_reg(s, 14, tmp);
130
+ gen_jmp_tb(s, s->base.pc_next, 1);
131
+
132
+ gen_set_label(nextlabel);
133
+ gen_jmp(s, read_pc(s) + a->imm);
134
+ return true;
135
+}
136
+
137
+static bool trans_LE(DisasContext *s, arg_LE *a)
138
+{
139
+ /*
138
+ /*
140
+ * M-profile low-overhead loop end. The architecture permits an
139
+ * Place default_nan_pattern [6:0] into bits [62:56],
141
+ * implementation to discard the LO_BRANCH_INFO cache at any time,
140
+ * and replecate bit [0] down into [55:0]
142
+ * and we take the IMPDEF option to never set it in the first place
143
+ * (equivalent to always discarding it immediately), because for QEMU
144
+ * a "real" implementation would be complicated and wouldn't execute
145
+ * any faster.
146
+ */
141
+ */
147
+ TCGv_i32 tmp;
142
+ frac = deposit64(0, DECOMPOSED_BINARY_POINT - 7, 7, dnan_pattern);
148
+
143
+ frac = deposit64(frac, 0, DECOMPOSED_BINARY_POINT - 7, -(dnan_pattern & 1));
149
+ if (!dc_isar_feature(aa32_lob, s)) {
144
150
+ return false;
145
*p = (FloatParts64) {
151
+ }
146
.cls = float_class_qnan,
152
+
153
+ if (!a->f) {
154
+ /* Not loop-forever. If LR <= 1 this is the last loop: do nothing. */
155
+ arm_gen_condlabel(s);
156
+ tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, s->condlabel);
157
+ /* Decrement LR */
158
+ tmp = load_reg(s, 14);
159
+ tcg_gen_addi_i32(tmp, tmp, -1);
160
+ store_reg(s, 14, tmp);
161
+ }
162
+ /* Jump back to the loop start */
163
+ gen_jmp(s, read_pc(s) - a->imm);
164
+ return true;
165
+}
166
+
167
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
168
{
169
TCGv_i32 addr, tmp;
170
--
147
--
171
2.20.1
148
2.34.1
172
173
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
v8.1M brings four new insns to M-profile:
1
Set the default NaN pattern explicitly for the arm target.
2
* CSEL : Rd = cond ? Rn : Rm
2
This includes setting it for the old linux-user nwfpe emulation.
3
* CSINC : Rd = cond ? Rn : Rm+1
3
For nwfpe, our default doesn't match the real kernel, but we
4
* CSINV : Rd = cond ? Rn : ~Rm
4
avoid making a behaviour change in this commit.
5
* CSNEG : Rd = cond ? Rn : -Rm
6
5
7
Implement these.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241202131347.498124-41-peter.maydell@linaro.org
9
---
10
linux-user/arm/nwfpe/fpa11.c | 5 +++++
11
target/arm/cpu.c | 2 ++
12
2 files changed, 7 insertions(+)
8
13
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20201019151301.2046-4-peter.maydell@linaro.org
12
---
13
target/arm/t32.decode | 3 +++
14
target/arm/translate.c | 60 ++++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 63 insertions(+)
16
17
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/t32.decode
16
--- a/linux-user/arm/nwfpe/fpa11.c
20
+++ b/target/arm/t32.decode
17
+++ b/linux-user/arm/nwfpe/fpa11.c
21
@@ -XXX,XX +XXX,XX @@ SBC_rrri 1110101 1011 . .... 0 ... .... .... .... @s_rrr_shi
18
@@ -XXX,XX +XXX,XX @@ void resetFPA11(void)
19
* this late date.
20
*/
21
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &fpa11->fp_status);
22
+ /*
23
+ * Use the same default NaN value as Arm VFP. This doesn't match
24
+ * the Linux kernel's nwfpe emulation, which uses an all-1s value.
25
+ */
26
+ set_float_default_nan_pattern(0b01000000, &fpa11->fp_status);
22
}
27
}
23
RSB_rrri 1110101 1110 . .... 0 ... .... .... .... @s_rrr_shi
28
24
29
void SetRoundingMode(const unsigned int opcode)
25
+# v8.1M CSEL and friends
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
26
+CSEL 1110101 0010 1 rn:4 10 op:2 rd:4 fcond:4 rm:4
27
+
28
# Data-processing (register-shifted register)
29
30
MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \
31
diff --git a/target/arm/translate.c b/target/arm/translate.c
32
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate.c
32
--- a/target/arm/cpu.c
34
+++ b/target/arm/translate.c
33
+++ b/target/arm/cpu.c
35
@@ -XXX,XX +XXX,XX @@ static bool trans_IT(DisasContext *s, arg_IT *a)
34
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
36
return true;
35
* the pseudocode function the arguments are in the order c, a, b.
36
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
37
* and the input NaN if it is signalling
38
+ * * Default NaN has sign bit clear, msb frac bit set
39
*/
40
static void arm_set_default_fp_behaviours(float_status *s)
41
{
42
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
44
set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
46
+ set_float_default_nan_pattern(0b01000000, s);
37
}
47
}
38
48
39
+/* v8.1M CSEL/CSINC/CSNEG/CSINV */
49
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
40
+static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
41
+{
42
+ TCGv_i32 rn, rm, zero;
43
+ DisasCompare c;
44
+
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
46
+ return false;
47
+ }
48
+
49
+ if (a->rm == 13) {
50
+ /* SEE "Related encodings" (MVE shifts) */
51
+ return false;
52
+ }
53
+
54
+ if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) {
55
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
56
+ return false;
57
+ }
58
+
59
+ /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
60
+ if (a->rn == 15) {
61
+ rn = tcg_const_i32(0);
62
+ } else {
63
+ rn = load_reg(s, a->rn);
64
+ }
65
+ if (a->rm == 15) {
66
+ rm = tcg_const_i32(0);
67
+ } else {
68
+ rm = load_reg(s, a->rm);
69
+ }
70
+
71
+ switch (a->op) {
72
+ case 0: /* CSEL */
73
+ break;
74
+ case 1: /* CSINC */
75
+ tcg_gen_addi_i32(rm, rm, 1);
76
+ break;
77
+ case 2: /* CSINV */
78
+ tcg_gen_not_i32(rm, rm);
79
+ break;
80
+ case 3: /* CSNEG */
81
+ tcg_gen_neg_i32(rm, rm);
82
+ break;
83
+ default:
84
+ g_assert_not_reached();
85
+ }
86
+
87
+ arm_test_cc(&c, a->fcond);
88
+ zero = tcg_const_i32(0);
89
+ tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
90
+ arm_free_cc(&c);
91
+ tcg_temp_free_i32(zero);
92
+
93
+ store_reg(s, a->rd, rn);
94
+ tcg_temp_free_i32(rm);
95
+
96
+ return true;
97
+}
98
+
99
/*
100
* Legacy decoder.
101
*/
102
--
50
--
103
2.20.1
51
2.34.1
104
105
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
For nested groups like:
1
Set the default NaN pattern explicitly for ppc.
2
2
3
{
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
[
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
pattern 1
5
Message-id: 20241202131347.498124-46-peter.maydell@linaro.org
6
pattern 2
6
---
7
]
7
target/ppc/cpu_init.c | 4 ++++
8
pattern 3
8
1 file changed, 4 insertions(+)
9
}
10
9
11
the intended behaviour is that patterns 1 and 2 must not
10
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
12
overlap with each other; if the insn matches neither then
13
we fall through to pattern 3 as the next thing in the
14
outer overlapping group.
15
16
Currently we generate incorrect code for this situation,
17
because in the code path for a failed match inside the
18
inner non-overlapping group we generate a "return" statement,
19
which causes decode to stop entirely rather than continuing
20
to the next thing in the outer group.
21
22
Generate a "break" instead, so that decode flow behaves
23
as required for this nested group case.
24
25
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Message-id: 20201019151301.2046-2-peter.maydell@linaro.org
29
---
30
scripts/decodetree.py | 2 +-
31
1 file changed, 1 insertion(+), 1 deletion(-)
32
33
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
34
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
35
--- a/scripts/decodetree.py
12
--- a/target/ppc/cpu_init.c
36
+++ b/scripts/decodetree.py
13
+++ b/target/ppc/cpu_init.c
37
@@ -XXX,XX +XXX,XX @@ class Tree:
14
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
38
output(ind, ' /* ',
15
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
39
str_match_bits(innerbits, innermask), ' */\n')
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
40
s.output_code(i + 4, extracted, innerbits, innermask)
17
41
- output(ind, ' return false;\n')
18
+ /* Default NaN: sign bit clear, set frac msb */
42
+ output(ind, ' break;\n')
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
43
output(ind, '}\n')
20
+ set_float_default_nan_pattern(0b01000000, &env->vec_status);
44
# end Tree
21
+
22
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
23
ppc_spr_t *spr = &env->spr_cb[i];
45
24
46
--
25
--
47
2.20.1
26
2.34.1
48
49
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
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.
2
4
3
Add trace events for GPU and CPU IRQs.
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(+)
4
11
5
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
12
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201017180731.1165871-2-f4bug@amsat.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/intc/bcm2835_ic.c | 4 +++-
11
hw/intc/trace-events | 4 ++++
12
2 files changed, 7 insertions(+), 1 deletion(-)
13
14
diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2835_ic.c
14
--- a/target/sh4/cpu.c
17
+++ b/hw/intc/bcm2835_ic.c
15
+++ b/target/sh4/cpu.c
18
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
19
#include "migration/vmstate.h"
17
set_flush_to_zero(1, &env->fp_status);
20
#include "qemu/log.h"
18
#endif
21
#include "qemu/module.h"
19
set_default_nan_mode(1, &env->fp_status);
22
+#include "trace.h"
20
+ /* sign bit clear, set all frac bits other than msb */
23
21
+ set_float_default_nan_pattern(0b00111111, &env->fp_status);
24
#define GPU_IRQS 64
25
#define ARM_IRQS 8
26
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_update(BCM2835ICState *s)
27
set = (s->gpu_irq_level & s->gpu_irq_enable)
28
|| (s->arm_irq_level & s->arm_irq_enable);
29
qemu_set_irq(s->irq, set);
30
-
31
}
22
}
32
23
33
static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
24
static void superh_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
34
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
35
BCM2835ICState *s = opaque;
36
37
assert(irq >= 0 && irq < 64);
38
+ trace_bcm2835_ic_set_gpu_irq(irq, level);
39
s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0);
40
bcm2835_ic_update(s);
41
}
42
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_arm_irq(void *opaque, int irq, int level)
43
BCM2835ICState *s = opaque;
44
45
assert(irq >= 0 && irq < 8);
46
+ trace_bcm2835_ic_set_cpu_irq(irq, level);
47
s->arm_irq_level = deposit32(s->arm_irq_level, irq, 1, level != 0);
48
bcm2835_ic_update(s);
49
}
50
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/intc/trace-events
53
+++ b/hw/intc/trace-events
54
@@ -XXX,XX +XXX,XX @@ nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg wri
55
heathrow_write(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
56
heathrow_read(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
57
heathrow_set_irq(int num, int level) "set_irq: num=0x%02x level=%d"
58
+
59
+# bcm2835_ic.c
60
+bcm2835_ic_set_gpu_irq(int irq, int level) "GPU irq #%d level %d"
61
+bcm2835_ic_set_cpu_irq(int irq, int level) "CPU irq #%d level %d"
62
--
25
--
63
2.20.1
26
2.34.1
64
65
diff view generated by jsdifflib
1
For AArch32, unlike the VCVT of integer to float, which honours the
1
Set the default NaN pattern explicitly for rx.
2
rounding mode specified by the FPSCR, VCVT of fixed-point to float is
3
always round-to-nearest. (AArch64 fixed-point-to-float conversions
4
always honour the FPCR rounding mode.)
5
6
Implement this by providing _round_to_nearest versions of the
7
relevant helpers which set the rounding mode temporarily when making
8
the call to the underlying softfloat function.
9
10
We only need to change the VFP VCVT instructions, because the
11
standard- FPSCR value used by the Neon VCVT is always set to
12
round-to-nearest, so we don't need to do the extra work of saving
13
and restoring the rounding mode.
14
2
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20201013103532.13391-1-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-48-peter.maydell@linaro.org
18
---
6
---
19
target/arm/helper.h | 13 +++++++++++++
7
target/rx/cpu.c | 2 ++
20
target/arm/vfp_helper.c | 23 ++++++++++++++++++++++-
8
1 file changed, 2 insertions(+)
21
target/arm/translate-vfp.c.inc | 24 ++++++++++++------------
22
3 files changed, 47 insertions(+), 13 deletions(-)
23
9
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
10
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
25
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.h
12
--- a/target/rx/cpu.c
27
+++ b/target/arm/helper.h
13
+++ b/target/rx/cpu.c
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
14
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_reset_hold(Object *obj, ResetType type)
29
DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
15
* then prefer dest over source", which is float_2nan_prop_s_ab.
30
DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
16
*/
31
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
32
+DEF_HELPER_3(vfp_shtos_round_to_nearest, f32, i32, i32, ptr)
18
+ /* Default NaN value: sign bit clear, set frac msb */
33
+DEF_HELPER_3(vfp_sltos_round_to_nearest, f32, i32, i32, ptr)
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
34
+DEF_HELPER_3(vfp_uhtos_round_to_nearest, f32, i32, i32, ptr)
35
+DEF_HELPER_3(vfp_ultos_round_to_nearest, f32, i32, i32, ptr)
36
+DEF_HELPER_3(vfp_shtod_round_to_nearest, f64, i64, i32, ptr)
37
+DEF_HELPER_3(vfp_sltod_round_to_nearest, f64, i64, i32, ptr)
38
+DEF_HELPER_3(vfp_uhtod_round_to_nearest, f64, i64, i32, ptr)
39
+DEF_HELPER_3(vfp_ultod_round_to_nearest, f64, i64, i32, ptr)
40
+DEF_HELPER_3(vfp_shtoh_round_to_nearest, f16, i32, i32, ptr)
41
+DEF_HELPER_3(vfp_uhtoh_round_to_nearest, f16, i32, i32, ptr)
42
+DEF_HELPER_3(vfp_sltoh_round_to_nearest, f16, i32, i32, ptr)
43
+DEF_HELPER_3(vfp_ultoh_round_to_nearest, f16, i32, i32, ptr)
44
+
45
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
46
47
DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f32, TCG_CALL_NO_RWG, f32, f16, ptr, i32)
48
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/vfp_helper.c
51
+++ b/target/arm/vfp_helper.c
52
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
53
return float64_to_float32(x, &env->vfp.fp_status);
54
}
20
}
55
21
56
-/* VFP3 fixed point conversion. */
22
static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
57
+/*
58
+ * VFP3 fixed point conversion. The AArch32 versions of fix-to-float
59
+ * must always round-to-nearest; the AArch64 ones honour the FPSCR
60
+ * rounding mode. (For AArch32 Neon the standard-FPSCR is set to
61
+ * round-to-nearest so either helper will work.) AArch32 float-to-fix
62
+ * must round-to-zero.
63
+ */
64
#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
65
ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
66
void *fpstp) \
67
{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
68
69
+#define VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
70
+ ftype HELPER(vfp_##name##to##p##_round_to_nearest)(uint##isz##_t x, \
71
+ uint32_t shift, \
72
+ void *fpstp) \
73
+ { \
74
+ ftype ret; \
75
+ float_status *fpst = fpstp; \
76
+ FloatRoundMode oldmode = fpst->float_rounding_mode; \
77
+ fpst->float_rounding_mode = float_round_nearest_even; \
78
+ ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); \
79
+ fpst->float_rounding_mode = oldmode; \
80
+ return ret; \
81
+ }
82
+
83
#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
84
uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
85
void *fpst) \
86
@@ -XXX,XX +XXX,XX @@ uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
87
88
#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \
89
VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
90
+VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
91
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
92
float_round_to_zero, _round_to_zero) \
93
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
94
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
95
index XXXXXXX..XXXXXXX 100644
96
--- a/target/arm/translate-vfp.c.inc
97
+++ b/target/arm/translate-vfp.c.inc
98
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
99
/* Switch on op:U:sx bits */
100
switch (a->opc) {
101
case 0:
102
- gen_helper_vfp_shtoh(vd, vd, shift, fpst);
103
+ gen_helper_vfp_shtoh_round_to_nearest(vd, vd, shift, fpst);
104
break;
105
case 1:
106
- gen_helper_vfp_sltoh(vd, vd, shift, fpst);
107
+ gen_helper_vfp_sltoh_round_to_nearest(vd, vd, shift, fpst);
108
break;
109
case 2:
110
- gen_helper_vfp_uhtoh(vd, vd, shift, fpst);
111
+ gen_helper_vfp_uhtoh_round_to_nearest(vd, vd, shift, fpst);
112
break;
113
case 3:
114
- gen_helper_vfp_ultoh(vd, vd, shift, fpst);
115
+ gen_helper_vfp_ultoh_round_to_nearest(vd, vd, shift, fpst);
116
break;
117
case 4:
118
gen_helper_vfp_toshh_round_to_zero(vd, vd, shift, fpst);
119
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
120
/* Switch on op:U:sx bits */
121
switch (a->opc) {
122
case 0:
123
- gen_helper_vfp_shtos(vd, vd, shift, fpst);
124
+ gen_helper_vfp_shtos_round_to_nearest(vd, vd, shift, fpst);
125
break;
126
case 1:
127
- gen_helper_vfp_sltos(vd, vd, shift, fpst);
128
+ gen_helper_vfp_sltos_round_to_nearest(vd, vd, shift, fpst);
129
break;
130
case 2:
131
- gen_helper_vfp_uhtos(vd, vd, shift, fpst);
132
+ gen_helper_vfp_uhtos_round_to_nearest(vd, vd, shift, fpst);
133
break;
134
case 3:
135
- gen_helper_vfp_ultos(vd, vd, shift, fpst);
136
+ gen_helper_vfp_ultos_round_to_nearest(vd, vd, shift, fpst);
137
break;
138
case 4:
139
gen_helper_vfp_toshs_round_to_zero(vd, vd, shift, fpst);
140
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
141
/* Switch on op:U:sx bits */
142
switch (a->opc) {
143
case 0:
144
- gen_helper_vfp_shtod(vd, vd, shift, fpst);
145
+ gen_helper_vfp_shtod_round_to_nearest(vd, vd, shift, fpst);
146
break;
147
case 1:
148
- gen_helper_vfp_sltod(vd, vd, shift, fpst);
149
+ gen_helper_vfp_sltod_round_to_nearest(vd, vd, shift, fpst);
150
break;
151
case 2:
152
- gen_helper_vfp_uhtod(vd, vd, shift, fpst);
153
+ gen_helper_vfp_uhtod_round_to_nearest(vd, vd, shift, fpst);
154
break;
155
case 3:
156
- gen_helper_vfp_ultod(vd, vd, shift, fpst);
157
+ gen_helper_vfp_ultod_round_to_nearest(vd, vd, shift, fpst);
158
break;
159
case 4:
160
gen_helper_vfp_toshd_round_to_zero(vd, vd, shift, fpst);
161
--
23
--
162
2.20.1
24
2.34.1
163
164
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for s390x.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-49-peter.maydell@linaro.org
6
---
7
target/s390x/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/s390x/cpu.c
13
+++ b/target/s390x/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
15
set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
16
set_float_infzeronan_rule(float_infzeronan_dnan_always,
17
&env->fpu_status);
18
+ /* Default NaN value: sign bit clear, frac msb set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fpu_status);
20
/* fall through */
21
case RESET_TYPE_S390_CPU_NORMAL:
22
env->psw.mask &= ~PSW_MASK_RI;
23
--
24
2.34.1
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Set the default NaN pattern explicitly for SPARC, and remove
2
the ifdef from parts64_default_nan.
2
3
3
The variable holding the CTRL_STATUS register is misnamed
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
'status'. Rename it 'ctrl_status' to make it more obvious
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
this register is also used to control the peripheral.
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(-)
6
11
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20201010203709.3116542-3-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/hw/timer/bcm2835_systmr.h | 2 +-
14
hw/timer/bcm2835_systmr.c | 8 ++++----
15
2 files changed, 5 insertions(+), 5 deletions(-)
16
17
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/timer/bcm2835_systmr.h
14
--- a/target/sparc/cpu.c
20
+++ b/include/hw/timer/bcm2835_systmr.h
15
+++ b/target/sparc/cpu.c
21
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
22
qemu_irq irq;
17
set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
23
18
/* For inf * 0 + NaN, return the input NaN */
24
struct {
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
25
- uint32_t status;
20
+ /* Default NaN value: sign bit clear, all frac bits set */
26
+ uint32_t ctrl_status;
21
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
27
uint32_t compare[BCM2835_SYSTIMER_COUNT];
22
28
} reg;
23
cpu_exec_realizefn(cs, &local_err);
29
};
24
if (local_err != NULL) {
30
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/bcm2835_systmr.c
27
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/hw/timer/bcm2835_systmr.c
28
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE3, 0x18)
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
35
30
uint8_t dnan_pattern = status->default_nan_pattern;
36
static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
31
37
{
32
if (dnan_pattern == 0) {
38
- bool enable = !!s->reg.status;
33
-#if defined(TARGET_SPARC)
39
+ bool enable = !!s->reg.ctrl_status;
34
- /* Sign bit clear, all frac bits set */
40
35
- dnan_pattern = 0b01111111;
41
trace_bcm2835_systmr_irq(enable);
36
-#elif defined(TARGET_HEXAGON)
42
qemu_set_irq(s->irq, enable);
37
+#if defined(TARGET_HEXAGON)
43
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
38
/* Sign bit set, all frac bits set. */
44
39
dnan_pattern = 0b11111111;
45
switch (offset) {
40
#else
46
case A_CTRL_STATUS:
47
- r = s->reg.status;
48
+ r = s->reg.ctrl_status;
49
break;
50
case A_COMPARE0 ... A_COMPARE3:
51
r = s->reg.compare[(offset - A_COMPARE0) >> 2];
52
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_write(void *opaque, hwaddr offset,
53
trace_bcm2835_systmr_write(offset, value);
54
switch (offset) {
55
case A_CTRL_STATUS:
56
- s->reg.status &= ~value; /* Ack */
57
+ s->reg.ctrl_status &= ~value; /* Ack */
58
bcm2835_systmr_update_irq(s);
59
break;
60
case A_COMPARE0 ... A_COMPARE3:
61
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
62
.version_id = 1,
63
.minimum_version_id = 1,
64
.fields = (VMStateField[]) {
65
- VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
66
+ VMSTATE_UINT32(reg.ctrl_status, BCM2835SystemTimerState),
67
VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
68
BCM2835_SYSTIMER_COUNT),
69
VMSTATE_END_OF_LIST()
70
--
41
--
71
2.20.1
42
2.34.1
72
73
diff view generated by jsdifflib
1
The t32 decode has a group which represents a set of insns
1
Set the default NaN pattern explicitly for xtensa.
2
which overlap with B_cond_thumb because they have [25:23]=111
3
(which is an invalid condition code field for the branch insn).
4
This group is currently defined using the {} overlap-OK syntax,
5
but it is almost entirely non-overlapping patterns. Switch
6
it over to use a non-overlapping group.
7
2
8
For this to be valid syntactically, CPS must move into the same
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
overlapping-group as the hint insns (CPS vs hints was the
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
only actual use of the overlap facility for the group).
5
Message-id: 20241202131347.498124-51-peter.maydell@linaro.org
6
---
7
target/xtensa/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
11
9
12
The non-overlapping subgroup for CLREX/DSB/DMB/ISB/SB is no longer
10
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
13
necessary and so we can remove it (promoting those insns to
14
be members of the parent group).
15
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20201019151301.2046-5-peter.maydell@linaro.org
19
---
20
target/arm/t32.decode | 26 ++++++++++++--------------
21
1 file changed, 12 insertions(+), 14 deletions(-)
22
23
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
24
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/t32.decode
12
--- a/target/xtensa/cpu.c
26
+++ b/target/arm/t32.decode
13
+++ b/target/xtensa/cpu.c
27
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
14
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
28
{
15
/* For inf * 0 + NaN, return the input NaN */
29
# Group insn[25:23] = 111, which is cond=111x for the branch below,
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
30
# or unconditional, which would be illegal for the branch.
17
set_no_signaling_nans(!dfpu, &env->fp_status);
31
- {
18
+ /* Default NaN value: sign bit clear, set frac msb */
32
- # Hints
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
33
+ [
20
xtensa_use_first_nan(env, !dfpu);
34
+ # Hints, and CPS
35
{
36
YIELD 1111 0011 1010 1111 1000 0000 0000 0001
37
WFE 1111 0011 1010 1111 1000 0000 0000 0010
38
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
39
# The canonical nop ends in 0000 0000, but the whole rest
40
# of the space is "reserved hint, behaves as nop".
41
NOP 1111 0011 1010 1111 1000 0000 ---- ----
42
+
43
+ # If imod == '00' && M == '0' then SEE "Hint instructions", above.
44
+ CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
45
+ &cps
46
}
47
48
- # If imod == '00' && M == '0' then SEE "Hint instructions", above.
49
- CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
50
- &cps
51
-
52
# Miscellaneous control
53
- [
54
- CLREX 1111 0011 1011 1111 1000 1111 0010 1111
55
- DSB 1111 0011 1011 1111 1000 1111 0100 ----
56
- DMB 1111 0011 1011 1111 1000 1111 0101 ----
57
- ISB 1111 0011 1011 1111 1000 1111 0110 ----
58
- SB 1111 0011 1011 1111 1000 1111 0111 0000
59
- ]
60
+ CLREX 1111 0011 1011 1111 1000 1111 0010 1111
61
+ DSB 1111 0011 1011 1111 1000 1111 0100 ----
62
+ DMB 1111 0011 1011 1111 1000 1111 0101 ----
63
+ ISB 1111 0011 1011 1111 1000 1111 0110 ----
64
+ SB 1111 0011 1011 1111 1000 1111 0111 0000
65
66
# Note that the v7m insn overlaps both the normal and banked insn.
67
{
68
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
69
HVC 1111 0111 1110 .... 1000 .... .... .... \
70
&i imm=%imm16_16_0
71
UDF 1111 0111 1111 ---- 1010 ---- ---- ----
72
- }
73
+ ]
74
B_cond_thumb 1111 0. cond:4 ...... 10.0 ............ &ci imm=%imm21
75
}
21
}
76
22
77
--
23
--
78
2.20.1
24
2.34.1
79
80
diff view generated by jsdifflib
1
From: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
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.
2
4
3
Current documentation is not too clear on the GETPC usage.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
In particular, when used outside the top level helper function
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
it causes unexpected behavior.
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(-)
6
12
7
Signed-off-by: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
13
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
8
Message-id: 20201015095147.1691-1-e.emanuelegiuseppe@gmail.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
docs/devel/loads-stores.rst | 8 +++++++-
13
1 file changed, 7 insertions(+), 1 deletion(-)
14
15
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/devel/loads-stores.rst
15
--- a/target/hexagon/cpu.c
18
+++ b/docs/devel/loads-stores.rst
16
+++ b/target/hexagon/cpu.c
19
@@ -XXX,XX +XXX,XX @@ guest CPU state in case of a guest CPU exception. This is passed
17
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
20
to ``cpu_restore_state()``. Therefore the value should either be 0,
18
21
to indicate that the guest CPU state is already synchronized, or
19
set_default_nan_mode(1, &env->fp_status);
22
the result of ``GETPC()`` from the top level ``HELPER(foo)``
20
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
23
-function, which is a return address into the generated code.
21
+ /* Default NaN value: sign bit set, all frac bits set */
24
+function, which is a return address into the generated code [#gpc]_.
22
+ set_float_default_nan_pattern(0b11111111, &env->fp_status);
25
+
23
}
26
+.. [#gpc] Note that ``GETPC()`` should be used with great care: calling
24
27
+ it in other functions that are *not* the top level
25
static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
28
+ ``HELPER(foo)`` will cause unexpected behavior. Instead, the
26
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
29
+ value of ``GETPC()`` should be read from the helper and passed
27
index XXXXXXX..XXXXXXX 100644
30
+ if needed to the functions that the helper calls.
28
--- a/fpu/softfloat-specialize.c.inc
31
29
+++ b/fpu/softfloat-specialize.c.inc
32
Function names follow the pattern:
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);
33
48
34
--
49
--
35
2.20.1
50
2.34.1
36
37
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Set the default NaN pattern explicitly for riscv.
2
2
3
The SYS_timer is not directly wired to the ARM core, but to the
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
SoC (peripheral) interrupt controller.
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-53-peter.maydell@linaro.org
6
---
7
target/riscv/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
5
9
6
Fixes: 0e5bbd74064 ("hw/arm/bcm2835_peripherals: Use the SYS_timer")
10
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20201010203709.3116542-5-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/bcm2835_peripherals.c | 13 +++++++++++--
14
1 file changed, 11 insertions(+), 2 deletions(-)
15
16
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
17
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/bcm2835_peripherals.c
12
--- a/target/riscv/cpu.c
19
+++ b/hw/arm/bcm2835_peripherals.c
13
+++ b/target/riscv/cpu.c
20
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
14
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
21
memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
15
cs->exception_index = RISCV_EXCP_NONE;
22
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systmr), 0));
16
env->load_res = -1;
23
sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 0,
17
set_default_nan_mode(1, &env->fp_status);
24
- qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
18
+ /* Default NaN value: sign bit clear, frac msb set */
25
- INTERRUPT_ARM_TIMER));
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
26
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
20
env->vill = true;
27
+ INTERRUPT_TIMER0));
21
28
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 1,
22
#ifndef CONFIG_USER_ONLY
29
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
30
+ INTERRUPT_TIMER1));
31
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 2,
32
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
33
+ INTERRUPT_TIMER2));
34
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 3,
35
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
36
+ INTERRUPT_TIMER3));
37
38
/* UART0 */
39
qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0));
40
--
23
--
41
2.20.1
24
2.34.1
42
43
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Set the default NaN pattern explicitly for tricore.
2
2
3
This peripheral has 1 free-running timer and 4 compare registers.
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-54-peter.maydell@linaro.org
6
---
7
target/tricore/helper.c | 2 ++
8
1 file changed, 2 insertions(+)
4
9
5
Only the free-running timer is implemented. Add support the
10
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
6
COMPARE registers (each register is wired to an IRQ).
7
8
Reference: "BCM2835 ARM Peripherals" datasheet [*]
9
chapter 12 "System Timer":
10
11
The System Timer peripheral provides four 32-bit timer channels
12
and a single 64-bit free running counter. Each channel has an
13
output compare register, which is compared against the 32 least
14
significant bits of the free running counter values. When the
15
two values match, the system timer peripheral generates a signal
16
to indicate a match for the appropriate channel. The match signal
17
is then fed into the interrupt controller.
18
19
This peripheral is used since Linux 3.7, commit ee4af5696720
20
("ARM: bcm2835: add system timer").
21
22
[*] https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
23
24
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Reviewed-by: Luc Michel <luc@lmichel.fr>
26
Message-id: 20201010203709.3116542-4-f4bug@amsat.org
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
---
29
include/hw/timer/bcm2835_systmr.h | 11 +++++--
30
hw/timer/bcm2835_systmr.c | 48 ++++++++++++++++++++-----------
31
hw/timer/trace-events | 6 ++--
32
3 files changed, 44 insertions(+), 21 deletions(-)
33
34
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
35
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/timer/bcm2835_systmr.h
12
--- a/target/tricore/helper.c
37
+++ b/include/hw/timer/bcm2835_systmr.h
13
+++ b/target/tricore/helper.c
38
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ void fpu_set_state(CPUTriCoreState *env)
39
15
set_flush_to_zero(1, &env->fp_status);
40
#include "hw/sysbus.h"
16
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
41
#include "hw/irq.h"
17
set_default_nan_mode(1, &env->fp_status);
42
+#include "qemu/timer.h"
18
+ /* Default NaN pattern: sign bit clear, frac msb set */
43
#include "qom/object.h"
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
44
45
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
46
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
47
48
#define BCM2835_SYSTIMER_COUNT 4
49
50
+typedef struct {
51
+ unsigned id;
52
+ QEMUTimer timer;
53
+ qemu_irq irq;
54
+ BCM2835SystemTimerState *state;
55
+} BCM2835SystemTimerCompare;
56
+
57
struct BCM2835SystemTimerState {
58
/*< private >*/
59
SysBusDevice parent_obj;
60
61
/*< public >*/
62
MemoryRegion iomem;
63
- qemu_irq irq;
64
-
65
struct {
66
uint32_t ctrl_status;
67
uint32_t compare[BCM2835_SYSTIMER_COUNT];
68
} reg;
69
+ BCM2835SystemTimerCompare tmr[BCM2835_SYSTIMER_COUNT];
70
};
71
72
#endif
73
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/timer/bcm2835_systmr.c
76
+++ b/hw/timer/bcm2835_systmr.c
77
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE1, 0x10)
78
REG32(COMPARE2, 0x14)
79
REG32(COMPARE3, 0x18)
80
81
-static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
82
+static void bcm2835_systmr_timer_expire(void *opaque)
83
{
84
- bool enable = !!s->reg.ctrl_status;
85
+ BCM2835SystemTimerCompare *tmr = opaque;
86
87
- trace_bcm2835_systmr_irq(enable);
88
- qemu_set_irq(s->irq, enable);
89
-}
90
-
91
-static void bcm2835_systmr_update_compare(BCM2835SystemTimerState *s,
92
- unsigned timer_index)
93
-{
94
- /* TODO fow now, since neither Linux nor U-boot use these timers. */
95
- qemu_log_mask(LOG_UNIMP, "COMPARE register %u not implemented\n",
96
- timer_index);
97
+ trace_bcm2835_systmr_timer_expired(tmr->id);
98
+ tmr->state->reg.ctrl_status |= 1 << tmr->id;
99
+ qemu_set_irq(tmr->irq, 1);
100
}
20
}
101
21
102
static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
22
uint32_t psw_read(CPUTriCoreState *env)
103
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
104
}
105
106
static void bcm2835_systmr_write(void *opaque, hwaddr offset,
107
- uint64_t value, unsigned size)
108
+ uint64_t value64, unsigned size)
109
{
110
BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
111
+ int index;
112
+ uint32_t value = value64;
113
+ uint32_t triggers_delay_us;
114
+ uint64_t now;
115
116
trace_bcm2835_systmr_write(offset, value);
117
switch (offset) {
118
case A_CTRL_STATUS:
119
s->reg.ctrl_status &= ~value; /* Ack */
120
- bcm2835_systmr_update_irq(s);
121
+ for (index = 0; index < ARRAY_SIZE(s->tmr); index++) {
122
+ if (extract32(value, index, 1)) {
123
+ trace_bcm2835_systmr_irq_ack(index);
124
+ qemu_set_irq(s->tmr[index].irq, 0);
125
+ }
126
+ }
127
break;
128
case A_COMPARE0 ... A_COMPARE3:
129
- s->reg.compare[(offset - A_COMPARE0) >> 2] = value;
130
- bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2);
131
+ index = (offset - A_COMPARE0) >> 2;
132
+ s->reg.compare[index] = value;
133
+ now = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
134
+ /* Compare lower 32-bits of the free-running counter. */
135
+ triggers_delay_us = value - now;
136
+ trace_bcm2835_systmr_run(index, triggers_delay_us);
137
+ timer_mod(&s->tmr[index].timer, now + triggers_delay_us);
138
break;
139
case A_COUNTER_LOW:
140
case A_COUNTER_HIGH:
141
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_realize(DeviceState *dev, Error **errp)
142
memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_systmr_ops,
143
s, "bcm2835-sys-timer", 0x20);
144
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
145
- sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
146
+
147
+ for (size_t i = 0; i < ARRAY_SIZE(s->tmr); i++) {
148
+ s->tmr[i].id = i;
149
+ s->tmr[i].state = s;
150
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->tmr[i].irq);
151
+ timer_init_us(&s->tmr[i].timer, QEMU_CLOCK_VIRTUAL,
152
+ bcm2835_systmr_timer_expire, &s->tmr[i]);
153
+ }
154
}
155
156
static const VMStateDescription bcm2835_systmr_vmstate = {
157
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
158
index XXXXXXX..XXXXXXX 100644
159
--- a/hw/timer/trace-events
160
+++ b/hw/timer/trace-events
161
@@ -XXX,XX +XXX,XX @@ nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size
162
nrf51_timer_set_count(uint8_t timer_id, uint8_t counter_id, uint32_t value) "timer %u counter %u count 0x%" PRIx32
163
164
# bcm2835_systmr.c
165
-bcm2835_systmr_irq(bool enable) "timer irq state %u"
166
+bcm2835_systmr_timer_expired(unsigned id) "timer #%u expired"
167
+bcm2835_systmr_irq_ack(unsigned id) "timer #%u acked"
168
bcm2835_systmr_read(uint64_t offset, uint64_t data) "timer read: offset 0x%" PRIx64 " data 0x%" PRIx64
169
-bcm2835_systmr_write(uint64_t offset, uint64_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx64
170
+bcm2835_systmr_write(uint64_t offset, uint32_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx32
171
+bcm2835_systmr_run(unsigned id, uint64_t delay_us) "timer #%u expiring in %"PRIu64" us"
172
173
# avr_timer16.c
174
avr_timer16_read(uint8_t addr, uint8_t value) "timer16 read addr:%u value:%u"
175
--
23
--
176
2.20.1
24
2.34.1
177
178
diff view generated by jsdifflib
1
The SMLAD instruction is supposed to:
1
Now that all our targets have bene converted to explicitly specify
2
* signed multiply Rn[15:0] * Rm[15:0]
2
their pattern for the default NaN value we can remove the remaining
3
* signed multiply Rn[31:16] * Rm[31:16]
3
fallback code in parts64_default_nan().
4
* perform a signed addition of the products and Ra
5
* set Rd to the low 32 bits of the theoretical
6
infinite-precision result
7
* set the Q flag if the sign-extension of Rd
8
would differ from the infinite-precision result
9
(ie on overflow)
10
11
Our current implementation doesn't quite do this, though: it performs
12
an addition of the products setting Q on overflow, and then it adds
13
Ra, again possibly setting Q. This sometimes incorrectly sets Q when
14
the architecturally mandated only-check-for-overflow-once algorithm
15
does not. For instance:
16
r1 = 0x80008000; r2 = 0x80008000; r3 = 0xffffffff
17
smlad r0, r1, r2, r3
18
This is (-32768 * -32768) + (-32768 * -32768) - 1
19
20
The products are both 0x4000_0000, so when added together as 32-bit
21
signed numbers they overflow (and QEMU sets Q), but because the
22
addition of Ra == -1 brings the total back down to 0x7fff_ffff
23
there is no overflow for the complete operation and setting Q is
24
incorrect.
25
26
Fix this edge case by resorting to 64-bit arithmetic for the
27
case where we need to add three values together.
28
4
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Message-id: 20201009144712.11187-1-peter.maydell@linaro.org
7
Message-id: 20241202131347.498124-55-peter.maydell@linaro.org
32
---
8
---
33
target/arm/translate.c | 58 ++++++++++++++++++++++++++++++++++--------
9
fpu/softfloat-specialize.c.inc | 14 --------------
34
1 file changed, 48 insertions(+), 10 deletions(-)
10
1 file changed, 14 deletions(-)
35
11
36
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
37
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate.c
14
--- a/fpu/softfloat-specialize.c.inc
39
+++ b/target/arm/translate.c
15
+++ b/fpu/softfloat-specialize.c.inc
40
@@ -XXX,XX +XXX,XX @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
16
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
41
gen_smul_dual(t1, t2);
17
uint64_t frac;
42
18
uint8_t dnan_pattern = status->default_nan_pattern;
43
if (sub) {
19
44
- /* This subtraction cannot overflow. */
20
- if (dnan_pattern == 0) {
45
+ /*
21
- /*
46
+ * This subtraction cannot overflow, so we can do a simple
22
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
47
+ * 32-bit subtraction and then a possible 32-bit saturating
23
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
48
+ * addition of Ra.
24
- * do not have floating-point.
49
+ */
25
- */
50
tcg_gen_sub_i32(t1, t1, t2);
26
- if (snan_bit_is_one(status)) {
51
+ tcg_temp_free_i32(t2);
27
- /* sign bit clear, set all frac bits other than msb */
52
+
28
- dnan_pattern = 0b00111111;
53
+ if (a->ra != 15) {
29
- } else {
54
+ t2 = load_reg(s, a->ra);
30
- /* sign bit clear, set frac msb */
55
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
31
- dnan_pattern = 0b01000000;
56
+ tcg_temp_free_i32(t2);
32
- }
57
+ }
58
+ } else if (a->ra == 15) {
59
+ /* Single saturation-checking addition */
60
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
61
+ tcg_temp_free_i32(t2);
62
} else {
63
/*
64
- * This addition cannot overflow 32 bits; however it may
65
- * overflow considered as a signed operation, in which case
66
- * we must set the Q flag.
67
+ * We need to add the products and Ra together and then
68
+ * determine whether the final result overflowed. Doing
69
+ * this as two separate add-and-check-overflow steps incorrectly
70
+ * sets Q for cases like (-32768 * -32768) + (-32768 * -32768) + -1.
71
+ * Do all the arithmetic at 64-bits and then check for overflow.
72
*/
73
- gen_helper_add_setq(t1, cpu_env, t1, t2);
74
- }
33
- }
75
- tcg_temp_free_i32(t2);
34
assert(dnan_pattern != 0);
76
+ TCGv_i64 p64, q64;
35
77
+ TCGv_i32 t3, qf, one;
36
sign = dnan_pattern >> 7;
78
79
- if (a->ra != 15) {
80
- t2 = load_reg(s, a->ra);
81
- gen_helper_add_setq(t1, cpu_env, t1, t2);
82
+ p64 = tcg_temp_new_i64();
83
+ q64 = tcg_temp_new_i64();
84
+ tcg_gen_ext_i32_i64(p64, t1);
85
+ tcg_gen_ext_i32_i64(q64, t2);
86
+ tcg_gen_add_i64(p64, p64, q64);
87
+ load_reg_var(s, t2, a->ra);
88
+ tcg_gen_ext_i32_i64(q64, t2);
89
+ tcg_gen_add_i64(p64, p64, q64);
90
+ tcg_temp_free_i64(q64);
91
+
92
+ tcg_gen_extr_i64_i32(t1, t2, p64);
93
+ tcg_temp_free_i64(p64);
94
+ /*
95
+ * t1 is the low half of the result which goes into Rd.
96
+ * We have overflow and must set Q if the high half (t2)
97
+ * is different from the sign-extension of t1.
98
+ */
99
+ t3 = tcg_temp_new_i32();
100
+ tcg_gen_sari_i32(t3, t1, 31);
101
+ qf = load_cpu_field(QF);
102
+ one = tcg_const_i32(1);
103
+ tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
104
+ store_cpu_field(qf, QF);
105
+ tcg_temp_free_i32(one);
106
+ tcg_temp_free_i32(t3);
107
tcg_temp_free_i32(t2);
108
}
109
store_reg(s, a->rd, t1);
110
--
37
--
111
2.20.1
38
2.34.1
112
113
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
When TBI is enabled in a given regime, 56 bits of the address
3
Inline pickNaNMulAdd into its only caller. This makes
4
are significant and we need to clear out any other matching
4
one assert redundant with the immediately preceding IF.
5
virtual addresses with differing tags.
6
5
7
The other uses of tlb_flush_page (without mmuidx) in this file
8
are only used by aarch32 mode.
9
10
Fixes: 38d931687fa1
11
Reported-by: Jordan Frank <jordanfrank@fb.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Message-id: 20201016210754.818257-3-richard.henderson@linaro.org
8
Message-id: 20241203203949.483774-3-richard.henderson@linaro.org
9
[PMM: keep comment from old code in new location]
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
11
---
18
target/arm/helper.c | 46 ++++++++++++++++++++++++++++++++++++++-------
12
fpu/softfloat-parts.c.inc | 41 +++++++++++++++++++++++++-
19
1 file changed, 39 insertions(+), 7 deletions(-)
13
fpu/softfloat-specialize.c.inc | 54 ----------------------------------
14
2 files changed, 40 insertions(+), 55 deletions(-)
20
15
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
18
--- a/fpu/softfloat-parts.c.inc
24
+++ b/target/arm/helper.c
19
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
26
#endif
21
}
27
22
28
static void switch_mode(CPUARMState *env, int mode);
23
if (s->default_nan_mode) {
29
+static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
24
+ /*
30
25
+ * We guarantee not to require the target to tell us how to
31
static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
26
+ * pick a NaN if we're always returning the default NaN.
32
{
27
+ * But if we're not in default-NaN mode then the target must
33
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
28
+ * specify.
29
+ */
30
which = 3;
31
+ } else if (infzero) {
32
+ /*
33
+ * Inf * 0 + NaN -- some implementations return the
34
+ * default NaN here, and some return the input NaN.
35
+ */
36
+ switch (s->float_infzeronan_rule) {
37
+ case float_infzeronan_dnan_never:
38
+ which = 2;
39
+ break;
40
+ case float_infzeronan_dnan_always:
41
+ which = 3;
42
+ break;
43
+ case float_infzeronan_dnan_if_qnan:
44
+ which = is_qnan(c->cls) ? 3 : 2;
45
+ break;
46
+ default:
47
+ g_assert_not_reached();
48
+ }
49
} else {
50
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
51
+ FloatClass cls[3] = { a->cls, b->cls, c->cls };
52
+ Float3NaNPropRule rule = s->float_3nan_prop_rule;
53
+
54
+ assert(rule != float_3nan_prop_none);
55
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
56
+ /* We have at least one SNaN input and should prefer it */
57
+ do {
58
+ which = rule & R_3NAN_1ST_MASK;
59
+ rule >>= R_3NAN_1ST_LENGTH;
60
+ } while (!is_snan(cls[which]));
61
+ } else {
62
+ do {
63
+ which = rule & R_3NAN_1ST_MASK;
64
+ rule >>= R_3NAN_1ST_LENGTH;
65
+ } while (!is_nan(cls[which]));
66
+ }
67
}
68
69
if (which == 3) {
70
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
71
index XXXXXXX..XXXXXXX 100644
72
--- a/fpu/softfloat-specialize.c.inc
73
+++ b/fpu/softfloat-specialize.c.inc
74
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
34
}
75
}
35
}
76
}
36
77
37
+/* Return 56 if TBI is enabled, 64 otherwise. */
78
-/*----------------------------------------------------------------------------
38
+static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
79
-| Select which NaN to propagate for a three-input operation.
39
+ uint64_t addr)
80
-| For the moment we assume that no CPU needs the 'larger significand'
40
+{
81
-| information.
41
+ uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
82
-| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
42
+ int tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
83
-*----------------------------------------------------------------------------*/
43
+ int select = extract64(addr, 55, 1);
84
-static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
44
+
85
- bool infzero, bool have_snan, float_status *status)
45
+ return (tbi >> select) & 1 ? 56 : 64;
86
-{
46
+}
87
- FloatClass cls[3] = { a_cls, b_cls, c_cls };
47
+
88
- Float3NaNPropRule rule = status->float_3nan_prop_rule;
48
+static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
89
- int which;
49
+{
90
-
50
+ ARMMMUIdx mmu_idx;
91
- /*
51
+
92
- * We guarantee not to require the target to tell us how to
52
+ /* Only the regime of the mmu_idx below is significant. */
93
- * pick a NaN if we're always returning the default NaN.
53
+ if (arm_is_secure_below_el3(env)) {
94
- * But if we're not in default-NaN mode then the target must
54
+ mmu_idx = ARMMMUIdx_SE10_0;
95
- * specify.
55
+ } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
96
- */
56
+ == (HCR_E2H | HCR_TGE)) {
97
- assert(!status->default_nan_mode);
57
+ mmu_idx = ARMMMUIdx_E20_0;
98
-
58
+ } else {
99
- if (infzero) {
59
+ mmu_idx = ARMMMUIdx_E10_0;
100
- /*
60
+ }
101
- * Inf * 0 + NaN -- some implementations return the default NaN here,
61
+ return tlbbits_for_regime(env, mmu_idx, addr);
102
- * and some return the input NaN.
62
+}
103
- */
63
+
104
- switch (status->float_infzeronan_rule) {
64
static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
105
- case float_infzeronan_dnan_never:
65
uint64_t value)
106
- return 2;
66
{
107
- case float_infzeronan_dnan_always:
67
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
108
- return 3;
68
CPUState *cs = env_cpu(env);
109
- case float_infzeronan_dnan_if_qnan:
69
int mask = vae1_tlbmask(env);
110
- return is_qnan(c_cls) ? 3 : 2;
70
uint64_t pageaddr = sextract64(value << 12, 0, 56);
111
- default:
71
+ int bits = vae1_tlbbits(env, pageaddr);
112
- g_assert_not_reached();
72
113
- }
73
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
114
- }
74
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
115
-
75
}
116
- assert(rule != float_3nan_prop_none);
76
117
- if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
77
static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
118
- /* We have at least one SNaN input and should prefer it */
78
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
119
- do {
79
CPUState *cs = env_cpu(env);
120
- which = rule & R_3NAN_1ST_MASK;
80
int mask = vae1_tlbmask(env);
121
- rule >>= R_3NAN_1ST_LENGTH;
81
uint64_t pageaddr = sextract64(value << 12, 0, 56);
122
- } while (!is_snan(cls[which]));
82
+ int bits = vae1_tlbbits(env, pageaddr);
123
- } else {
83
124
- do {
84
if (tlb_force_broadcast(env)) {
125
- which = rule & R_3NAN_1ST_MASK;
85
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
126
- rule >>= R_3NAN_1ST_LENGTH;
86
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
127
- } while (!is_nan(cls[which]));
87
} else {
128
- }
88
- tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
129
- return which;
89
+ tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits);
130
-}
90
}
131
-
91
}
132
/*----------------------------------------------------------------------------
92
133
| Returns 1 if the double-precision floating-point value `a' is a quiet
93
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
134
| NaN; otherwise returns 0.
94
{
95
CPUState *cs = env_cpu(env);
96
uint64_t pageaddr = sextract64(value << 12, 0, 56);
97
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
98
99
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
100
- ARMMMUIdxBit_E2);
101
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
102
+ ARMMMUIdxBit_E2, bits);
103
}
104
105
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
106
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
107
{
108
CPUState *cs = env_cpu(env);
109
uint64_t pageaddr = sextract64(value << 12, 0, 56);
110
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_SE3, pageaddr);
111
112
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
113
- ARMMMUIdxBit_SE3);
114
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
115
+ ARMMMUIdxBit_SE3, bits);
116
}
117
118
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
119
--
135
--
120
2.20.1
136
2.34.1
121
137
122
138
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The second loop uses a loop induction variable, and the first
3
Remove "3" as a special case for which and simply
4
does not. Transform the first to match the second, to simplify
4
branch to return the desired value.
5
a following patch moving code between them.
6
5
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20201016184207.786698-7-richard.henderson@linaro.org
8
Message-id: 20241203203949.483774-4-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
linux-user/elfload.c | 9 +++++----
11
fpu/softfloat-parts.c.inc | 20 ++++++++++----------
13
1 file changed, 5 insertions(+), 4 deletions(-)
12
1 file changed, 10 insertions(+), 10 deletions(-)
14
13
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
16
--- a/fpu/softfloat-parts.c.inc
18
+++ b/linux-user/elfload.c
17
+++ b/fpu/softfloat-parts.c.inc
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
20
loaddr = -1, hiaddr = 0;
19
* But if we're not in default-NaN mode then the target must
21
info->alignment = 0;
20
* specify.
22
for (i = 0; i < ehdr->e_phnum; ++i) {
21
*/
23
- if (phdr[i].p_type == PT_LOAD) {
22
- which = 3;
24
- abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
23
+ goto default_nan;
25
+ struct elf_phdr *eppnt = phdr + i;
24
} else if (infzero) {
26
+ if (eppnt->p_type == PT_LOAD) {
25
/*
27
+ abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
26
* Inf * 0 + NaN -- some implementations return the
28
if (a < loaddr) {
27
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
29
loaddr = a;
28
*/
30
}
29
switch (s->float_infzeronan_rule) {
31
- a = phdr[i].p_vaddr + phdr[i].p_memsz;
30
case float_infzeronan_dnan_never:
32
+ a = eppnt->p_vaddr + eppnt->p_memsz;
31
- which = 2;
33
if (a > hiaddr) {
32
break;
34
hiaddr = a;
33
case float_infzeronan_dnan_always:
35
}
34
- which = 3;
36
++info->nsegs;
35
- break;
37
- info->alignment |= phdr[i].p_align;
36
+ goto default_nan;
38
+ info->alignment |= eppnt->p_align;
37
case float_infzeronan_dnan_if_qnan:
38
- which = is_qnan(c->cls) ? 3 : 2;
39
+ if (is_qnan(c->cls)) {
40
+ goto default_nan;
41
+ }
42
break;
43
default:
44
g_assert_not_reached();
45
}
46
+ which = 2;
47
} else {
48
FloatClass cls[3] = { a->cls, b->cls, c->cls };
49
Float3NaNPropRule rule = s->float_3nan_prop_rule;
50
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
39
}
51
}
40
}
52
}
41
53
54
- if (which == 3) {
55
- parts_default_nan(a, s);
56
- return a;
57
- }
58
-
59
switch (which) {
60
case 0:
61
break;
62
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
63
parts_silence_nan(a, s);
64
}
65
return a;
66
+
67
+ default_nan:
68
+ parts_default_nan(a, s);
69
+ return a;
70
}
71
72
/*
42
--
73
--
43
2.20.1
74
2.34.1
44
75
45
76
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
For BTI, we need to know if the executable is static or dynamic,
3
Assign the pointer return value to 'a' directly,
4
which means looking for PT_INTERP earlier.
4
rather than going through an intermediary index.
5
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201016184207.786698-8-richard.henderson@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-5-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
linux-user/elfload.c | 60 +++++++++++++++++++++++---------------------
11
fpu/softfloat-parts.c.inc | 32 ++++++++++----------------------
12
1 file changed, 31 insertions(+), 29 deletions(-)
12
1 file changed, 10 insertions(+), 22 deletions(-)
13
13
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
16
--- a/fpu/softfloat-parts.c.inc
17
+++ b/linux-user/elfload.c
17
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
19
FloatPartsN *c, float_status *s,
20
mmap_lock();
20
int ab_mask, int abc_mask)
21
21
{
22
- /* Find the maximum size of the image and allocate an appropriate
22
- int which;
23
- amount of memory to handle that. */
23
bool infzero = (ab_mask == float_cmask_infzero);
24
+ /*
24
bool have_snan = (abc_mask & float_cmask_snan);
25
+ * Find the maximum size of the image and allocate an appropriate
25
+ FloatPartsN *ret;
26
+ * amount of memory to handle that. Locate the interpreter, if any.
26
27
+ */
27
if (unlikely(have_snan)) {
28
loaddr = -1, hiaddr = 0;
28
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
29
info->alignment = 0;
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
30
for (i = 0; i < ehdr->e_phnum; ++i) {
30
default:
31
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
31
g_assert_not_reached();
32
}
32
}
33
++info->nsegs;
33
- which = 2;
34
info->alignment |= eppnt->p_align;
34
+ ret = c;
35
+ } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
35
} else {
36
+ g_autofree char *interp_name = NULL;
36
- FloatClass cls[3] = { a->cls, b->cls, c->cls };
37
+
37
+ FloatPartsN *val[3] = { a, b, c };
38
+ if (*pinterp_name) {
38
Float3NaNPropRule rule = s->float_3nan_prop_rule;
39
+ errmsg = "Multiple PT_INTERP entries";
39
40
+ goto exit_errmsg;
40
assert(rule != float_3nan_prop_none);
41
+ }
41
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
42
+ interp_name = g_malloc(eppnt->p_filesz);
42
/* We have at least one SNaN input and should prefer it */
43
+ if (!interp_name) {
43
do {
44
+ goto exit_perror;
44
- which = rule & R_3NAN_1ST_MASK;
45
+ }
45
+ ret = val[rule & R_3NAN_1ST_MASK];
46
+
46
rule >>= R_3NAN_1ST_LENGTH;
47
+ if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
47
- } while (!is_snan(cls[which]));
48
+ memcpy(interp_name, bprm_buf + eppnt->p_offset,
48
+ } while (!is_snan(ret->cls));
49
+ eppnt->p_filesz);
49
} else {
50
+ } else {
50
do {
51
+ retval = pread(image_fd, interp_name, eppnt->p_filesz,
51
- which = rule & R_3NAN_1ST_MASK;
52
+ eppnt->p_offset);
52
+ ret = val[rule & R_3NAN_1ST_MASK];
53
+ if (retval != eppnt->p_filesz) {
53
rule >>= R_3NAN_1ST_LENGTH;
54
+ goto exit_perror;
54
- } while (!is_nan(cls[which]));
55
+ }
55
+ } while (!is_nan(ret->cls));
56
+ }
57
+ if (interp_name[eppnt->p_filesz - 1] != 0) {
58
+ errmsg = "Invalid PT_INTERP entry";
59
+ goto exit_errmsg;
60
+ }
61
+ *pinterp_name = g_steal_pointer(&interp_name);
62
}
56
}
63
}
57
}
64
58
65
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
59
- switch (which) {
66
if (vaddr_em > info->brk) {
60
- case 0:
67
info->brk = vaddr_em;
61
- break;
68
}
62
- case 1:
69
- } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
63
- a = b;
70
- g_autofree char *interp_name = NULL;
64
- break;
71
-
65
- case 2:
72
- if (*pinterp_name) {
66
- a = c;
73
- errmsg = "Multiple PT_INTERP entries";
67
- break;
74
- goto exit_errmsg;
68
- default:
75
- }
69
- g_assert_not_reached();
76
- interp_name = g_malloc(eppnt->p_filesz);
70
+ if (is_snan(ret->cls)) {
77
- if (!interp_name) {
71
+ parts_silence_nan(ret, s);
78
- goto exit_perror;
72
}
79
- }
73
- if (is_snan(a->cls)) {
80
-
74
- parts_silence_nan(a, s);
81
- if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
75
- }
82
- memcpy(interp_name, bprm_buf + eppnt->p_offset,
76
- return a;
83
- eppnt->p_filesz);
77
+ return ret;
84
- } else {
78
85
- retval = pread(image_fd, interp_name, eppnt->p_filesz,
79
default_nan:
86
- eppnt->p_offset);
80
parts_default_nan(a, s);
87
- if (retval != eppnt->p_filesz) {
88
- goto exit_perror;
89
- }
90
- }
91
- if (interp_name[eppnt->p_filesz - 1] != 0) {
92
- errmsg = "Invalid PT_INTERP entry";
93
- goto exit_errmsg;
94
- }
95
- *pinterp_name = g_steal_pointer(&interp_name);
96
#ifdef TARGET_MIPS
97
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
98
Mips_elf_abiflags_v0 abiflags;
99
--
81
--
100
2.20.1
82
2.34.1
101
83
102
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
Use the new generic support for NT_GNU_PROPERTY_TYPE_0.
3
While all indices into val[] should be in [0-2], the mask
4
applied is two bits. To help static analysis see there is
5
no possibility of read beyond the end of the array, pad the
6
array to 4 entries, with the final being (implicitly) NULL.
4
7
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201016184207.786698-12-richard.henderson@linaro.org
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20241203203949.483774-6-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
12
---
10
linux-user/elfload.c | 48 ++++++++++++++++++++++++++++++++++++++++++--
13
fpu/softfloat-parts.c.inc | 2 +-
11
1 file changed, 46 insertions(+), 2 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
12
15
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
18
--- a/fpu/softfloat-parts.c.inc
16
+++ b/linux-user/elfload.c
19
+++ b/fpu/softfloat-parts.c.inc
17
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
18
21
}
19
#include "elf.h"
22
ret = c;
20
23
} else {
21
+/* We must delay the following stanzas until after "elf.h". */
24
- FloatPartsN *val[3] = { a, b, c };
22
+#if defined(TARGET_AARCH64)
25
+ FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
23
+
26
Float3NaNPropRule rule = s->float_3nan_prop_rule;
24
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
27
25
+ const uint32_t *data,
28
assert(rule != float_3nan_prop_none);
26
+ struct image_info *info,
27
+ Error **errp)
28
+{
29
+ if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
30
+ if (pr_datasz != sizeof(uint32_t)) {
31
+ error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
32
+ return false;
33
+ }
34
+ /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
35
+ info->note_flags = *data;
36
+ }
37
+ return true;
38
+}
39
+#define ARCH_USE_GNU_PROPERTY 1
40
+
41
+#else
42
+
43
static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
44
const uint32_t *data,
45
struct image_info *info,
46
@@ -XXX,XX +XXX,XX @@ static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
47
}
48
#define ARCH_USE_GNU_PROPERTY 0
49
50
+#endif
51
+
52
struct exec
53
{
54
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
55
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
56
struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
57
struct elf_phdr *phdr;
58
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
59
- int i, retval;
60
+ int i, retval, prot_exec;
61
Error *err = NULL;
62
63
/* First of all, some simple consistency checks */
64
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
65
info->brk = 0;
66
info->elf_flags = ehdr->e_flags;
67
68
+ prot_exec = PROT_EXEC;
69
+#ifdef TARGET_AARCH64
70
+ /*
71
+ * If the BTI feature is present, this indicates that the executable
72
+ * pages of the startup binary should be mapped with PROT_BTI, so that
73
+ * branch targets are enforced.
74
+ *
75
+ * The startup binary is either the interpreter or the static executable.
76
+ * The interpreter is responsible for all pages of a dynamic executable.
77
+ *
78
+ * Elf notes are backward compatible to older cpus.
79
+ * Do not enable BTI unless it is supported.
80
+ */
81
+ if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
82
+ && (pinterp_name == NULL || *pinterp_name == 0)
83
+ && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
84
+ prot_exec |= TARGET_PROT_BTI;
85
+ }
86
+#endif
87
+
88
for (i = 0; i < ehdr->e_phnum; i++) {
89
struct elf_phdr *eppnt = phdr + i;
90
if (eppnt->p_type == PT_LOAD) {
91
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
92
elf_prot |= PROT_WRITE;
93
}
94
if (eppnt->p_flags & PF_X) {
95
- elf_prot |= PROT_EXEC;
96
+ elf_prot |= prot_exec;
97
}
98
99
vaddr = load_bias + eppnt->p_vaddr;
100
--
29
--
101
2.20.1
30
2.34.1
102
31
103
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
This is generic support, with the code disabled for all targets.
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
Message-id: 20201016184207.786698-11-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-7-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
linux-user/qemu.h | 4 ++
11
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++++++++
11
linux-user/elfload.c | 157 +++++++++++++++++++++++++++++++++++++++++++
12
fpu/softfloat-specialize.c.inc | 52 ----------------------------------
12
2 files changed, 161 insertions(+)
13
2 files changed, 52 insertions(+), 52 deletions(-)
13
14
14
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/qemu.h
17
--- a/fpu/softfloat.c
17
+++ b/linux-user/qemu.h
18
+++ b/fpu/softfloat.c
18
@@ -XXX,XX +XXX,XX @@ struct image_info {
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
19
abi_ulong interpreter_loadmap_addr;
20
*zExpPtr = 1 - shiftCount;
20
abi_ulong interpreter_pt_dynamic_addr;
21
}
21
struct image_info *other_info;
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
+ /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
29
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
24
+ uint32_t note_flags;
30
+{
31
+ bool aIsLargerSignificand;
32
+ FloatClass a_cls, b_cls;
25
+
33
+
26
#ifdef TARGET_MIPS
34
+ /* This is not complete, but is good enough for pickNaN. */
27
int fp_abi;
35
+ a_cls = (!floatx80_is_any_nan(a)
28
int interp_fp_abi;
36
+ ? float_class_normal
29
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
37
+ : floatx80_is_signaling_nan(a, status)
30
index XXXXXXX..XXXXXXX 100644
38
+ ? float_class_snan
31
--- a/linux-user/elfload.c
39
+ : float_class_qnan);
32
+++ b/linux-user/elfload.c
40
+ b_cls = (!floatx80_is_any_nan(b)
33
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
41
+ ? float_class_normal
34
42
+ : floatx80_is_signaling_nan(b, status)
35
#include "elf.h"
43
+ ? float_class_snan
36
44
+ : float_class_qnan);
37
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
38
+ const uint32_t *data,
39
+ struct image_info *info,
40
+ Error **errp)
41
+{
42
+ g_assert_not_reached();
43
+}
44
+#define ARCH_USE_GNU_PROPERTY 0
45
+
45
+
46
struct exec
46
+ if (is_snan(a_cls) || is_snan(b_cls)) {
47
{
47
+ float_raise(float_flag_invalid, status);
48
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
49
@@ -XXX,XX +XXX,XX @@ void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
50
"@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
51
}
52
53
+enum {
54
+ /* The string "GNU\0" as a magic number. */
55
+ GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16),
56
+ NOTE_DATA_SZ = 1 * KiB,
57
+ NOTE_NAME_SZ = 4,
58
+ ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8,
59
+};
60
+
61
+/*
62
+ * Process a single gnu_property entry.
63
+ * Return false for error.
64
+ */
65
+static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
66
+ struct image_info *info, bool have_prev_type,
67
+ uint32_t *prev_type, Error **errp)
68
+{
69
+ uint32_t pr_type, pr_datasz, step;
70
+
71
+ if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) {
72
+ goto error_data;
73
+ }
74
+ datasz -= *off;
75
+ data += *off / sizeof(uint32_t);
76
+
77
+ if (datasz < 2 * sizeof(uint32_t)) {
78
+ goto error_data;
79
+ }
80
+ pr_type = data[0];
81
+ pr_datasz = data[1];
82
+ data += 2;
83
+ datasz -= 2 * sizeof(uint32_t);
84
+ step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN);
85
+ if (step > datasz) {
86
+ goto error_data;
87
+ }
48
+ }
88
+
49
+
89
+ /* Properties are supposed to be unique and sorted on pr_type. */
50
+ if (status->default_nan_mode) {
90
+ if (have_prev_type && pr_type <= *prev_type) {
51
+ return floatx80_default_nan(status);
91
+ if (pr_type == *prev_type) {
92
+ error_setg(errp, "Duplicate property in PT_GNU_PROPERTY");
93
+ } else {
94
+ error_setg(errp, "Unsorted property in PT_GNU_PROPERTY");
95
+ }
96
+ return false;
97
+ }
98
+ *prev_type = pr_type;
99
+
100
+ if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) {
101
+ return false;
102
+ }
52
+ }
103
+
53
+
104
+ *off += 2 * sizeof(uint32_t) + step;
54
+ if (a.low < b.low) {
105
+ return true;
55
+ aIsLargerSignificand = 0;
106
+
56
+ } else if (b.low < a.low) {
107
+ error_data:
57
+ aIsLargerSignificand = 1;
108
+ error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY");
58
+ } else {
109
+ return false;
59
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
110
+}
111
+
112
+/* Process NT_GNU_PROPERTY_TYPE_0. */
113
+static bool parse_elf_properties(int image_fd,
114
+ struct image_info *info,
115
+ const struct elf_phdr *phdr,
116
+ char bprm_buf[BPRM_BUF_SIZE],
117
+ Error **errp)
118
+{
119
+ union {
120
+ struct elf_note nhdr;
121
+ uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)];
122
+ } note;
123
+
124
+ int n, off, datasz;
125
+ bool have_prev_type;
126
+ uint32_t prev_type;
127
+
128
+ /* Unless the arch requires properties, ignore them. */
129
+ if (!ARCH_USE_GNU_PROPERTY) {
130
+ return true;
131
+ }
60
+ }
132
+
61
+
133
+ /* If the properties are crazy large, that's too bad. */
62
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
134
+ n = phdr->p_filesz;
63
+ if (is_snan(b_cls)) {
135
+ if (n > sizeof(note)) {
64
+ return floatx80_silence_nan(b, status);
136
+ error_setg(errp, "PT_GNU_PROPERTY too large");
65
+ }
137
+ return false;
66
+ return b;
138
+ }
139
+ if (n < sizeof(note.nhdr)) {
140
+ error_setg(errp, "PT_GNU_PROPERTY too small");
141
+ return false;
142
+ }
143
+
144
+ if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
145
+ memcpy(&note, bprm_buf + phdr->p_offset, n);
146
+ } else {
67
+ } else {
147
+ ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
68
+ if (is_snan(a_cls)) {
148
+ if (len != n) {
69
+ return floatx80_silence_nan(a, status);
149
+ error_setg_errno(errp, errno, "Error reading file header");
150
+ return false;
151
+ }
70
+ }
152
+ }
71
+ return a;
153
+
154
+ /*
155
+ * The contents of a valid PT_GNU_PROPERTY is a sequence
156
+ * of uint32_t -- swap them all now.
157
+ */
158
+#ifdef BSWAP_NEEDED
159
+ for (int i = 0; i < n / 4; i++) {
160
+ bswap32s(note.data + i);
161
+ }
162
+#endif
163
+
164
+ /*
165
+ * Note that nhdr is 3 words, and that the "name" described by namesz
166
+ * immediately follows nhdr and is thus at the 4th word. Further, all
167
+ * of the inputs to the kernel's round_up are multiples of 4.
168
+ */
169
+ if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
170
+ note.nhdr.n_namesz != NOTE_NAME_SZ ||
171
+ note.data[3] != GNU0_MAGIC) {
172
+ error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
173
+ return false;
174
+ }
175
+ off = sizeof(note.nhdr) + NOTE_NAME_SZ;
176
+
177
+ datasz = note.nhdr.n_descsz + off;
178
+ if (datasz > n) {
179
+ error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
180
+ return false;
181
+ }
182
+
183
+ have_prev_type = false;
184
+ prev_type = 0;
185
+ while (1) {
186
+ if (off == datasz) {
187
+ return true; /* end, exit ok */
188
+ }
189
+ if (!parse_elf_property(note.data, &off, datasz, info,
190
+ have_prev_type, &prev_type, errp)) {
191
+ return false;
192
+ }
193
+ have_prev_type = true;
194
+ }
72
+ }
195
+}
73
+}
196
+
74
+
197
/* Load an ELF image into the address space.
75
/*----------------------------------------------------------------------------
198
76
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
199
IMAGE_NAME is the filename of the image, to use in error messages.
77
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
200
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
78
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
201
goto exit_errmsg;
79
index XXXXXXX..XXXXXXX 100644
202
}
80
--- a/fpu/softfloat-specialize.c.inc
203
*pinterp_name = g_steal_pointer(&interp_name);
81
+++ b/fpu/softfloat-specialize.c.inc
204
+ } else if (eppnt->p_type == PT_GNU_PROPERTY) {
82
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
205
+ if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
83
return a;
206
+ goto exit_errmsg;
84
}
207
+ }
85
208
}
86
-/*----------------------------------------------------------------------------
209
}
87
-| Takes two extended double-precision floating-point values `a' and `b', one
210
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.
211
--
141
--
212
2.20.1
142
2.34.1
213
214
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Fixing this now will clarify following patches.
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.
4
6
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20241203203949.483774-8-richard.henderson@linaro.org
7
Message-id: 20201016184207.786698-6-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
linux-user/elfload.c | 12 +++++++++---
12
fpu/softfloat.c | 43 +++++--------------------------------------
11
1 file changed, 9 insertions(+), 3 deletions(-)
13
1 file changed, 5 insertions(+), 38 deletions(-)
12
14
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
17
--- a/fpu/softfloat.c
16
+++ b/linux-user/elfload.c
18
+++ b/fpu/softfloat.c
17
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
18
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
20
19
int elf_prot = 0;
21
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
20
22
{
21
- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
23
- bool aIsLargerSignificand;
22
- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
24
- FloatClass a_cls, b_cls;
23
- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
25
+ FloatParts128 pa, pb, *pr;
24
+ if (eppnt->p_flags & PF_R) {
26
25
+ elf_prot |= PROT_READ;
27
- /* This is not complete, but is good enough for pickNaN. */
26
+ }
28
- a_cls = (!floatx80_is_any_nan(a)
27
+ if (eppnt->p_flags & PF_W) {
29
- ? float_class_normal
28
+ elf_prot |= PROT_WRITE;
30
- : floatx80_is_signaling_nan(a, status)
29
+ }
31
- ? float_class_snan
30
+ if (eppnt->p_flags & PF_X) {
32
- : float_class_qnan);
31
+ elf_prot |= PROT_EXEC;
33
- b_cls = (!floatx80_is_any_nan(b)
32
+ }
34
- ? float_class_normal
33
35
- : floatx80_is_signaling_nan(b, status)
34
vaddr = load_bias + eppnt->p_vaddr;
36
- ? float_class_snan
35
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
37
- : float_class_qnan);
38
-
39
- if (is_snan(a_cls) || is_snan(b_cls)) {
40
- float_raise(float_flag_invalid, status);
41
- }
42
-
43
- if (status->default_nan_mode) {
44
+ if (!floatx80_unpack_canonical(&pa, a, status) ||
45
+ !floatx80_unpack_canonical(&pb, b, status)) {
46
return floatx80_default_nan(status);
47
}
48
49
- if (a.low < b.low) {
50
- aIsLargerSignificand = 0;
51
- } else if (b.low < a.low) {
52
- aIsLargerSignificand = 1;
53
- } else {
54
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
55
- }
56
-
57
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
58
- if (is_snan(b_cls)) {
59
- return floatx80_silence_nan(b, status);
60
- }
61
- return b;
62
- } else {
63
- if (is_snan(a_cls)) {
64
- return floatx80_silence_nan(a, status);
65
- }
66
- return a;
67
- }
68
+ pr = parts_pick_nan(&pa, &pb, status);
69
+ return floatx80_round_pack_canonical(pr, status);
70
}
71
72
/*----------------------------------------------------------------------------
36
--
73
--
37
2.20.1
74
2.34.1
38
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
On ARM, the Top Byte Ignore feature means that only 56 bits of
3
Inline pickNaN into its only caller. This makes one assert
4
the address are significant in the virtual address. We are
4
redundant with the immediately preceding IF.
5
required to give the entire 64-bit address to FAR_ELx on fault,
6
which means that we do not "clean" the top byte early in TCG.
7
8
This new interface allows us to flush all 256 possible aliases
9
for a given page, currently missed by tlb_flush_page*.
10
5
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241203203949.483774-9-richard.henderson@linaro.org
14
Message-id: 20201016210754.818257-2-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
10
---
17
include/exec/exec-all.h | 36 ++++++
11
fpu/softfloat-parts.c.inc | 82 +++++++++++++++++++++++++----
18
accel/tcg/cputlb.c | 275 ++++++++++++++++++++++++++++++++++++++--
12
fpu/softfloat-specialize.c.inc | 96 ----------------------------------
19
2 files changed, 302 insertions(+), 9 deletions(-)
13
2 files changed, 73 insertions(+), 105 deletions(-)
20
14
21
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
15
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/include/exec/exec-all.h
17
--- a/fpu/softfloat-parts.c.inc
24
+++ b/include/exec/exec-all.h
18
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *cpu, uint16_t idxmap);
19
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
26
* depend on when the guests translation ends the TB.
20
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
27
*/
21
float_status *s)
28
void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
22
{
23
+ int cmp, which;
29
+
24
+
30
+/**
25
if (is_snan(a->cls) || is_snan(b->cls)) {
31
+ * tlb_flush_page_bits_by_mmuidx
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
32
+ * @cpu: CPU whose TLB should be flushed
27
}
33
+ * @addr: virtual address of page to be flushed
28
34
+ * @idxmap: bitmap of mmu indexes to flush
29
if (s->default_nan_mode) {
35
+ * @bits: number of significant bits in address
30
parts_default_nan(a, s);
36
+ *
31
- } else {
37
+ * Similar to tlb_flush_page_mask, but with a bitmap of indexes.
32
- int cmp = frac_cmp(a, b);
38
+ */
33
- if (cmp == 0) {
39
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
34
- cmp = a->sign < b->sign;
40
+ uint16_t idxmap, unsigned bits);
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
+ }
41
+
46
+
42
+/* Similarly, with broadcast and syncing. */
47
+ switch (s->float_2nan_prop_rule) {
43
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu, target_ulong addr,
48
+ case float_2nan_prop_s_ab:
44
+ uint16_t idxmap, unsigned bits);
49
if (is_snan(a->cls)) {
45
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced
50
- parts_silence_nan(a, s);
46
+ (CPUState *cpu, target_ulong addr, uint16_t idxmap, unsigned bits);
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
+ }
47
+
108
+
48
/**
109
+ if (which) {
49
* tlb_set_page_with_attrs:
110
+ a = b;
50
* @cpu: CPU to add this TLB entry for
111
+ }
51
@@ -XXX,XX +XXX,XX @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
112
+ if (is_snan(a->cls)) {
52
uint16_t idxmap)
113
+ parts_silence_nan(a, s);
53
{
114
}
115
return a;
54
}
116
}
55
+static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu,
117
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
56
+ target_ulong addr,
57
+ uint16_t idxmap,
58
+ unsigned bits)
59
+{
60
+}
61
+static inline void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu,
62
+ target_ulong addr,
63
+ uint16_t idxmap,
64
+ unsigned bits)
65
+{
66
+}
67
+static inline void
68
+tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, target_ulong addr,
69
+ uint16_t idxmap, unsigned bits)
70
+{
71
+}
72
#endif
73
/**
74
* probe_access:
75
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
76
index XXXXXXX..XXXXXXX 100644
118
index XXXXXXX..XXXXXXX 100644
77
--- a/accel/tcg/cputlb.c
119
--- a/fpu/softfloat-specialize.c.inc
78
+++ b/accel/tcg/cputlb.c
120
+++ b/fpu/softfloat-specialize.c.inc
79
@@ -XXX,XX +XXX,XX @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu)
121
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
80
tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS);
81
}
82
83
+static bool tlb_hit_page_mask_anyprot(CPUTLBEntry *tlb_entry,
84
+ target_ulong page, target_ulong mask)
85
+{
86
+ page &= mask;
87
+ mask &= TARGET_PAGE_MASK | TLB_INVALID_MASK;
88
+
89
+ return (page == (tlb_entry->addr_read & mask) ||
90
+ page == (tlb_addr_write(tlb_entry) & mask) ||
91
+ page == (tlb_entry->addr_code & mask));
92
+}
93
+
94
static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
95
target_ulong page)
96
{
97
- return tlb_hit_page(tlb_entry->addr_read, page) ||
98
- tlb_hit_page(tlb_addr_write(tlb_entry), page) ||
99
- tlb_hit_page(tlb_entry->addr_code, page);
100
+ return tlb_hit_page_mask_anyprot(tlb_entry, page, -1);
101
}
102
103
/**
104
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_entry_is_empty(const CPUTLBEntry *te)
105
}
106
107
/* Called with tlb_c.lock held */
108
-static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
109
- target_ulong page)
110
+static bool tlb_flush_entry_mask_locked(CPUTLBEntry *tlb_entry,
111
+ target_ulong page,
112
+ target_ulong mask)
113
{
114
- if (tlb_hit_page_anyprot(tlb_entry, page)) {
115
+ if (tlb_hit_page_mask_anyprot(tlb_entry, page, mask)) {
116
memset(tlb_entry, -1, sizeof(*tlb_entry));
117
return true;
118
}
119
return false;
120
}
121
122
+static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
123
+ target_ulong page)
124
+{
125
+ return tlb_flush_entry_mask_locked(tlb_entry, page, -1);
126
+}
127
+
128
/* Called with tlb_c.lock held */
129
-static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
130
- target_ulong page)
131
+static void tlb_flush_vtlb_page_mask_locked(CPUArchState *env, int mmu_idx,
132
+ target_ulong page,
133
+ target_ulong mask)
134
{
135
CPUTLBDesc *d = &env_tlb(env)->d[mmu_idx];
136
int k;
137
138
assert_cpu_is_self(env_cpu(env));
139
for (k = 0; k < CPU_VTLB_SIZE; k++) {
140
- if (tlb_flush_entry_locked(&d->vtable[k], page)) {
141
+ if (tlb_flush_entry_mask_locked(&d->vtable[k], page, mask)) {
142
tlb_n_used_entries_dec(env, mmu_idx);
143
}
144
}
122
}
145
}
123
}
146
124
147
+static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
125
-/*----------------------------------------------------------------------------
148
+ target_ulong page)
126
-| Select which NaN to propagate for a two-input operation.
149
+{
127
-| IEEE754 doesn't specify all the details of this, so the
150
+ tlb_flush_vtlb_page_mask_locked(env, mmu_idx, page, -1);
128
-| algorithm is target-specific.
151
+}
129
-| The routine is passed various bits of information about the
152
+
130
-| two NaNs and should return 0 to select NaN a and 1 for NaN b.
153
static void tlb_flush_page_locked(CPUArchState *env, int midx,
131
-| Note that signalling NaNs are always squashed to quiet NaNs
154
target_ulong page)
132
-| by the caller, by calling floatXX_silence_nan() before
155
{
133
-| returning them.
156
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
134
-|
157
tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
135
-| aIsLargerSignificand is only valid if both a and b are NaNs
158
}
136
-| of some kind, and is true if a has the larger significand,
159
137
-| or if both a and b have the same significand but a is
160
+static void tlb_flush_page_bits_locked(CPUArchState *env, int midx,
138
-| positive but b is negative. It is only needed for the x87
161
+ target_ulong page, unsigned bits)
139
-| tie-break rule.
162
+{
140
-*----------------------------------------------------------------------------*/
163
+ CPUTLBDesc *d = &env_tlb(env)->d[midx];
141
-
164
+ CPUTLBDescFast *f = &env_tlb(env)->f[midx];
142
-static int pickNaN(FloatClass a_cls, FloatClass b_cls,
165
+ target_ulong mask = MAKE_64BIT_MASK(0, bits);
143
- bool aIsLargerSignificand, float_status *status)
166
+
144
-{
167
+ /*
145
- /*
168
+ * If @bits is smaller than the tlb size, there may be multiple entries
146
- * We guarantee not to require the target to tell us how to
169
+ * within the TLB; otherwise all addresses that match under @mask hit
147
- * pick a NaN if we're always returning the default NaN.
170
+ * the same TLB entry.
148
- * But if we're not in default-NaN mode then the target must
171
+ *
149
- * specify via set_float_2nan_prop_rule().
172
+ * TODO: Perhaps allow bits to be a few bits less than the size.
150
- */
173
+ * For now, just flush the entire TLB.
151
- assert(!status->default_nan_mode);
174
+ */
152
-
175
+ if (mask < f->mask) {
153
- switch (status->float_2nan_prop_rule) {
176
+ tlb_debug("forcing full flush midx %d ("
154
- case float_2nan_prop_s_ab:
177
+ TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
155
- if (is_snan(a_cls)) {
178
+ midx, page, mask);
156
- return 0;
179
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
157
- } else if (is_snan(b_cls)) {
180
+ return;
158
- return 1;
181
+ }
159
- } else if (is_qnan(a_cls)) {
182
+
160
- return 0;
183
+ /* Check if we need to flush due to large pages. */
161
- } else {
184
+ if ((page & d->large_page_mask) == d->large_page_addr) {
162
- return 1;
185
+ tlb_debug("forcing full flush midx %d ("
163
- }
186
+ TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
164
- break;
187
+ midx, d->large_page_addr, d->large_page_mask);
165
- case float_2nan_prop_s_ba:
188
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
166
- if (is_snan(b_cls)) {
189
+ return;
167
- return 1;
190
+ }
168
- } else if (is_snan(a_cls)) {
191
+
169
- return 0;
192
+ if (tlb_flush_entry_mask_locked(tlb_entry(env, midx, page), page, mask)) {
170
- } else if (is_qnan(b_cls)) {
193
+ tlb_n_used_entries_dec(env, midx);
171
- return 1;
194
+ }
172
- } else {
195
+ tlb_flush_vtlb_page_mask_locked(env, midx, page, mask);
173
- return 0;
196
+}
174
- }
197
+
175
- break;
198
+typedef struct {
176
- case float_2nan_prop_ab:
199
+ target_ulong addr;
177
- if (is_nan(a_cls)) {
200
+ uint16_t idxmap;
178
- return 0;
201
+ uint16_t bits;
179
- } else {
202
+} TLBFlushPageBitsByMMUIdxData;
180
- return 1;
203
+
181
- }
204
+static void
182
- break;
205
+tlb_flush_page_bits_by_mmuidx_async_0(CPUState *cpu,
183
- case float_2nan_prop_ba:
206
+ TLBFlushPageBitsByMMUIdxData d)
184
- if (is_nan(b_cls)) {
207
+{
185
- return 1;
208
+ CPUArchState *env = cpu->env_ptr;
186
- } else {
209
+ int mmu_idx;
187
- return 0;
210
+
188
- }
211
+ assert_cpu_is_self(cpu);
189
- break;
212
+
190
- case float_2nan_prop_x87:
213
+ tlb_debug("page addr:" TARGET_FMT_lx "/%u mmu_map:0x%x\n",
191
- /*
214
+ d.addr, d.bits, d.idxmap);
192
- * This implements x87 NaN propagation rules:
215
+
193
- * SNaN + QNaN => return the QNaN
216
+ qemu_spin_lock(&env_tlb(env)->c.lock);
194
- * two SNaNs => return the one with the larger significand, silenced
217
+ for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
195
- * two QNaNs => return the one with the larger significand
218
+ if ((d.idxmap >> mmu_idx) & 1) {
196
- * SNaN and a non-NaN => return the SNaN, silenced
219
+ tlb_flush_page_bits_locked(env, mmu_idx, d.addr, d.bits);
197
- * QNaN and a non-NaN => return the QNaN
220
+ }
198
- *
221
+ }
199
- * If we get down to comparing significands and they are the same,
222
+ qemu_spin_unlock(&env_tlb(env)->c.lock);
200
- * return the NaN with the positive sign bit (if any).
223
+
201
- */
224
+ tb_flush_jmp_cache(cpu, d.addr);
202
- if (is_snan(a_cls)) {
225
+}
203
- if (is_snan(b_cls)) {
226
+
204
- return aIsLargerSignificand ? 0 : 1;
227
+static bool encode_pbm_to_runon(run_on_cpu_data *out,
205
- }
228
+ TLBFlushPageBitsByMMUIdxData d)
206
- return is_qnan(b_cls) ? 1 : 0;
229
+{
207
- } else if (is_qnan(a_cls)) {
230
+ /* We need 6 bits to hold to hold @bits up to 63. */
208
- if (is_snan(b_cls) || !is_qnan(b_cls)) {
231
+ if (d.idxmap <= MAKE_64BIT_MASK(0, TARGET_PAGE_BITS - 6)) {
209
- return 0;
232
+ *out = RUN_ON_CPU_TARGET_PTR(d.addr | (d.idxmap << 6) | d.bits);
210
- } else {
233
+ return true;
211
- return aIsLargerSignificand ? 0 : 1;
234
+ }
212
- }
235
+ return false;
213
- } else {
236
+}
214
- return 1;
237
+
215
- }
238
+static TLBFlushPageBitsByMMUIdxData
216
- default:
239
+decode_runon_to_pbm(run_on_cpu_data data)
217
- g_assert_not_reached();
240
+{
218
- }
241
+ target_ulong addr_map_bits = (target_ulong) data.target_ptr;
219
-}
242
+ return (TLBFlushPageBitsByMMUIdxData){
220
-
243
+ .addr = addr_map_bits & TARGET_PAGE_MASK,
221
/*----------------------------------------------------------------------------
244
+ .idxmap = (addr_map_bits & ~TARGET_PAGE_MASK) >> 6,
222
| Returns 1 if the double-precision floating-point value `a' is a quiet
245
+ .bits = addr_map_bits & 0x3f
223
| NaN; otherwise returns 0.
246
+ };
247
+}
248
+
249
+static void tlb_flush_page_bits_by_mmuidx_async_1(CPUState *cpu,
250
+ run_on_cpu_data runon)
251
+{
252
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, decode_runon_to_pbm(runon));
253
+}
254
+
255
+static void tlb_flush_page_bits_by_mmuidx_async_2(CPUState *cpu,
256
+ run_on_cpu_data data)
257
+{
258
+ TLBFlushPageBitsByMMUIdxData *d = data.host_ptr;
259
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, *d);
260
+ g_free(d);
261
+}
262
+
263
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
264
+ uint16_t idxmap, unsigned bits)
265
+{
266
+ TLBFlushPageBitsByMMUIdxData d;
267
+ run_on_cpu_data runon;
268
+
269
+ /* If all bits are significant, this devolves to tlb_flush_page. */
270
+ if (bits >= TARGET_LONG_BITS) {
271
+ tlb_flush_page_by_mmuidx(cpu, addr, idxmap);
272
+ return;
273
+ }
274
+ /* If no page bits are significant, this devolves to tlb_flush. */
275
+ if (bits < TARGET_PAGE_BITS) {
276
+ tlb_flush_by_mmuidx(cpu, idxmap);
277
+ return;
278
+ }
279
+
280
+ /* This should already be page aligned */
281
+ d.addr = addr & TARGET_PAGE_MASK;
282
+ d.idxmap = idxmap;
283
+ d.bits = bits;
284
+
285
+ if (qemu_cpu_is_self(cpu)) {
286
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, d);
287
+ } else if (encode_pbm_to_runon(&runon, d)) {
288
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
289
+ } else {
290
+ TLBFlushPageBitsByMMUIdxData *p
291
+ = g_new(TLBFlushPageBitsByMMUIdxData, 1);
292
+
293
+ /* Otherwise allocate a structure, freed by the worker. */
294
+ *p = d;
295
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_2,
296
+ RUN_ON_CPU_HOST_PTR(p));
297
+ }
298
+}
299
+
300
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu,
301
+ target_ulong addr,
302
+ uint16_t idxmap,
303
+ unsigned bits)
304
+{
305
+ TLBFlushPageBitsByMMUIdxData d;
306
+ run_on_cpu_data runon;
307
+
308
+ /* If all bits are significant, this devolves to tlb_flush_page. */
309
+ if (bits >= TARGET_LONG_BITS) {
310
+ tlb_flush_page_by_mmuidx_all_cpus(src_cpu, addr, idxmap);
311
+ return;
312
+ }
313
+ /* If no page bits are significant, this devolves to tlb_flush. */
314
+ if (bits < TARGET_PAGE_BITS) {
315
+ tlb_flush_by_mmuidx_all_cpus(src_cpu, idxmap);
316
+ return;
317
+ }
318
+
319
+ /* This should already be page aligned */
320
+ d.addr = addr & TARGET_PAGE_MASK;
321
+ d.idxmap = idxmap;
322
+ d.bits = bits;
323
+
324
+ if (encode_pbm_to_runon(&runon, d)) {
325
+ flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
326
+ } else {
327
+ CPUState *dst_cpu;
328
+ TLBFlushPageBitsByMMUIdxData *p;
329
+
330
+ /* Allocate a separate data block for each destination cpu. */
331
+ CPU_FOREACH(dst_cpu) {
332
+ if (dst_cpu != src_cpu) {
333
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
334
+ *p = d;
335
+ async_run_on_cpu(dst_cpu,
336
+ tlb_flush_page_bits_by_mmuidx_async_2,
337
+ RUN_ON_CPU_HOST_PTR(p));
338
+ }
339
+ }
340
+ }
341
+
342
+ tlb_flush_page_bits_by_mmuidx_async_0(src_cpu, d);
343
+}
344
+
345
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
346
+ target_ulong addr,
347
+ uint16_t idxmap,
348
+ unsigned bits)
349
+{
350
+ TLBFlushPageBitsByMMUIdxData d;
351
+ run_on_cpu_data runon;
352
+
353
+ /* If all bits are significant, this devolves to tlb_flush_page. */
354
+ if (bits >= TARGET_LONG_BITS) {
355
+ tlb_flush_page_by_mmuidx_all_cpus_synced(src_cpu, addr, idxmap);
356
+ return;
357
+ }
358
+ /* If no page bits are significant, this devolves to tlb_flush. */
359
+ if (bits < TARGET_PAGE_BITS) {
360
+ tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, idxmap);
361
+ return;
362
+ }
363
+
364
+ /* This should already be page aligned */
365
+ d.addr = addr & TARGET_PAGE_MASK;
366
+ d.idxmap = idxmap;
367
+ d.bits = bits;
368
+
369
+ if (encode_pbm_to_runon(&runon, d)) {
370
+ flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
371
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1,
372
+ runon);
373
+ } else {
374
+ CPUState *dst_cpu;
375
+ TLBFlushPageBitsByMMUIdxData *p;
376
+
377
+ /* Allocate a separate data block for each destination cpu. */
378
+ CPU_FOREACH(dst_cpu) {
379
+ if (dst_cpu != src_cpu) {
380
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
381
+ *p = d;
382
+ async_run_on_cpu(dst_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
383
+ RUN_ON_CPU_HOST_PTR(p));
384
+ }
385
+ }
386
+
387
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
388
+ *p = d;
389
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
390
+ RUN_ON_CPU_HOST_PTR(p));
391
+ }
392
+}
393
+
394
/* update the TLBs so that writes to code in the virtual page 'addr'
395
can be detected */
396
void tlb_protect_code(ram_addr_t ram_addr)
397
--
224
--
398
2.20.1
225
2.34.1
399
226
400
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
Unlike many other bits in HCR_EL2, the description for this
3
Remember if there was an SNaN, and use that to simplify
4
bit does not contain the phrase "if ... this field behaves
4
float_2nan_prop_s_{ab,ba} to only the snan component.
5
as 0 for all purposes other than", so do not squash the bit
5
Then, fall through to the corresponding
6
in arm_hcr_el2_eff.
6
float_2nan_prop_{ab,ba} case to handle any remaining
7
nans, which must be quiet.
7
8
8
Instead, replicate the E2H+TGE test in the two places that
9
require it.
10
11
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
11
Message-id: 20241203203949.483774-10-richard.henderson@linaro.org
15
Message-id: 20201008162155.161886-4-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
13
---
18
target/arm/internals.h | 9 +++++----
14
fpu/softfloat-parts.c.inc | 32 ++++++++++++--------------------
19
target/arm/helper.c | 9 +++++----
15
1 file changed, 12 insertions(+), 20 deletions(-)
20
2 files changed, 10 insertions(+), 8 deletions(-)
21
16
22
diff --git a/target/arm/internals.h b/target/arm/internals.h
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
23
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/internals.h
19
--- a/fpu/softfloat-parts.c.inc
25
+++ b/target/arm/internals.h
20
+++ b/fpu/softfloat-parts.c.inc
26
@@ -XXX,XX +XXX,XX @@ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
21
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
27
&& !(env->cp15.scr_el3 & SCR_ATA)) {
22
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
28
return false;
23
float_status *s)
24
{
25
+ bool have_snan = false;
26
int cmp, which;
27
28
if (is_snan(a->cls) || is_snan(b->cls)) {
29
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
30
+ have_snan = true;
29
}
31
}
30
- if (el < 2
32
31
- && arm_feature(env, ARM_FEATURE_EL2)
33
if (s->default_nan_mode) {
32
- && !(arm_hcr_el2_eff(env) & HCR_ATA)) {
34
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
33
- return false;
35
34
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
36
switch (s->float_2nan_prop_rule) {
35
+ uint64_t hcr = arm_hcr_el2_eff(env);
37
case float_2nan_prop_s_ab:
36
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
38
- if (is_snan(a->cls)) {
37
+ return false;
39
- which = 0;
40
- } else if (is_snan(b->cls)) {
41
- which = 1;
42
- } else if (is_qnan(a->cls)) {
43
- which = 0;
44
- } else {
45
- which = 1;
46
+ if (have_snan) {
47
+ which = is_snan(a->cls) ? 0 : 1;
48
+ break;
49
}
50
- break;
51
- case float_2nan_prop_s_ba:
52
- if (is_snan(b->cls)) {
53
- which = 1;
54
- } else if (is_snan(a->cls)) {
55
- which = 0;
56
- } else if (is_qnan(b->cls)) {
57
- which = 1;
58
- } else {
59
- which = 0;
60
- }
61
- break;
62
+ /* fall through */
63
case float_2nan_prop_ab:
64
which = is_nan(a->cls) ? 0 : 1;
65
break;
66
+ case float_2nan_prop_s_ba:
67
+ if (have_snan) {
68
+ which = is_snan(b->cls) ? 1 : 0;
69
+ break;
38
+ }
70
+ }
39
}
71
+ /* fall through */
40
sctlr &= (el == 0 ? SCTLR_ATA0 : SCTLR_ATA);
72
case float_2nan_prop_ba:
41
return sctlr != 0;
73
which = is_nan(b->cls) ? 1 : 0;
42
diff --git a/target/arm/helper.c b/target/arm/helper.c
74
break;
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/helper.c
45
+++ b/target/arm/helper.c
46
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri,
47
{
48
int el = arm_current_el(env);
49
50
- if (el < 2 &&
51
- arm_feature(env, ARM_FEATURE_EL2) &&
52
- !(arm_hcr_el2_eff(env) & HCR_ATA)) {
53
- return CP_ACCESS_TRAP_EL2;
54
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
55
+ uint64_t hcr = arm_hcr_el2_eff(env);
56
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
57
+ return CP_ACCESS_TRAP_EL2;
58
+ }
59
}
60
if (el < 3 &&
61
arm_feature(env, ARM_FEATURE_EL3) &&
62
--
75
--
63
2.20.1
76
2.34.1
64
65
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We already have the full ARMMMUIdx as computed from the
3
Move the fractional comparison to the end of the
4
function parameter.
4
float_2nan_prop_x87 case. This is not required for
5
5
any other 2nan propagation rule. Reorganize the
6
For the purpose of regime_has_2_ranges, we can ignore any
6
x87 case itself to break out of the switch when the
7
difference between AccType_Normal and AccType_Unpriv, which
7
fractional comparison is not required.
8
would be the only difference between the passed mmu_idx
9
and arm_mmu_idx_el.
10
8
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
11
Message-id: 20241203203949.483774-11-richard.henderson@linaro.org
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-2-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
13
---
18
target/arm/mte_helper.c | 3 +--
14
fpu/softfloat-parts.c.inc | 19 +++++++++----------
19
1 file changed, 1 insertion(+), 2 deletions(-)
15
1 file changed, 9 insertions(+), 10 deletions(-)
20
16
21
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
22
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/mte_helper.c
19
--- a/fpu/softfloat-parts.c.inc
24
+++ b/target/arm/mte_helper.c
20
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
21
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
26
22
return a;
27
case 2:
23
}
28
/* Tag check fail causes asynchronous flag set. */
24
29
- mmu_idx = arm_mmu_idx_el(env, el);
25
- cmp = frac_cmp(a, b);
30
- if (regime_has_2_ranges(mmu_idx)) {
26
- if (cmp == 0) {
31
+ if (regime_has_2_ranges(arm_mmu_idx)) {
27
- cmp = a->sign < b->sign;
32
select = extract64(dirty_ptr, 55, 1);
28
- }
29
-
30
switch (s->float_2nan_prop_rule) {
31
case float_2nan_prop_s_ab:
32
if (have_snan) {
33
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
34
* return the NaN with the positive sign bit (if any).
35
*/
36
if (is_snan(a->cls)) {
37
- if (is_snan(b->cls)) {
38
- which = cmp > 0 ? 0 : 1;
39
- } else {
40
+ if (!is_snan(b->cls)) {
41
which = is_qnan(b->cls) ? 1 : 0;
42
+ break;
43
}
44
} else if (is_qnan(a->cls)) {
45
if (is_snan(b->cls) || !is_qnan(b->cls)) {
46
which = 0;
47
- } else {
48
- which = cmp > 0 ? 0 : 1;
49
+ break;
50
}
33
} else {
51
} else {
34
select = 0;
52
which = 1;
53
+ break;
54
}
55
+ cmp = frac_cmp(a, b);
56
+ if (cmp == 0) {
57
+ cmp = a->sign < b->sign;
58
+ }
59
+ which = cmp > 0 ? 0 : 1;
60
break;
61
default:
62
g_assert_not_reached();
35
--
63
--
36
2.20.1
64
2.34.1
37
38
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This is slightly clearer than just using strerror, though
3
Replace the "index" selecting between A and B with a result variable
4
the different forms produced by error_setg_file_open and
4
of the proper type. This improves clarity within the function.
5
error_setg_errno isn't entirely convenient.
6
5
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20201016184207.786698-10-richard.henderson@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
linux-user/elfload.c | 15 ++++++++-------
11
fpu/softfloat-parts.c.inc | 28 +++++++++++++---------------
13
1 file changed, 8 insertions(+), 7 deletions(-)
12
1 file changed, 13 insertions(+), 15 deletions(-)
14
13
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
16
--- a/fpu/softfloat-parts.c.inc
18
+++ b/linux-user/elfload.c
17
+++ b/fpu/softfloat-parts.c.inc
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_interp(const char *filename, struct image_info *info,
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
20
char bprm_buf[BPRM_BUF_SIZE])
19
float_status *s)
21
{
20
{
22
int fd, retval;
21
bool have_snan = false;
23
+ Error *err = NULL;
22
- int cmp, which;
24
23
+ FloatPartsN *ret;
25
fd = open(path(filename), O_RDONLY);
24
+ int cmp;
26
if (fd < 0) {
25
27
- goto exit_perror;
26
if (is_snan(a->cls) || is_snan(b->cls)) {
28
+ error_setg_file_open(&err, errno, filename);
27
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
29
+ error_report_err(err);
28
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
30
+ exit(-1);
29
switch (s->float_2nan_prop_rule) {
30
case float_2nan_prop_s_ab:
31
if (have_snan) {
32
- which = is_snan(a->cls) ? 0 : 1;
33
+ ret = is_snan(a->cls) ? a : b;
34
break;
35
}
36
/* fall through */
37
case float_2nan_prop_ab:
38
- which = is_nan(a->cls) ? 0 : 1;
39
+ ret = is_nan(a->cls) ? a : b;
40
break;
41
case float_2nan_prop_s_ba:
42
if (have_snan) {
43
- which = is_snan(b->cls) ? 1 : 0;
44
+ ret = is_snan(b->cls) ? b : a;
45
break;
46
}
47
/* fall through */
48
case float_2nan_prop_ba:
49
- which = is_nan(b->cls) ? 1 : 0;
50
+ ret = is_nan(b->cls) ? b : a;
51
break;
52
case float_2nan_prop_x87:
53
/*
54
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
55
*/
56
if (is_snan(a->cls)) {
57
if (!is_snan(b->cls)) {
58
- which = is_qnan(b->cls) ? 1 : 0;
59
+ ret = is_qnan(b->cls) ? b : a;
60
break;
61
}
62
} else if (is_qnan(a->cls)) {
63
if (is_snan(b->cls) || !is_qnan(b->cls)) {
64
- which = 0;
65
+ ret = a;
66
break;
67
}
68
} else {
69
- which = 1;
70
+ ret = b;
71
break;
72
}
73
cmp = frac_cmp(a, b);
74
if (cmp == 0) {
75
cmp = a->sign < b->sign;
76
}
77
- which = cmp > 0 ? 0 : 1;
78
+ ret = cmp > 0 ? a : b;
79
break;
80
default:
81
g_assert_not_reached();
31
}
82
}
32
83
33
retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
84
- if (which) {
34
if (retval < 0) {
85
- a = b;
35
- goto exit_perror;
86
+ if (is_snan(ret->cls)) {
36
+ error_setg_errno(&err, errno, "Error reading file header");
87
+ parts_silence_nan(ret, s);
37
+ error_reportf_err(err, "%s: ", filename);
38
+ exit(-1);
39
}
88
}
40
+
89
- if (is_snan(a->cls)) {
41
if (retval < BPRM_BUF_SIZE) {
90
- parts_silence_nan(a, s);
42
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
91
- }
43
}
92
- return a;
44
93
+ return ret;
45
load_elf_image(filename, fd, info, NULL, bprm_buf);
46
- return;
47
-
48
- exit_perror:
49
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
50
- exit(-1);
51
}
94
}
52
95
53
static int symfind(const void *s0, const void *s1)
96
static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
54
--
97
--
55
2.20.1
98
2.34.1
56
99
57
100
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
Use the BCM2835_SYSTIMER_COUNT definition instead of the
3
I'm migrating to Qualcomm's new open source email infrastructure, so
4
magic '4' value.
4
update my email address, and update the mailmap to match.
5
5
6
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
6
Signed-off-by: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
9
Message-id: 20201010203709.3116542-2-f4bug@amsat.org
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
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
include/hw/timer/bcm2835_systmr.h | 4 +++-
14
MAINTAINERS | 2 +-
13
hw/timer/bcm2835_systmr.c | 3 ++-
15
.mailmap | 5 +++--
14
2 files changed, 5 insertions(+), 2 deletions(-)
16
2 files changed, 4 insertions(+), 3 deletions(-)
15
17
16
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
18
diff --git a/MAINTAINERS b/MAINTAINERS
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/timer/bcm2835_systmr.h
20
--- a/MAINTAINERS
19
+++ b/include/hw/timer/bcm2835_systmr.h
21
+++ b/MAINTAINERS
20
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
21
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
23
SBSA-REF
22
OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
24
M: Radoslaw Biernacki <rad@semihalf.com>
23
25
M: Peter Maydell <peter.maydell@linaro.org>
24
+#define BCM2835_SYSTIMER_COUNT 4
26
-R: Leif Lindholm <quic_llindhol@quicinc.com>
25
+
27
+R: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
26
struct BCM2835SystemTimerState {
28
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
27
/*< private >*/
29
L: qemu-arm@nongnu.org
28
SysBusDevice parent_obj;
30
S: Maintained
29
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
31
diff --git a/.mailmap b/.mailmap
30
31
struct {
32
uint32_t status;
33
- uint32_t compare[4];
34
+ uint32_t compare[BCM2835_SYSTIMER_COUNT];
35
} reg;
36
};
37
38
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
39
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/timer/bcm2835_systmr.c
33
--- a/.mailmap
41
+++ b/hw/timer/bcm2835_systmr.c
34
+++ b/.mailmap
42
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
35
@@ -XXX,XX +XXX,XX @@ Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
43
.minimum_version_id = 1,
36
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
44
.fields = (VMStateField[]) {
37
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
45
VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
38
Juan Quintela <quintela@trasno.org> <quintela@redhat.com>
46
- VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4),
39
-Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
47
+ VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
40
-Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
48
+ BCM2835_SYSTIMER_COUNT),
41
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <quic_llindhol@quicinc.com>
49
VMSTATE_END_OF_LIST()
42
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif.lindholm@linaro.org>
50
}
43
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif@nuviainc.com>
51
};
44
Luc Michel <luc@lmichel.fr> <luc.michel@git.antfield.fr>
45
Luc Michel <luc@lmichel.fr> <luc.michel@greensocs.com>
46
Luc Michel <luc@lmichel.fr> <lmichel@kalray.eu>
52
--
47
--
53
2.20.1
48
2.34.1
54
49
55
50
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Vikram Garhwal <vikram.garhwal@bytedance.com>
2
2
3
While APEI is a generic ACPI feature (usable by X86 and ARM64), only
3
Previously, maintainer role was paused due to inactive email id. Commit id:
4
the 'virt' machine uses it, by enabling the RAS Virtualization. See
4
c009d715721861984c4987bcc78b7ee183e86d75.
5
commit 2afa8c8519: "hw/arm/virt: Introduce a RAS machine option").
6
5
7
Restrict the APEI tables generation code to the single user: the virt
6
Signed-off-by: Vikram Garhwal <vikram.garhwal@bytedance.com>
8
machine. If another machine wants to use it, it simply has to 'select
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
9
ACPI_APEI' in its Kconfig.
8
Message-id: 20241204184205.12952-1-vikram.garhwal@bytedance.com
10
11
Fixes: aa16508f1d ("ACPI: Build related register address fields via hardware error fw_cfg blob")
12
Acked-by: Michael S. Tsirkin <mst@redhat.com>
13
Reviewed-by: Dongjiu Geng <gengdongjiu@huawei.com>
14
Acked-by: Laszlo Ersek <lersek@redhat.com>
15
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
16
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
Message-id: 20201008161414.2672569-1-philmd@redhat.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
10
---
20
default-configs/devices/arm-softmmu.mak | 1 -
11
MAINTAINERS | 2 ++
21
hw/arm/Kconfig | 1 +
12
1 file changed, 2 insertions(+)
22
2 files changed, 1 insertion(+), 1 deletion(-)
23
13
24
diff --git a/default-configs/devices/arm-softmmu.mak b/default-configs/devices/arm-softmmu.mak
14
diff --git a/MAINTAINERS b/MAINTAINERS
25
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
26
--- a/default-configs/devices/arm-softmmu.mak
16
--- a/MAINTAINERS
27
+++ b/default-configs/devices/arm-softmmu.mak
17
+++ b/MAINTAINERS
28
@@ -XXX,XX +XXX,XX @@ CONFIG_FSL_IMX7=y
18
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-sb16-test.c
29
CONFIG_FSL_IMX6UL=y
19
30
CONFIG_SEMIHOSTING=y
20
Xilinx CAN
31
CONFIG_ALLWINNER_H3=y
21
M: Francisco Iglesias <francisco.iglesias@amd.com>
32
-CONFIG_ACPI_APEI=y
22
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
33
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
23
S: Maintained
34
index XXXXXXX..XXXXXXX 100644
24
F: hw/net/can/xlnx-*
35
--- a/hw/arm/Kconfig
25
F: include/hw/net/xlnx-*
36
+++ b/hw/arm/Kconfig
26
@@ -XXX,XX +XXX,XX @@ F: include/hw/rx/
37
@@ -XXX,XX +XXX,XX @@ config ARM_VIRT
27
CAN bus subsystem and hardware
38
select ACPI_MEMORY_HOTPLUG
28
M: Pavel Pisa <pisa@cmp.felk.cvut.cz>
39
select ACPI_HW_REDUCED
29
M: Francisco Iglesias <francisco.iglesias@amd.com>
40
select ACPI_NVDIMM
30
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
41
+ select ACPI_APEI
31
S: Maintained
42
32
W: https://canbus.pages.fel.cvut.cz/
43
config CHEETAH
33
F: net/can/*
44
bool
45
--
34
--
46
2.20.1
35
2.34.1
47
48
diff view generated by jsdifflib