1
target-arm queue; this one has a fair scattering of more
1
First arm pullreq of the cycle; this is mostly my softfloat NaN
2
miscellaneous things in it which I've sent out this week.
2
handling series. (Lots more in my to-review queue, but I don't
3
I've shoved those in as well as it seemed the least-effort
3
like pullreqs growing too close to a hundred patches at a time :-))
4
way of getting them into master; a few of them are dependencies
5
on arm-related patches I have brewing.
6
4
7
thanks
5
thanks
8
-- PMM
6
-- PMM
9
7
8
The following changes since commit 97f2796a3736ed37a1b85dc1c76a6c45b829dd17:
10
9
11
The following changes since commit 2702c2d3eb74e3908c0c5dbf3a71c8987595a86e:
10
Open 10.0 development tree (2024-12-10 17:41:17 +0000)
12
13
Merge remote-tracking branch 'remotes/stsquad/tags/pull-travis-updates-140618-1' into staging (2018-06-15 12:49:36 +0100)
14
11
15
are available in the Git repository at:
12
are available in the Git repository at:
16
13
17
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180615
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20241211
18
15
19
for you to fetch changes up to 14120108f87b3f9e1beacdf0a6096e464e62bb65:
16
for you to fetch changes up to 1abe28d519239eea5cf9620bb13149423e5665f8:
20
17
21
target/arm: Allow ARMv6-M Thumb2 instructions (2018-06-15 15:23:34 +0100)
18
MAINTAINERS: Add correct email address for Vikram Garhwal (2024-12-11 15:31:09 +0000)
22
19
23
----------------------------------------------------------------
20
----------------------------------------------------------------
24
target-arm and miscellaneous queue:
21
target-arm queue:
25
* fix KVM state save/restore for GICv3 priority registers for high IRQ numbers
22
* hw/net/lan9118: Extract PHY model, reuse with imx_fec, fix bugs
26
* hw/arm/mps2-tz: Put ethernet controller behind PPC
23
* fpu: Make muladd NaN handling runtime-selected, not compile-time
27
* hw/sh/sh7750: Convert away from old_mmio
24
* fpu: Make default NaN pattern runtime-selected, not compile-time
28
* hw/m68k/mcf5206: Convert away from old_mmio
25
* fpu: Minor NaN-related cleanups
29
* hw/block/pflash_cfi02: Convert away from old_mmio
26
* MAINTAINERS: email address updates
30
* hw/watchdog/wdt_i6300esb: Convert away from old_mmio
31
* hw/input/pckbd: Convert away from old_mmio
32
* hw/char/parallel: Convert away from old_mmio
33
* armv7m: refactor to get rid of armv7m_init() function
34
* arm: Don't crash if user tries to use a Cortex-M CPU without an NVIC
35
* hw/core/or-irq: Support more than 16 inputs to an OR gate
36
* cpu-defs.h: Document CPUIOTLBEntry 'addr' field
37
* cputlb: Pass cpu_transaction_failed() the correct physaddr
38
* CODING_STYLE: Define our preferred form for multiline comments
39
* Add and use new stn_*_p() and ldn_*_p() memory access functions
40
* target/arm: More parts of the upcoming SVE support
41
* aspeed_scu: Implement RNG register
42
* m25p80: add support for two bytes WRSR for Macronix chips
43
* exec.c: Handle IOMMUs being in the path of TCG CPU memory accesses
44
* target/arm: Allow ARMv6-M Thumb2 instructions
45
27
46
----------------------------------------------------------------
28
----------------------------------------------------------------
47
Cédric Le Goater (1):
29
Bernhard Beschow (5):
48
m25p80: add support for two bytes WRSR for Macronix chips
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
49
35
50
Joel Stanley (1):
36
Leif Lindholm (1):
51
aspeed_scu: Implement RNG register
37
MAINTAINERS: update email address for Leif Lindholm
52
38
53
Julia Suvorova (1):
39
Peter Maydell (54):
54
target/arm: Allow ARMv6-M Thumb2 instructions
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
55
94
56
Peter Maydell (21):
95
Richard Henderson (11):
57
hw/arm/mps2-tz: Put ethernet controller behind PPC
96
target/arm: Copy entire float_status in is_ebf
58
hw/sh/sh7750: Convert away from old_mmio
97
softfloat: Inline pickNaNMulAdd
59
hw/m68k/mcf5206: Convert away from old_mmio
98
softfloat: Use goto for default nan case in pick_nan_muladd
60
hw/block/pflash_cfi02: Convert away from old_mmio
99
softfloat: Remove which from parts_pick_nan_muladd
61
hw/watchdog/wdt_i6300esb: Convert away from old_mmio
100
softfloat: Pad array size in pick_nan_muladd
62
hw/input/pckbd: Convert away from old_mmio
101
softfloat: Move propagateFloatx80NaN to softfloat.c
63
hw/char/parallel: Convert away from old_mmio
102
softfloat: Use parts_pick_nan in propagateFloatx80NaN
64
stellaris: Stop using armv7m_init()
103
softfloat: Inline pickNaN
65
hw/arm/armv7m: Remove unused armv7m_init() function
104
softfloat: Share code between parts_pick_nan cases
66
arm: Don't crash if user tries to use a Cortex-M CPU without an NVIC
105
softfloat: Sink frac_cmp in parts_pick_nan until needed
67
hw/core/or-irq: Support more than 16 inputs to an OR gate
106
softfloat: Replace WHICH with RET in parts_pick_nan
68
cpu-defs.h: Document CPUIOTLBEntry 'addr' field
69
cputlb: Pass cpu_transaction_failed() the correct physaddr
70
CODING_STYLE: Define our preferred form for multiline comments
71
bswap: Add new stn_*_p() and ldn_*_p() memory access functions
72
exec.c: Don't accidentally sign-extend 4-byte loads in subpage_read()
73
exec.c: Use stn_p() and ldn_p() instead of explicit switches
74
iommu: Add IOMMU index concept to IOMMU API
75
iommu: Add IOMMU index argument to notifier APIs
76
iommu: Add IOMMU index argument to translate method
77
exec.c: Handle IOMMUs in address_space_translate_for_iotlb()
78
107
79
Richard Henderson (18):
108
Vikram Garhwal (1):
80
target/arm: Extend vec_reg_offset to larger sizes
109
MAINTAINERS: Add correct email address for Vikram Garhwal
81
target/arm: Implement SVE Permute - Unpredicated Group
82
target/arm: Implement SVE Permute - Predicates Group
83
target/arm: Implement SVE Permute - Interleaving Group
84
target/arm: Implement SVE compress active elements
85
target/arm: Implement SVE conditionally broadcast/extract element
86
target/arm: Implement SVE copy to vector (predicated)
87
target/arm: Implement SVE reverse within elements
88
target/arm: Implement SVE vector splice (predicated)
89
target/arm: Implement SVE Select Vectors Group
90
target/arm: Implement SVE Integer Compare - Vectors Group
91
target/arm: Implement SVE Integer Compare - Immediate Group
92
target/arm: Implement SVE Partition Break Group
93
target/arm: Implement SVE Predicate Count Group
94
target/arm: Implement SVE Integer Compare - Scalars Group
95
target/arm: Implement FDUP/DUP
96
target/arm: Implement SVE Integer Wide Immediate - Unpredicated Group
97
target/arm: Implement SVE Floating Point Arithmetic - Unpredicated Group
98
110
99
Shannon Zhao (1):
111
MAINTAINERS | 4 +-
100
arm_gicv3_kvm: kvm_dist_get/put_priority: skip the registers banked by GICR_IPRIORITYR
112
include/fpu/softfloat-helpers.h | 38 +++-
101
113
include/fpu/softfloat-types.h | 89 +++++++-
102
include/exec/cpu-all.h | 4 +
114
include/hw/net/imx_fec.h | 9 +-
103
include/exec/cpu-defs.h | 9 +
115
include/hw/net/lan9118_phy.h | 37 ++++
104
include/exec/exec-all.h | 16 +-
116
include/hw/net/mii.h | 6 +
105
include/exec/memory.h | 65 +-
117
target/mips/fpu_helper.h | 20 ++
106
include/hw/arm/arm.h | 8 +-
118
target/sparc/helper.h | 4 +-
107
include/hw/or-irq.h | 5 +-
119
fpu/softfloat.c | 19 ++
108
include/qemu/bswap.h | 52 ++
120
hw/net/imx_fec.c | 146 ++------------
109
include/qom/cpu.h | 3 +
121
hw/net/lan9118.c | 137 ++-----------
110
target/arm/helper-sve.h | 294 +++++++++
122
hw/net/lan9118_phy.c | 222 ++++++++++++++++++++
111
target/arm/helper.h | 19 +
123
linux-user/arm/nwfpe/fpa11.c | 5 +
112
target/arm/translate-a64.h | 26 +-
124
target/alpha/cpu.c | 2 +
113
accel/tcg/cputlb.c | 59 +-
125
target/arm/cpu.c | 10 +
114
exec.c | 263 ++++----
126
target/arm/tcg/vec_helper.c | 20 +-
115
hw/alpha/typhoon.c | 3 +-
127
target/hexagon/cpu.c | 2 +
116
hw/arm/armv7m.c | 28 +-
128
target/hppa/fpu_helper.c | 12 ++
117
hw/arm/mps2-tz.c | 32 +-
129
target/i386/tcg/fpu_helper.c | 12 ++
118
hw/arm/smmuv3.c | 2 +-
130
target/loongarch/tcg/fpu_helper.c | 14 +-
119
hw/arm/stellaris.c | 12 +-
131
target/m68k/cpu.c | 14 +-
120
hw/block/m25p80.c | 1 +
132
target/m68k/fpu_helper.c | 6 +-
121
hw/block/pflash_cfi02.c | 97 +--
133
target/m68k/helper.c | 6 +-
122
hw/char/parallel.c | 50 +-
134
target/microblaze/cpu.c | 2 +
123
hw/core/or-irq.c | 39 +-
135
target/mips/msa.c | 10 +
124
hw/dma/rc4030.c | 2 +-
136
target/openrisc/cpu.c | 2 +
125
hw/i386/amd_iommu.c | 2 +-
137
target/ppc/cpu_init.c | 19 ++
126
hw/i386/intel_iommu.c | 8 +-
138
target/ppc/fpu_helper.c | 3 +-
127
hw/input/pckbd.c | 14 +-
139
target/riscv/cpu.c | 2 +
128
hw/intc/arm_gicv3_kvm.c | 18 +-
140
target/rx/cpu.c | 2 +
129
hw/intc/armv7m_nvic.c | 6 +-
141
target/s390x/cpu.c | 5 +
130
hw/m68k/mcf5206.c | 48 +-
142
target/sh4/cpu.c | 2 +
131
hw/misc/aspeed_scu.c | 20 +
143
target/sparc/cpu.c | 6 +
132
hw/ppc/spapr_iommu.c | 5 +-
144
target/sparc/fop_helper.c | 8 +-
133
hw/s390x/s390-pci-bus.c | 2 +-
145
target/sparc/translate.c | 4 +-
134
hw/s390x/s390-pci-inst.c | 4 +-
146
target/tricore/helper.c | 2 +
135
hw/sh4/sh7750.c | 44 +-
147
target/xtensa/cpu.c | 4 +
136
hw/sparc/sun4m_iommu.c | 3 +-
148
target/xtensa/fpu_helper.c | 3 +-
137
hw/sparc64/sun4u_iommu.c | 2 +-
149
tests/fp/fp-bench.c | 7 +
138
hw/vfio/common.c | 6 +-
150
tests/fp/fp-test-log2.c | 1 +
139
hw/virtio/vhost.c | 7 +-
151
tests/fp/fp-test.c | 7 +
140
hw/watchdog/wdt_i6300esb.c | 48 +-
152
fpu/softfloat-parts.c.inc | 152 +++++++++++---
141
memory.c | 33 +-
153
fpu/softfloat-specialize.c.inc | 412 ++------------------------------------
142
target/arm/cpu.c | 18 +
154
.mailmap | 5 +-
143
target/arm/sve_helper.c | 1250 +++++++++++++++++++++++++++++++++++++
155
hw/net/Kconfig | 5 +
144
target/arm/translate-sve.c | 1458 +++++++++++++++++++++++++++++++++++++++++++
156
hw/net/meson.build | 1 +
145
target/arm/translate.c | 43 +-
157
hw/net/trace-events | 10 +-
146
target/arm/vec_helper.c | 69 ++
158
47 files changed, 778 insertions(+), 730 deletions(-)
147
CODING_STYLE | 17 +
159
create mode 100644 include/hw/net/lan9118_phy.h
148
docs/devel/loads-stores.rst | 15 +
160
create mode 100644 hw/net/lan9118_phy.c
149
target/arm/sve.decode | 248 ++++++++
150
48 files changed, 4114 insertions(+), 363 deletions(-)
151
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
A very similar implementation of the same device exists in imx_fec. Prepare for
4
a common implementation by extracting a device model into its own files.
5
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>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20241102125724.532843-2-shentey@gmail.com
5
Message-id: 20180613015641.5667-3-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
22
---
8
target/arm/helper-sve.h | 23 +++++++
23
include/hw/net/lan9118_phy.h | 37 ++++++++
9
target/arm/sve_helper.c | 114 +++++++++++++++++++++++++++++++
24
hw/net/lan9118.c | 137 +++++-----------------------
10
target/arm/translate-sve.c | 133 +++++++++++++++++++++++++++++++++++++
25
hw/net/lan9118_phy.c | 169 +++++++++++++++++++++++++++++++++++
11
target/arm/sve.decode | 27 ++++++++
26
hw/net/Kconfig | 4 +
12
4 files changed, 297 insertions(+)
27
hw/net/meson.build | 1 +
28
5 files changed, 233 insertions(+), 115 deletions(-)
29
create mode 100644 include/hw/net/lan9118_phy.h
30
create mode 100644 hw/net/lan9118_phy.c
13
31
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
32
diff --git a/include/hw/net/lan9118_phy.h b/include/hw/net/lan9118_phy.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/net/lan9118_phy.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * SMSC LAN9118 PHY emulation
40
+ *
41
+ * Copyright (c) 2009 CodeSourcery, LLC.
42
+ * Written by Paul Brook
43
+ *
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
45
+ * See the COPYING file in the top-level directory.
46
+ */
47
+
48
+#ifndef HW_NET_LAN9118_PHY_H
49
+#define HW_NET_LAN9118_PHY_H
50
+
51
+#include "qom/object.h"
52
+#include "hw/sysbus.h"
53
+
54
+#define TYPE_LAN9118_PHY "lan9118-phy"
55
+OBJECT_DECLARE_SIMPLE_TYPE(Lan9118PhyState, LAN9118_PHY)
56
+
57
+typedef struct Lan9118PhyState {
58
+ SysBusDevice parent_obj;
59
+
60
+ uint16_t status;
61
+ uint16_t control;
62
+ uint16_t advertise;
63
+ uint16_t ints;
64
+ uint16_t int_mask;
65
+ qemu_irq irq;
66
+ bool link_down;
67
+} Lan9118PhyState;
68
+
69
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down);
70
+void lan9118_phy_reset(Lan9118PhyState *s);
71
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg);
72
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val);
73
+
74
+#endif
75
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
15
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
77
--- a/hw/net/lan9118.c
17
+++ b/target/arm/helper-sve.h
78
+++ b/hw/net/lan9118.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_cpy_z_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
79
@@ -XXX,XX +XXX,XX @@
19
80
#include "net/net.h"
20
DEF_HELPER_FLAGS_4(sve_ext, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
81
#include "net/eth.h"
21
82
#include "hw/irq.h"
22
+DEF_HELPER_FLAGS_4(sve_insr_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
83
+#include "hw/net/lan9118_phy.h"
23
+DEF_HELPER_FLAGS_4(sve_insr_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
84
#include "hw/net/lan9118.h"
24
+DEF_HELPER_FLAGS_4(sve_insr_s, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
85
#include "hw/ptimer.h"
25
+DEF_HELPER_FLAGS_4(sve_insr_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
86
#include "hw/qdev-properties.h"
26
+
87
@@ -XXX,XX +XXX,XX @@ do { printf("lan9118: " fmt , ## __VA_ARGS__); } while (0)
27
+DEF_HELPER_FLAGS_3(sve_rev_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
88
#define MAC_CR_RXEN 0x00000004
28
+DEF_HELPER_FLAGS_3(sve_rev_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
89
#define MAC_CR_RESERVED 0x7f404213
29
+DEF_HELPER_FLAGS_3(sve_rev_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
90
30
+DEF_HELPER_FLAGS_3(sve_rev_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
91
-#define PHY_INT_ENERGYON 0x80
31
+
92
-#define PHY_INT_AUTONEG_COMPLETE 0x40
32
+DEF_HELPER_FLAGS_4(sve_tbl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
93
-#define PHY_INT_FAULT 0x20
33
+DEF_HELPER_FLAGS_4(sve_tbl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
94
-#define PHY_INT_DOWN 0x10
34
+DEF_HELPER_FLAGS_4(sve_tbl_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
95
-#define PHY_INT_AUTONEG_LP 0x08
35
+DEF_HELPER_FLAGS_4(sve_tbl_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
96
-#define PHY_INT_PARFAULT 0x04
36
+
97
-#define PHY_INT_AUTONEG_PAGE 0x02
37
+DEF_HELPER_FLAGS_3(sve_sunpk_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
98
-
38
+DEF_HELPER_FLAGS_3(sve_sunpk_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
99
#define GPT_TIMER_EN 0x20000000
39
+DEF_HELPER_FLAGS_3(sve_sunpk_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
100
40
+
101
/*
41
+DEF_HELPER_FLAGS_3(sve_uunpk_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
102
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
42
+DEF_HELPER_FLAGS_3(sve_uunpk_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
103
uint32_t mac_mii_data;
43
+DEF_HELPER_FLAGS_3(sve_uunpk_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
104
uint32_t mac_flow;
44
+
105
45
DEF_HELPER_FLAGS_5(sve_and_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
106
- uint32_t phy_status;
46
DEF_HELPER_FLAGS_5(sve_bic_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
107
- uint32_t phy_control;
47
DEF_HELPER_FLAGS_5(sve_eor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
108
- uint32_t phy_advertise;
48
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
109
- uint32_t phy_int;
49
index XXXXXXX..XXXXXXX 100644
110
- uint32_t phy_int_mask;
50
--- a/target/arm/sve_helper.c
111
+ Lan9118PhyState mii;
51
+++ b/target/arm/sve_helper.c
112
+ IRQState mii_irq;
52
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_ext)(void *vd, void *vn, void *vm, uint32_t desc)
113
53
memcpy(vd + n_siz, &tmp, n_ofs);
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)
54
}
208
}
55
}
209
}
56
+
210
57
+#define DO_INSR(NAME, TYPE, H) \
211
-static uint32_t do_phy_read(lan9118_state *s, int reg)
58
+void HELPER(NAME)(void *vd, void *vn, uint64_t val, uint32_t desc) \
212
-{
59
+{ \
213
- uint32_t val;
60
+ intptr_t opr_sz = simd_oprsz(desc); \
214
-
61
+ swap_memmove(vd + sizeof(TYPE), vn, opr_sz - sizeof(TYPE)); \
215
- switch (reg) {
62
+ *(TYPE *)(vd + H(0)) = val; \
216
- case 0: /* Basic Control */
63
+}
217
- return s->phy_control;
64
+
218
- case 1: /* Basic Status */
65
+DO_INSR(sve_insr_b, uint8_t, H1)
219
- return s->phy_status;
66
+DO_INSR(sve_insr_h, uint16_t, H1_2)
220
- case 2: /* ID1 */
67
+DO_INSR(sve_insr_s, uint32_t, H1_4)
221
- return 0x0007;
68
+DO_INSR(sve_insr_d, uint64_t, )
222
- case 3: /* ID2 */
69
+
223
- return 0xc0d1;
70
+#undef DO_INSR
224
- case 4: /* Auto-neg advertisement */
71
+
225
- return s->phy_advertise;
72
+void HELPER(sve_rev_b)(void *vd, void *vn, uint32_t desc)
226
- case 5: /* Auto-neg Link Partner Ability */
73
+{
227
- return 0x0f71;
74
+ intptr_t i, j, opr_sz = simd_oprsz(desc);
228
- case 6: /* Auto-neg Expansion */
75
+ for (i = 0, j = opr_sz - 8; i < opr_sz / 2; i += 8, j -= 8) {
229
- return 1;
76
+ uint64_t f = *(uint64_t *)(vn + i);
230
- /* TODO 17, 18, 27, 29, 30, 31 */
77
+ uint64_t b = *(uint64_t *)(vn + j);
231
- case 29: /* Interrupt source. */
78
+ *(uint64_t *)(vd + i) = bswap64(b);
232
- val = s->phy_int;
79
+ *(uint64_t *)(vd + j) = bswap64(f);
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;
80
+ }
305
+ }
81
+}
306
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
82
+
307
+
83
+static inline uint64_t hswap64(uint64_t h)
308
memory_region_init_io(&s->mmio, OBJECT(dev), mem_ops, s,
84
+{
309
"lan9118-mmio", 0x100);
85
+ uint64_t m = 0x0000ffff0000ffffull;
310
sysbus_init_mmio(sbd, &s->mmio);
86
+ h = rol64(h, 32);
311
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
87
+ return ((h & m) << 16) | ((h >> 16) & m);
312
new file mode 100644
88
+}
313
index XXXXXXX..XXXXXXX
89
+
314
--- /dev/null
90
+void HELPER(sve_rev_h)(void *vd, void *vn, uint32_t desc)
315
+++ b/hw/net/lan9118_phy.c
91
+{
316
@@ -XXX,XX +XXX,XX @@
92
+ intptr_t i, j, opr_sz = simd_oprsz(desc);
317
+/*
93
+ for (i = 0, j = opr_sz - 8; i < opr_sz / 2; i += 8, j -= 8) {
318
+ * SMSC LAN9118 PHY emulation
94
+ uint64_t f = *(uint64_t *)(vn + i);
319
+ *
95
+ uint64_t b = *(uint64_t *)(vn + j);
320
+ * Copyright (c) 2009 CodeSourcery, LLC.
96
+ *(uint64_t *)(vd + i) = hswap64(b);
321
+ * Written by Paul Brook
97
+ *(uint64_t *)(vd + j) = hswap64(f);
322
+ *
323
+ * This code is licensed under the GNU GPL v2
324
+ *
325
+ * Contributions after 2012-01-13 are licensed under the terms of the
326
+ * GNU GPL, version 2 or (at your option) any later version.
327
+ */
328
+
329
+#include "qemu/osdep.h"
330
+#include "hw/net/lan9118_phy.h"
331
+#include "hw/irq.h"
332
+#include "hw/resettable.h"
333
+#include "migration/vmstate.h"
334
+#include "qemu/log.h"
335
+
336
+#define PHY_INT_ENERGYON (1 << 7)
337
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
338
+#define PHY_INT_FAULT (1 << 5)
339
+#define PHY_INT_DOWN (1 << 4)
340
+#define PHY_INT_AUTONEG_LP (1 << 3)
341
+#define PHY_INT_PARFAULT (1 << 2)
342
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
343
+
344
+static void lan9118_phy_update_irq(Lan9118PhyState *s)
345
+{
346
+ qemu_set_irq(s->irq, !!(s->ints & s->int_mask));
347
+}
348
+
349
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
350
+{
351
+ uint16_t val;
352
+
353
+ switch (reg) {
354
+ case 0: /* Basic Control */
355
+ return s->control;
356
+ case 1: /* Basic Status */
357
+ return s->status;
358
+ case 2: /* ID1 */
359
+ return 0x0007;
360
+ case 3: /* ID2 */
361
+ return 0xc0d1;
362
+ case 4: /* Auto-neg advertisement */
363
+ return s->advertise;
364
+ case 5: /* Auto-neg Link Partner Ability */
365
+ return 0x0f71;
366
+ case 6: /* Auto-neg Expansion */
367
+ return 1;
368
+ /* TODO 17, 18, 27, 29, 30, 31 */
369
+ case 29: /* Interrupt source. */
370
+ val = s->ints;
371
+ s->ints = 0;
372
+ lan9118_phy_update_irq(s);
373
+ return val;
374
+ case 30: /* Interrupt mask */
375
+ return s->int_mask;
376
+ default:
377
+ qemu_log_mask(LOG_GUEST_ERROR,
378
+ "lan9118_phy_read: PHY read reg %d\n", reg);
379
+ return 0;
98
+ }
380
+ }
99
+}
381
+}
100
+
382
+
101
+void HELPER(sve_rev_s)(void *vd, void *vn, uint32_t desc)
383
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
102
+{
384
+{
103
+ intptr_t i, j, opr_sz = simd_oprsz(desc);
385
+ switch (reg) {
104
+ for (i = 0, j = opr_sz - 8; i < opr_sz / 2; i += 8, j -= 8) {
386
+ case 0: /* Basic Control */
105
+ uint64_t f = *(uint64_t *)(vn + i);
387
+ if (val & 0x8000) {
106
+ uint64_t b = *(uint64_t *)(vn + j);
388
+ lan9118_phy_reset(s);
107
+ *(uint64_t *)(vd + i) = rol64(b, 32);
389
+ break;
108
+ *(uint64_t *)(vd + j) = rol64(f, 32);
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);
109
+ }
408
+ }
110
+}
409
+}
111
+
410
+
112
+void HELPER(sve_rev_d)(void *vd, void *vn, uint32_t desc)
411
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
113
+{
412
+{
114
+ intptr_t i, j, opr_sz = simd_oprsz(desc);
413
+ s->link_down = link_down;
115
+ for (i = 0, j = opr_sz - 8; i < opr_sz / 2; i += 8, j -= 8) {
414
+
116
+ uint64_t f = *(uint64_t *)(vn + i);
415
+ /* Autonegotiation status mirrors link status. */
117
+ uint64_t b = *(uint64_t *)(vn + j);
416
+ if (link_down) {
118
+ *(uint64_t *)(vd + i) = b;
417
+ s->status &= ~0x0024;
119
+ *(uint64_t *)(vd + j) = f;
418
+ s->ints |= PHY_INT_DOWN;
419
+ } else {
420
+ s->status |= 0x0024;
421
+ s->ints |= PHY_INT_ENERGYON;
422
+ s->ints |= PHY_INT_AUTONEG_COMPLETE;
120
+ }
423
+ }
121
+}
424
+ lan9118_phy_update_irq(s);
122
+
425
+}
123
+#define DO_TBL(NAME, TYPE, H) \
426
+
124
+void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
427
+void lan9118_phy_reset(Lan9118PhyState *s)
125
+{ \
428
+{
126
+ intptr_t i, opr_sz = simd_oprsz(desc); \
429
+ s->control = 0x3000;
127
+ uintptr_t elem = opr_sz / sizeof(TYPE); \
430
+ s->status = 0x7809;
128
+ TYPE *d = vd, *n = vn, *m = vm; \
431
+ s->advertise = 0x01e1;
129
+ ARMVectorReg tmp; \
432
+ s->int_mask = 0;
130
+ if (unlikely(vd == vn)) { \
433
+ s->ints = 0;
131
+ n = memcpy(&tmp, vn, opr_sz); \
434
+ lan9118_phy_update_link(s, s->link_down);
132
+ } \
435
+}
133
+ for (i = 0; i < elem; i++) { \
436
+
134
+ TYPE j = m[H(i)]; \
437
+static void lan9118_phy_reset_hold(Object *obj, ResetType type)
135
+ d[H(i)] = j < elem ? n[H(j)] : 0; \
438
+{
136
+ } \
439
+ Lan9118PhyState *s = LAN9118_PHY(obj);
137
+}
440
+
138
+
441
+ lan9118_phy_reset(s);
139
+DO_TBL(sve_tbl_b, uint8_t, H1)
442
+}
140
+DO_TBL(sve_tbl_h, uint16_t, H2)
443
+
141
+DO_TBL(sve_tbl_s, uint32_t, H4)
444
+static void lan9118_phy_init(Object *obj)
142
+DO_TBL(sve_tbl_d, uint64_t, )
445
+{
143
+
446
+ Lan9118PhyState *s = LAN9118_PHY(obj);
144
+#undef TBL
447
+
145
+
448
+ qdev_init_gpio_out(DEVICE(s), &s->irq, 1);
146
+#define DO_UNPK(NAME, TYPED, TYPES, HD, HS) \
449
+}
147
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
450
+
148
+{ \
451
+static const VMStateDescription vmstate_lan9118_phy = {
149
+ intptr_t i, opr_sz = simd_oprsz(desc); \
452
+ .name = "lan9118-phy",
150
+ TYPED *d = vd; \
453
+ .version_id = 1,
151
+ TYPES *n = vn; \
454
+ .minimum_version_id = 1,
152
+ ARMVectorReg tmp; \
455
+ .fields = (const VMStateField[]) {
153
+ if (unlikely(vn - vd < opr_sz)) { \
456
+ VMSTATE_UINT16(control, Lan9118PhyState),
154
+ n = memcpy(&tmp, n, opr_sz / 2); \
457
+ VMSTATE_UINT16(status, Lan9118PhyState),
155
+ } \
458
+ VMSTATE_UINT16(advertise, Lan9118PhyState),
156
+ for (i = 0; i < opr_sz / sizeof(TYPED); i++) { \
459
+ VMSTATE_UINT16(ints, Lan9118PhyState),
157
+ d[HD(i)] = n[HS(i)]; \
460
+ VMSTATE_UINT16(int_mask, Lan9118PhyState),
158
+ } \
461
+ VMSTATE_BOOL(link_down, Lan9118PhyState),
159
+}
462
+ VMSTATE_END_OF_LIST()
160
+
463
+ }
161
+DO_UNPK(sve_sunpk_h, int16_t, int8_t, H2, H1)
464
+};
162
+DO_UNPK(sve_sunpk_s, int32_t, int16_t, H4, H2)
465
+
163
+DO_UNPK(sve_sunpk_d, int64_t, int32_t, , H4)
466
+static void lan9118_phy_class_init(ObjectClass *klass, void *data)
164
+
467
+{
165
+DO_UNPK(sve_uunpk_h, uint16_t, uint8_t, H2, H1)
468
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
166
+DO_UNPK(sve_uunpk_s, uint32_t, uint16_t, H4, H2)
469
+ DeviceClass *dc = DEVICE_CLASS(klass);
167
+DO_UNPK(sve_uunpk_d, uint64_t, uint32_t, , H4)
470
+
168
+
471
+ rc->phases.hold = lan9118_phy_reset_hold;
169
+#undef DO_UNPK
472
+ dc->vmsd = &vmstate_lan9118_phy;
170
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
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
171
index XXXXXXX..XXXXXXX 100644
487
index XXXXXXX..XXXXXXX 100644
172
--- a/target/arm/translate-sve.c
488
--- a/hw/net/Kconfig
173
+++ b/target/arm/translate-sve.c
489
+++ b/hw/net/Kconfig
174
@@ -XXX,XX +XXX,XX @@ static bool trans_EXT(DisasContext *s, arg_EXT *a, uint32_t insn)
490
@@ -XXX,XX +XXX,XX @@ config VMXNET3_PCI
175
return true;
491
config SMC91C111
176
}
492
bool
177
493
178
+/*
494
+config LAN9118_PHY
179
+ *** SVE Permute - Unpredicated Group
495
+ bool
180
+ */
496
+
181
+
497
config LAN9118
182
+static bool trans_DUP_s(DisasContext *s, arg_DUP_s *a, uint32_t insn)
498
bool
183
+{
499
+ select LAN9118_PHY
184
+ if (sve_access_check(s)) {
500
select PTIMER
185
+ unsigned vsz = vec_full_reg_size(s);
501
186
+ tcg_gen_gvec_dup_i64(a->esz, vec_full_reg_offset(s, a->rd),
502
config NE2000_ISA
187
+ vsz, vsz, cpu_reg_sp(s, a->rn));
503
diff --git a/hw/net/meson.build b/hw/net/meson.build
188
+ }
189
+ return true;
190
+}
191
+
192
+static bool trans_DUP_x(DisasContext *s, arg_DUP_x *a, uint32_t insn)
193
+{
194
+ if ((a->imm & 0x1f) == 0) {
195
+ return false;
196
+ }
197
+ if (sve_access_check(s)) {
198
+ unsigned vsz = vec_full_reg_size(s);
199
+ unsigned dofs = vec_full_reg_offset(s, a->rd);
200
+ unsigned esz, index;
201
+
202
+ esz = ctz32(a->imm);
203
+ index = a->imm >> (esz + 1);
204
+
205
+ if ((index << esz) < vsz) {
206
+ unsigned nofs = vec_reg_offset(s, a->rn, index, esz);
207
+ tcg_gen_gvec_dup_mem(esz, dofs, nofs, vsz, vsz);
208
+ } else {
209
+ tcg_gen_gvec_dup64i(dofs, vsz, vsz, 0);
210
+ }
211
+ }
212
+ return true;
213
+}
214
+
215
+static void do_insr_i64(DisasContext *s, arg_rrr_esz *a, TCGv_i64 val)
216
+{
217
+ typedef void gen_insr(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_i32);
218
+ static gen_insr * const fns[4] = {
219
+ gen_helper_sve_insr_b, gen_helper_sve_insr_h,
220
+ gen_helper_sve_insr_s, gen_helper_sve_insr_d,
221
+ };
222
+ unsigned vsz = vec_full_reg_size(s);
223
+ TCGv_i32 desc = tcg_const_i32(simd_desc(vsz, vsz, 0));
224
+ TCGv_ptr t_zd = tcg_temp_new_ptr();
225
+ TCGv_ptr t_zn = tcg_temp_new_ptr();
226
+
227
+ tcg_gen_addi_ptr(t_zd, cpu_env, vec_full_reg_offset(s, a->rd));
228
+ tcg_gen_addi_ptr(t_zn, cpu_env, vec_full_reg_offset(s, a->rn));
229
+
230
+ fns[a->esz](t_zd, t_zn, val, desc);
231
+
232
+ tcg_temp_free_ptr(t_zd);
233
+ tcg_temp_free_ptr(t_zn);
234
+ tcg_temp_free_i32(desc);
235
+}
236
+
237
+static bool trans_INSR_f(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
238
+{
239
+ if (sve_access_check(s)) {
240
+ TCGv_i64 t = tcg_temp_new_i64();
241
+ tcg_gen_ld_i64(t, cpu_env, vec_reg_offset(s, a->rm, 0, MO_64));
242
+ do_insr_i64(s, a, t);
243
+ tcg_temp_free_i64(t);
244
+ }
245
+ return true;
246
+}
247
+
248
+static bool trans_INSR_r(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
249
+{
250
+ if (sve_access_check(s)) {
251
+ do_insr_i64(s, a, cpu_reg(s, a->rm));
252
+ }
253
+ return true;
254
+}
255
+
256
+static bool trans_REV_v(DisasContext *s, arg_rr_esz *a, uint32_t insn)
257
+{
258
+ static gen_helper_gvec_2 * const fns[4] = {
259
+ gen_helper_sve_rev_b, gen_helper_sve_rev_h,
260
+ gen_helper_sve_rev_s, gen_helper_sve_rev_d
261
+ };
262
+
263
+ if (sve_access_check(s)) {
264
+ unsigned vsz = vec_full_reg_size(s);
265
+ tcg_gen_gvec_2_ool(vec_full_reg_offset(s, a->rd),
266
+ vec_full_reg_offset(s, a->rn),
267
+ vsz, vsz, 0, fns[a->esz]);
268
+ }
269
+ return true;
270
+}
271
+
272
+static bool trans_TBL(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
273
+{
274
+ static gen_helper_gvec_3 * const fns[4] = {
275
+ gen_helper_sve_tbl_b, gen_helper_sve_tbl_h,
276
+ gen_helper_sve_tbl_s, gen_helper_sve_tbl_d
277
+ };
278
+
279
+ if (sve_access_check(s)) {
280
+ unsigned vsz = vec_full_reg_size(s);
281
+ tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd),
282
+ vec_full_reg_offset(s, a->rn),
283
+ vec_full_reg_offset(s, a->rm),
284
+ vsz, vsz, 0, fns[a->esz]);
285
+ }
286
+ return true;
287
+}
288
+
289
+static bool trans_UNPK(DisasContext *s, arg_UNPK *a, uint32_t insn)
290
+{
291
+ static gen_helper_gvec_2 * const fns[4][2] = {
292
+ { NULL, NULL },
293
+ { gen_helper_sve_sunpk_h, gen_helper_sve_uunpk_h },
294
+ { gen_helper_sve_sunpk_s, gen_helper_sve_uunpk_s },
295
+ { gen_helper_sve_sunpk_d, gen_helper_sve_uunpk_d },
296
+ };
297
+
298
+ if (a->esz == 0) {
299
+ return false;
300
+ }
301
+ if (sve_access_check(s)) {
302
+ unsigned vsz = vec_full_reg_size(s);
303
+ tcg_gen_gvec_2_ool(vec_full_reg_offset(s, a->rd),
304
+ vec_full_reg_offset(s, a->rn)
305
+ + (a->h ? vsz / 2 : 0),
306
+ vsz, vsz, 0, fns[a->esz][a->u]);
307
+ }
308
+ return true;
309
+}
310
+
311
/*
312
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
313
*/
314
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
315
index XXXXXXX..XXXXXXX 100644
504
index XXXXXXX..XXXXXXX 100644
316
--- a/target/arm/sve.decode
505
--- a/hw/net/meson.build
317
+++ b/target/arm/sve.decode
506
+++ b/hw/net/meson.build
318
@@ -XXX,XX +XXX,XX @@
507
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('vmxnet3.c'))
319
508
320
%imm4_16_p1 16:4 !function=plus1
509
system_ss.add(when: 'CONFIG_SMC91C111', if_true: files('smc91c111.c'))
321
%imm6_22_5 22:1 5:5
510
system_ss.add(when: 'CONFIG_LAN9118', if_true: files('lan9118.c'))
322
+%imm7_22_16 22:2 16:5
511
+system_ss.add(when: 'CONFIG_LAN9118_PHY', if_true: files('lan9118_phy.c'))
323
%imm8_16_10 16:5 10:3
512
system_ss.add(when: 'CONFIG_NE2000_ISA', if_true: files('ne2000-isa.c'))
324
%imm9_16_10 16:s6 10:3
513
system_ss.add(when: 'CONFIG_OPENCORES_ETH', if_true: files('opencores_eth.c'))
325
514
system_ss.add(when: 'CONFIG_XGMAC', if_true: files('xgmac.c'))
326
@@ -XXX,XX +XXX,XX @@
327
328
# Three operand, vector element size
329
@rd_rn_rm ........ esz:2 . rm:5 ... ... rn:5 rd:5 &rrr_esz
330
+@rdn_rm ........ esz:2 ...... ...... rm:5 rd:5 \
331
+ &rrr_esz rn=%reg_movprfx
332
333
# Three operand with "memory" size, aka immediate left shift
334
@rd_rn_msz_rm ........ ... rm:5 .... imm:2 rn:5 rd:5 &rrri
335
@@ -XXX,XX +XXX,XX @@ CPY_z_i 00000101 .. 01 .... 00 . ........ ..... @rdn_pg4 imm=%sh8_i8s
336
EXT 00000101 001 ..... 000 ... rm:5 rd:5 \
337
&rrri rn=%reg_movprfx imm=%imm8_16_10
338
339
+### SVE Permute - Unpredicated Group
340
+
341
+# SVE broadcast general register
342
+DUP_s 00000101 .. 1 00000 001110 ..... ..... @rd_rn
343
+
344
+# SVE broadcast indexed element
345
+DUP_x 00000101 .. 1 ..... 001000 rn:5 rd:5 \
346
+ &rri imm=%imm7_22_16
347
+
348
+# SVE insert SIMD&FP scalar register
349
+INSR_f 00000101 .. 1 10100 001110 ..... ..... @rdn_rm
350
+
351
+# SVE insert general register
352
+INSR_r 00000101 .. 1 00100 001110 ..... ..... @rdn_rm
353
+
354
+# SVE reverse vector elements
355
+REV_v 00000101 .. 1 11000 001110 ..... ..... @rd_rn
356
+
357
+# SVE vector table lookup
358
+TBL 00000101 .. 1 ..... 001100 ..... ..... @rd_rn_rm
359
+
360
+# SVE unpack vector elements
361
+UNPK 00000101 esz:2 1100 u:1 h:1 001110 rn:5 rd:5
362
+
363
### SVE Predicate Logical Operations Group
364
365
# SVE predicate logical operations
366
--
515
--
367
2.17.1
516
2.34.1
368
369
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
imx_fec models the same PHY as lan9118_phy. The code is almost the same with
4
imx_fec having more logging and tracing. Merge these improvements into
5
lan9118_phy and reuse in imx_fec to fix the code duplication.
6
7
Some migration state how resides in the new device model which breaks migration
8
compatibility for the following machines:
9
* imx25-pdk
10
* sabrelite
11
* mcimx7d-sabre
12
* mcimx6ul-evk
13
14
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
15
Tested-by: Guenter Roeck <linux@roeck-us.net>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20241102125724.532843-3-shentey@gmail.com
5
Message-id: 20180613015641.5667-12-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
19
---
8
target/arm/helper-sve.h | 115 +++++++++++++++++++++++
20
include/hw/net/imx_fec.h | 9 ++-
9
target/arm/sve_helper.c | 187 +++++++++++++++++++++++++++++++++++++
21
hw/net/imx_fec.c | 146 ++++-----------------------------------
10
target/arm/translate-sve.c | 91 ++++++++++++++++++
22
hw/net/lan9118_phy.c | 82 ++++++++++++++++------
11
target/arm/sve.decode | 24 +++++
23
hw/net/Kconfig | 1 +
12
4 files changed, 417 insertions(+)
24
hw/net/trace-events | 10 +--
25
5 files changed, 85 insertions(+), 163 deletions(-)
13
26
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
27
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
15
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
29
--- a/include/hw/net/imx_fec.h
17
+++ b/target/arm/helper-sve.h
30
+++ b/include/hw/net/imx_fec.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_rbit_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC)
19
32
#define TYPE_IMX_ENET "imx.enet"
20
DEF_HELPER_FLAGS_5(sve_splice, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
33
21
34
#include "hw/sysbus.h"
22
+DEF_HELPER_FLAGS_5(sve_cmpeq_ppzz_b, TCG_CALL_NO_RWG,
35
+#include "hw/net/lan9118_phy.h"
23
+ i32, ptr, ptr, ptr, ptr, i32)
36
+#include "hw/irq.h"
24
+DEF_HELPER_FLAGS_5(sve_cmpne_ppzz_b, TCG_CALL_NO_RWG,
37
#include "net/net.h"
25
+ i32, ptr, ptr, ptr, ptr, i32)
38
26
+DEF_HELPER_FLAGS_5(sve_cmpge_ppzz_b, TCG_CALL_NO_RWG,
39
#define ENET_EIR 1
27
+ i32, ptr, ptr, ptr, ptr, i32)
40
@@ -XXX,XX +XXX,XX @@ struct IMXFECState {
28
+DEF_HELPER_FLAGS_5(sve_cmpgt_ppzz_b, TCG_CALL_NO_RWG,
41
uint32_t tx_descriptor[ENET_TX_RING_NUM];
29
+ i32, ptr, ptr, ptr, ptr, i32)
42
uint32_t tx_ring_num;
30
+DEF_HELPER_FLAGS_5(sve_cmphi_ppzz_b, TCG_CALL_NO_RWG,
43
31
+ i32, ptr, ptr, ptr, ptr, i32)
44
- uint32_t phy_status;
32
+DEF_HELPER_FLAGS_5(sve_cmphs_ppzz_b, TCG_CALL_NO_RWG,
45
- uint32_t phy_control;
33
+ i32, ptr, ptr, ptr, ptr, i32)
46
- uint32_t phy_advertise;
34
+
47
- uint32_t phy_int;
35
+DEF_HELPER_FLAGS_5(sve_cmpeq_ppzz_h, TCG_CALL_NO_RWG,
48
- uint32_t phy_int_mask;
36
+ i32, ptr, ptr, ptr, ptr, i32)
49
+ Lan9118PhyState mii;
37
+DEF_HELPER_FLAGS_5(sve_cmpne_ppzz_h, TCG_CALL_NO_RWG,
50
+ IRQState mii_irq;
38
+ i32, ptr, ptr, ptr, ptr, i32)
51
uint32_t phy_num;
39
+DEF_HELPER_FLAGS_5(sve_cmpge_ppzz_h, TCG_CALL_NO_RWG,
52
bool phy_connected;
40
+ i32, ptr, ptr, ptr, ptr, i32)
53
struct IMXFECState *phy_consumer;
41
+DEF_HELPER_FLAGS_5(sve_cmpgt_ppzz_h, TCG_CALL_NO_RWG,
54
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
42
+ i32, ptr, ptr, ptr, ptr, i32)
43
+DEF_HELPER_FLAGS_5(sve_cmphi_ppzz_h, TCG_CALL_NO_RWG,
44
+ i32, ptr, ptr, ptr, ptr, i32)
45
+DEF_HELPER_FLAGS_5(sve_cmphs_ppzz_h, TCG_CALL_NO_RWG,
46
+ i32, ptr, ptr, ptr, ptr, i32)
47
+
48
+DEF_HELPER_FLAGS_5(sve_cmpeq_ppzz_s, TCG_CALL_NO_RWG,
49
+ i32, ptr, ptr, ptr, ptr, i32)
50
+DEF_HELPER_FLAGS_5(sve_cmpne_ppzz_s, TCG_CALL_NO_RWG,
51
+ i32, ptr, ptr, ptr, ptr, i32)
52
+DEF_HELPER_FLAGS_5(sve_cmpge_ppzz_s, TCG_CALL_NO_RWG,
53
+ i32, ptr, ptr, ptr, ptr, i32)
54
+DEF_HELPER_FLAGS_5(sve_cmpgt_ppzz_s, TCG_CALL_NO_RWG,
55
+ i32, ptr, ptr, ptr, ptr, i32)
56
+DEF_HELPER_FLAGS_5(sve_cmphi_ppzz_s, TCG_CALL_NO_RWG,
57
+ i32, ptr, ptr, ptr, ptr, i32)
58
+DEF_HELPER_FLAGS_5(sve_cmphs_ppzz_s, TCG_CALL_NO_RWG,
59
+ i32, ptr, ptr, ptr, ptr, i32)
60
+
61
+DEF_HELPER_FLAGS_5(sve_cmpeq_ppzz_d, TCG_CALL_NO_RWG,
62
+ i32, ptr, ptr, ptr, ptr, i32)
63
+DEF_HELPER_FLAGS_5(sve_cmpne_ppzz_d, TCG_CALL_NO_RWG,
64
+ i32, ptr, ptr, ptr, ptr, i32)
65
+DEF_HELPER_FLAGS_5(sve_cmpge_ppzz_d, TCG_CALL_NO_RWG,
66
+ i32, ptr, ptr, ptr, ptr, i32)
67
+DEF_HELPER_FLAGS_5(sve_cmpgt_ppzz_d, TCG_CALL_NO_RWG,
68
+ i32, ptr, ptr, ptr, ptr, i32)
69
+DEF_HELPER_FLAGS_5(sve_cmphi_ppzz_d, TCG_CALL_NO_RWG,
70
+ i32, ptr, ptr, ptr, ptr, i32)
71
+DEF_HELPER_FLAGS_5(sve_cmphs_ppzz_d, TCG_CALL_NO_RWG,
72
+ i32, ptr, ptr, ptr, ptr, i32)
73
+
74
+DEF_HELPER_FLAGS_5(sve_cmpeq_ppzw_b, TCG_CALL_NO_RWG,
75
+ i32, ptr, ptr, ptr, ptr, i32)
76
+DEF_HELPER_FLAGS_5(sve_cmpne_ppzw_b, TCG_CALL_NO_RWG,
77
+ i32, ptr, ptr, ptr, ptr, i32)
78
+DEF_HELPER_FLAGS_5(sve_cmpge_ppzw_b, TCG_CALL_NO_RWG,
79
+ i32, ptr, ptr, ptr, ptr, i32)
80
+DEF_HELPER_FLAGS_5(sve_cmpgt_ppzw_b, TCG_CALL_NO_RWG,
81
+ i32, ptr, ptr, ptr, ptr, i32)
82
+DEF_HELPER_FLAGS_5(sve_cmphi_ppzw_b, TCG_CALL_NO_RWG,
83
+ i32, ptr, ptr, ptr, ptr, i32)
84
+DEF_HELPER_FLAGS_5(sve_cmphs_ppzw_b, TCG_CALL_NO_RWG,
85
+ i32, ptr, ptr, ptr, ptr, i32)
86
+DEF_HELPER_FLAGS_5(sve_cmple_ppzw_b, TCG_CALL_NO_RWG,
87
+ i32, ptr, ptr, ptr, ptr, i32)
88
+DEF_HELPER_FLAGS_5(sve_cmplt_ppzw_b, TCG_CALL_NO_RWG,
89
+ i32, ptr, ptr, ptr, ptr, i32)
90
+DEF_HELPER_FLAGS_5(sve_cmplo_ppzw_b, TCG_CALL_NO_RWG,
91
+ i32, ptr, ptr, ptr, ptr, i32)
92
+DEF_HELPER_FLAGS_5(sve_cmpls_ppzw_b, TCG_CALL_NO_RWG,
93
+ i32, ptr, ptr, ptr, ptr, i32)
94
+
95
+DEF_HELPER_FLAGS_5(sve_cmpeq_ppzw_h, TCG_CALL_NO_RWG,
96
+ i32, ptr, ptr, ptr, ptr, i32)
97
+DEF_HELPER_FLAGS_5(sve_cmpne_ppzw_h, TCG_CALL_NO_RWG,
98
+ i32, ptr, ptr, ptr, ptr, i32)
99
+DEF_HELPER_FLAGS_5(sve_cmpge_ppzw_h, TCG_CALL_NO_RWG,
100
+ i32, ptr, ptr, ptr, ptr, i32)
101
+DEF_HELPER_FLAGS_5(sve_cmpgt_ppzw_h, TCG_CALL_NO_RWG,
102
+ i32, ptr, ptr, ptr, ptr, i32)
103
+DEF_HELPER_FLAGS_5(sve_cmphi_ppzw_h, TCG_CALL_NO_RWG,
104
+ i32, ptr, ptr, ptr, ptr, i32)
105
+DEF_HELPER_FLAGS_5(sve_cmphs_ppzw_h, TCG_CALL_NO_RWG,
106
+ i32, ptr, ptr, ptr, ptr, i32)
107
+DEF_HELPER_FLAGS_5(sve_cmple_ppzw_h, TCG_CALL_NO_RWG,
108
+ i32, ptr, ptr, ptr, ptr, i32)
109
+DEF_HELPER_FLAGS_5(sve_cmplt_ppzw_h, TCG_CALL_NO_RWG,
110
+ i32, ptr, ptr, ptr, ptr, i32)
111
+DEF_HELPER_FLAGS_5(sve_cmplo_ppzw_h, TCG_CALL_NO_RWG,
112
+ i32, ptr, ptr, ptr, ptr, i32)
113
+DEF_HELPER_FLAGS_5(sve_cmpls_ppzw_h, TCG_CALL_NO_RWG,
114
+ i32, ptr, ptr, ptr, ptr, i32)
115
+
116
+DEF_HELPER_FLAGS_5(sve_cmpeq_ppzw_s, TCG_CALL_NO_RWG,
117
+ i32, ptr, ptr, ptr, ptr, i32)
118
+DEF_HELPER_FLAGS_5(sve_cmpne_ppzw_s, TCG_CALL_NO_RWG,
119
+ i32, ptr, ptr, ptr, ptr, i32)
120
+DEF_HELPER_FLAGS_5(sve_cmpge_ppzw_s, TCG_CALL_NO_RWG,
121
+ i32, ptr, ptr, ptr, ptr, i32)
122
+DEF_HELPER_FLAGS_5(sve_cmpgt_ppzw_s, TCG_CALL_NO_RWG,
123
+ i32, ptr, ptr, ptr, ptr, i32)
124
+DEF_HELPER_FLAGS_5(sve_cmphi_ppzw_s, TCG_CALL_NO_RWG,
125
+ i32, ptr, ptr, ptr, ptr, i32)
126
+DEF_HELPER_FLAGS_5(sve_cmphs_ppzw_s, TCG_CALL_NO_RWG,
127
+ i32, ptr, ptr, ptr, ptr, i32)
128
+DEF_HELPER_FLAGS_5(sve_cmple_ppzw_s, TCG_CALL_NO_RWG,
129
+ i32, ptr, ptr, ptr, ptr, i32)
130
+DEF_HELPER_FLAGS_5(sve_cmplt_ppzw_s, TCG_CALL_NO_RWG,
131
+ i32, ptr, ptr, ptr, ptr, i32)
132
+DEF_HELPER_FLAGS_5(sve_cmplo_ppzw_s, TCG_CALL_NO_RWG,
133
+ i32, ptr, ptr, ptr, ptr, i32)
134
+DEF_HELPER_FLAGS_5(sve_cmpls_ppzw_s, TCG_CALL_NO_RWG,
135
+ i32, ptr, ptr, ptr, ptr, i32)
136
+
137
DEF_HELPER_FLAGS_5(sve_and_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
138
DEF_HELPER_FLAGS_5(sve_bic_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
139
DEF_HELPER_FLAGS_5(sve_eor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
140
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
141
index XXXXXXX..XXXXXXX 100644
55
index XXXXXXX..XXXXXXX 100644
142
--- a/target/arm/sve_helper.c
56
--- a/hw/net/imx_fec.c
143
+++ b/target/arm/sve_helper.c
57
+++ b/hw/net/imx_fec.c
144
@@ -XXX,XX +XXX,XX @@ static uint32_t iter_predtest_fwd(uint64_t d, uint64_t g, uint32_t flags)
58
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_eth_txdescs = {
145
return flags;
59
146
}
60
static const VMStateDescription vmstate_imx_eth = {
147
61
.name = TYPE_IMX_FEC,
148
+/* This is an iterative function, called for each Pd and Pg word
62
- .version_id = 2,
149
+ * moving backward.
63
- .minimum_version_id = 2,
150
+ */
64
+ .version_id = 3,
151
+static uint32_t iter_predtest_bwd(uint64_t d, uint64_t g, uint32_t flags)
65
+ .minimum_version_id = 3,
152
+{
66
.fields = (const VMStateField[]) {
153
+ if (likely(g)) {
67
VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
154
+ /* Compute C from first (i.e last) !(D & G).
68
VMSTATE_UINT32(rx_descriptor, IMXFECState),
155
+ Use bit 2 to signal first G bit seen. */
69
VMSTATE_UINT32(tx_descriptor[0], IMXFECState),
156
+ if (!(flags & 4)) {
70
- VMSTATE_UINT32(phy_status, IMXFECState),
157
+ flags += 4 - 1; /* add bit 2, subtract C from PREDTEST_INIT */
71
- VMSTATE_UINT32(phy_control, IMXFECState),
158
+ flags |= (d & pow2floor(g)) == 0;
72
- VMSTATE_UINT32(phy_advertise, IMXFECState),
159
+ }
73
- VMSTATE_UINT32(phy_int, IMXFECState),
160
+
74
- VMSTATE_UINT32(phy_int_mask, IMXFECState),
161
+ /* Accumulate Z from each D & G. */
75
VMSTATE_END_OF_LIST()
162
+ flags |= ((d & g) != 0) << 1;
76
},
163
+
77
.subsections = (const VMStateDescription * const []) {
164
+ /* Compute N from last (i.e first) D & G. Replace previous. */
78
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_eth = {
165
+ flags = deposit32(flags, 31, 1, (d & (g & -g)) != 0);
79
},
80
};
81
82
-#define PHY_INT_ENERGYON (1 << 7)
83
-#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
84
-#define PHY_INT_FAULT (1 << 5)
85
-#define PHY_INT_DOWN (1 << 4)
86
-#define PHY_INT_AUTONEG_LP (1 << 3)
87
-#define PHY_INT_PARFAULT (1 << 2)
88
-#define PHY_INT_AUTONEG_PAGE (1 << 1)
89
-
90
static void imx_eth_update(IMXFECState *s);
91
92
/*
93
@@ -XXX,XX +XXX,XX @@ static void imx_eth_update(IMXFECState *s);
94
* For now we don't handle any GPIO/interrupt line, so the OS will
95
* have to poll for the PHY status.
96
*/
97
-static void imx_phy_update_irq(IMXFECState *s)
98
+static void imx_phy_update_irq(void *opaque, int n, int level)
99
{
100
- imx_eth_update(s);
101
-}
102
-
103
-static void imx_phy_update_link(IMXFECState *s)
104
-{
105
- /* Autonegotiation status mirrors link status. */
106
- if (qemu_get_queue(s->nic)->link_down) {
107
- trace_imx_phy_update_link("down");
108
- s->phy_status &= ~0x0024;
109
- s->phy_int |= PHY_INT_DOWN;
110
- } else {
111
- trace_imx_phy_update_link("up");
112
- s->phy_status |= 0x0024;
113
- s->phy_int |= PHY_INT_ENERGYON;
114
- s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
115
- }
116
- imx_phy_update_irq(s);
117
+ imx_eth_update(opaque);
118
}
119
120
static void imx_eth_set_link(NetClientState *nc)
121
{
122
- imx_phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
123
-}
124
-
125
-static void imx_phy_reset(IMXFECState *s)
126
-{
127
- trace_imx_phy_reset();
128
-
129
- s->phy_status = 0x7809;
130
- s->phy_control = 0x3000;
131
- s->phy_advertise = 0x01e1;
132
- s->phy_int_mask = 0;
133
- s->phy_int = 0;
134
- imx_phy_update_link(s);
135
+ lan9118_phy_update_link(&IMX_FEC(qemu_get_nic_opaque(nc))->mii,
136
+ nc->link_down);
137
}
138
139
static uint32_t imx_phy_read(IMXFECState *s, int reg)
140
{
141
- uint32_t val;
142
uint32_t phy = reg / 32;
143
144
if (!s->phy_connected) {
145
@@ -XXX,XX +XXX,XX @@ static uint32_t imx_phy_read(IMXFECState *s, int reg)
146
147
reg %= 32;
148
149
- switch (reg) {
150
- case 0: /* Basic Control */
151
- val = s->phy_control;
152
- break;
153
- case 1: /* Basic Status */
154
- val = s->phy_status;
155
- break;
156
- case 2: /* ID1 */
157
- val = 0x0007;
158
- break;
159
- case 3: /* ID2 */
160
- val = 0xc0d1;
161
- break;
162
- case 4: /* Auto-neg advertisement */
163
- val = s->phy_advertise;
164
- break;
165
- case 5: /* Auto-neg Link Partner Ability */
166
- val = 0x0f71;
167
- break;
168
- case 6: /* Auto-neg Expansion */
169
- val = 1;
170
- break;
171
- case 29: /* Interrupt source. */
172
- val = s->phy_int;
173
- s->phy_int = 0;
174
- imx_phy_update_irq(s);
175
- break;
176
- case 30: /* Interrupt mask */
177
- val = s->phy_int_mask;
178
- break;
179
- case 17:
180
- case 18:
181
- case 27:
182
- case 31:
183
- qemu_log_mask(LOG_UNIMP, "[%s.phy]%s: reg %d not implemented\n",
184
- TYPE_IMX_FEC, __func__, reg);
185
- val = 0;
186
- break;
187
- default:
188
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
189
- TYPE_IMX_FEC, __func__, reg);
190
- val = 0;
191
- break;
192
- }
193
-
194
- trace_imx_phy_read(val, phy, reg);
195
-
196
- return val;
197
+ return lan9118_phy_read(&s->mii, reg);
198
}
199
200
static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
201
@@ -XXX,XX +XXX,XX @@ static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
202
203
reg %= 32;
204
205
- trace_imx_phy_write(val, phy, reg);
206
-
207
- switch (reg) {
208
- case 0: /* Basic Control */
209
- if (val & 0x8000) {
210
- imx_phy_reset(s);
211
- } else {
212
- s->phy_control = val & 0x7980;
213
- /* Complete autonegotiation immediately. */
214
- if (val & 0x1000) {
215
- s->phy_status |= 0x0020;
216
- }
217
- }
218
- break;
219
- case 4: /* Auto-neg advertisement */
220
- s->phy_advertise = (val & 0x2d7f) | 0x80;
221
- break;
222
- case 30: /* Interrupt mask */
223
- s->phy_int_mask = val & 0xff;
224
- imx_phy_update_irq(s);
225
- break;
226
- case 17:
227
- case 18:
228
- case 27:
229
- case 31:
230
- qemu_log_mask(LOG_UNIMP, "[%s.phy)%s: reg %d not implemented\n",
231
- TYPE_IMX_FEC, __func__, reg);
232
- break;
233
- default:
234
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
235
- TYPE_IMX_FEC, __func__, reg);
236
- break;
237
- }
238
+ lan9118_phy_write(&s->mii, reg, val);
239
}
240
241
static void imx_fec_read_bd(IMXFECBufDesc *bd, dma_addr_t addr)
242
@@ -XXX,XX +XXX,XX @@ static void imx_eth_reset(DeviceState *d)
243
244
s->rx_descriptor = 0;
245
memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor));
246
-
247
- /* We also reset the PHY */
248
- imx_phy_reset(s);
249
}
250
251
static uint32_t imx_default_read(IMXFECState *s, uint32_t index)
252
@@ -XXX,XX +XXX,XX @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
253
sysbus_init_irq(sbd, &s->irq[0]);
254
sysbus_init_irq(sbd, &s->irq[1]);
255
256
+ qemu_init_irq(&s->mii_irq, imx_phy_update_irq, s, 0);
257
+ object_initialize_child(OBJECT(s), "mii", &s->mii, TYPE_LAN9118_PHY);
258
+ if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->mii), errp)) {
259
+ return;
166
+ }
260
+ }
167
+ return flags;
261
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
168
+}
262
+
169
+
263
qemu_macaddr_default_if_unset(&s->conf.macaddr);
170
/* The same for a single word predicate. */
264
171
uint32_t HELPER(sve_predtest1)(uint64_t d, uint64_t g)
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)
172
{
353
{
173
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_sel_zpzz_d)(void *vd, void *vn, void *vm,
354
+ trace_lan9118_phy_write(val, reg);
174
d[i] = (pg[H1(i)] & 1 ? nn : mm);
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;
175
}
395
}
176
}
396
}
177
+
397
178
+/* Two operand comparison controlled by a predicate.
398
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
179
+ * ??? It is very tempting to want to be able to expand this inline
399
180
+ * with x86 instructions, e.g.
400
/* Autonegotiation status mirrors link status. */
181
+ *
401
if (link_down) {
182
+ * vcmpeqw zm, zn, %ymm0
402
+ trace_lan9118_phy_update_link("down");
183
+ * vpmovmskb %ymm0, %eax
403
s->status &= ~0x0024;
184
+ * and $0x5555, %eax
404
s->ints |= PHY_INT_DOWN;
185
+ * and pg, %eax
405
} else {
186
+ *
406
+ trace_lan9118_phy_update_link("up");
187
+ * or even aarch64, e.g.
407
s->status |= 0x0024;
188
+ *
408
s->ints |= PHY_INT_ENERGYON;
189
+ * // mask = 4000 1000 0400 0100 0040 0010 0004 0001
409
s->ints |= PHY_INT_AUTONEG_COMPLETE;
190
+ * cmeq v0.8h, zn, zm
410
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
191
+ * and v0.8h, v0.8h, mask
411
192
+ * addv h0, v0.8h
412
void lan9118_phy_reset(Lan9118PhyState *s)
193
+ * and v0.8b, pg
413
{
194
+ *
414
+ trace_lan9118_phy_reset();
195
+ * However, coming up with an abstraction that allows vector inputs and
415
+
196
+ * a scalar output, and also handles the byte-ordering of sub-uint64_t
416
s->control = 0x3000;
197
+ * scalar outputs, is tricky.
417
s->status = 0x7809;
198
+ */
418
s->advertise = 0x01e1;
199
+#define DO_CMP_PPZZ(NAME, TYPE, OP, H, MASK) \
419
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118_phy = {
200
+uint32_t HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \
420
.version_id = 1,
201
+{ \
421
.minimum_version_id = 1,
202
+ intptr_t opr_sz = simd_oprsz(desc); \
422
.fields = (const VMStateField[]) {
203
+ uint32_t flags = PREDTEST_INIT; \
423
- VMSTATE_UINT16(control, Lan9118PhyState),
204
+ intptr_t i = opr_sz; \
424
VMSTATE_UINT16(status, Lan9118PhyState),
205
+ do { \
425
+ VMSTATE_UINT16(control, Lan9118PhyState),
206
+ uint64_t out = 0, pg; \
426
VMSTATE_UINT16(advertise, Lan9118PhyState),
207
+ do { \
427
VMSTATE_UINT16(ints, Lan9118PhyState),
208
+ i -= sizeof(TYPE), out <<= sizeof(TYPE); \
428
VMSTATE_UINT16(int_mask, Lan9118PhyState),
209
+ TYPE nn = *(TYPE *)(vn + H(i)); \
429
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
210
+ TYPE mm = *(TYPE *)(vm + H(i)); \
211
+ out |= nn OP mm; \
212
+ } while (i & 63); \
213
+ pg = *(uint64_t *)(vg + (i >> 3)) & MASK; \
214
+ out &= pg; \
215
+ *(uint64_t *)(vd + (i >> 3)) = out; \
216
+ flags = iter_predtest_bwd(out, pg, flags); \
217
+ } while (i > 0); \
218
+ return flags; \
219
+}
220
+
221
+#define DO_CMP_PPZZ_B(NAME, TYPE, OP) \
222
+ DO_CMP_PPZZ(NAME, TYPE, OP, H1, 0xffffffffffffffffull)
223
+#define DO_CMP_PPZZ_H(NAME, TYPE, OP) \
224
+ DO_CMP_PPZZ(NAME, TYPE, OP, H1_2, 0x5555555555555555ull)
225
+#define DO_CMP_PPZZ_S(NAME, TYPE, OP) \
226
+ DO_CMP_PPZZ(NAME, TYPE, OP, H1_4, 0x1111111111111111ull)
227
+#define DO_CMP_PPZZ_D(NAME, TYPE, OP) \
228
+ DO_CMP_PPZZ(NAME, TYPE, OP, , 0x0101010101010101ull)
229
+
230
+DO_CMP_PPZZ_B(sve_cmpeq_ppzz_b, uint8_t, ==)
231
+DO_CMP_PPZZ_H(sve_cmpeq_ppzz_h, uint16_t, ==)
232
+DO_CMP_PPZZ_S(sve_cmpeq_ppzz_s, uint32_t, ==)
233
+DO_CMP_PPZZ_D(sve_cmpeq_ppzz_d, uint64_t, ==)
234
+
235
+DO_CMP_PPZZ_B(sve_cmpne_ppzz_b, uint8_t, !=)
236
+DO_CMP_PPZZ_H(sve_cmpne_ppzz_h, uint16_t, !=)
237
+DO_CMP_PPZZ_S(sve_cmpne_ppzz_s, uint32_t, !=)
238
+DO_CMP_PPZZ_D(sve_cmpne_ppzz_d, uint64_t, !=)
239
+
240
+DO_CMP_PPZZ_B(sve_cmpgt_ppzz_b, int8_t, >)
241
+DO_CMP_PPZZ_H(sve_cmpgt_ppzz_h, int16_t, >)
242
+DO_CMP_PPZZ_S(sve_cmpgt_ppzz_s, int32_t, >)
243
+DO_CMP_PPZZ_D(sve_cmpgt_ppzz_d, int64_t, >)
244
+
245
+DO_CMP_PPZZ_B(sve_cmpge_ppzz_b, int8_t, >=)
246
+DO_CMP_PPZZ_H(sve_cmpge_ppzz_h, int16_t, >=)
247
+DO_CMP_PPZZ_S(sve_cmpge_ppzz_s, int32_t, >=)
248
+DO_CMP_PPZZ_D(sve_cmpge_ppzz_d, int64_t, >=)
249
+
250
+DO_CMP_PPZZ_B(sve_cmphi_ppzz_b, uint8_t, >)
251
+DO_CMP_PPZZ_H(sve_cmphi_ppzz_h, uint16_t, >)
252
+DO_CMP_PPZZ_S(sve_cmphi_ppzz_s, uint32_t, >)
253
+DO_CMP_PPZZ_D(sve_cmphi_ppzz_d, uint64_t, >)
254
+
255
+DO_CMP_PPZZ_B(sve_cmphs_ppzz_b, uint8_t, >=)
256
+DO_CMP_PPZZ_H(sve_cmphs_ppzz_h, uint16_t, >=)
257
+DO_CMP_PPZZ_S(sve_cmphs_ppzz_s, uint32_t, >=)
258
+DO_CMP_PPZZ_D(sve_cmphs_ppzz_d, uint64_t, >=)
259
+
260
+#undef DO_CMP_PPZZ_B
261
+#undef DO_CMP_PPZZ_H
262
+#undef DO_CMP_PPZZ_S
263
+#undef DO_CMP_PPZZ_D
264
+#undef DO_CMP_PPZZ
265
+
266
+/* Similar, but the second source is "wide". */
267
+#define DO_CMP_PPZW(NAME, TYPE, TYPEW, OP, H, MASK) \
268
+uint32_t HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \
269
+{ \
270
+ intptr_t opr_sz = simd_oprsz(desc); \
271
+ uint32_t flags = PREDTEST_INIT; \
272
+ intptr_t i = opr_sz; \
273
+ do { \
274
+ uint64_t out = 0, pg; \
275
+ do { \
276
+ TYPEW mm = *(TYPEW *)(vm + i - 8); \
277
+ do { \
278
+ i -= sizeof(TYPE), out <<= sizeof(TYPE); \
279
+ TYPE nn = *(TYPE *)(vn + H(i)); \
280
+ out |= nn OP mm; \
281
+ } while (i & 7); \
282
+ } while (i & 63); \
283
+ pg = *(uint64_t *)(vg + (i >> 3)) & MASK; \
284
+ out &= pg; \
285
+ *(uint64_t *)(vd + (i >> 3)) = out; \
286
+ flags = iter_predtest_bwd(out, pg, flags); \
287
+ } while (i > 0); \
288
+ return flags; \
289
+}
290
+
291
+#define DO_CMP_PPZW_B(NAME, TYPE, TYPEW, OP) \
292
+ DO_CMP_PPZW(NAME, TYPE, TYPEW, OP, H1, 0xffffffffffffffffull)
293
+#define DO_CMP_PPZW_H(NAME, TYPE, TYPEW, OP) \
294
+ DO_CMP_PPZW(NAME, TYPE, TYPEW, OP, H1_2, 0x5555555555555555ull)
295
+#define DO_CMP_PPZW_S(NAME, TYPE, TYPEW, OP) \
296
+ DO_CMP_PPZW(NAME, TYPE, TYPEW, OP, H1_4, 0x1111111111111111ull)
297
+
298
+DO_CMP_PPZW_B(sve_cmpeq_ppzw_b, uint8_t, uint64_t, ==)
299
+DO_CMP_PPZW_H(sve_cmpeq_ppzw_h, uint16_t, uint64_t, ==)
300
+DO_CMP_PPZW_S(sve_cmpeq_ppzw_s, uint32_t, uint64_t, ==)
301
+
302
+DO_CMP_PPZW_B(sve_cmpne_ppzw_b, uint8_t, uint64_t, !=)
303
+DO_CMP_PPZW_H(sve_cmpne_ppzw_h, uint16_t, uint64_t, !=)
304
+DO_CMP_PPZW_S(sve_cmpne_ppzw_s, uint32_t, uint64_t, !=)
305
+
306
+DO_CMP_PPZW_B(sve_cmpgt_ppzw_b, int8_t, int64_t, >)
307
+DO_CMP_PPZW_H(sve_cmpgt_ppzw_h, int16_t, int64_t, >)
308
+DO_CMP_PPZW_S(sve_cmpgt_ppzw_s, int32_t, int64_t, >)
309
+
310
+DO_CMP_PPZW_B(sve_cmpge_ppzw_b, int8_t, int64_t, >=)
311
+DO_CMP_PPZW_H(sve_cmpge_ppzw_h, int16_t, int64_t, >=)
312
+DO_CMP_PPZW_S(sve_cmpge_ppzw_s, int32_t, int64_t, >=)
313
+
314
+DO_CMP_PPZW_B(sve_cmphi_ppzw_b, uint8_t, uint64_t, >)
315
+DO_CMP_PPZW_H(sve_cmphi_ppzw_h, uint16_t, uint64_t, >)
316
+DO_CMP_PPZW_S(sve_cmphi_ppzw_s, uint32_t, uint64_t, >)
317
+
318
+DO_CMP_PPZW_B(sve_cmphs_ppzw_b, uint8_t, uint64_t, >=)
319
+DO_CMP_PPZW_H(sve_cmphs_ppzw_h, uint16_t, uint64_t, >=)
320
+DO_CMP_PPZW_S(sve_cmphs_ppzw_s, uint32_t, uint64_t, >=)
321
+
322
+DO_CMP_PPZW_B(sve_cmplt_ppzw_b, int8_t, int64_t, <)
323
+DO_CMP_PPZW_H(sve_cmplt_ppzw_h, int16_t, int64_t, <)
324
+DO_CMP_PPZW_S(sve_cmplt_ppzw_s, int32_t, int64_t, <)
325
+
326
+DO_CMP_PPZW_B(sve_cmple_ppzw_b, int8_t, int64_t, <=)
327
+DO_CMP_PPZW_H(sve_cmple_ppzw_h, int16_t, int64_t, <=)
328
+DO_CMP_PPZW_S(sve_cmple_ppzw_s, int32_t, int64_t, <=)
329
+
330
+DO_CMP_PPZW_B(sve_cmplo_ppzw_b, uint8_t, uint64_t, <)
331
+DO_CMP_PPZW_H(sve_cmplo_ppzw_h, uint16_t, uint64_t, <)
332
+DO_CMP_PPZW_S(sve_cmplo_ppzw_s, uint32_t, uint64_t, <)
333
+
334
+DO_CMP_PPZW_B(sve_cmpls_ppzw_b, uint8_t, uint64_t, <=)
335
+DO_CMP_PPZW_H(sve_cmpls_ppzw_h, uint16_t, uint64_t, <=)
336
+DO_CMP_PPZW_S(sve_cmpls_ppzw_s, uint32_t, uint64_t, <=)
337
+
338
+#undef DO_CMP_PPZW_B
339
+#undef DO_CMP_PPZW_H
340
+#undef DO_CMP_PPZW_S
341
+#undef DO_CMP_PPZW
342
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
343
index XXXXXXX..XXXXXXX 100644
430
index XXXXXXX..XXXXXXX 100644
344
--- a/target/arm/translate-sve.c
431
--- a/hw/net/Kconfig
345
+++ b/target/arm/translate-sve.c
432
+++ b/hw/net/Kconfig
346
@@ -XXX,XX +XXX,XX @@
433
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_SUN8I_EMAC
347
#include "trace-tcg.h"
434
348
#include "translate-a64.h"
435
config IMX_FEC
349
436
bool
350
+
437
+ select LAN9118_PHY
351
+typedef void gen_helper_gvec_flags_4(TCGv_i32, TCGv_ptr, TCGv_ptr,
438
352
+ TCGv_ptr, TCGv_ptr, TCGv_i32);
439
config CADENCE
353
+
440
bool
354
/*
441
diff --git a/hw/net/trace-events b/hw/net/trace-events
355
* Helpers for extracting complex instruction fields.
356
*/
357
@@ -XXX,XX +XXX,XX @@ static bool trans_SPLICE(DisasContext *s, arg_rprr_esz *a, uint32_t insn)
358
return true;
359
}
360
361
+/*
362
+ *** SVE Integer Compare - Vectors Group
363
+ */
364
+
365
+static bool do_ppzz_flags(DisasContext *s, arg_rprr_esz *a,
366
+ gen_helper_gvec_flags_4 *gen_fn)
367
+{
368
+ TCGv_ptr pd, zn, zm, pg;
369
+ unsigned vsz;
370
+ TCGv_i32 t;
371
+
372
+ if (gen_fn == NULL) {
373
+ return false;
374
+ }
375
+ if (!sve_access_check(s)) {
376
+ return true;
377
+ }
378
+
379
+ vsz = vec_full_reg_size(s);
380
+ t = tcg_const_i32(simd_desc(vsz, vsz, 0));
381
+ pd = tcg_temp_new_ptr();
382
+ zn = tcg_temp_new_ptr();
383
+ zm = tcg_temp_new_ptr();
384
+ pg = tcg_temp_new_ptr();
385
+
386
+ tcg_gen_addi_ptr(pd, cpu_env, pred_full_reg_offset(s, a->rd));
387
+ tcg_gen_addi_ptr(zn, cpu_env, vec_full_reg_offset(s, a->rn));
388
+ tcg_gen_addi_ptr(zm, cpu_env, vec_full_reg_offset(s, a->rm));
389
+ tcg_gen_addi_ptr(pg, cpu_env, pred_full_reg_offset(s, a->pg));
390
+
391
+ gen_fn(t, pd, zn, zm, pg, t);
392
+
393
+ tcg_temp_free_ptr(pd);
394
+ tcg_temp_free_ptr(zn);
395
+ tcg_temp_free_ptr(zm);
396
+ tcg_temp_free_ptr(pg);
397
+
398
+ do_pred_flags(t);
399
+
400
+ tcg_temp_free_i32(t);
401
+ return true;
402
+}
403
+
404
+#define DO_PPZZ(NAME, name) \
405
+static bool trans_##NAME##_ppzz(DisasContext *s, arg_rprr_esz *a, \
406
+ uint32_t insn) \
407
+{ \
408
+ static gen_helper_gvec_flags_4 * const fns[4] = { \
409
+ gen_helper_sve_##name##_ppzz_b, gen_helper_sve_##name##_ppzz_h, \
410
+ gen_helper_sve_##name##_ppzz_s, gen_helper_sve_##name##_ppzz_d, \
411
+ }; \
412
+ return do_ppzz_flags(s, a, fns[a->esz]); \
413
+}
414
+
415
+DO_PPZZ(CMPEQ, cmpeq)
416
+DO_PPZZ(CMPNE, cmpne)
417
+DO_PPZZ(CMPGT, cmpgt)
418
+DO_PPZZ(CMPGE, cmpge)
419
+DO_PPZZ(CMPHI, cmphi)
420
+DO_PPZZ(CMPHS, cmphs)
421
+
422
+#undef DO_PPZZ
423
+
424
+#define DO_PPZW(NAME, name) \
425
+static bool trans_##NAME##_ppzw(DisasContext *s, arg_rprr_esz *a, \
426
+ uint32_t insn) \
427
+{ \
428
+ static gen_helper_gvec_flags_4 * const fns[4] = { \
429
+ gen_helper_sve_##name##_ppzw_b, gen_helper_sve_##name##_ppzw_h, \
430
+ gen_helper_sve_##name##_ppzw_s, NULL \
431
+ }; \
432
+ return do_ppzz_flags(s, a, fns[a->esz]); \
433
+}
434
+
435
+DO_PPZW(CMPEQ, cmpeq)
436
+DO_PPZW(CMPNE, cmpne)
437
+DO_PPZW(CMPGT, cmpgt)
438
+DO_PPZW(CMPGE, cmpge)
439
+DO_PPZW(CMPHI, cmphi)
440
+DO_PPZW(CMPHS, cmphs)
441
+DO_PPZW(CMPLT, cmplt)
442
+DO_PPZW(CMPLE, cmple)
443
+DO_PPZW(CMPLO, cmplo)
444
+DO_PPZW(CMPLS, cmpls)
445
+
446
+#undef DO_PPZW
447
+
448
/*
449
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
450
*/
451
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
452
index XXXXXXX..XXXXXXX 100644
442
index XXXXXXX..XXXXXXX 100644
453
--- a/target/arm/sve.decode
443
--- a/hw/net/trace-events
454
+++ b/target/arm/sve.decode
444
+++ b/hw/net/trace-events
455
@@ -XXX,XX +XXX,XX @@
445
@@ -XXX,XX +XXX,XX @@ allwinner_sun8i_emac_set_link(bool active) "Set link: active=%u"
456
@rdm_pg_rn ........ esz:2 ... ... ... pg:3 rn:5 rd:5 \
446
allwinner_sun8i_emac_read(uint64_t offset, uint64_t val) "MMIO read: offset=0x%" PRIx64 " value=0x%" PRIx64
457
&rprr_esz rm=%reg_movprfx
447
allwinner_sun8i_emac_write(uint64_t offset, uint64_t val) "MMIO write: offset=0x%" PRIx64 " value=0x%" PRIx64
458
@rd_pg4_rn_rm ........ esz:2 . rm:5 .. pg:4 rn:5 rd:5 &rprr_esz
448
459
+@pd_pg_rn_rm ........ esz:2 . rm:5 ... pg:3 rn:5 . rd:4 &rprr_esz
449
+# lan9118_phy.c
460
450
+lan9118_phy_read(uint16_t val, int reg) "[0x%02x] -> 0x%04" PRIx16
461
# Three register operand, with governing predicate, vector element size
451
+lan9118_phy_write(uint16_t val, int reg) "[0x%02x] <- 0x%04" PRIx16
462
@rda_pg_rn_rm ........ esz:2 . rm:5 ... pg:3 rn:5 rd:5 \
452
+lan9118_phy_update_link(const char *s) "%s"
463
@@ -XXX,XX +XXX,XX @@ SPLICE 00000101 .. 101 100 100 ... ..... ..... @rdn_pg_rm
453
+lan9118_phy_reset(void) ""
464
# SVE select vector elements (predicated)
454
+
465
SEL_zpzz 00000101 .. 1 ..... 11 .... ..... ..... @rd_pg4_rn_rm
455
# lance.c
466
456
lance_mem_readw(uint64_t addr, uint32_t ret) "addr=0x%"PRIx64"val=0x%04x"
467
+### SVE Integer Compare - Vectors Group
457
lance_mem_writew(uint64_t addr, uint32_t val) "addr=0x%"PRIx64"val=0x%04x"
468
+
458
@@ -XXX,XX +XXX,XX @@ i82596_set_multicast(uint16_t count) "Added %d multicast entries"
469
+# SVE integer compare_vectors
459
i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION"
470
+CMPHS_ppzz 00100100 .. 0 ..... 000 ... ..... 0 .... @pd_pg_rn_rm
460
471
+CMPHI_ppzz 00100100 .. 0 ..... 000 ... ..... 1 .... @pd_pg_rn_rm
461
# imx_fec.c
472
+CMPGE_ppzz 00100100 .. 0 ..... 100 ... ..... 0 .... @pd_pg_rn_rm
462
-imx_phy_read(uint32_t val, int phy, int reg) "0x%04"PRIx32" <= phy[%d].reg[%d]"
473
+CMPGT_ppzz 00100100 .. 0 ..... 100 ... ..... 1 .... @pd_pg_rn_rm
463
imx_phy_read_num(int phy, int configured) "read request from unconfigured phy %d (configured %d)"
474
+CMPEQ_ppzz 00100100 .. 0 ..... 101 ... ..... 0 .... @pd_pg_rn_rm
464
-imx_phy_write(uint32_t val, int phy, int reg) "0x%04"PRIx32" => phy[%d].reg[%d]"
475
+CMPNE_ppzz 00100100 .. 0 ..... 101 ... ..... 1 .... @pd_pg_rn_rm
465
imx_phy_write_num(int phy, int configured) "write request to unconfigured phy %d (configured %d)"
476
+
466
-imx_phy_update_link(const char *s) "%s"
477
+# SVE integer compare with wide elements
467
-imx_phy_reset(void) ""
478
+# Note these require esz != 3.
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"
479
+CMPEQ_ppzw 00100100 .. 0 ..... 001 ... ..... 0 .... @pd_pg_rn_rm
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"
480
+CMPNE_ppzw 00100100 .. 0 ..... 001 ... ..... 1 .... @pd_pg_rn_rm
470
imx_eth_tx_bd_busy(void) "tx_bd ran out of descriptors to transmit"
481
+CMPGE_ppzw 00100100 .. 0 ..... 010 ... ..... 0 .... @pd_pg_rn_rm
482
+CMPGT_ppzw 00100100 .. 0 ..... 010 ... ..... 1 .... @pd_pg_rn_rm
483
+CMPLT_ppzw 00100100 .. 0 ..... 011 ... ..... 0 .... @pd_pg_rn_rm
484
+CMPLE_ppzw 00100100 .. 0 ..... 011 ... ..... 1 .... @pd_pg_rn_rm
485
+CMPHS_ppzw 00100100 .. 0 ..... 110 ... ..... 0 .... @pd_pg_rn_rm
486
+CMPHI_ppzw 00100100 .. 0 ..... 110 ... ..... 1 .... @pd_pg_rn_rm
487
+CMPLO_ppzw 00100100 .. 0 ..... 111 ... ..... 0 .... @pd_pg_rn_rm
488
+CMPLS_ppzw 00100100 .. 0 ..... 111 ... ..... 1 .... @pd_pg_rn_rm
489
+
490
### SVE Predicate Logical Operations Group
491
492
# SVE predicate logical operations
493
--
471
--
494
2.17.1
472
2.34.1
495
496
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Turns 0x70 into 0xe0 (== 0x70 << 1) which adds the missing MII_ANLPAR_TX and
4
fixes the MSB of selector field to be zero, as specified in the datasheet.
5
6
Fixes: 2a424990170b "LAN9118 emulation"
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Tested-by: Guenter Roeck <linux@roeck-us.net>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241102125724.532843-4-shentey@gmail.com
5
Message-id: 20180613015641.5667-19-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
12
---
8
target/arm/helper-sve.h | 14 ++++++++
13
hw/net/lan9118_phy.c | 2 +-
9
target/arm/helper.h | 19 +++++++++++
14
1 file changed, 1 insertion(+), 1 deletion(-)
10
target/arm/translate-sve.c | 42 +++++++++++++++++++++++
11
target/arm/vec_helper.c | 69 ++++++++++++++++++++++++++++++++++++++
12
target/arm/sve.decode | 10 ++++++
13
5 files changed, 154 insertions(+)
14
15
15
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-sve.h
18
--- a/hw/net/lan9118_phy.c
18
+++ b/target/arm/helper-sve.h
19
+++ b/hw/net/lan9118_phy.c
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_umini_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
20
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
20
DEF_HELPER_FLAGS_4(sve_umini_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
21
val = s->advertise;
21
DEF_HELPER_FLAGS_4(sve_umini_s, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
22
break;
22
DEF_HELPER_FLAGS_4(sve_umini_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
23
case 5: /* Auto-neg Link Partner Ability */
23
+
24
- val = 0x0f71;
24
+DEF_HELPER_FLAGS_5(gvec_recps_h, TCG_CALL_NO_RWG,
25
+ val = 0x0fe1;
25
+ void, ptr, ptr, ptr, ptr, i32)
26
break;
26
+DEF_HELPER_FLAGS_5(gvec_recps_s, TCG_CALL_NO_RWG,
27
case 6: /* Auto-neg Expansion */
27
+ void, ptr, ptr, ptr, ptr, i32)
28
val = 1;
28
+DEF_HELPER_FLAGS_5(gvec_recps_d, TCG_CALL_NO_RWG,
29
+ void, ptr, ptr, ptr, ptr, i32)
30
+
31
+DEF_HELPER_FLAGS_5(gvec_rsqrts_h, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_5(gvec_rsqrts_s, TCG_CALL_NO_RWG,
34
+ void, ptr, ptr, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_5(gvec_rsqrts_d, TCG_CALL_NO_RWG,
36
+ void, ptr, ptr, ptr, ptr, i32)
37
diff --git a/target/arm/helper.h b/target/arm/helper.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/helper.h
40
+++ b/target/arm/helper.h
41
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fcmlas_idx, TCG_CALL_NO_RWG,
42
DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG,
43
void, ptr, ptr, ptr, ptr, i32)
44
45
+DEF_HELPER_FLAGS_5(gvec_fadd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
46
+DEF_HELPER_FLAGS_5(gvec_fadd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
47
+DEF_HELPER_FLAGS_5(gvec_fadd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
48
+
49
+DEF_HELPER_FLAGS_5(gvec_fsub_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
50
+DEF_HELPER_FLAGS_5(gvec_fsub_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
51
+DEF_HELPER_FLAGS_5(gvec_fsub_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
52
+
53
+DEF_HELPER_FLAGS_5(gvec_fmul_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
54
+DEF_HELPER_FLAGS_5(gvec_fmul_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
55
+DEF_HELPER_FLAGS_5(gvec_fmul_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
56
+
57
+DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
58
+ void, ptr, ptr, ptr, ptr, i32)
59
+DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
60
+ void, ptr, ptr, ptr, ptr, i32)
61
+DEF_HELPER_FLAGS_5(gvec_ftsmul_d, TCG_CALL_NO_RWG,
62
+ void, ptr, ptr, ptr, ptr, i32)
63
+
64
#ifdef TARGET_AARCH64
65
#include "helper-a64.h"
66
#include "helper-sve.h"
67
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/translate-sve.c
70
+++ b/target/arm/translate-sve.c
71
@@ -XXX,XX +XXX,XX @@ DO_ZZI(UMIN, umin)
72
73
#undef DO_ZZI
74
75
+/*
76
+ *** SVE Floating Point Arithmetic - Unpredicated Group
77
+ */
78
+
79
+static bool do_zzz_fp(DisasContext *s, arg_rrr_esz *a,
80
+ gen_helper_gvec_3_ptr *fn)
81
+{
82
+ if (fn == NULL) {
83
+ return false;
84
+ }
85
+ if (sve_access_check(s)) {
86
+ unsigned vsz = vec_full_reg_size(s);
87
+ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
88
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
89
+ vec_full_reg_offset(s, a->rn),
90
+ vec_full_reg_offset(s, a->rm),
91
+ status, vsz, vsz, 0, fn);
92
+ tcg_temp_free_ptr(status);
93
+ }
94
+ return true;
95
+}
96
+
97
+
98
+#define DO_FP3(NAME, name) \
99
+static bool trans_##NAME(DisasContext *s, arg_rrr_esz *a, uint32_t insn) \
100
+{ \
101
+ static gen_helper_gvec_3_ptr * const fns[4] = { \
102
+ NULL, gen_helper_gvec_##name##_h, \
103
+ gen_helper_gvec_##name##_s, gen_helper_gvec_##name##_d \
104
+ }; \
105
+ return do_zzz_fp(s, a, fns[a->esz]); \
106
+}
107
+
108
+DO_FP3(FADD_zzz, fadd)
109
+DO_FP3(FSUB_zzz, fsub)
110
+DO_FP3(FMUL_zzz, fmul)
111
+DO_FP3(FTSMUL, ftsmul)
112
+DO_FP3(FRECPS, recps)
113
+DO_FP3(FRSQRTS, rsqrts)
114
+
115
+#undef DO_FP3
116
+
117
/*
118
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
119
*/
120
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/target/arm/vec_helper.c
123
+++ b/target/arm/vec_helper.c
124
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
125
}
126
clear_tail(d, opr_sz, simd_maxsz(desc));
127
}
128
+
129
+/* Floating-point trigonometric starting value.
130
+ * See the ARM ARM pseudocode function FPTrigSMul.
131
+ */
132
+static float16 float16_ftsmul(float16 op1, uint16_t op2, float_status *stat)
133
+{
134
+ float16 result = float16_mul(op1, op1, stat);
135
+ if (!float16_is_any_nan(result)) {
136
+ result = float16_set_sign(result, op2 & 1);
137
+ }
138
+ return result;
139
+}
140
+
141
+static float32 float32_ftsmul(float32 op1, uint32_t op2, float_status *stat)
142
+{
143
+ float32 result = float32_mul(op1, op1, stat);
144
+ if (!float32_is_any_nan(result)) {
145
+ result = float32_set_sign(result, op2 & 1);
146
+ }
147
+ return result;
148
+}
149
+
150
+static float64 float64_ftsmul(float64 op1, uint64_t op2, float_status *stat)
151
+{
152
+ float64 result = float64_mul(op1, op1, stat);
153
+ if (!float64_is_any_nan(result)) {
154
+ result = float64_set_sign(result, op2 & 1);
155
+ }
156
+ return result;
157
+}
158
+
159
+#define DO_3OP(NAME, FUNC, TYPE) \
160
+void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
161
+{ \
162
+ intptr_t i, oprsz = simd_oprsz(desc); \
163
+ TYPE *d = vd, *n = vn, *m = vm; \
164
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
165
+ d[i] = FUNC(n[i], m[i], stat); \
166
+ } \
167
+}
168
+
169
+DO_3OP(gvec_fadd_h, float16_add, float16)
170
+DO_3OP(gvec_fadd_s, float32_add, float32)
171
+DO_3OP(gvec_fadd_d, float64_add, float64)
172
+
173
+DO_3OP(gvec_fsub_h, float16_sub, float16)
174
+DO_3OP(gvec_fsub_s, float32_sub, float32)
175
+DO_3OP(gvec_fsub_d, float64_sub, float64)
176
+
177
+DO_3OP(gvec_fmul_h, float16_mul, float16)
178
+DO_3OP(gvec_fmul_s, float32_mul, float32)
179
+DO_3OP(gvec_fmul_d, float64_mul, float64)
180
+
181
+DO_3OP(gvec_ftsmul_h, float16_ftsmul, float16)
182
+DO_3OP(gvec_ftsmul_s, float32_ftsmul, float32)
183
+DO_3OP(gvec_ftsmul_d, float64_ftsmul, float64)
184
+
185
+#ifdef TARGET_AARCH64
186
+
187
+DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
188
+DO_3OP(gvec_recps_s, helper_recpsf_f32, float32)
189
+DO_3OP(gvec_recps_d, helper_recpsf_f64, float64)
190
+
191
+DO_3OP(gvec_rsqrts_h, helper_rsqrtsf_f16, float16)
192
+DO_3OP(gvec_rsqrts_s, helper_rsqrtsf_f32, float32)
193
+DO_3OP(gvec_rsqrts_d, helper_rsqrtsf_f64, float64)
194
+
195
+#endif
196
+#undef DO_3OP
197
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
198
index XXXXXXX..XXXXXXX 100644
199
--- a/target/arm/sve.decode
200
+++ b/target/arm/sve.decode
201
@@ -XXX,XX +XXX,XX @@ UMIN_zzi 00100101 .. 101 011 110 ........ ..... @rdn_i8u
202
# SVE integer multiply immediate (unpredicated)
203
MUL_zzi 00100101 .. 110 000 110 ........ ..... @rdn_i8s
204
205
+### SVE Floating Point Arithmetic - Unpredicated Group
206
+
207
+# SVE floating-point arithmetic (unpredicated)
208
+FADD_zzz 01100101 .. 0 ..... 000 000 ..... ..... @rd_rn_rm
209
+FSUB_zzz 01100101 .. 0 ..... 000 001 ..... ..... @rd_rn_rm
210
+FMUL_zzz 01100101 .. 0 ..... 000 010 ..... ..... @rd_rn_rm
211
+FTSMUL 01100101 .. 0 ..... 000 011 ..... ..... @rd_rn_rm
212
+FRECPS 01100101 .. 0 ..... 000 110 ..... ..... @rd_rn_rm
213
+FRSQRTS 01100101 .. 0 ..... 000 111 ..... ..... @rd_rn_rm
214
+
215
### SVE Memory - 32-bit Gather and Unsized Contiguous Group
216
217
# SVE load predicate register
218
--
29
--
219
2.17.1
30
2.34.1
220
221
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
3
Prefer named constants over magic values for better readability.
2
4
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
Message-id: 20180613015641.5667-18-richard.henderson@linaro.org
7
Tested-by: Guenter Roeck <linux@roeck-us.net>
8
Message-id: 20241102125724.532843-5-shentey@gmail.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 25 +++++++
11
include/hw/net/mii.h | 6 +++++
9
target/arm/sve_helper.c | 41 +++++++++++
12
hw/net/lan9118_phy.c | 63 ++++++++++++++++++++++++++++----------------
10
target/arm/translate-sve.c | 144 +++++++++++++++++++++++++++++++++++++
13
2 files changed, 46 insertions(+), 23 deletions(-)
11
target/arm/sve.decode | 26 +++++++
12
4 files changed, 236 insertions(+)
13
14
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
17
--- a/include/hw/net/mii.h
17
+++ b/target/arm/helper-sve.h
18
+++ b/include/hw/net/mii.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_brkns, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
19
@@ -XXX,XX +XXX,XX @@
19
DEF_HELPER_FLAGS_3(sve_cntp, TCG_CALL_NO_RWG, i64, ptr, ptr, i32)
20
#define MII_BMSR_JABBER (1 << 1) /* Jabber detected */
20
21
#define MII_BMSR_EXTCAP (1 << 0) /* Ext-reg capability */
21
DEF_HELPER_FLAGS_3(sve_while, TCG_CALL_NO_RWG, i32, ptr, i32, i32)
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
22
+
42
+
23
+DEF_HELPER_FLAGS_4(sve_subri_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
43
/* RealTek 8211E */
24
+DEF_HELPER_FLAGS_4(sve_subri_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
44
#define RTL8211E_PHYID1 0x001c
25
+DEF_HELPER_FLAGS_4(sve_subri_s, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
45
#define RTL8211E_PHYID2 0xc915
26
+DEF_HELPER_FLAGS_4(sve_subri_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
46
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
27
+
28
+DEF_HELPER_FLAGS_4(sve_smaxi_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
29
+DEF_HELPER_FLAGS_4(sve_smaxi_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
30
+DEF_HELPER_FLAGS_4(sve_smaxi_s, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
31
+DEF_HELPER_FLAGS_4(sve_smaxi_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
32
+
33
+DEF_HELPER_FLAGS_4(sve_smini_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
34
+DEF_HELPER_FLAGS_4(sve_smini_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
35
+DEF_HELPER_FLAGS_4(sve_smini_s, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
36
+DEF_HELPER_FLAGS_4(sve_smini_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
37
+
38
+DEF_HELPER_FLAGS_4(sve_umaxi_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
39
+DEF_HELPER_FLAGS_4(sve_umaxi_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
40
+DEF_HELPER_FLAGS_4(sve_umaxi_s, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
41
+DEF_HELPER_FLAGS_4(sve_umaxi_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
42
+
43
+DEF_HELPER_FLAGS_4(sve_umini_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
44
+DEF_HELPER_FLAGS_4(sve_umini_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
45
+DEF_HELPER_FLAGS_4(sve_umini_s, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
46
+DEF_HELPER_FLAGS_4(sve_umini_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
47
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
48
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/sve_helper.c
48
--- a/hw/net/lan9118_phy.c
50
+++ b/target/arm/sve_helper.c
49
+++ b/hw/net/lan9118_phy.c
51
@@ -XXX,XX +XXX,XX @@ DO_VPZ_D(sve_uminv_d, uint64_t, uint64_t, -1, DO_MIN)
52
#undef DO_VPZ
53
#undef DO_VPZ_D
54
55
+/* Two vector operand, one scalar operand, unpredicated. */
56
+#define DO_ZZI(NAME, TYPE, OP) \
57
+void HELPER(NAME)(void *vd, void *vn, uint64_t s64, uint32_t desc) \
58
+{ \
59
+ intptr_t i, opr_sz = simd_oprsz(desc) / sizeof(TYPE); \
60
+ TYPE s = s64, *d = vd, *n = vn; \
61
+ for (i = 0; i < opr_sz; ++i) { \
62
+ d[i] = OP(n[i], s); \
63
+ } \
64
+}
65
+
66
+#define DO_SUBR(X, Y) (Y - X)
67
+
68
+DO_ZZI(sve_subri_b, uint8_t, DO_SUBR)
69
+DO_ZZI(sve_subri_h, uint16_t, DO_SUBR)
70
+DO_ZZI(sve_subri_s, uint32_t, DO_SUBR)
71
+DO_ZZI(sve_subri_d, uint64_t, DO_SUBR)
72
+
73
+DO_ZZI(sve_smaxi_b, int8_t, DO_MAX)
74
+DO_ZZI(sve_smaxi_h, int16_t, DO_MAX)
75
+DO_ZZI(sve_smaxi_s, int32_t, DO_MAX)
76
+DO_ZZI(sve_smaxi_d, int64_t, DO_MAX)
77
+
78
+DO_ZZI(sve_smini_b, int8_t, DO_MIN)
79
+DO_ZZI(sve_smini_h, int16_t, DO_MIN)
80
+DO_ZZI(sve_smini_s, int32_t, DO_MIN)
81
+DO_ZZI(sve_smini_d, int64_t, DO_MIN)
82
+
83
+DO_ZZI(sve_umaxi_b, uint8_t, DO_MAX)
84
+DO_ZZI(sve_umaxi_h, uint16_t, DO_MAX)
85
+DO_ZZI(sve_umaxi_s, uint32_t, DO_MAX)
86
+DO_ZZI(sve_umaxi_d, uint64_t, DO_MAX)
87
+
88
+DO_ZZI(sve_umini_b, uint8_t, DO_MIN)
89
+DO_ZZI(sve_umini_h, uint16_t, DO_MIN)
90
+DO_ZZI(sve_umini_s, uint32_t, DO_MIN)
91
+DO_ZZI(sve_umini_d, uint64_t, DO_MIN)
92
+
93
+#undef DO_ZZI
94
+
95
#undef DO_AND
96
#undef DO_ORR
97
#undef DO_EOR
98
@@ -XXX,XX +XXX,XX @@ DO_VPZ_D(sve_uminv_d, uint64_t, uint64_t, -1, DO_MIN)
99
#undef DO_ASR
100
#undef DO_LSR
101
#undef DO_LSL
102
+#undef DO_SUBR
103
104
/* Similar to the ARM LastActiveElement pseudocode function, except the
105
result is multiplied by the element size. This includes the not found
106
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/target/arm/translate-sve.c
109
+++ b/target/arm/translate-sve.c
110
@@ -XXX,XX +XXX,XX @@ static inline int expand_imm_sh8s(int x)
111
return (int8_t)x << (x & 0x100 ? 8 : 0);
112
}
113
114
+static inline int expand_imm_sh8u(int x)
115
+{
116
+ return (uint8_t)x << (x & 0x100 ? 8 : 0);
117
+}
118
+
119
/*
120
* Include the generated decoder.
121
*/
122
@@ -XXX,XX +XXX,XX @@ static bool trans_DUP_i(DisasContext *s, arg_DUP_i *a, uint32_t insn)
123
return true;
124
}
125
126
+static bool trans_ADD_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn)
127
+{
128
+ if (a->esz == 0 && extract32(insn, 13, 1)) {
129
+ return false;
130
+ }
131
+ if (sve_access_check(s)) {
132
+ unsigned vsz = vec_full_reg_size(s);
133
+ tcg_gen_gvec_addi(a->esz, vec_full_reg_offset(s, a->rd),
134
+ vec_full_reg_offset(s, a->rn), a->imm, vsz, vsz);
135
+ }
136
+ return true;
137
+}
138
+
139
+static bool trans_SUB_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn)
140
+{
141
+ a->imm = -a->imm;
142
+ return trans_ADD_zzi(s, a, insn);
143
+}
144
+
145
+static bool trans_SUBR_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn)
146
+{
147
+ static const GVecGen2s op[4] = {
148
+ { .fni8 = tcg_gen_vec_sub8_i64,
149
+ .fniv = tcg_gen_sub_vec,
150
+ .fno = gen_helper_sve_subri_b,
151
+ .opc = INDEX_op_sub_vec,
152
+ .vece = MO_8,
153
+ .scalar_first = true },
154
+ { .fni8 = tcg_gen_vec_sub16_i64,
155
+ .fniv = tcg_gen_sub_vec,
156
+ .fno = gen_helper_sve_subri_h,
157
+ .opc = INDEX_op_sub_vec,
158
+ .vece = MO_16,
159
+ .scalar_first = true },
160
+ { .fni4 = tcg_gen_sub_i32,
161
+ .fniv = tcg_gen_sub_vec,
162
+ .fno = gen_helper_sve_subri_s,
163
+ .opc = INDEX_op_sub_vec,
164
+ .vece = MO_32,
165
+ .scalar_first = true },
166
+ { .fni8 = tcg_gen_sub_i64,
167
+ .fniv = tcg_gen_sub_vec,
168
+ .fno = gen_helper_sve_subri_d,
169
+ .opc = INDEX_op_sub_vec,
170
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
171
+ .vece = MO_64,
172
+ .scalar_first = true }
173
+ };
174
+
175
+ if (a->esz == 0 && extract32(insn, 13, 1)) {
176
+ return false;
177
+ }
178
+ if (sve_access_check(s)) {
179
+ unsigned vsz = vec_full_reg_size(s);
180
+ TCGv_i64 c = tcg_const_i64(a->imm);
181
+ tcg_gen_gvec_2s(vec_full_reg_offset(s, a->rd),
182
+ vec_full_reg_offset(s, a->rn),
183
+ vsz, vsz, c, &op[a->esz]);
184
+ tcg_temp_free_i64(c);
185
+ }
186
+ return true;
187
+}
188
+
189
+static bool trans_MUL_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn)
190
+{
191
+ if (sve_access_check(s)) {
192
+ unsigned vsz = vec_full_reg_size(s);
193
+ tcg_gen_gvec_muli(a->esz, vec_full_reg_offset(s, a->rd),
194
+ vec_full_reg_offset(s, a->rn), a->imm, vsz, vsz);
195
+ }
196
+ return true;
197
+}
198
+
199
+static bool do_zzi_sat(DisasContext *s, arg_rri_esz *a, uint32_t insn,
200
+ bool u, bool d)
201
+{
202
+ if (a->esz == 0 && extract32(insn, 13, 1)) {
203
+ return false;
204
+ }
205
+ if (sve_access_check(s)) {
206
+ TCGv_i64 val = tcg_const_i64(a->imm);
207
+ do_sat_addsub_vec(s, a->esz, a->rd, a->rn, val, u, d);
208
+ tcg_temp_free_i64(val);
209
+ }
210
+ return true;
211
+}
212
+
213
+static bool trans_SQADD_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn)
214
+{
215
+ return do_zzi_sat(s, a, insn, false, false);
216
+}
217
+
218
+static bool trans_UQADD_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn)
219
+{
220
+ return do_zzi_sat(s, a, insn, true, false);
221
+}
222
+
223
+static bool trans_SQSUB_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn)
224
+{
225
+ return do_zzi_sat(s, a, insn, false, true);
226
+}
227
+
228
+static bool trans_UQSUB_zzi(DisasContext *s, arg_rri_esz *a, uint32_t insn)
229
+{
230
+ return do_zzi_sat(s, a, insn, true, true);
231
+}
232
+
233
+static bool do_zzi_ool(DisasContext *s, arg_rri_esz *a, gen_helper_gvec_2i *fn)
234
+{
235
+ if (sve_access_check(s)) {
236
+ unsigned vsz = vec_full_reg_size(s);
237
+ TCGv_i64 c = tcg_const_i64(a->imm);
238
+
239
+ tcg_gen_gvec_2i_ool(vec_full_reg_offset(s, a->rd),
240
+ vec_full_reg_offset(s, a->rn),
241
+ c, vsz, vsz, 0, fn);
242
+ tcg_temp_free_i64(c);
243
+ }
244
+ return true;
245
+}
246
+
247
+#define DO_ZZI(NAME, name) \
248
+static bool trans_##NAME##_zzi(DisasContext *s, arg_rri_esz *a, \
249
+ uint32_t insn) \
250
+{ \
251
+ static gen_helper_gvec_2i * const fns[4] = { \
252
+ gen_helper_sve_##name##i_b, gen_helper_sve_##name##i_h, \
253
+ gen_helper_sve_##name##i_s, gen_helper_sve_##name##i_d, \
254
+ }; \
255
+ return do_zzi_ool(s, a, fns[a->esz]); \
256
+}
257
+
258
+DO_ZZI(SMAX, smax)
259
+DO_ZZI(UMAX, umax)
260
+DO_ZZI(SMIN, smin)
261
+DO_ZZI(UMIN, umin)
262
+
263
+#undef DO_ZZI
264
+
265
/*
266
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
267
*/
268
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
269
index XXXXXXX..XXXXXXX 100644
270
--- a/target/arm/sve.decode
271
+++ b/target/arm/sve.decode
272
@@ -XXX,XX +XXX,XX @@
50
@@ -XXX,XX +XXX,XX @@
273
51
274
# Signed 8-bit immediate, optionally shifted left by 8.
52
#include "qemu/osdep.h"
275
%sh8_i8s 5:9 !function=expand_imm_sh8s
53
#include "hw/net/lan9118_phy.h"
276
+# Unsigned 8-bit immediate, optionally shifted left by 8.
54
+#include "hw/net/mii.h"
277
+%sh8_i8u 5:9 !function=expand_imm_sh8u
55
#include "hw/irq.h"
278
56
#include "hw/resettable.h"
279
# Either a copy of rd (at bit 0), or a different source
57
#include "migration/vmstate.h"
280
# as propagated via the MOVPRFX instruction.
58
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
281
@@ -XXX,XX +XXX,XX @@
59
uint16_t val;
282
@pd_pn_pm ........ esz:2 .. rm:4 ....... rn:4 . rd:4 &rrr_esz
60
283
@rdn_rm ........ esz:2 ...... ...... rm:5 rd:5 \
61
switch (reg) {
284
&rrr_esz rn=%reg_movprfx
62
- case 0: /* Basic Control */
285
+@rdn_sh_i8u ........ esz:2 ...... ...... ..... rd:5 \
63
+ case MII_BMCR:
286
+ &rri_esz rn=%reg_movprfx imm=%sh8_i8u
64
val = s->control;
287
+@rdn_i8u ........ esz:2 ...... ... imm:8 rd:5 \
65
break;
288
+ &rri_esz rn=%reg_movprfx
66
- case 1: /* Basic Status */
289
+@rdn_i8s ........ esz:2 ...... ... imm:s8 rd:5 \
67
+ case MII_BMSR:
290
+ &rri_esz rn=%reg_movprfx
68
val = s->status;
291
69
break;
292
# Three operand with "memory" size, aka immediate left shift
70
- case 2: /* ID1 */
293
@rd_rn_msz_rm ........ ... rm:5 .... imm:2 rn:5 rd:5 &rrri
71
- val = 0x0007;
294
@@ -XXX,XX +XXX,XX @@ FDUP 00100101 esz:2 111 00 1110 imm:8 rd:5
72
+ case MII_PHYID1:
295
# SVE broadcast integer immediate (unpredicated)
73
+ val = SMSCLAN9118_PHYID1;
296
DUP_i 00100101 esz:2 111 00 011 . ........ rd:5 imm=%sh8_i8s
74
break;
297
75
- case 3: /* ID2 */
298
+# SVE integer add/subtract immediate (unpredicated)
76
- val = 0xc0d1;
299
+ADD_zzi 00100101 .. 100 000 11 . ........ ..... @rdn_sh_i8u
77
+ case MII_PHYID2:
300
+SUB_zzi 00100101 .. 100 001 11 . ........ ..... @rdn_sh_i8u
78
+ val = SMSCLAN9118_PHYID2;
301
+SUBR_zzi 00100101 .. 100 011 11 . ........ ..... @rdn_sh_i8u
79
break;
302
+SQADD_zzi 00100101 .. 100 100 11 . ........ ..... @rdn_sh_i8u
80
- case 4: /* Auto-neg advertisement */
303
+UQADD_zzi 00100101 .. 100 101 11 . ........ ..... @rdn_sh_i8u
81
+ case MII_ANAR:
304
+SQSUB_zzi 00100101 .. 100 110 11 . ........ ..... @rdn_sh_i8u
82
val = s->advertise;
305
+UQSUB_zzi 00100101 .. 100 111 11 . ........ ..... @rdn_sh_i8u
83
break;
306
+
84
- case 5: /* Auto-neg Link Partner Ability */
307
+# SVE integer min/max immediate (unpredicated)
85
- val = 0x0fe1;
308
+SMAX_zzi 00100101 .. 101 000 110 ........ ..... @rdn_i8s
86
+ case MII_ANLPAR:
309
+UMAX_zzi 00100101 .. 101 001 110 ........ ..... @rdn_i8u
87
+ val = MII_ANLPAR_PAUSEASY | MII_ANLPAR_PAUSE | MII_ANLPAR_T4 |
310
+SMIN_zzi 00100101 .. 101 010 110 ........ ..... @rdn_i8s
88
+ MII_ANLPAR_TXFD | MII_ANLPAR_TX | MII_ANLPAR_10FD |
311
+UMIN_zzi 00100101 .. 101 011 110 ........ ..... @rdn_i8u
89
+ MII_ANLPAR_10 | MII_ANLPAR_CSMACD;
312
+
90
break;
313
+# SVE integer multiply immediate (unpredicated)
91
- case 6: /* Auto-neg Expansion */
314
+MUL_zzi 00100101 .. 110 000 110 ........ ..... @rdn_i8s
92
- val = 1;
315
+
93
+ case MII_ANER:
316
### SVE Memory - 32-bit Gather and Unsized Contiguous Group
94
+ val = MII_ANER_NWAY;
317
95
break;
318
# SVE load predicate register
96
case 29: /* Interrupt source. */
97
val = s->ints;
98
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
99
trace_lan9118_phy_write(val, reg);
100
101
switch (reg) {
102
- case 0: /* Basic Control */
103
- if (val & 0x8000) {
104
+ case MII_BMCR:
105
+ if (val & MII_BMCR_RESET) {
106
lan9118_phy_reset(s);
107
} else {
108
- s->control = val & 0x7980;
109
+ s->control = val & (MII_BMCR_LOOPBACK | MII_BMCR_SPEED100 |
110
+ MII_BMCR_AUTOEN | MII_BMCR_PDOWN | MII_BMCR_FD |
111
+ MII_BMCR_CTST);
112
/* Complete autonegotiation immediately. */
113
- if (val & 0x1000) {
114
- s->status |= 0x0020;
115
+ if (val & MII_BMCR_AUTOEN) {
116
+ s->status |= MII_BMSR_AN_COMP;
117
}
118
}
119
break;
120
- case 4: /* Auto-neg advertisement */
121
- s->advertise = (val & 0x2d7f) | 0x80;
122
+ case MII_ANAR:
123
+ s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
124
+ MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
125
+ MII_ANAR_SELECT))
126
+ | MII_ANAR_TX;
127
break;
128
case 30: /* Interrupt mask */
129
s->int_mask = val & 0xff;
130
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
131
/* Autonegotiation status mirrors link status. */
132
if (link_down) {
133
trace_lan9118_phy_update_link("down");
134
- s->status &= ~0x0024;
135
+ s->status &= ~(MII_BMSR_AN_COMP | MII_BMSR_LINK_ST);
136
s->ints |= PHY_INT_DOWN;
137
} else {
138
trace_lan9118_phy_update_link("up");
139
- s->status |= 0x0024;
140
+ s->status |= MII_BMSR_AN_COMP | MII_BMSR_LINK_ST;
141
s->ints |= PHY_INT_ENERGYON;
142
s->ints |= PHY_INT_AUTONEG_COMPLETE;
143
}
144
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_reset(Lan9118PhyState *s)
145
{
146
trace_lan9118_phy_reset();
147
148
- s->control = 0x3000;
149
- s->status = 0x7809;
150
- s->advertise = 0x01e1;
151
+ s->control = MII_BMCR_AUTOEN | MII_BMCR_SPEED100;
152
+ s->status = MII_BMSR_100TX_FD
153
+ | MII_BMSR_100TX_HD
154
+ | MII_BMSR_10T_FD
155
+ | MII_BMSR_10T_HD
156
+ | MII_BMSR_AUTONEG
157
+ | MII_BMSR_EXTCAP;
158
+ s->advertise = MII_ANAR_TXFD
159
+ | MII_ANAR_TX
160
+ | MII_ANAR_10FD
161
+ | MII_ANAR_10
162
+ | MII_ANAR_CSMACD;
163
s->int_mask = 0;
164
s->ints = 0;
165
lan9118_phy_update_link(s, s->link_down);
319
--
166
--
320
2.17.1
167
2.34.1
321
322
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
3
The real device advertises this mode and the device model already advertises
4
100 mbps half duplex and 10 mbps full+half duplex. So advertise this mode to
5
make the model more realistic.
2
6
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
5
Message-id: 20180613015641.5667-15-richard.henderson@linaro.org
9
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
Message-id: 20241102125724.532843-6-shentey@gmail.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
12
---
8
target/arm/helper-sve.h | 2 +
13
hw/net/lan9118_phy.c | 4 ++--
9
target/arm/sve_helper.c | 14 ++++
14
1 file changed, 2 insertions(+), 2 deletions(-)
10
target/arm/translate-sve.c | 133 +++++++++++++++++++++++++++++++++++++
11
target/arm/sve.decode | 27 ++++++++
12
4 files changed, 176 insertions(+)
13
15
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
18
--- a/hw/net/lan9118_phy.c
17
+++ b/target/arm/helper-sve.h
19
+++ b/hw/net/lan9118_phy.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_brkbs_m, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
20
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
19
21
break;
20
DEF_HELPER_FLAGS_4(sve_brkn, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
case MII_ANAR:
21
DEF_HELPER_FLAGS_4(sve_brkns, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
23
s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
22
+
24
- MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
23
+DEF_HELPER_FLAGS_3(sve_cntp, TCG_CALL_NO_RWG, i64, ptr, ptr, i32)
25
- MII_ANAR_SELECT))
24
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
26
+ MII_ANAR_PAUSE | MII_ANAR_TXFD | MII_ANAR_10FD |
25
index XXXXXXX..XXXXXXX 100644
27
+ MII_ANAR_10 | MII_ANAR_SELECT))
26
--- a/target/arm/sve_helper.c
28
| MII_ANAR_TX;
27
+++ b/target/arm/sve_helper.c
29
break;
28
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc)
30
case 30: /* Interrupt mask */
29
return do_zero(vd, oprsz);
30
}
31
}
32
+
33
+uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
34
+{
35
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
36
+ intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
37
+ uint64_t *n = vn, *g = vg, sum = 0, mask = pred_esz_masks[esz];
38
+ intptr_t i;
39
+
40
+ for (i = 0; i < DIV_ROUND_UP(oprsz, 8); ++i) {
41
+ uint64_t t = n[i] & g[i] & mask;
42
+ sum += ctpop64(t);
43
+ }
44
+ return sum;
45
+}
46
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/translate-sve.c
49
+++ b/target/arm/translate-sve.c
50
@@ -XXX,XX +XXX,XX @@
51
#include "translate-a64.h"
52
53
54
+typedef void GVecGen2sFn(unsigned, uint32_t, uint32_t,
55
+ TCGv_i64, uint32_t, uint32_t);
56
+
57
typedef void gen_helper_gvec_flags_3(TCGv_i32, TCGv_ptr, TCGv_ptr,
58
TCGv_ptr, TCGv_i32);
59
typedef void gen_helper_gvec_flags_4(TCGv_i32, TCGv_ptr, TCGv_ptr,
60
@@ -XXX,XX +XXX,XX @@ static bool trans_BRKN(DisasContext *s, arg_rpr_s *a, uint32_t insn)
61
return do_brk2(s, a, gen_helper_sve_brkn, gen_helper_sve_brkns);
62
}
63
64
+/*
65
+ *** SVE Predicate Count Group
66
+ */
67
+
68
+static void do_cntp(DisasContext *s, TCGv_i64 val, int esz, int pn, int pg)
69
+{
70
+ unsigned psz = pred_full_reg_size(s);
71
+
72
+ if (psz <= 8) {
73
+ uint64_t psz_mask;
74
+
75
+ tcg_gen_ld_i64(val, cpu_env, pred_full_reg_offset(s, pn));
76
+ if (pn != pg) {
77
+ TCGv_i64 g = tcg_temp_new_i64();
78
+ tcg_gen_ld_i64(g, cpu_env, pred_full_reg_offset(s, pg));
79
+ tcg_gen_and_i64(val, val, g);
80
+ tcg_temp_free_i64(g);
81
+ }
82
+
83
+ /* Reduce the pred_esz_masks value simply to reduce the
84
+ * size of the code generated here.
85
+ */
86
+ psz_mask = MAKE_64BIT_MASK(0, psz * 8);
87
+ tcg_gen_andi_i64(val, val, pred_esz_masks[esz] & psz_mask);
88
+
89
+ tcg_gen_ctpop_i64(val, val);
90
+ } else {
91
+ TCGv_ptr t_pn = tcg_temp_new_ptr();
92
+ TCGv_ptr t_pg = tcg_temp_new_ptr();
93
+ unsigned desc;
94
+ TCGv_i32 t_desc;
95
+
96
+ desc = psz - 2;
97
+ desc = deposit32(desc, SIMD_DATA_SHIFT, 2, esz);
98
+
99
+ tcg_gen_addi_ptr(t_pn, cpu_env, pred_full_reg_offset(s, pn));
100
+ tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
101
+ t_desc = tcg_const_i32(desc);
102
+
103
+ gen_helper_sve_cntp(val, t_pn, t_pg, t_desc);
104
+ tcg_temp_free_ptr(t_pn);
105
+ tcg_temp_free_ptr(t_pg);
106
+ tcg_temp_free_i32(t_desc);
107
+ }
108
+}
109
+
110
+static bool trans_CNTP(DisasContext *s, arg_CNTP *a, uint32_t insn)
111
+{
112
+ if (sve_access_check(s)) {
113
+ do_cntp(s, cpu_reg(s, a->rd), a->esz, a->rn, a->pg);
114
+ }
115
+ return true;
116
+}
117
+
118
+static bool trans_INCDECP_r(DisasContext *s, arg_incdec_pred *a,
119
+ uint32_t insn)
120
+{
121
+ if (sve_access_check(s)) {
122
+ TCGv_i64 reg = cpu_reg(s, a->rd);
123
+ TCGv_i64 val = tcg_temp_new_i64();
124
+
125
+ do_cntp(s, val, a->esz, a->pg, a->pg);
126
+ if (a->d) {
127
+ tcg_gen_sub_i64(reg, reg, val);
128
+ } else {
129
+ tcg_gen_add_i64(reg, reg, val);
130
+ }
131
+ tcg_temp_free_i64(val);
132
+ }
133
+ return true;
134
+}
135
+
136
+static bool trans_INCDECP_z(DisasContext *s, arg_incdec2_pred *a,
137
+ uint32_t insn)
138
+{
139
+ if (a->esz == 0) {
140
+ return false;
141
+ }
142
+ if (sve_access_check(s)) {
143
+ unsigned vsz = vec_full_reg_size(s);
144
+ TCGv_i64 val = tcg_temp_new_i64();
145
+ GVecGen2sFn *gvec_fn = a->d ? tcg_gen_gvec_subs : tcg_gen_gvec_adds;
146
+
147
+ do_cntp(s, val, a->esz, a->pg, a->pg);
148
+ gvec_fn(a->esz, vec_full_reg_offset(s, a->rd),
149
+ vec_full_reg_offset(s, a->rn), val, vsz, vsz);
150
+ }
151
+ return true;
152
+}
153
+
154
+static bool trans_SINCDECP_r_32(DisasContext *s, arg_incdec_pred *a,
155
+ uint32_t insn)
156
+{
157
+ if (sve_access_check(s)) {
158
+ TCGv_i64 reg = cpu_reg(s, a->rd);
159
+ TCGv_i64 val = tcg_temp_new_i64();
160
+
161
+ do_cntp(s, val, a->esz, a->pg, a->pg);
162
+ do_sat_addsub_32(reg, val, a->u, a->d);
163
+ }
164
+ return true;
165
+}
166
+
167
+static bool trans_SINCDECP_r_64(DisasContext *s, arg_incdec_pred *a,
168
+ uint32_t insn)
169
+{
170
+ if (sve_access_check(s)) {
171
+ TCGv_i64 reg = cpu_reg(s, a->rd);
172
+ TCGv_i64 val = tcg_temp_new_i64();
173
+
174
+ do_cntp(s, val, a->esz, a->pg, a->pg);
175
+ do_sat_addsub_64(reg, val, a->u, a->d);
176
+ }
177
+ return true;
178
+}
179
+
180
+static bool trans_SINCDECP_z(DisasContext *s, arg_incdec2_pred *a,
181
+ uint32_t insn)
182
+{
183
+ if (a->esz == 0) {
184
+ return false;
185
+ }
186
+ if (sve_access_check(s)) {
187
+ TCGv_i64 val = tcg_temp_new_i64();
188
+ do_cntp(s, val, a->esz, a->pg, a->pg);
189
+ do_sat_addsub_vec(s, a->esz, a->rd, a->rn, val, a->u, a->d);
190
+ }
191
+ return true;
192
+}
193
+
194
/*
195
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
196
*/
197
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
198
index XXXXXXX..XXXXXXX 100644
199
--- a/target/arm/sve.decode
200
+++ b/target/arm/sve.decode
201
@@ -XXX,XX +XXX,XX @@
202
&ptrue rd esz pat s
203
&incdec_cnt rd pat esz imm d u
204
&incdec2_cnt rd rn pat esz imm d u
205
+&incdec_pred rd pg esz d u
206
+&incdec2_pred rd rn pg esz d u
207
208
###########################################################################
209
# Named instruction formats. These are generally used to
210
@@ -XXX,XX +XXX,XX @@
211
212
# One register operand, with governing predicate, vector element size
213
@rd_pg_rn ........ esz:2 ... ... ... pg:3 rn:5 rd:5 &rpr_esz
214
+@rd_pg4_pn ........ esz:2 ... ... .. pg:4 . rn:4 rd:5 &rpr_esz
215
216
# Two register operands with a 6-bit signed immediate.
217
@rd_rn_i6 ........ ... rn:5 ..... imm:s6 rd:5 &rri
218
@@ -XXX,XX +XXX,XX @@
219
@incdec2_cnt ........ esz:2 .. .... ...... pat:5 rd:5 \
220
&incdec2_cnt imm=%imm4_16_p1 rn=%reg_movprfx
221
222
+# One register, predicate.
223
+# User must fill in U and D.
224
+@incdec_pred ........ esz:2 .... .. ..... .. pg:4 rd:5 &incdec_pred
225
+@incdec2_pred ........ esz:2 .... .. ..... .. pg:4 rd:5 \
226
+ &incdec2_pred rn=%reg_movprfx
227
+
228
###########################################################################
229
# Instruction patterns. Grouped according to the SVE encodingindex.xhtml.
230
231
@@ -XXX,XX +XXX,XX @@ BRKB_m 00100101 1. 01000001 .... 0 .... 1 .... @pd_pg_pn_s
232
# SVE propagate break to next partition
233
BRKN 00100101 0. 01100001 .... 0 .... 0 .... @pd_pg_pn_s
234
235
+### SVE Predicate Count Group
236
+
237
+# SVE predicate count
238
+CNTP 00100101 .. 100 000 10 .... 0 .... ..... @rd_pg4_pn
239
+
240
+# SVE inc/dec register by predicate count
241
+INCDECP_r 00100101 .. 10110 d:1 10001 00 .... ..... @incdec_pred u=1
242
+
243
+# SVE inc/dec vector by predicate count
244
+INCDECP_z 00100101 .. 10110 d:1 10000 00 .... ..... @incdec2_pred u=1
245
+
246
+# SVE saturating inc/dec register by predicate count
247
+SINCDECP_r_32 00100101 .. 1010 d:1 u:1 10001 00 .... ..... @incdec_pred
248
+SINCDECP_r_64 00100101 .. 1010 d:1 u:1 10001 10 .... ..... @incdec_pred
249
+
250
+# SVE saturating inc/dec vector by predicate count
251
+SINCDECP_z 00100101 .. 1010 d:1 u:1 10000 00 .... ..... @incdec2_pred
252
+
253
### SVE Memory - 32-bit Gather and Unsized Contiguous Group
254
255
# SVE load predicate register
256
--
31
--
257
2.17.1
32
2.34.1
258
259
diff view generated by jsdifflib
1
Currently we don't support board configurations that put an IOMMU
1
For IEEE fused multiply-add, the (0 * inf) + NaN case should raise
2
in the path of the CPU's memory transactions, and instead just
2
Invalid for the multiplication of 0 by infinity. Currently we handle
3
assert() if the memory region fonud in address_space_translate_for_iotlb()
3
this in the per-architecture ifdef ladder in pickNaNMulAdd().
4
is an IOMMUMemoryRegion.
4
However, since this isn't really architecture specific we can hoist
5
it up to the generic code.
5
6
6
Remove this limitation by having the function handle IOMMUs.
7
For the cases where the infzero test in pickNaNMulAdd was
7
This is mostly straightforward, but we must make sure we have
8
returning 2, we can delete the check entirely and allow the
8
a notifier registered for every IOMMU that a transaction has
9
code to fall into the normal pick-a-NaN handling, because this
9
passed through, so that we can flush the TLB appropriately
10
will return 2 anyway (input 'c' being the only NaN in this case).
10
when any of the IOMMUs change their mappings.
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.
11
33
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20180604152941.20374-5-peter.maydell@linaro.org
36
Message-id: 20241202131347.498124-2-peter.maydell@linaro.org
15
---
37
---
16
include/exec/exec-all.h | 3 +-
38
fpu/softfloat-parts.c.inc | 13 +++++++------
17
include/qom/cpu.h | 3 +
39
fpu/softfloat-specialize.c.inc | 29 +----------------------------
18
accel/tcg/cputlb.c | 3 +-
40
2 files changed, 8 insertions(+), 34 deletions(-)
19
exec.c | 135 +++++++++++++++++++++++++++++++++++++++-
20
4 files changed, 140 insertions(+), 4 deletions(-)
21
41
22
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
42
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
23
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
24
--- a/include/exec/exec-all.h
44
--- a/fpu/softfloat-parts.c.inc
25
+++ b/include/exec/exec-all.h
45
+++ b/fpu/softfloat-parts.c.inc
26
@@ -XXX,XX +XXX,XX @@ void tb_flush_jmp_cache(CPUState *cpu, target_ulong addr);
46
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
27
47
int ab_mask, int abc_mask)
28
MemoryRegionSection *
48
{
29
address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr,
49
int which;
30
- hwaddr *xlat, hwaddr *plen);
50
+ bool infzero = (ab_mask == float_cmask_infzero);
31
+ hwaddr *xlat, hwaddr *plen,
51
32
+ MemTxAttrs attrs, int *prot);
52
if (unlikely(abc_mask & float_cmask_snan)) {
33
hwaddr memory_region_section_get_iotlb(CPUState *cpu,
53
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
34
MemoryRegionSection *section,
35
target_ulong vaddr,
36
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/qom/cpu.h
39
+++ b/include/qom/cpu.h
40
@@ -XXX,XX +XXX,XX @@ struct CPUState {
41
uint16_t pending_tlb_flush;
42
43
int hvf_fd;
44
+
45
+ /* track IOMMUs whose translations we've cached in the TCG TLB */
46
+ GArray *iommu_notifiers;
47
};
48
49
QTAILQ_HEAD(CPUTailQ, CPUState);
50
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/accel/tcg/cputlb.c
53
+++ b/accel/tcg/cputlb.c
54
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
55
}
54
}
56
55
57
sz = size;
56
- which = pickNaNMulAdd(a->cls, b->cls, c->cls,
58
- section = address_space_translate_for_iotlb(cpu, asidx, paddr, &xlat, &sz);
57
- ab_mask == float_cmask_infzero, s);
59
+ section = address_space_translate_for_iotlb(cpu, asidx, paddr, &xlat, &sz,
58
+ if (infzero) {
60
+ attrs, &prot);
59
+ /* This is (0 * inf) + NaN or (inf * 0) + NaN */
61
assert(sz >= TARGET_PAGE_SIZE);
60
+ float_raise(float_flag_invalid | float_flag_invalid_imz, s);
62
63
tlb_debug("vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
64
diff --git a/exec.c b/exec.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/exec.c
67
+++ b/exec.c
68
@@ -XXX,XX +XXX,XX @@ MemoryRegion *flatview_translate(FlatView *fv, hwaddr addr, hwaddr *xlat,
69
return mr;
70
}
71
72
+typedef struct TCGIOMMUNotifier {
73
+ IOMMUNotifier n;
74
+ MemoryRegion *mr;
75
+ CPUState *cpu;
76
+ int iommu_idx;
77
+ bool active;
78
+} TCGIOMMUNotifier;
79
+
80
+static void tcg_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
81
+{
82
+ TCGIOMMUNotifier *notifier = container_of(n, TCGIOMMUNotifier, n);
83
+
84
+ if (!notifier->active) {
85
+ return;
86
+ }
87
+ tlb_flush(notifier->cpu);
88
+ notifier->active = false;
89
+ /* We leave the notifier struct on the list to avoid reallocating it later.
90
+ * Generally the number of IOMMUs a CPU deals with will be small.
91
+ * In any case we can't unregister the iommu notifier from a notify
92
+ * callback.
93
+ */
94
+}
95
+
96
+static void tcg_register_iommu_notifier(CPUState *cpu,
97
+ IOMMUMemoryRegion *iommu_mr,
98
+ int iommu_idx)
99
+{
100
+ /* Make sure this CPU has an IOMMU notifier registered for this
101
+ * IOMMU/IOMMU index combination, so that we can flush its TLB
102
+ * when the IOMMU tells us the mappings we've cached have changed.
103
+ */
104
+ MemoryRegion *mr = MEMORY_REGION(iommu_mr);
105
+ TCGIOMMUNotifier *notifier;
106
+ int i;
107
+
108
+ for (i = 0; i < cpu->iommu_notifiers->len; i++) {
109
+ notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
110
+ if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) {
111
+ break;
112
+ }
113
+ }
114
+ if (i == cpu->iommu_notifiers->len) {
115
+ /* Not found, add a new entry at the end of the array */
116
+ cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1);
117
+ notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
118
+
119
+ notifier->mr = mr;
120
+ notifier->iommu_idx = iommu_idx;
121
+ notifier->cpu = cpu;
122
+ /* Rather than trying to register interest in the specific part
123
+ * of the iommu's address space that we've accessed and then
124
+ * expand it later as subsequent accesses touch more of it, we
125
+ * just register interest in the whole thing, on the assumption
126
+ * that iommu reconfiguration will be rare.
127
+ */
128
+ iommu_notifier_init(&notifier->n,
129
+ tcg_iommu_unmap_notify,
130
+ IOMMU_NOTIFIER_UNMAP,
131
+ 0,
132
+ HWADDR_MAX,
133
+ iommu_idx);
134
+ memory_region_register_iommu_notifier(notifier->mr, &notifier->n);
135
+ }
61
+ }
136
+
62
+
137
+ if (!notifier->active) {
63
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
138
+ notifier->active = true;
64
139
+ }
65
if (s->default_nan_mode || which == 3) {
140
+}
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
- }
141
+
112
+
142
+static void tcg_iommu_free_notifier_list(CPUState *cpu)
113
/* Prefer sNaN over qNaN, in the c, a, b order. */
143
+{
114
if (is_snan(c_cls)) {
144
+ /* Destroy the CPU's notifier list */
115
return 2;
145
+ int i;
116
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
146
+ TCGIOMMUNotifier *notifier;
117
* to return an input NaN if we have one (ie c) rather than generating
147
+
118
* a default NaN
148
+ for (i = 0; i < cpu->iommu_notifiers->len; i++) {
119
*/
149
+ notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
120
- if (infzero) {
150
+ memory_region_unregister_iommu_notifier(notifier->mr, &notifier->n);
121
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
151
+ }
122
- return 2;
152
+ g_array_free(cpu->iommu_notifiers, true);
123
- }
153
+}
124
154
+
125
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
155
/* Called from RCU critical section */
126
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
156
MemoryRegionSection *
127
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
157
address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr,
128
return 1;
158
- hwaddr *xlat, hwaddr *plen)
159
+ hwaddr *xlat, hwaddr *plen,
160
+ MemTxAttrs attrs, int *prot)
161
{
162
MemoryRegionSection *section;
163
+ IOMMUMemoryRegion *iommu_mr;
164
+ IOMMUMemoryRegionClass *imrc;
165
+ IOMMUTLBEntry iotlb;
166
+ int iommu_idx;
167
AddressSpaceDispatch *d = atomic_rcu_read(&cpu->cpu_ases[asidx].memory_dispatch);
168
169
- section = address_space_translate_internal(d, addr, xlat, plen, false);
170
+ for (;;) {
171
+ section = address_space_translate_internal(d, addr, &addr, plen, false);
172
+
173
+ iommu_mr = memory_region_get_iommu(section->mr);
174
+ if (!iommu_mr) {
175
+ break;
176
+ }
177
+
178
+ imrc = memory_region_get_iommu_class_nocheck(iommu_mr);
179
+
180
+ iommu_idx = imrc->attrs_to_index(iommu_mr, attrs);
181
+ tcg_register_iommu_notifier(cpu, iommu_mr, iommu_idx);
182
+ /* We need all the permissions, so pass IOMMU_NONE so the IOMMU
183
+ * doesn't short-cut its translation table walk.
184
+ */
185
+ iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE, iommu_idx);
186
+ addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
187
+ | (addr & iotlb.addr_mask));
188
+ /* Update the caller's prot bits to remove permissions the IOMMU
189
+ * is giving us a failure response for. If we get down to no
190
+ * permissions left at all we can give up now.
191
+ */
192
+ if (!(iotlb.perm & IOMMU_RO)) {
193
+ *prot &= ~(PAGE_READ | PAGE_EXEC);
194
+ }
195
+ if (!(iotlb.perm & IOMMU_WO)) {
196
+ *prot &= ~PAGE_WRITE;
197
+ }
198
+
199
+ if (!*prot) {
200
+ goto translate_fail;
201
+ }
202
+
203
+ d = flatview_to_dispatch(address_space_to_flatview(iotlb.target_as));
204
+ }
205
206
assert(!memory_region_is_iommu(section->mr));
207
+ *xlat = addr;
208
return section;
209
+
210
+translate_fail:
211
+ return &d->map.sections[PHYS_SECTION_UNASSIGNED];
212
}
213
#endif
214
215
@@ -XXX,XX +XXX,XX @@ void cpu_exec_unrealizefn(CPUState *cpu)
216
if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
217
vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
218
}
129
}
219
+#ifndef CONFIG_USER_ONLY
130
#elif defined(TARGET_RISCV)
220
+ tcg_iommu_free_notifier_list(cpu);
131
- /* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
221
+#endif
132
- if (infzero) {
222
}
133
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
223
134
- }
224
Property cpu_common_props[] = {
135
return 3; /* default NaN */
225
@@ -XXX,XX +XXX,XX @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
136
#elif defined(TARGET_S390X)
226
if (cc->vmsd != NULL) {
137
if (infzero) {
227
vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu);
138
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
139
return 3;
228
}
140
}
229
+
141
230
+ cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier));
142
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
231
#endif
143
return 2;
232
}
144
}
233
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;
234
--
165
--
235
2.17.1
166
2.34.1
236
237
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: Richard Henderson <richard.henderson@linaro.org>
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
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
architectures thus do different things:
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
* some return the default NaN
5
Message-id: 20180613015641.5667-10-richard.henderson@linaro.org
5
* some return the input NaN
6
* Arm returns the default NaN if the input NaN is quiet,
7
and the input NaN if it is signalling
8
9
We want to make this logic be runtime selected rather than
10
hardcoded into the binary, because:
11
* this will let us have multiple targets in one QEMU binary
12
* the Arm FEAT_AFP architectural feature includes letting
13
the guest select a NaN propagation rule at runtime
14
15
In this commit we add an enum for the propagation rule, the field in
16
float_status, and the corresponding getters and setters. We change
17
pickNaNMulAdd to honour this, but because all targets still leave
18
this field at its default 0 value, the fallback logic will pick the
19
rule type with the old ifdef ladder.
20
21
Note that four architectures both use the muladd softfloat functions
22
and did not have a branch of the ifdef ladder to specify their
23
behaviour (and so were ending up with the "default" case, probably
24
wrongly): i386, HPPA, SH4 and Tricore. SH4 and Tricore both set
25
default_nan_mode, and so will never get into pickNaNMulAdd(). For
26
HPPA and i386 we retain the same behaviour as the old default-case,
27
which is to not ever return the default NaN. This might not be
28
correct but it is not a behaviour change.
29
6
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
7
---
33
---
8
target/arm/helper-sve.h | 2 ++
34
include/fpu/softfloat-helpers.h | 11 ++++
9
target/arm/sve_helper.c | 37 +++++++++++++++++++++++++++++++++++++
35
include/fpu/softfloat-types.h | 23 +++++++++
10
target/arm/translate-sve.c | 13 +++++++++++++
36
fpu/softfloat-specialize.c.inc | 91 ++++++++++++++++++++++-----------
11
target/arm/sve.decode | 3 +++
37
3 files changed, 95 insertions(+), 30 deletions(-)
12
4 files changed, 55 insertions(+)
38
13
39
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
41
--- a/include/fpu/softfloat-helpers.h
17
+++ b/target/arm/helper-sve.h
42
+++ b/include/fpu/softfloat-helpers.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_rbit_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
43
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
19
DEF_HELPER_FLAGS_4(sve_rbit_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
44
status->float_2nan_prop_rule = rule;
20
DEF_HELPER_FLAGS_4(sve_rbit_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
45
}
21
46
22
+DEF_HELPER_FLAGS_5(sve_splice, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
47
+static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
23
+
48
+ float_status *status)
24
DEF_HELPER_FLAGS_5(sve_and_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
49
+{
25
DEF_HELPER_FLAGS_5(sve_bic_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
50
+ status->float_infzeronan_rule = rule;
26
DEF_HELPER_FLAGS_5(sve_eor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
51
+}
27
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
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
28
index XXXXXXX..XXXXXXX 100644
69
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/sve_helper.c
70
--- a/include/fpu/softfloat-types.h
30
+++ b/target/arm/sve_helper.c
71
+++ b/include/fpu/softfloat-types.h
31
@@ -XXX,XX +XXX,XX @@ int32_t HELPER(sve_last_active_element)(void *vg, uint32_t pred_desc)
72
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
32
73
float_2nan_prop_x87,
33
return last_active_element(vg, DIV_ROUND_UP(oprsz, 8), esz);
74
} Float2NaNPropRule;
34
}
75
35
+
76
+/*
36
+void HELPER(sve_splice)(void *vd, void *vn, void *vm, void *vg, uint32_t desc)
77
+ * Rule for result of fused multiply-add 0 * Inf + NaN.
37
+{
78
+ * This must be a NaN, but implementations differ on whether this
38
+ intptr_t opr_sz = simd_oprsz(desc) / 8;
79
+ * is the input NaN or the default NaN.
39
+ int esz = simd_data(desc);
80
+ *
40
+ uint64_t pg, first_g, last_g, len, mask = pred_esz_masks[esz];
81
+ * You don't need to set this if default_nan_mode is enabled.
41
+ intptr_t i, first_i, last_i;
82
+ * When not in default-NaN mode, it is an error for the target
42
+ ARMVectorReg tmp;
83
+ * not to set the rule in float_status if it uses muladd, and we
43
+
84
+ * will assert if we need to handle an input NaN and no rule was
44
+ first_i = last_i = 0;
85
+ * selected.
45
+ first_g = last_g = 0;
86
+ */
46
+
87
+typedef enum __attribute__((__packed__)) {
47
+ /* Find the extent of the active elements within VG. */
88
+ /* No propagation rule specified */
48
+ for (i = QEMU_ALIGN_UP(opr_sz, 8) - 8; i >= 0; i -= 8) {
89
+ float_infzeronan_none = 0,
49
+ pg = *(uint64_t *)(vg + i) & mask;
90
+ /* Result is never the default NaN (so always the input NaN) */
50
+ if (pg) {
91
+ float_infzeronan_dnan_never,
51
+ if (last_g == 0) {
92
+ /* Result is always the default NaN */
52
+ last_g = pg;
93
+ float_infzeronan_dnan_always,
53
+ last_i = i;
94
+ /* Result is the default NaN if the input NaN is quiet */
54
+ }
95
+ float_infzeronan_dnan_if_qnan,
55
+ first_g = pg;
96
+} FloatInfZeroNaNRule;
56
+ first_i = i;
97
+
98
/*
99
* Floating Point Status. Individual architectures may maintain
100
* several versions of float_status for different functions. The
101
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
102
FloatRoundMode float_rounding_mode;
103
FloatX80RoundPrec floatx80_rounding_precision;
104
Float2NaNPropRule float_2nan_prop_rule;
105
+ FloatInfZeroNaNRule float_infzeronan_rule;
106
bool tininess_before_rounding;
107
/* should denormalised results go to zero and set the inexact flag? */
108
bool flush_to_zero;
109
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
110
index XXXXXXX..XXXXXXX 100644
111
--- a/fpu/softfloat-specialize.c.inc
112
+++ b/fpu/softfloat-specialize.c.inc
113
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
114
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
115
bool infzero, float_status *status)
116
{
117
+ FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
118
+
119
/*
120
* We guarantee not to require the target to tell us how to
121
* pick a NaN if we're always returning the default NaN.
122
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
123
* specify.
124
*/
125
assert(!status->default_nan_mode);
126
+
127
+ if (rule == float_infzeronan_none) {
128
+ /*
129
+ * Temporarily fall back to ifdef ladder
130
+ */
131
#if defined(TARGET_ARM)
132
- /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
133
- * the default NaN
134
- */
135
- if (infzero && is_qnan(c_cls)) {
136
- return 3;
137
+ /*
138
+ * For ARM, the (inf,zero,qnan) case returns the default NaN,
139
+ * but (inf,zero,snan) returns the input NaN.
140
+ */
141
+ rule = float_infzeronan_dnan_if_qnan;
142
+#elif defined(TARGET_MIPS)
143
+ if (snan_bit_is_one(status)) {
144
+ /*
145
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
146
+ * case sets InvalidOp and returns the default NaN
147
+ */
148
+ rule = float_infzeronan_dnan_always;
149
+ } else {
150
+ /*
151
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
152
+ * case sets InvalidOp and returns the input value 'c'
153
+ */
154
+ rule = float_infzeronan_dnan_never;
155
+ }
156
+#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
157
+ defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
158
+ defined(TARGET_I386) || defined(TARGET_LOONGARCH)
159
+ /*
160
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
161
+ * case sets InvalidOp and returns the input value 'c'
162
+ */
163
+ /*
164
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
165
+ * to return an input NaN if we have one (ie c) rather than generating
166
+ * a default NaN
167
+ */
168
+ rule = float_infzeronan_dnan_never;
169
+#elif defined(TARGET_S390X)
170
+ rule = float_infzeronan_dnan_always;
171
+#endif
172
}
173
174
+ if (infzero) {
175
+ /*
176
+ * Inf * 0 + NaN -- some implementations return the default NaN here,
177
+ * and some return the input NaN.
178
+ */
179
+ switch (rule) {
180
+ case float_infzeronan_dnan_never:
181
+ return 2;
182
+ case float_infzeronan_dnan_always:
183
+ return 3;
184
+ case float_infzeronan_dnan_if_qnan:
185
+ return is_qnan(c_cls) ? 3 : 2;
186
+ default:
187
+ g_assert_not_reached();
57
+ }
188
+ }
58
+ }
189
+ }
59
+
190
+
60
+ len = 0;
191
+#if defined(TARGET_ARM)
61
+ if (first_g != 0) {
192
+
62
+ first_i = first_i * 8 + ctz64(first_g);
193
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
63
+ last_i = last_i * 8 + 63 - clz64(last_g);
194
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
64
+ len = last_i - first_i + (1 << esz);
195
*/
65
+ if (vd == vm) {
196
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
66
+ vm = memcpy(&tmp, vm, opr_sz * 8);
197
}
67
+ }
198
#elif defined(TARGET_MIPS)
68
+ swap_memmove(vd, vn + first_i, len);
199
if (snan_bit_is_one(status)) {
69
+ }
200
- /*
70
+ swap_memmove(vd + len, vm, opr_sz * 8 - len);
201
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
71
+}
202
- * case sets InvalidOp and returns the default NaN
72
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
203
- */
73
index XXXXXXX..XXXXXXX 100644
204
- if (infzero) {
74
--- a/target/arm/translate-sve.c
205
- return 3;
75
+++ b/target/arm/translate-sve.c
206
- }
76
@@ -XXX,XX +XXX,XX @@ static bool trans_RBIT(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
207
/* Prefer sNaN over qNaN, in the a, b, c order. */
77
return do_zpz_ool(s, a, fns[a->esz]);
208
if (is_snan(a_cls)) {
78
}
209
return 0;
79
210
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
80
+static bool trans_SPLICE(DisasContext *s, arg_rprr_esz *a, uint32_t insn)
211
return 2;
81
+{
212
}
82
+ if (sve_access_check(s)) {
213
} else {
83
+ unsigned vsz = vec_full_reg_size(s);
214
- /*
84
+ tcg_gen_gvec_4_ool(vec_full_reg_offset(s, a->rd),
215
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
85
+ vec_full_reg_offset(s, a->rn),
216
- * case sets InvalidOp and returns the input value 'c'
86
+ vec_full_reg_offset(s, a->rm),
217
- */
87
+ pred_full_reg_offset(s, a->pg),
218
/* Prefer sNaN over qNaN, in the c, a, b order. */
88
+ vsz, vsz, a->esz, gen_helper_sve_splice);
219
if (is_snan(c_cls)) {
89
+ }
220
return 2;
90
+ return true;
221
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
91
+}
222
}
92
+
223
}
93
/*
224
#elif defined(TARGET_LOONGARCH64)
94
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
225
- /*
95
*/
226
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
96
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
227
- * case sets InvalidOp and returns the input value 'c'
97
index XXXXXXX..XXXXXXX 100644
228
- */
98
--- a/target/arm/sve.decode
229
-
99
+++ b/target/arm/sve.decode
230
/* Prefer sNaN over qNaN, in the c, a, b order. */
100
@@ -XXX,XX +XXX,XX @@ REVH 00000101 .. 1001 01 100 ... ..... ..... @rd_pg_rn
231
if (is_snan(c_cls)) {
101
REVW 00000101 .. 1001 10 100 ... ..... ..... @rd_pg_rn
232
return 2;
102
RBIT 00000101 .. 1001 11 100 ... ..... ..... @rd_pg_rn
233
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
103
234
return 1;
104
+# SVE vector splice (predicated)
235
}
105
+SPLICE 00000101 .. 101 100 100 ... ..... ..... @rdn_pg_rm
236
#elif defined(TARGET_PPC)
106
+
237
- /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
107
### SVE Predicate Logical Operations Group
238
- * to return an input NaN if we have one (ie c) rather than generating
108
239
- * a default NaN
109
# SVE predicate logical operations
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)) {
110
--
256
--
111
2.17.1
257
2.34.1
112
113
diff view generated by jsdifflib
New patch
1
Explicitly set a rule in the softfloat tests for the inf-zero-nan
2
muladd special case. In meson.build we put -DTARGET_ARM in fpcflags,
3
and so we should select here the Arm rule of
4
float_infzeronan_dnan_if_qnan.
1
5
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241202131347.498124-5-peter.maydell@linaro.org
9
---
10
tests/fp/fp-bench.c | 5 +++++
11
tests/fp/fp-test.c | 5 +++++
12
2 files changed, 10 insertions(+)
13
14
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/fp/fp-bench.c
17
+++ b/tests/fp/fp-bench.c
18
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
19
{
20
bench_func_t f;
21
22
+ /*
23
+ * These implementation-defined choices for various things IEEE
24
+ * doesn't specify match those used by the Arm architecture.
25
+ */
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
28
29
f = bench_funcs[operation][precision];
30
g_assert(f);
31
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/tests/fp/fp-test.c
34
+++ b/tests/fp/fp-test.c
35
@@ -XXX,XX +XXX,XX @@ void run_test(void)
36
{
37
unsigned int i;
38
39
+ /*
40
+ * These implementation-defined choices for various things IEEE
41
+ * doesn't specify match those used by the Arm architecture.
42
+ */
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
44
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
45
46
genCases_setLevel(test_level);
47
verCases_maxErrorCount = n_max_errors;
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the Arm target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-6-peter.maydell@linaro.org
7
---
8
target/arm/cpu.c | 3 +++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 4 insertions(+), 7 deletions(-)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
17
* * tininess-before-rounding
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
21
+ * and the input NaN if it is signalling
22
*/
23
static void arm_set_default_fp_behaviours(float_status *s)
24
{
25
set_float_detect_tininess(float_tininess_before_rounding, s);
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
28
}
29
30
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
/*
37
* Temporarily fall back to ifdef ladder
38
*/
39
-#if defined(TARGET_ARM)
40
- /*
41
- * For ARM, the (inf,zero,qnan) case returns the default NaN,
42
- * but (inf,zero,snan) returns the input NaN.
43
- */
44
- rule = float_infzeronan_dnan_if_qnan;
45
-#elif defined(TARGET_MIPS)
46
+#if defined(TARGET_MIPS)
47
if (snan_bit_is_one(status)) {
48
/*
49
* For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
50
--
51
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for s390, so we
2
can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-7-peter.maydell@linaro.org
7
---
8
target/s390x/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/s390x/cpu.c
15
+++ b/target/s390x/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
17
set_float_detect_tininess(float_tininess_before_rounding,
18
&env->fpu_status);
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
20
+ set_float_infzeronan_rule(float_infzeronan_dnan_always,
21
+ &env->fpu_status);
22
/* fall through */
23
case RESET_TYPE_S390_CPU_NORMAL:
24
env->psw.mask &= ~PSW_MASK_RI;
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
* a default NaN
31
*/
32
rule = float_infzeronan_dnan_never;
33
-#elif defined(TARGET_S390X)
34
- rule = float_infzeronan_dnan_always;
35
#endif
36
}
37
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the PPC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-8-peter.maydell@linaro.org
7
---
8
target/ppc/cpu_init.c | 7 +++++++
9
fpu/softfloat-specialize.c.inc | 7 +------
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
15
+++ b/target/ppc/cpu_init.c
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
21
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
22
+ * to return an input NaN if we have one (ie c) rather than generating
23
+ * a default NaN
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
27
28
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
29
ppc_spr_t *spr = &env->spr_cb[i];
30
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
index XXXXXXX..XXXXXXX 100644
32
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
*/
36
rule = float_infzeronan_dnan_never;
37
}
38
-#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
39
+#elif defined(TARGET_SPARC) || \
40
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
41
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
42
/*
43
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
44
* case sets InvalidOp and returns the input value 'c'
45
*/
46
- /*
47
- * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
48
- * to return an input NaN if we have one (ie c) rather than generating
49
- * a default NaN
50
- */
51
rule = float_infzeronan_dnan_never;
52
#endif
53
}
54
--
55
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the MIPS target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-9-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 9 +++++++++
9
target/mips/msa.c | 4 ++++
10
fpu/softfloat-specialize.c.inc | 16 +---------------
11
3 files changed, 14 insertions(+), 15 deletions(-)
12
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_flush_mode(CPUMIPSState *env)
18
static inline void restore_snan_bit_mode(CPUMIPSState *env)
19
{
20
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
21
+ FloatInfZeroNaNRule izn_rule;
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
set_snan_bit_is_one(!nan2008, &env->active_fpu.fp_status);
28
set_default_nan_mode(!nan2008, &env->active_fpu.fp_status);
29
+ /*
30
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
31
+ * case sets InvalidOp and returns the default NaN.
32
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
33
+ * case sets InvalidOp and returns the input value 'c'.
34
+ */
35
+ izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
36
+ set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
37
}
38
39
static inline void restore_fp_status(CPUMIPSState *env)
40
diff --git a/target/mips/msa.c b/target/mips/msa.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/mips/msa.c
43
+++ b/target/mips/msa.c
44
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
45
46
/* set proper signanling bit meaning ("1" means "quiet") */
47
set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
48
+
49
+ /* Inf * 0 + NaN returns the input NaN */
50
+ set_float_infzeronan_rule(float_infzeronan_dnan_never,
51
+ &env->active_tc.msa_fp_status);
52
}
53
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
54
index XXXXXXX..XXXXXXX 100644
55
--- a/fpu/softfloat-specialize.c.inc
56
+++ b/fpu/softfloat-specialize.c.inc
57
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
58
/*
59
* Temporarily fall back to ifdef ladder
60
*/
61
-#if defined(TARGET_MIPS)
62
- if (snan_bit_is_one(status)) {
63
- /*
64
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
65
- * case sets InvalidOp and returns the default NaN
66
- */
67
- rule = float_infzeronan_dnan_always;
68
- } else {
69
- /*
70
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
71
- * case sets InvalidOp and returns the input value 'c'
72
- */
73
- rule = float_infzeronan_dnan_never;
74
- }
75
-#elif defined(TARGET_SPARC) || \
76
+#if defined(TARGET_SPARC) || \
77
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
78
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
79
/*
80
--
81
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the SPARC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-10-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 +--
10
2 files changed, 3 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
23
cpu_exec_realizefn(cs, &local_err);
24
if (local_err != NULL) {
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_SPARC) || \
34
- defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
35
+#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
36
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
37
/*
38
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the xtensa target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-11-peter.maydell@linaro.org
7
---
8
target/xtensa/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 +-
10
2 files changed, 3 insertions(+), 1 deletion(-)
11
12
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/xtensa/cpu.c
15
+++ b/target/xtensa/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
17
reset_mmu(env);
18
cs->halted = env->runstall;
19
#endif
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
set_no_signaling_nans(!dfpu, &env->fp_status);
23
xtensa_use_first_nan(env, !dfpu);
24
}
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
34
+#if defined(TARGET_HPPA) || \
35
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
36
/*
37
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the x86 target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-12-peter.maydell@linaro.org
6
---
7
target/i386/tcg/fpu_helper.c | 7 +++++++
8
fpu/softfloat-specialize.c.inc | 2 +-
9
2 files changed, 8 insertions(+), 1 deletion(-)
10
11
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/i386/tcg/fpu_helper.c
14
+++ b/target/i386/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->mmx_status);
18
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->sse_status);
19
+ /*
20
+ * Only SSE has multiply-add instructions. In the SDM Section 14.5.2
21
+ * "Fused-Multiply-ADD (FMA) Numeric Behavior" the NaN handling is
22
+ * specified -- for 0 * inf + NaN the input NaN is selected, and if
23
+ * there are multiple input NaNs they are selected in the order a, b, c.
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
26
}
27
28
static inline uint8_t save_exception_flags(CPUX86State *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
34
* Temporarily fall back to ifdef ladder
35
*/
36
#if defined(TARGET_HPPA) || \
37
- defined(TARGET_I386) || defined(TARGET_LOONGARCH)
38
+ defined(TARGET_LOONGARCH)
39
/*
40
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
41
* case sets InvalidOp and returns the input value 'c'
42
--
43
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the loongarch target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-13-peter.maydell@linaro.org
6
---
7
target/loongarch/tcg/fpu_helper.c | 5 +++++
8
fpu/softfloat-specialize.c.inc | 7 +------
9
2 files changed, 6 insertions(+), 6 deletions(-)
10
11
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/loongarch/tcg/fpu_helper.c
14
+++ b/target/loongarch/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
16
&env->fp_status);
17
set_flush_to_zero(0, &env->fp_status);
18
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
19
+ /*
20
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
21
+ * case sets InvalidOp and returns the input value 'c'
22
+ */
23
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
}
25
26
int ieee_ex_to_loongarch(int xcpt)
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
index XXXXXXX..XXXXXXX 100644
29
--- a/fpu/softfloat-specialize.c.inc
30
+++ b/fpu/softfloat-specialize.c.inc
31
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
32
/*
33
* Temporarily fall back to ifdef ladder
34
*/
35
-#if defined(TARGET_HPPA) || \
36
- defined(TARGET_LOONGARCH)
37
- /*
38
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
- * case sets InvalidOp and returns the input value 'c'
40
- */
41
+#if defined(TARGET_HPPA)
42
rule = float_infzeronan_dnan_never;
43
#endif
44
}
45
--
46
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the HPPA target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
As this is the last target to be converted to explicitly setting
5
the rule, we can remove the fallback code in pickNaNMulAdd()
6
entirely.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241202131347.498124-14-peter.maydell@linaro.org
11
---
12
target/hppa/fpu_helper.c | 2 ++
13
fpu/softfloat-specialize.c.inc | 13 +------------
14
2 files changed, 3 insertions(+), 12 deletions(-)
15
16
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/hppa/fpu_helper.c
19
+++ b/target/hppa/fpu_helper.c
20
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
21
* HPPA does note implement a CPU reset method at all...
22
*/
23
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
24
+ /* For inf * 0 + NaN, return the input NaN */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
}
27
28
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
34
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
bool infzero, float_status *status)
36
{
37
- FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
38
-
39
/*
40
* We guarantee not to require the target to tell us how to
41
* pick a NaN if we're always returning the default NaN.
42
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
43
*/
44
assert(!status->default_nan_mode);
45
46
- if (rule == float_infzeronan_none) {
47
- /*
48
- * Temporarily fall back to ifdef ladder
49
- */
50
-#if defined(TARGET_HPPA)
51
- rule = float_infzeronan_dnan_never;
52
-#endif
53
- }
54
-
55
if (infzero) {
56
/*
57
* Inf * 0 + NaN -- some implementations return the default NaN here,
58
* and some return the input NaN.
59
*/
60
- switch (rule) {
61
+ switch (status->float_infzeronan_rule) {
62
case float_infzeronan_dnan_never:
63
return 2;
64
case float_infzeronan_dnan_always:
65
--
66
2.34.1
diff view generated by jsdifflib
1
From: Julia Suvorova <jusual@mail.ru>
1
The new implementation of pickNaNMulAdd() will find it convenient
2
to know whether at least one of the three arguments to the muladd
3
was a signaling NaN. We already calculate that in the caller,
4
so pass it in as a new bool have_snan.
2
5
3
ARMv6-M supports 6 Thumb2 instructions. This patch checks for these
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
instructions and allows their execution.
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Like Thumb2 cores, ARMv6-M always interprets BL instruction as 32-bit.
8
Message-id: 20241202131347.498124-15-peter.maydell@linaro.org
9
---
10
fpu/softfloat-parts.c.inc | 5 +++--
11
fpu/softfloat-specialize.c.inc | 2 +-
12
2 files changed, 4 insertions(+), 3 deletions(-)
6
13
7
This patch is required for future Cortex-M0 support.
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
8
9
Signed-off-by: Julia Suvorova <jusual@mail.ru>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-id: 20180612204632.28780-1-jusual@mail.ru
12
[PMM: move armv6m_insn[] and armv6m_mask[] closer to
13
point of use, and mark 'const'. Check for M-and-not-v7
14
rather than M-and-6.]
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/translate.c | 43 +++++++++++++++++++++++++++++++++++++-----
19
1 file changed, 38 insertions(+), 5 deletions(-)
20
21
diff --git a/target/arm/translate.c b/target/arm/translate.c
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/translate.c
16
--- a/fpu/softfloat-parts.c.inc
24
+++ b/target/arm/translate.c
17
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ static bool thumb_insn_is_16bit(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
26
* end up actually treating this as two 16-bit insns, though,
19
{
27
* if it's half of a bl/blx pair that might span a page boundary.
20
int which;
28
*/
21
bool infzero = (ab_mask == float_cmask_infzero);
29
- if (arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
22
+ bool have_snan = (abc_mask & float_cmask_snan);
30
+ if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
23
31
+ arm_dc_feature(s, ARM_FEATURE_M)) {
24
- if (unlikely(abc_mask & float_cmask_snan)) {
32
/* Thumb2 cores (including all M profile ones) always treat
25
+ if (unlikely(have_snan)) {
33
* 32-bit insns as 32-bit.
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
34
*/
35
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
36
int conds;
37
int logic_cc;
38
39
- /* The only 32 bit insn that's allowed for Thumb1 is the combined
40
- * BL/BLX prefix and suffix.
41
+ /*
42
+ * ARMv6-M supports a limited subset of Thumb2 instructions.
43
+ * Other Thumb1 architectures allow only 32-bit
44
+ * combined BL/BLX prefix and suffix.
45
*/
46
- if ((insn & 0xf800e800) != 0xf000e800) {
47
+ if (arm_dc_feature(s, ARM_FEATURE_M) &&
48
+ !arm_dc_feature(s, ARM_FEATURE_V7)) {
49
+ int i;
50
+ bool found = false;
51
+ const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
52
+ 0xf3b08040 /* dsb */,
53
+ 0xf3b08050 /* dmb */,
54
+ 0xf3b08060 /* isb */,
55
+ 0xf3e08000 /* mrs */,
56
+ 0xf000d000 /* bl */};
57
+ const uint32_t armv6m_mask[] = {0xffe0d000,
58
+ 0xfff0d0f0,
59
+ 0xfff0d0f0,
60
+ 0xfff0d0f0,
61
+ 0xffe0d000,
62
+ 0xf800d000};
63
+
64
+ for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
65
+ if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
66
+ found = true;
67
+ break;
68
+ }
69
+ }
70
+ if (!found) {
71
+ goto illegal_op;
72
+ }
73
+ } else if ((insn & 0xf800e800) != 0xf000e800) {
74
ARCH(6T2);
75
}
27
}
76
28
77
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
78
}
30
if (s->default_nan_mode) {
79
break;
31
which = 3;
80
case 3: /* Special control operations. */
32
} else {
81
- ARCH(7);
33
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
82
+ if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
34
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
83
+ !(arm_dc_feature(s, ARM_FEATURE_V6) &&
35
}
84
+ arm_dc_feature(s, ARM_FEATURE_M))) {
36
85
+ goto illegal_op;
37
if (which == 3) {
86
+ }
38
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
87
op = (insn >> 4) & 0xf;
39
index XXXXXXX..XXXXXXX 100644
88
switch (op) {
40
--- a/fpu/softfloat-specialize.c.inc
89
case 2: /* clrex */
41
+++ b/fpu/softfloat-specialize.c.inc
42
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
43
| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
44
*----------------------------------------------------------------------------*/
45
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
46
- bool infzero, float_status *status)
47
+ bool infzero, bool have_snan, float_status *status)
48
{
49
/*
50
* We guarantee not to require the target to tell us how to
90
--
51
--
91
2.17.1
52
2.34.1
92
93
diff view generated by jsdifflib
1
Convert the parallel device away from using the old_mmio field
1
IEEE 758 does not define a fixed rule for which NaN to pick as the
2
of MemoryRegionOps. This change only affects the memory-mapped
2
result if both operands of a 3-operand fused multiply-add operation
3
variant, which is used by the MIPS Jazz boards 'magnum' and 'pica61'.
3
are NaNs. As a result different architectures have ended up with
4
different rules for propagating NaNs.
5
6
QEMU currently hardcodes the NaN propagation logic into the binary
7
because pickNaNMulAdd() has an ifdef ladder for different targets.
8
We want to make the propagation rule instead be selectable at
9
runtime, because:
10
* this will let us have multiple targets in one QEMU binary
11
* the Arm FEAT_AFP architectural feature includes letting
12
the guest select a NaN propagation rule at runtime
13
14
In this commit we add an enum for the propagation rule, the field in
15
float_status, and the corresponding getters and setters. We change
16
pickNaNMulAdd to honour this, but because all targets still leave
17
this field at its default 0 value, the fallback logic will pick the
18
rule type with the old ifdef ladder.
19
20
It's valid not to set a propagation rule if default_nan_mode is
21
enabled, because in that case there's no need to pick a NaN; all the
22
callers of pickNaNMulAdd() catch this case and skip calling it.
4
23
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180601141223.26630-7-peter.maydell@linaro.org
26
Message-id: 20241202131347.498124-16-peter.maydell@linaro.org
8
---
27
---
9
hw/char/parallel.c | 50 ++++++++++------------------------------------
28
include/fpu/softfloat-helpers.h | 11 +++
10
1 file changed, 11 insertions(+), 39 deletions(-)
29
include/fpu/softfloat-types.h | 55 +++++++++++
11
30
fpu/softfloat-specialize.c.inc | 167 ++++++++------------------------
12
diff --git a/hw/char/parallel.c b/hw/char/parallel.c
31
3 files changed, 107 insertions(+), 126 deletions(-)
32
33
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
13
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/char/parallel.c
35
--- a/include/fpu/softfloat-helpers.h
15
+++ b/hw/char/parallel.c
36
+++ b/include/fpu/softfloat-helpers.h
16
@@ -XXX,XX +XXX,XX @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
37
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
38
status->float_2nan_prop_rule = rule;
17
}
39
}
18
40
19
/* Memory mapped interface */
41
+static inline void set_float_3nan_prop_rule(Float3NaNPropRule rule,
20
-static uint32_t parallel_mm_readb (void *opaque, hwaddr addr)
42
+ float_status *status)
21
+static uint64_t parallel_mm_readfn(void *opaque, hwaddr addr, unsigned size)
43
+{
44
+ status->float_3nan_prop_rule = rule;
45
+}
46
+
47
static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
float_status *status)
22
{
49
{
23
ParallelState *s = opaque;
50
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
24
51
return status->float_2nan_prop_rule;
25
- return parallel_ioport_read_sw(s, addr >> s->it_shift) & 0xFF;
26
+ return parallel_ioport_read_sw(s, addr >> s->it_shift) &
27
+ MAKE_64BIT_MASK(0, size * 8);
28
}
52
}
29
53
30
-static void parallel_mm_writeb (void *opaque,
54
+static inline Float3NaNPropRule get_float_3nan_prop_rule(float_status *status)
31
- hwaddr addr, uint32_t value)
55
+{
32
+static void parallel_mm_writefn(void *opaque, hwaddr addr,
56
+ return status->float_3nan_prop_rule;
33
+ uint64_t value, unsigned size)
57
+}
58
+
59
static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
34
{
60
{
35
ParallelState *s = opaque;
61
return status->float_infzeronan_rule;
36
62
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
37
- parallel_ioport_write_sw(s, addr >> s->it_shift, value & 0xFF);
63
index XXXXXXX..XXXXXXX 100644
38
-}
64
--- a/include/fpu/softfloat-types.h
65
+++ b/include/fpu/softfloat-types.h
66
@@ -XXX,XX +XXX,XX @@ this code that are retained.
67
#ifndef SOFTFLOAT_TYPES_H
68
#define SOFTFLOAT_TYPES_H
69
70
+#include "hw/registerfields.h"
71
+
72
/*
73
* Software IEC/IEEE floating-point types.
74
*/
75
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
76
float_2nan_prop_x87,
77
} Float2NaNPropRule;
78
79
+/*
80
+ * 3-input NaN propagation rule, for fused multiply-add. Individual
81
+ * architectures have different rules for which input NaN is
82
+ * propagated to the output when there is more than one NaN on the
83
+ * input.
84
+ *
85
+ * If default_nan_mode is enabled then it is valid not to set a NaN
86
+ * propagation rule, because the softfloat code guarantees not to try
87
+ * to pick a NaN to propagate in default NaN mode. When not in
88
+ * default-NaN mode, it is an error for the target not to set the rule
89
+ * in float_status if it uses a muladd, and we will assert if we need
90
+ * to handle an input NaN and no rule was selected.
91
+ *
92
+ * The naming scheme for Float3NaNPropRule values is:
93
+ * float_3nan_prop_s_abc:
94
+ * = "Prefer SNaN over QNaN, then operand A over B over C"
95
+ * float_3nan_prop_abc:
96
+ * = "Prefer A over B over C regardless of SNaN vs QNAN"
97
+ *
98
+ * For QEMU, the multiply-add operation is A * B + C.
99
+ */
100
+
101
+/*
102
+ * We set the Float3NaNPropRule enum values up so we can select the
103
+ * right value in pickNaNMulAdd in a data driven way.
104
+ */
105
+FIELD(3NAN, 1ST, 0, 2) /* which operand is most preferred ? */
106
+FIELD(3NAN, 2ND, 2, 2) /* which operand is next most preferred ? */
107
+FIELD(3NAN, 3RD, 4, 2) /* which operand is least preferred ? */
108
+FIELD(3NAN, SNAN, 6, 1) /* do we prefer SNaN over QNaN ? */
109
+
110
+#define PROPRULE(X, Y, Z) \
111
+ ((X << R_3NAN_1ST_SHIFT) | (Y << R_3NAN_2ND_SHIFT) | (Z << R_3NAN_3RD_SHIFT))
112
+
113
+typedef enum __attribute__((__packed__)) {
114
+ float_3nan_prop_none = 0, /* No propagation rule specified */
115
+ float_3nan_prop_abc = PROPRULE(0, 1, 2),
116
+ float_3nan_prop_acb = PROPRULE(0, 2, 1),
117
+ float_3nan_prop_bac = PROPRULE(1, 0, 2),
118
+ float_3nan_prop_bca = PROPRULE(1, 2, 0),
119
+ float_3nan_prop_cab = PROPRULE(2, 0, 1),
120
+ float_3nan_prop_cba = PROPRULE(2, 1, 0),
121
+ float_3nan_prop_s_abc = float_3nan_prop_abc | R_3NAN_SNAN_MASK,
122
+ float_3nan_prop_s_acb = float_3nan_prop_acb | R_3NAN_SNAN_MASK,
123
+ float_3nan_prop_s_bac = float_3nan_prop_bac | R_3NAN_SNAN_MASK,
124
+ float_3nan_prop_s_bca = float_3nan_prop_bca | R_3NAN_SNAN_MASK,
125
+ float_3nan_prop_s_cab = float_3nan_prop_cab | R_3NAN_SNAN_MASK,
126
+ float_3nan_prop_s_cba = float_3nan_prop_cba | R_3NAN_SNAN_MASK,
127
+} Float3NaNPropRule;
128
+
129
+#undef PROPRULE
130
+
131
/*
132
* Rule for result of fused multiply-add 0 * Inf + NaN.
133
* This must be a NaN, but implementations differ on whether this
134
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
135
FloatRoundMode float_rounding_mode;
136
FloatX80RoundPrec floatx80_rounding_precision;
137
Float2NaNPropRule float_2nan_prop_rule;
138
+ Float3NaNPropRule float_3nan_prop_rule;
139
FloatInfZeroNaNRule float_infzeronan_rule;
140
bool tininess_before_rounding;
141
/* should denormalised results go to zero and set the inexact flag? */
142
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
143
index XXXXXXX..XXXXXXX 100644
144
--- a/fpu/softfloat-specialize.c.inc
145
+++ b/fpu/softfloat-specialize.c.inc
146
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
147
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
148
bool infzero, bool have_snan, float_status *status)
149
{
150
+ FloatClass cls[3] = { a_cls, b_cls, c_cls };
151
+ Float3NaNPropRule rule = status->float_3nan_prop_rule;
152
+ int which;
153
+
154
/*
155
* We guarantee not to require the target to tell us how to
156
* pick a NaN if we're always returning the default NaN.
157
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
158
}
159
}
160
161
+ if (rule == float_3nan_prop_none) {
162
#if defined(TARGET_ARM)
39
-
163
-
40
-static uint32_t parallel_mm_readw (void *opaque, hwaddr addr)
164
- /* This looks different from the ARM ARM pseudocode, because the ARM ARM
41
-{
165
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
42
- ParallelState *s = opaque;
166
- */
43
-
167
- if (is_snan(c_cls)) {
44
- return parallel_ioport_read_sw(s, addr >> s->it_shift) & 0xFFFF;
168
- return 2;
45
-}
169
- } else if (is_snan(a_cls)) {
46
-
170
- return 0;
47
-static void parallel_mm_writew (void *opaque,
171
- } else if (is_snan(b_cls)) {
48
- hwaddr addr, uint32_t value)
172
- return 1;
49
-{
173
- } else if (is_qnan(c_cls)) {
50
- ParallelState *s = opaque;
174
- return 2;
51
-
175
- } else if (is_qnan(a_cls)) {
52
- parallel_ioport_write_sw(s, addr >> s->it_shift, value & 0xFFFF);
176
- return 0;
53
-}
177
- } else {
54
-
178
- return 1;
55
-static uint32_t parallel_mm_readl (void *opaque, hwaddr addr)
179
- }
56
-{
180
+ /*
57
- ParallelState *s = opaque;
181
+ * This looks different from the ARM ARM pseudocode, because the ARM ARM
58
-
182
+ * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
59
- return parallel_ioport_read_sw(s, addr >> s->it_shift);
183
+ */
60
-}
184
+ rule = float_3nan_prop_s_cab;
61
-
185
#elif defined(TARGET_MIPS)
62
-static void parallel_mm_writel (void *opaque,
186
- if (snan_bit_is_one(status)) {
63
- hwaddr addr, uint32_t value)
187
- /* Prefer sNaN over qNaN, in the a, b, c order. */
64
-{
188
- if (is_snan(a_cls)) {
65
- ParallelState *s = opaque;
189
- return 0;
66
-
190
- } else if (is_snan(b_cls)) {
67
- parallel_ioport_write_sw(s, addr >> s->it_shift, value);
191
- return 1;
68
+ parallel_ioport_write_sw(s, addr >> s->it_shift,
192
- } else if (is_snan(c_cls)) {
69
+ value & MAKE_64BIT_MASK(0, size * 8));
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;
70
}
337
}
71
338
72
static const MemoryRegionOps parallel_mm_ops = {
339
/*----------------------------------------------------------------------------
73
- .old_mmio = {
74
- .read = { parallel_mm_readb, parallel_mm_readw, parallel_mm_readl },
75
- .write = { parallel_mm_writeb, parallel_mm_writew, parallel_mm_writel },
76
- },
77
+ .read = parallel_mm_readfn,
78
+ .write = parallel_mm_writefn,
79
+ .valid.min_access_size = 1,
80
+ .valid.max_access_size = 4,
81
.endianness = DEVICE_NATIVE_ENDIAN,
82
};
83
84
--
340
--
85
2.17.1
341
2.34.1
86
87
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
The Cortex-M CPU and its NVIC are two intimately intertwined parts of
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
the same hardware; it is not possible to use one without the other.
2
ifdef from pickNaNMulAdd().
3
Unfortunately a lot of our board models don't do any sanity checking
4
on the CPU type the user asks for, so a command line like
5
qemu-system-arm -M versatilepb -cpu cortex-m3
6
will create an M3 without an NVIC, and coredump immediately.
7
In the other direction, trying a non-M-profile CPU in an M-profile
8
board won't blow up, but doesn't do anything useful either:
9
qemu-system-arm -M lm3s6965evb -cpu arm926
10
3
11
Add some checking in the NVIC and CPU realize functions that the
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
user isn't trying to use an NVIC without an M-profile CPU or
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
an M-profile CPU without an NVIC, so we can produce a helpful
6
Message-id: 20241202131347.498124-18-peter.maydell@linaro.org
14
error message rather than a core dump.
7
---
8
target/arm/cpu.c | 5 +++++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 6 insertions(+), 7 deletions(-)
15
11
16
Fixes: https://bugs.launchpad.net/qemu/+bug/1766896
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Message-id: 20180601160355.15393-1-peter.maydell@linaro.org
20
---
21
hw/arm/armv7m.c | 7 ++++++-
22
hw/intc/armv7m_nvic.c | 6 +++++-
23
target/arm/cpu.c | 18 ++++++++++++++++++
24
3 files changed, 29 insertions(+), 2 deletions(-)
25
26
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/armv7m.c
29
+++ b/hw/arm/armv7m.c
30
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
31
return;
32
}
33
}
34
+
35
+ /* Tell the CPU where the NVIC is; it will fail realize if it doesn't
36
+ * have one.
37
+ */
38
+ s->cpu->env.nvic = &s->nvic;
39
+
40
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
41
if (err != NULL) {
42
error_propagate(errp, err);
43
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
44
sbd = SYS_BUS_DEVICE(&s->nvic);
45
sysbus_connect_irq(sbd, 0,
46
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
47
- s->cpu->env.nvic = &s->nvic;
48
49
memory_region_add_subregion(&s->container, 0xe000e000,
50
sysbus_mmio_get_region(sbd, 0));
51
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/intc/armv7m_nvic.c
54
+++ b/hw/intc/armv7m_nvic.c
55
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
56
int regionlen;
57
58
s->cpu = ARM_CPU(qemu_get_cpu(0));
59
- assert(s->cpu);
60
+
61
+ if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
62
+ error_setg(errp, "The NVIC can only be used with a Cortex-M CPU");
63
+ return;
64
+ }
65
66
if (s->num_irq > NVIC_MAX_IRQ) {
67
error_setg(errp, "num-irq %d exceeds NVIC maximum", s->num_irq);
68
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
69
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
70
--- a/target/arm/cpu.c
14
--- a/target/arm/cpu.c
71
+++ b/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
72
@@ -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,
73
return;
17
* * tininess-before-rounding
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
21
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
22
+ * but note that for QEMU muladd is a * b + c, whereas for
23
+ * the pseudocode function the arguments are in the order c, a, b.
24
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
25
* and the input NaN if it is signalling
26
*/
27
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
28
{
29
set_float_detect_tininess(float_tininess_before_rounding, s);
30
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
31
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
32
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
33
}
34
35
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
36
index XXXXXXX..XXXXXXX 100644
37
--- a/fpu/softfloat-specialize.c.inc
38
+++ b/fpu/softfloat-specialize.c.inc
39
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
74
}
40
}
75
41
76
+#ifndef CONFIG_USER_ONLY
42
if (rule == float_3nan_prop_none) {
77
+ /* The NVIC and M-profile CPU are two halves of a single piece of
43
-#if defined(TARGET_ARM)
78
+ * hardware; trying to use one without the other is a command line
44
- /*
79
+ * error and will result in segfaults if not caught here.
45
- * This looks different from the ARM ARM pseudocode, because the ARM ARM
80
+ */
46
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
81
+ if (arm_feature(env, ARM_FEATURE_M)) {
47
- */
82
+ if (!env->nvic) {
48
- rule = float_3nan_prop_s_cab;
83
+ error_setg(errp, "This board cannot be used with Cortex-M CPUs");
49
-#elif defined(TARGET_MIPS)
84
+ return;
50
+#if defined(TARGET_MIPS)
85
+ }
51
if (snan_bit_is_one(status)) {
86
+ } else {
52
rule = float_3nan_prop_s_abc;
87
+ if (env->nvic) {
53
} else {
88
+ error_setg(errp, "This board can only be used with Cortex-M CPUs");
89
+ return;
90
+ }
91
+ }
92
+#endif
93
+
94
cpu_exec_realizefn(cs, &local_err);
95
if (local_err != NULL) {
96
error_propagate(errp, local_err);
97
--
54
--
98
2.17.1
55
2.34.1
99
100
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
1
The ethernet controller in the AN505 MPC FPGA image is behind
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
the same AHB Peripheral Protection Controller that handles
2
ifdef from pickNaNMulAdd().
3
the graphics and GPIOs. (In the documentation this is clear
4
in the block diagram but the ethernet controller was omitted
5
from the table listing devices connected to the PPC.)
6
The ethernet sits behind AHB PPCEXP0 interface 5. We had
7
incorrectly claimed that this was a "gpio4", but there are
8
only 4 GPIOs in this image.
9
3
10
Correct the QEMU model to match the hardware.
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(-)
11
12
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20180515171446.10834-1-peter.maydell@linaro.org
15
---
16
hw/arm/mps2-tz.c | 32 +++++++++++++++++++++++---------
17
1 file changed, 23 insertions(+), 9 deletions(-)
18
19
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/mps2-tz.c
15
--- a/target/mips/fpu_helper.h
22
+++ b/hw/arm/mps2-tz.c
16
+++ b/target/mips/fpu_helper.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
24
UnimplementedDeviceState spi[5];
18
{
25
UnimplementedDeviceState i2c[4];
19
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
26
UnimplementedDeviceState i2s_audio;
20
FloatInfZeroNaNRule izn_rule;
27
- UnimplementedDeviceState gpio[5];
21
+ Float3NaNPropRule nan3_rule;
28
+ UnimplementedDeviceState gpio[4];
22
29
UnimplementedDeviceState dma[4];
23
/*
30
UnimplementedDeviceState gfx;
24
* With nan2008, SNaNs are silenced in the usual way.
31
CMSDKAPBUART uart[5];
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
32
SplitIRQ sec_resp_splitter;
26
*/
33
qemu_or_irq uart_irq_orgate;
27
izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
34
+ DeviceState *lan9118;
28
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
35
} MPS2TZMachineState;
29
+ nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
36
30
+ set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
37
#define TYPE_MPS2TZ_MACHINE "mps2tz"
31
+
38
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
39
return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
40
}
32
}
41
33
42
+static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
34
static inline void restore_fp_status(CPUMIPSState *env)
43
+ const char *name, hwaddr size)
35
diff --git a/target/mips/msa.c b/target/mips/msa.c
44
+{
36
index XXXXXXX..XXXXXXX 100644
45
+ SysBusDevice *s;
37
--- a/target/mips/msa.c
46
+ DeviceState *iotkitdev = DEVICE(&mms->iotkit);
38
+++ b/target/mips/msa.c
47
+ NICInfo *nd = &nd_table[0];
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);
48
+
45
+
49
+ /* In hardware this is a LAN9220; the LAN9118 is software compatible
46
/* clear float_status exception flags */
50
+ * except that it doesn't support the checksum-offload feature.
47
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
51
+ */
48
52
+ qemu_check_nic_model(nd, "lan9118");
49
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
53
+ mms->lan9118 = qdev_create(NULL, "lan9118");
50
index XXXXXXX..XXXXXXX 100644
54
+ qdev_set_nic_properties(mms->lan9118, nd);
51
--- a/fpu/softfloat-specialize.c.inc
55
+ qdev_init_nofail(mms->lan9118);
52
+++ b/fpu/softfloat-specialize.c.inc
56
+
53
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
57
+ s = SYS_BUS_DEVICE(mms->lan9118);
58
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
59
+ return sysbus_mmio_get_region(s, 0);
60
+}
61
+
62
static void mps2tz_common_init(MachineState *machine)
63
{
64
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
65
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
66
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
67
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
68
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
69
- { "gpio4", make_unimp_dev, &mms->gpio[4], 0x40104000, 0x1000 },
70
+ { "eth", make_eth_dev, NULL, 0x42000000, 0x100000 },
71
},
72
}, {
73
.name = "ahb_ppcexp1",
74
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
75
"cfg_sec_resp", 0));
76
}
54
}
77
55
78
- /* In hardware this is a LAN9220; the LAN9118 is software compatible
56
if (rule == float_3nan_prop_none) {
79
- * except that it doesn't support the checksum-offload feature.
57
-#if defined(TARGET_MIPS)
80
- * The ethernet controller is not behind a PPC.
58
- if (snan_bit_is_one(status)) {
81
- */
59
- rule = float_3nan_prop_s_abc;
82
- lan9118_init(&nd_table[0], 0x42000000,
60
- } else {
83
- qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
61
- rule = float_3nan_prop_s_cab;
84
-
62
- }
85
create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
63
-#elif defined(TARGET_XTENSA)
86
64
+#if defined(TARGET_XTENSA)
87
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
65
if (status->use_first_nan) {
66
rule = float_3nan_prop_abc;
67
} else {
88
--
68
--
89
2.17.1
69
2.34.1
90
91
diff view generated by jsdifflib
1
Add support for multiple IOMMU indexes to the IOMMU notifier APIs.
1
Set the Float3NaNPropRule explicitly for xtensa, and remove the
2
When initializing a notifier with iommu_notifier_init(), the caller
2
ifdef from pickNaNMulAdd().
3
must pass the IOMMU index that it is interested in. When a change
4
happens, the IOMMU implementation must pass
5
memory_region_notify_iommu() the IOMMU index that has changed and
6
that notifiers must be called for.
7
8
IOMMUs which support only a single index don't need to change.
9
Callers which only really support working with IOMMUs with a single
10
index can use the result of passing MEMTXATTRS_UNSPECIFIED to
11
memory_region_iommu_attrs_to_index().
12
3
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 20241202131347.498124-24-peter.maydell@linaro.org
16
Message-id: 20180604152941.20374-3-peter.maydell@linaro.org
17
---
7
---
18
include/exec/memory.h | 7 ++++++-
8
target/xtensa/fpu_helper.c | 2 ++
19
hw/i386/intel_iommu.c | 6 +++---
9
fpu/softfloat-specialize.c.inc | 8 --------
20
hw/ppc/spapr_iommu.c | 2 +-
10
2 files changed, 2 insertions(+), 8 deletions(-)
21
hw/s390x/s390-pci-inst.c | 4 ++--
22
hw/vfio/common.c | 6 +++++-
23
hw/virtio/vhost.c | 7 ++++++-
24
memory.c | 8 +++++++-
25
7 files changed, 30 insertions(+), 10 deletions(-)
26
11
27
diff --git a/include/exec/memory.h b/include/exec/memory.h
12
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
28
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
29
--- a/include/exec/memory.h
14
--- a/target/xtensa/fpu_helper.c
30
+++ b/include/exec/memory.h
15
+++ b/target/xtensa/fpu_helper.c
31
@@ -XXX,XX +XXX,XX @@ struct IOMMUNotifier {
16
@@ -XXX,XX +XXX,XX @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
32
/* Notify for address space range start <= addr <= end */
17
set_use_first_nan(use_first, &env->fp_status);
33
hwaddr start;
18
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
34
hwaddr end;
19
&env->fp_status);
35
+ int iommu_idx;
20
+ set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
36
QLIST_ENTRY(IOMMUNotifier) node;
21
+ &env->fp_status);
37
};
38
typedef struct IOMMUNotifier IOMMUNotifier;
39
40
static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn,
41
IOMMUNotifierFlag flags,
42
- hwaddr start, hwaddr end)
43
+ hwaddr start, hwaddr end,
44
+ int iommu_idx)
45
{
46
n->notify = fn;
47
n->notifier_flags = flags;
48
n->start = start;
49
n->end = end;
50
+ n->iommu_idx = iommu_idx;
51
}
22
}
52
23
53
/*
24
void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
54
@@ -XXX,XX +XXX,XX @@ uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr);
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
55
* should be notified with an UNMAP followed by a MAP.
56
*
57
* @iommu_mr: the memory region that was changed
58
+ * @iommu_idx: the IOMMU index for the translation table which has changed
59
* @entry: the new entry in the IOMMU translation table. The entry
60
* replaces all old entries for the same virtual I/O address range.
61
* Deleted entries have .@perm == 0.
62
*/
63
void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
64
+ int iommu_idx,
65
IOMMUTLBEntry entry);
66
67
/**
68
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
69
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/i386/intel_iommu.c
27
--- a/fpu/softfloat-specialize.c.inc
71
+++ b/hw/i386/intel_iommu.c
28
+++ b/fpu/softfloat-specialize.c.inc
72
@@ -XXX,XX +XXX,XX @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
73
static int vtd_sync_shadow_page_hook(IOMMUTLBEntry *entry,
74
void *private)
75
{
76
- memory_region_notify_iommu((IOMMUMemoryRegion *)private, *entry);
77
+ memory_region_notify_iommu((IOMMUMemoryRegion *)private, 0, *entry);
78
return 0;
79
}
80
81
@@ -XXX,XX +XXX,XX @@ static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s,
82
.addr_mask = size - 1,
83
.perm = IOMMU_NONE,
84
};
85
- memory_region_notify_iommu(&vtd_as->iommu, entry);
86
+ memory_region_notify_iommu(&vtd_as->iommu, 0, entry);
87
}
88
}
89
}
30
}
90
@@ -XXX,XX +XXX,XX @@ static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s,
31
91
entry.iova = addr;
32
if (rule == float_3nan_prop_none) {
92
entry.perm = IOMMU_NONE;
33
-#if defined(TARGET_XTENSA)
93
entry.translated_addr = 0;
34
- if (status->use_first_nan) {
94
- memory_region_notify_iommu(&vtd_dev_as->iommu, entry);
35
- rule = float_3nan_prop_abc;
95
+ memory_region_notify_iommu(&vtd_dev_as->iommu, 0, entry);
36
- } else {
96
37
- rule = float_3nan_prop_cba;
97
done:
38
- }
98
return true;
39
-#else
99
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
40
rule = float_3nan_prop_abc;
100
index XXXXXXX..XXXXXXX 100644
41
-#endif
101
--- a/hw/ppc/spapr_iommu.c
102
+++ b/hw/ppc/spapr_iommu.c
103
@@ -XXX,XX +XXX,XX @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
104
entry.translated_addr = tce & page_mask;
105
entry.addr_mask = ~page_mask;
106
entry.perm = spapr_tce_iommu_access_flags(tce);
107
- memory_region_notify_iommu(&tcet->iommu, entry);
108
+ memory_region_notify_iommu(&tcet->iommu, 0, entry);
109
110
return H_SUCCESS;
111
}
112
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/hw/s390x/s390-pci-inst.c
115
+++ b/hw/s390x/s390-pci-inst.c
116
@@ -XXX,XX +XXX,XX @@ static void s390_pci_update_iotlb(S390PCIIOMMU *iommu, S390IOTLBEntry *entry)
117
}
118
119
notify.perm = IOMMU_NONE;
120
- memory_region_notify_iommu(&iommu->iommu_mr, notify);
121
+ memory_region_notify_iommu(&iommu->iommu_mr, 0, notify);
122
notify.perm = entry->perm;
123
}
124
125
@@ -XXX,XX +XXX,XX @@ static void s390_pci_update_iotlb(S390PCIIOMMU *iommu, S390IOTLBEntry *entry)
126
g_hash_table_replace(iommu->iotlb, &cache->iova, cache);
127
}
42
}
128
43
129
- memory_region_notify_iommu(&iommu->iommu_mr, notify);
44
assert(rule != float_3nan_prop_none);
130
+ memory_region_notify_iommu(&iommu->iommu_mr, 0, notify);
131
}
132
133
int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
134
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/hw/vfio/common.c
137
+++ b/hw/vfio/common.c
138
@@ -XXX,XX +XXX,XX @@ static void vfio_listener_region_add(MemoryListener *listener,
139
if (memory_region_is_iommu(section->mr)) {
140
VFIOGuestIOMMU *giommu;
141
IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
142
+ int iommu_idx;
143
144
trace_vfio_listener_region_add_iommu(iova, end);
145
/*
146
@@ -XXX,XX +XXX,XX @@ static void vfio_listener_region_add(MemoryListener *listener,
147
llend = int128_add(int128_make64(section->offset_within_region),
148
section->size);
149
llend = int128_sub(llend, int128_one());
150
+ iommu_idx = memory_region_iommu_attrs_to_index(iommu_mr,
151
+ MEMTXATTRS_UNSPECIFIED);
152
iommu_notifier_init(&giommu->n, vfio_iommu_map_notify,
153
IOMMU_NOTIFIER_ALL,
154
section->offset_within_region,
155
- int128_get64(llend));
156
+ int128_get64(llend),
157
+ iommu_idx);
158
QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
159
160
memory_region_register_iommu_notifier(section->mr, &giommu->n);
161
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/hw/virtio/vhost.c
164
+++ b/hw/virtio/vhost.c
165
@@ -XXX,XX +XXX,XX @@ static void vhost_iommu_region_add(MemoryListener *listener,
166
iommu_listener);
167
struct vhost_iommu *iommu;
168
Int128 end;
169
+ int iommu_idx;
170
+ IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
171
172
if (!memory_region_is_iommu(section->mr)) {
173
return;
174
@@ -XXX,XX +XXX,XX @@ static void vhost_iommu_region_add(MemoryListener *listener,
175
end = int128_add(int128_make64(section->offset_within_region),
176
section->size);
177
end = int128_sub(end, int128_one());
178
+ iommu_idx = memory_region_iommu_attrs_to_index(iommu_mr,
179
+ MEMTXATTRS_UNSPECIFIED);
180
iommu_notifier_init(&iommu->n, vhost_iommu_unmap_notify,
181
IOMMU_NOTIFIER_UNMAP,
182
section->offset_within_region,
183
- int128_get64(end));
184
+ int128_get64(end),
185
+ iommu_idx);
186
iommu->mr = section->mr;
187
iommu->iommu_offset = section->offset_within_address_space -
188
section->offset_within_region;
189
diff --git a/memory.c b/memory.c
190
index XXXXXXX..XXXXXXX 100644
191
--- a/memory.c
192
+++ b/memory.c
193
@@ -XXX,XX +XXX,XX @@ void memory_region_register_iommu_notifier(MemoryRegion *mr,
194
iommu_mr = IOMMU_MEMORY_REGION(mr);
195
assert(n->notifier_flags != IOMMU_NOTIFIER_NONE);
196
assert(n->start <= n->end);
197
+ assert(n->iommu_idx >= 0 &&
198
+ n->iommu_idx < memory_region_iommu_num_indexes(iommu_mr));
199
+
200
QLIST_INSERT_HEAD(&iommu_mr->iommu_notify, n, node);
201
memory_region_update_iommu_notify_flags(iommu_mr);
202
}
203
@@ -XXX,XX +XXX,XX @@ void memory_region_notify_one(IOMMUNotifier *notifier,
204
}
205
206
void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
207
+ int iommu_idx,
208
IOMMUTLBEntry entry)
209
{
210
IOMMUNotifier *iommu_notifier;
211
@@ -XXX,XX +XXX,XX @@ void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
212
assert(memory_region_is_iommu(MEMORY_REGION(iommu_mr)));
213
214
IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
215
- memory_region_notify_one(iommu_notifier, &entry);
216
+ if (iommu_notifier->iommu_idx == iommu_idx) {
217
+ memory_region_notify_one(iommu_notifier, &entry);
218
+ }
219
}
220
}
221
222
--
45
--
223
2.17.1
46
2.34.1
224
225
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.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
On Macronix chips, two bytes can written to the WRSR. First byte will
4
configure the status register and the second the configuration
5
register. It is important to save the configuration value as it
6
contains the dummy cycle setting when using dual or quad IO mode.
7
8
Signed-off-by: Cédric Le Goater <clg@kaod.org>
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241202131347.498124-25-peter.maydell@linaro.org
11
---
9
---
12
hw/block/m25p80.c | 1 +
10
target/i386/tcg/fpu_helper.c | 1 +
13
1 file changed, 1 insertion(+)
11
1 file changed, 1 insertion(+)
14
12
15
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
13
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/block/m25p80.c
15
--- a/target/i386/tcg/fpu_helper.c
18
+++ b/hw/block/m25p80.c
16
+++ b/target/i386/tcg/fpu_helper.c
19
@@ -XXX,XX +XXX,XX @@ static void complete_collecting_data(Flash *s)
17
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
20
case MAN_MACRONIX:
18
* there are multiple input NaNs they are selected in the order a, b, c.
21
s->quad_enable = extract32(s->data[0], 6, 1);
19
*/
22
if (s->len > 1) {
20
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
23
+ s->volatile_cfg = s->data[1];
21
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
24
s->four_bytes_address_mode = extract32(s->data[1], 5, 1);
22
}
25
}
23
26
break;
24
static inline uint8_t save_exception_flags(CPUX86State *env)
27
--
25
--
28
2.17.1
26
2.34.1
29
30
diff view generated by jsdifflib
1
From: Joel Stanley <joel@jms.id.au>
1
Set the Float3NaNPropRule explicitly for HPPA, and remove the
2
ifdef from pickNaNMulAdd().
2
3
3
The ASPEED SoCs contain a single register that returns random data when
4
HPPA is the only target that was using the default branch of the
4
read. This models that register so that guests can use it.
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).
5
9
6
The random number data register has a corresponding control register,
10
We add a TODO note that the HPPA rule is probably wrong; this is
7
however it returns data regardless of the state of the enabled bit, so
11
not a behavioural change for this refactoring.
8
the model follows this behaviour.
9
12
10
When the qcrypto call fails we exit as the guest uses the random number
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
device to feed it's entropy pool, which is used for cryptographic
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
purposes.
15
Message-id: 20241202131347.498124-26-peter.maydell@linaro.org
16
---
17
target/hppa/fpu_helper.c | 8 ++++++++
18
fpu/softfloat-specialize.c.inc | 4 ----
19
2 files changed, 8 insertions(+), 4 deletions(-)
13
20
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
21
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
15
Signed-off-by: Joel Stanley <joel@jms.id.au>
16
Message-id: 20180613114836.9265-1-joel@jms.id.au
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
hw/misc/aspeed_scu.c | 20 ++++++++++++++++++++
20
1 file changed, 20 insertions(+)
21
22
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
23
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/misc/aspeed_scu.c
23
--- a/target/hppa/fpu_helper.c
25
+++ b/hw/misc/aspeed_scu.c
24
+++ b/target/hppa/fpu_helper.c
26
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
27
#include "qapi/visitor.h"
26
* HPPA does note implement a CPU reset method at all...
28
#include "qemu/bitops.h"
27
*/
29
#include "qemu/log.h"
28
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
30
+#include "crypto/random.h"
29
+ /*
31
#include "trace.h"
30
+ * TODO: The HPPA architecture reference only documents its NaN
32
31
+ * propagation rule for 2-operand operations. Testing on real hardware
33
#define TO_REG(offset) ((offset) >> 2)
32
+ * might be necessary to confirm whether this order for muladd is correct.
34
@@ -XXX,XX +XXX,XX @@ static const uint32_t ast2500_a1_resets[ASPEED_SCU_NR_REGS] = {
33
+ * Not preferring the SNaN is almost certainly incorrect as it diverges
35
[BMC_DEV_ID] = 0x00002402U
34
+ * from the documented rules for 2-operand operations.
36
};
35
+ */
37
36
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
38
+static uint32_t aspeed_scu_get_random(void)
37
/* For inf * 0 + NaN, return the input NaN */
39
+{
38
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
40
+ Error *err = NULL;
39
}
41
+ uint32_t num;
40
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
42
+
41
index XXXXXXX..XXXXXXX 100644
43
+ if (qcrypto_random_bytes((uint8_t *)&num, sizeof(num), &err)) {
42
--- a/fpu/softfloat-specialize.c.inc
44
+ error_report_err(err);
43
+++ b/fpu/softfloat-specialize.c.inc
45
+ exit(1);
44
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
46
+ }
45
}
47
+
48
+ return num;
49
+}
50
+
51
static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
52
{
53
AspeedSCUState *s = ASPEED_SCU(opaque);
54
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
55
}
46
}
56
47
57
switch (reg) {
48
- if (rule == float_3nan_prop_none) {
58
+ case RNG_DATA:
49
- rule = float_3nan_prop_abc;
59
+ /* On hardware, RNG_DATA works regardless of
50
- }
60
+ * the state of the enable bit in RNG_CTRL
51
-
61
+ */
52
assert(rule != float_3nan_prop_none);
62
+ s->regs[RNG_DATA] = aspeed_scu_get_random();
53
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
63
+ break;
54
/* We have at least one SNaN input and should prefer it */
64
case WAKEUP_EN:
65
qemu_log_mask(LOG_GUEST_ERROR,
66
"%s: Read of write-only offset 0x%" HWADDR_PRIx "\n",
67
--
55
--
68
2.17.1
56
2.34.1
69
70
diff view generated by jsdifflib
1
Remove the now-unused armv7m_init() function. This was a legacy from
1
The use_first_nan field in float_status was an xtensa-specific way to
2
before we properly QOMified ARMv7M, and it has some flaws:
2
select at runtime from two different NaN propagation rules. Now that
3
3
xtensa is using the target-agnostic NaN propagation rule selection
4
* it combines work that needs to be done by an SoC object (creating
4
that we've just added, we can remove use_first_nan, because there is
5
and initializing the TYPE_ARMV7M object) with work that needs to
5
no longer any code that reads it.
6
be done by the board model (setting the system up to load the ELF
7
file specified with -kernel)
8
* TYPE_ARMV7M creation failure is fatal, but an SoC object wants to
9
arrange to propagate the failure outward
10
* it uses allocate-and-create via qdev_create() whereas the current
11
preferred style for SoC objects is to do creation in-place
12
13
Board and SoC models can instead do the two jobs this function
14
was doing themselves, in the right places and with whatever their
15
preferred style/error handling is.
16
6
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-id: 20241202131347.498124-27-peter.maydell@linaro.org
20
Message-id: 20180601144328.23817-3-peter.maydell@linaro.org
21
---
10
---
22
include/hw/arm/arm.h | 8 ++------
11
include/fpu/softfloat-helpers.h | 5 -----
23
hw/arm/armv7m.c | 21 ---------------------
12
include/fpu/softfloat-types.h | 1 -
24
2 files changed, 2 insertions(+), 27 deletions(-)
13
target/xtensa/fpu_helper.c | 1 -
14
3 files changed, 7 deletions(-)
25
15
26
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
16
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
27
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/arm/arm.h
18
--- a/include/fpu/softfloat-helpers.h
29
+++ b/include/hw/arm/arm.h
19
+++ b/include/fpu/softfloat-helpers.h
30
@@ -XXX,XX +XXX,XX @@ typedef enum {
20
@@ -XXX,XX +XXX,XX @@ static inline void set_snan_bit_is_one(bool val, float_status *status)
31
ARM_ENDIANNESS_BE32,
21
status->snan_bit_is_one = val;
32
} arm_endianness;
33
34
-/* armv7m.c */
35
-DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
36
- const char *kernel_filename, const char *cpu_type);
37
/**
38
* armv7m_load_kernel:
39
* @cpu: CPU
40
@@ -XXX,XX +XXX,XX @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
41
* @mem_size: mem_size: maximum image size to load
42
*
43
* Load the guest image for an ARMv7M system. This must be called by
44
- * any ARMv7M board, either directly or via armv7m_init(). (This is
45
- * necessary to ensure that the CPU resets correctly on system reset,
46
- * as well as for kernel loading.)
47
+ * any ARMv7M board. (This is necessary to ensure that the CPU resets
48
+ * correctly on system reset, as well as for kernel loading.)
49
*/
50
void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size);
51
52
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/arm/armv7m.c
55
+++ b/hw/arm/armv7m.c
56
@@ -XXX,XX +XXX,XX @@ static void armv7m_reset(void *opaque)
57
cpu_reset(CPU(cpu));
58
}
22
}
59
23
60
-/* Init CPU and memory for a v7-M based board.
24
-static inline void set_use_first_nan(bool val, float_status *status)
61
- mem_size is in bytes.
62
- Returns the ARMv7M device. */
63
-
64
-DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
65
- const char *kernel_filename, const char *cpu_type)
66
-{
25
-{
67
- DeviceState *armv7m;
26
- status->use_first_nan = val;
68
-
69
- armv7m = qdev_create(NULL, TYPE_ARMV7M);
70
- qdev_prop_set_uint32(armv7m, "num-irq", num_irq);
71
- qdev_prop_set_string(armv7m, "cpu-type", cpu_type);
72
- object_property_set_link(OBJECT(armv7m), OBJECT(get_system_memory()),
73
- "memory", &error_abort);
74
- /* This will exit with an error if the user passed us a bad cpu_type */
75
- qdev_init_nofail(armv7m);
76
-
77
- armv7m_load_kernel(ARM_CPU(first_cpu), kernel_filename, mem_size);
78
- return armv7m;
79
-}
27
-}
80
-
28
-
81
void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
29
static inline void set_no_signaling_nans(bool val, float_status *status)
82
{
30
{
83
int image_size;
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,
84
--
56
--
85
2.17.1
57
2.34.1
86
87
diff view generated by jsdifflib
New patch
1
Currently m68k_cpu_reset_hold() calls floatx80_default_nan(NULL)
2
to get the NaN bit pattern to reset the FPU registers. This
3
works because it happens that our implementation of
4
floatx80_default_nan() doesn't actually look at the float_status
5
pointer except for TARGET_MIPS. However, this isn't guaranteed,
6
and to be able to remove the ifdef in floatx80_default_nan()
7
we're going to need a real float_status here.
1
8
9
Rearrange m68k_cpu_reset_hold() so that we initialize env->fp_status
10
earlier, and thus can pass it to floatx80_default_nan().
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20241202131347.498124-28-peter.maydell@linaro.org
15
---
16
target/m68k/cpu.c | 12 +++++++-----
17
1 file changed, 7 insertions(+), 5 deletions(-)
18
19
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/m68k/cpu.c
22
+++ b/target/m68k/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
24
CPUState *cs = CPU(obj);
25
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(obj);
26
CPUM68KState *env = cpu_env(cs);
27
- floatx80 nan = floatx80_default_nan(NULL);
28
+ floatx80 nan;
29
int i;
30
31
if (mcc->parent_phases.hold) {
32
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
33
#else
34
cpu_m68k_set_sr(env, SR_S | SR_I);
35
#endif
36
- for (i = 0; i < 8; i++) {
37
- env->fregs[i].d = nan;
38
- }
39
- cpu_m68k_set_fpcr(env, 0);
40
/*
41
* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
42
* 3.4 FLOATING-POINT INSTRUCTION DETAILS
43
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
44
* preceding paragraph for nonsignaling NaNs.
45
*/
46
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
47
+
48
+ nan = floatx80_default_nan(&env->fp_status);
49
+ for (i = 0; i < 8; i++) {
50
+ env->fregs[i].d = nan;
51
+ }
52
+ cpu_m68k_set_fpcr(env, 0);
53
env->fpsr = 0;
54
55
/* TODO: We should set PC from the interrupt vector. */
56
--
57
2.34.1
diff view generated by jsdifflib
New patch
1
We create our 128-bit default NaN by calling parts64_default_nan()
2
and then adjusting the result. We can do the same trick for creating
3
the floatx80 default NaN, which lets us drop a target ifdef.
1
4
5
floatx80 is used only by:
6
i386
7
m68k
8
arm nwfpe old floating-point emulation emulation support
9
(which is essentially dead, especially the parts involving floatx80)
10
PPC (only in the xsrqpxp instruction, which just rounds an input
11
value by converting to floatx80 and back, so will never generate
12
the default NaN)
13
14
The floatx80 default NaN as currently implemented is:
15
m68k: sign = 0, exp = 1...1, int = 1, frac = 1....1
16
i386: sign = 1, exp = 1...1, int = 1, frac = 10...0
17
18
These are the same as the parts64_default_nan for these architectures.
19
20
This is technically a possible behaviour change for arm linux-user
21
nwfpe emulation emulation, because the default NaN will now have the
22
sign bit clear. But we were already generating a different floatx80
23
default NaN from the real kernel emulation we are supposedly
24
following, which appears to use an all-bits-1 value:
25
https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L267
26
27
This won't affect the only "real" use of the nwfpe emulation, which
28
is ancient binaries that used it as part of the old floating point
29
calling convention; that only uses loads and stores of 32 and 64 bit
30
floats, not any of the floatx80 behaviour the original hardware had.
31
We also get the nwfpe float64 default NaN value wrong:
32
https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L166
33
so if we ever cared about this obscure corner the right fix would be
34
to correct that so nwfpe used its own default-NaN setting rather
35
than the Arm VFP one.
36
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
39
Message-id: 20241202131347.498124-29-peter.maydell@linaro.org
40
---
41
fpu/softfloat-specialize.c.inc | 20 ++++++++++----------
42
1 file changed, 10 insertions(+), 10 deletions(-)
43
44
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
45
index XXXXXXX..XXXXXXX 100644
46
--- a/fpu/softfloat-specialize.c.inc
47
+++ b/fpu/softfloat-specialize.c.inc
48
@@ -XXX,XX +XXX,XX @@ static void parts128_silence_nan(FloatParts128 *p, float_status *status)
49
floatx80 floatx80_default_nan(float_status *status)
50
{
51
floatx80 r;
52
+ /*
53
+ * Extrapolate from the choices made by parts64_default_nan to fill
54
+ * in the floatx80 format. We assume that floatx80's explicit
55
+ * integer bit is always set (this is true for i386 and m68k,
56
+ * which are the only real users of this format).
57
+ */
58
+ FloatParts64 p64;
59
+ parts64_default_nan(&p64, status);
60
61
- /* None of the targets that have snan_bit_is_one use floatx80. */
62
- assert(!snan_bit_is_one(status));
63
-#if defined(TARGET_M68K)
64
- r.low = UINT64_C(0xFFFFFFFFFFFFFFFF);
65
- r.high = 0x7FFF;
66
-#else
67
- /* X86 */
68
- r.low = UINT64_C(0xC000000000000000);
69
- r.high = 0xFFFF;
70
-#endif
71
+ r.high = 0x7FFF | (p64.sign << 15);
72
+ r.low = (1ULL << DECOMPOSED_BINARY_POINT) | p64.frac;
73
return r;
74
}
75
76
--
77
2.34.1
diff view generated by jsdifflib
New patch
1
In target/loongarch's helper_fclass_s() and helper_fclass_d() we pass
2
a zero-initialized float_status struct to float32_is_quiet_nan() and
3
float64_is_quiet_nan(), with the cryptic comment "for
4
snan_bit_is_one".
1
5
6
This pattern appears to have been copied from target/riscv, where it
7
is used because the functions there do not have ready access to the
8
CPU state struct. The comment presumably refers to the fact that the
9
main reason the is_quiet_nan() functions want the float_state is
10
because they want to know about the snan_bit_is_one config.
11
12
In the loongarch helpers, though, we have the CPU state struct
13
to hand. Use the usual env->fp_status here. This avoids our needing
14
to track that we need to update the initializer of the local
15
float_status structs when the core softfloat code adds new
16
options for targets to configure their behaviour.
17
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20241202131347.498124-30-peter.maydell@linaro.org
21
---
22
target/loongarch/tcg/fpu_helper.c | 6 ++----
23
1 file changed, 2 insertions(+), 4 deletions(-)
24
25
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/loongarch/tcg/fpu_helper.c
28
+++ b/target/loongarch/tcg/fpu_helper.c
29
@@ -XXX,XX +XXX,XX @@ uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj)
30
} else if (float32_is_zero_or_denormal(f)) {
31
return sign ? 1 << 4 : 1 << 8;
32
} else if (float32_is_any_nan(f)) {
33
- float_status s = { }; /* for snan_bit_is_one */
34
- return float32_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
35
+ return float32_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0;
36
} else {
37
return sign ? 1 << 3 : 1 << 7;
38
}
39
@@ -XXX,XX +XXX,XX @@ uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj)
40
} else if (float64_is_zero_or_denormal(f)) {
41
return sign ? 1 << 4 : 1 << 8;
42
} else if (float64_is_any_nan(f)) {
43
- float_status s = { }; /* for snan_bit_is_one */
44
- return float64_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
45
+ return float64_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0;
46
} else {
47
return sign ? 1 << 3 : 1 << 7;
48
}
49
--
50
2.34.1
diff view generated by jsdifflib
New patch
1
In the frem helper, we have a local float_status because we want to
2
execute the floatx80_div() with a custom rounding mode. Instead of
3
zero-initializing the local float_status and then having to set it up
4
with the m68k standard behaviour (including the NaN propagation rule
5
and copying the rounding precision from env->fp_status), initialize
6
it as a complete copy of env->fp_status. This will avoid our having
7
to add new code in this function for every new config knob we add
8
to fp_status.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-31-peter.maydell@linaro.org
13
---
14
target/m68k/fpu_helper.c | 6 ++----
15
1 file changed, 2 insertions(+), 4 deletions(-)
16
17
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/m68k/fpu_helper.c
20
+++ b/target/m68k/fpu_helper.c
21
@@ -XXX,XX +XXX,XX @@ void HELPER(frem)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
22
23
fp_rem = floatx80_rem(val1->d, val0->d, &env->fp_status);
24
if (!floatx80_is_any_nan(fp_rem)) {
25
- float_status fp_status = { };
26
+ /* Use local temporary fp_status to set different rounding mode */
27
+ float_status fp_status = env->fp_status;
28
uint32_t quotient;
29
int sign;
30
31
/* Calculate quotient directly using round to nearest mode */
32
- set_float_2nan_prop_rule(float_2nan_prop_ab, &fp_status);
33
set_float_rounding_mode(float_round_nearest_even, &fp_status);
34
- set_floatx80_rounding_precision(
35
- get_floatx80_rounding_precision(&env->fp_status), &fp_status);
36
fp_quot.d = floatx80_div(val1->d, val0->d, &fp_status);
37
38
sign = extractFloatx80Sign(fp_quot.d);
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
In cf_fpu_gdb_get_reg() and cf_fpu_gdb_set_reg() we do the conversion
2
from float64 to floatx80 using a scratch float_status, because we
3
don't want the conversion to affect the CPU's floating point exception
4
status. Currently we use a zero-initialized float_status. This will
5
get steadily more awkward as we add config knobs to float_status
6
that the target must initialize. Avoid having to add any of that
7
configuration here by instead initializing our local float_status
8
from the env->fp_status.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-32-peter.maydell@linaro.org
13
---
14
target/m68k/helper.c | 6 ++++--
15
1 file changed, 4 insertions(+), 2 deletions(-)
16
17
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/m68k/helper.c
20
+++ b/target/m68k/helper.c
21
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_get_reg(CPUState *cs, GByteArray *mem_buf, int n)
22
CPUM68KState *env = &cpu->env;
23
24
if (n < 8) {
25
- float_status s = {};
26
+ /* Use scratch float_status so any exceptions don't change CPU state */
27
+ float_status s = env->fp_status;
28
return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
29
}
30
switch (n) {
31
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n)
32
CPUM68KState *env = &cpu->env;
33
34
if (n < 8) {
35
- float_status s = {};
36
+ /* Use scratch float_status so any exceptions don't change CPU state */
37
+ float_status s = env->fp_status;
38
env->fregs[n].d = float64_to_floatx80(ldq_be_p(mem_buf), &s);
39
return 8;
40
}
41
--
42
2.34.1
diff view generated by jsdifflib
1
Convert the pflash_cfi02 device away from using the old_mmio field
1
In the helper functions flcmps and flcmpd we use a scratch float_status
2
of MemoryRegionOps.
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.
7
8
To do this we need to pass the CPU env pointer in to the helper.
3
9
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Acked-by: Max Reitz <mreitz@redhat.com>
12
Message-id: 20241202131347.498124-33-peter.maydell@linaro.org
7
Message-id: 20180601141223.26630-4-peter.maydell@linaro.org
8
---
13
---
9
hw/block/pflash_cfi02.c | 97 ++++++++---------------------------------
14
target/sparc/helper.h | 4 ++--
10
1 file changed, 18 insertions(+), 79 deletions(-)
15
target/sparc/fop_helper.c | 8 ++++----
16
target/sparc/translate.c | 4 ++--
17
3 files changed, 8 insertions(+), 8 deletions(-)
11
18
12
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
19
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
13
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/block/pflash_cfi02.c
21
--- a/target/sparc/helper.h
15
+++ b/hw/block/pflash_cfi02.c
22
+++ b/target/sparc/helper.h
16
@@ -XXX,XX +XXX,XX @@ static void pflash_write (pflash_t *pfl, hwaddr offset,
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
17
pfl->cmd = 0;
24
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
25
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128)
26
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128)
27
-DEF_HELPER_FLAGS_2(flcmps, TCG_CALL_NO_RWG_SE, i32, f32, f32)
28
-DEF_HELPER_FLAGS_2(flcmpd, TCG_CALL_NO_RWG_SE, i32, f64, f64)
29
+DEF_HELPER_FLAGS_3(flcmps, TCG_CALL_NO_RWG_SE, i32, env, f32, f32)
30
+DEF_HELPER_FLAGS_3(flcmpd, TCG_CALL_NO_RWG_SE, i32, env, f64, f64)
31
DEF_HELPER_2(raise_exception, noreturn, env, int)
32
33
DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64)
34
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/sparc/fop_helper.c
37
+++ b/target/sparc/fop_helper.c
38
@@ -XXX,XX +XXX,XX @@ uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
39
return finish_fcmp(env, r, GETPC());
18
}
40
}
19
41
20
-
42
-uint32_t helper_flcmps(float32 src1, float32 src2)
21
-static uint32_t pflash_readb_be(void *opaque, hwaddr addr)
43
+uint32_t helper_flcmps(CPUSPARCState *env, float32 src1, float32 src2)
22
+static uint64_t pflash_be_readfn(void *opaque, hwaddr addr, unsigned size)
23
{
44
{
24
- return pflash_read(opaque, addr, 1, 1);
45
/*
25
+ return pflash_read(opaque, addr, size, 1);
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();
26
}
56
}
27
57
28
-static uint32_t pflash_readb_le(void *opaque, hwaddr addr)
58
-uint32_t helper_flcmpd(float64 src1, float64 src2)
29
+static void pflash_be_writefn(void *opaque, hwaddr addr,
59
+uint32_t helper_flcmpd(CPUSPARCState *env, float64 src1, float64 src2)
30
+ uint64_t value, unsigned size)
31
{
60
{
32
- return pflash_read(opaque, addr, 1, 0);
61
- float_status discard = { };
33
+ pflash_write(opaque, addr, value, size, 1);
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);
34
}
77
}
35
78
36
-static uint32_t pflash_readw_be(void *opaque, hwaddr addr)
79
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
37
+static uint64_t pflash_le_readfn(void *opaque, hwaddr addr, unsigned size)
80
38
{
81
src1 = gen_load_fpr_D(dc, a->rs1);
39
- pflash_t *pfl = opaque;
82
src2 = gen_load_fpr_D(dc, a->rs2);
40
-
83
- gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
41
- return pflash_read(pfl, addr, 2, 1);
84
+ gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
42
+ return pflash_read(opaque, addr, size, 0);
85
return advance_pc(dc);
43
}
86
}
44
87
45
-static uint32_t pflash_readw_le(void *opaque, hwaddr addr)
46
+static void pflash_le_writefn(void *opaque, hwaddr addr,
47
+ uint64_t value, unsigned size)
48
{
49
- pflash_t *pfl = opaque;
50
-
51
- return pflash_read(pfl, addr, 2, 0);
52
-}
53
-
54
-static uint32_t pflash_readl_be(void *opaque, hwaddr addr)
55
-{
56
- pflash_t *pfl = opaque;
57
-
58
- return pflash_read(pfl, addr, 4, 1);
59
-}
60
-
61
-static uint32_t pflash_readl_le(void *opaque, hwaddr addr)
62
-{
63
- pflash_t *pfl = opaque;
64
-
65
- return pflash_read(pfl, addr, 4, 0);
66
-}
67
-
68
-static void pflash_writeb_be(void *opaque, hwaddr addr,
69
- uint32_t value)
70
-{
71
- pflash_write(opaque, addr, value, 1, 1);
72
-}
73
-
74
-static void pflash_writeb_le(void *opaque, hwaddr addr,
75
- uint32_t value)
76
-{
77
- pflash_write(opaque, addr, value, 1, 0);
78
-}
79
-
80
-static void pflash_writew_be(void *opaque, hwaddr addr,
81
- uint32_t value)
82
-{
83
- pflash_t *pfl = opaque;
84
-
85
- pflash_write(pfl, addr, value, 2, 1);
86
-}
87
-
88
-static void pflash_writew_le(void *opaque, hwaddr addr,
89
- uint32_t value)
90
-{
91
- pflash_t *pfl = opaque;
92
-
93
- pflash_write(pfl, addr, value, 2, 0);
94
-}
95
-
96
-static void pflash_writel_be(void *opaque, hwaddr addr,
97
- uint32_t value)
98
-{
99
- pflash_t *pfl = opaque;
100
-
101
- pflash_write(pfl, addr, value, 4, 1);
102
-}
103
-
104
-static void pflash_writel_le(void *opaque, hwaddr addr,
105
- uint32_t value)
106
-{
107
- pflash_t *pfl = opaque;
108
-
109
- pflash_write(pfl, addr, value, 4, 0);
110
+ pflash_write(opaque, addr, value, size, 0);
111
}
112
113
static const MemoryRegionOps pflash_cfi02_ops_be = {
114
- .old_mmio = {
115
- .read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, },
116
- .write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, },
117
- },
118
+ .read = pflash_be_readfn,
119
+ .write = pflash_be_writefn,
120
+ .valid.min_access_size = 1,
121
+ .valid.max_access_size = 4,
122
.endianness = DEVICE_NATIVE_ENDIAN,
123
};
124
125
static const MemoryRegionOps pflash_cfi02_ops_le = {
126
- .old_mmio = {
127
- .read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, },
128
- .write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, },
129
- },
130
+ .read = pflash_le_readfn,
131
+ .write = pflash_le_writefn,
132
+ .valid.min_access_size = 1,
133
+ .valid.max_access_size = 4,
134
.endianness = DEVICE_NATIVE_ENDIAN,
135
};
136
137
--
88
--
138
2.17.1
89
2.34.1
139
140
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
Now that float_status has a bunch of fp parameters,
4
it is easier to copy an existing structure than create
5
one from scratch. Begin by copying the structure that
6
corresponds to the FPSR and make only the adjustments
7
required for BFloat16 semantics.
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241203203949.483774-2-richard.henderson@linaro.org
5
Message-id: 20180613015641.5667-17-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
14
---
8
target/arm/translate-sve.c | 37 +++++++++++++++++++++++++++++++++++++
15
target/arm/tcg/vec_helper.c | 20 +++++++-------------
9
target/arm/sve.decode | 8 ++++++++
16
1 file changed, 7 insertions(+), 13 deletions(-)
10
2 files changed, 45 insertions(+)
11
17
12
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
18
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
13
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-sve.c
20
--- a/target/arm/tcg/vec_helper.c
15
+++ b/target/arm/translate-sve.c
21
+++ b/target/arm/tcg/vec_helper.c
16
@@ -XXX,XX +XXX,XX @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a, uint32_t insn)
22
@@ -XXX,XX +XXX,XX @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp)
17
return true;
23
* no effect on AArch32 instructions.
24
*/
25
bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF;
26
- *statusp = (float_status){
27
- .tininess_before_rounding = float_tininess_before_rounding,
28
- .float_rounding_mode = float_round_to_odd_inf,
29
- .flush_to_zero = true,
30
- .flush_inputs_to_zero = true,
31
- .default_nan_mode = true,
32
- };
33
+
34
+ *statusp = env->vfp.fp_status;
35
+ set_default_nan_mode(true, statusp);
36
37
if (ebf) {
38
- float_status *fpst = &env->vfp.fp_status;
39
- set_flush_to_zero(get_flush_to_zero(fpst), statusp);
40
- set_flush_inputs_to_zero(get_flush_inputs_to_zero(fpst), statusp);
41
- set_float_rounding_mode(get_float_rounding_mode(fpst), statusp);
42
-
43
/* EBF=1 needs to do a step with round-to-odd semantics */
44
*oddstatusp = *statusp;
45
set_float_rounding_mode(float_round_to_odd, oddstatusp);
46
+ } else {
47
+ set_flush_to_zero(true, statusp);
48
+ set_flush_inputs_to_zero(true, statusp);
49
+ set_float_rounding_mode(float_round_to_odd_inf, statusp);
50
}
51
-
52
return ebf;
18
}
53
}
19
54
20
+/*
21
+ *** SVE Integer Wide Immediate - Unpredicated Group
22
+ */
23
+
24
+static bool trans_FDUP(DisasContext *s, arg_FDUP *a, uint32_t insn)
25
+{
26
+ if (a->esz == 0) {
27
+ return false;
28
+ }
29
+ if (sve_access_check(s)) {
30
+ unsigned vsz = vec_full_reg_size(s);
31
+ int dofs = vec_full_reg_offset(s, a->rd);
32
+ uint64_t imm;
33
+
34
+ /* Decode the VFP immediate. */
35
+ imm = vfp_expand_imm(a->esz, a->imm);
36
+ imm = dup_const(a->esz, imm);
37
+
38
+ tcg_gen_gvec_dup64i(dofs, vsz, vsz, imm);
39
+ }
40
+ return true;
41
+}
42
+
43
+static bool trans_DUP_i(DisasContext *s, arg_DUP_i *a, uint32_t insn)
44
+{
45
+ if (a->esz == 0 && extract32(insn, 13, 1)) {
46
+ return false;
47
+ }
48
+ if (sve_access_check(s)) {
49
+ unsigned vsz = vec_full_reg_size(s);
50
+ int dofs = vec_full_reg_offset(s, a->rd);
51
+
52
+ tcg_gen_gvec_dup64i(dofs, vsz, vsz, dup_const(a->esz, a->imm));
53
+ }
54
+ return true;
55
+}
56
+
57
/*
58
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
59
*/
60
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/sve.decode
63
+++ b/target/arm/sve.decode
64
@@ -XXX,XX +XXX,XX @@ CTERM 00100101 1 sf:1 1 rm:5 001000 rn:5 ne:1 0000
65
# SVE integer compare scalar count and limit
66
WHILE 00100101 esz:2 1 rm:5 000 sf:1 u:1 1 rn:5 eq:1 rd:4
67
68
+### SVE Integer Wide Immediate - Unpredicated Group
69
+
70
+# SVE broadcast floating-point immediate (unpredicated)
71
+FDUP 00100101 esz:2 111 00 1110 imm:8 rd:5
72
+
73
+# SVE broadcast integer immediate (unpredicated)
74
+DUP_i 00100101 esz:2 111 00 011 . ........ rd:5 imm=%sh8_i8s
75
+
76
### SVE Memory - 32-bit Gather and Unsized Contiguous Group
77
78
# SVE load predicate register
79
--
55
--
80
2.17.1
56
2.34.1
81
57
82
58
diff view generated by jsdifflib
1
If an IOMMU supports mappings that care about the memory
1
Currently we hardcode the default NaN value in parts64_default_nan()
2
transaction attributes, then it no longer has a unique
2
using a compile-time ifdef ladder. This is awkward for two cases:
3
address -> output mapping, but more than one. We can
3
* for single-QEMU-binary we can't hard-code target-specifics like this
4
represent these using an IOMMU index, analogous to TCG's
4
* for Arm FEAT_AFP the default NaN value depends on FPCR.AH
5
mmu indexes.
5
(specifically the sign bit is different)
6
7
Add a field to float_status to specify the default NaN value; fall
8
back to the old ifdef behaviour if these are not set.
9
10
The default NaN value is specified by setting a uint8_t to a
11
pattern corresponding to the sign and upper fraction parts of
12
the NaN; the lower bits of the fraction are set from bit 0 of
13
the pattern.
6
14
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20241202131347.498124-35-peter.maydell@linaro.org
10
Message-id: 20180604152941.20374-2-peter.maydell@linaro.org
11
---
18
---
12
include/exec/memory.h | 55 +++++++++++++++++++++++++++++++++++++++++++
19
include/fpu/softfloat-helpers.h | 11 +++++++
13
memory.c | 23 ++++++++++++++++++
20
include/fpu/softfloat-types.h | 10 ++++++
14
2 files changed, 78 insertions(+)
21
fpu/softfloat-specialize.c.inc | 55 ++++++++++++++++++++-------------
22
3 files changed, 54 insertions(+), 22 deletions(-)
15
23
16
diff --git a/include/exec/memory.h b/include/exec/memory.h
24
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
17
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
18
--- a/include/exec/memory.h
26
--- a/include/fpu/softfloat-helpers.h
19
+++ b/include/exec/memory.h
27
+++ b/include/fpu/softfloat-helpers.h
20
@@ -XXX,XX +XXX,XX @@ enum IOMMUMemoryRegionAttr {
28
@@ -XXX,XX +XXX,XX @@ static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
21
* to report whenever mappings are changed, by calling
29
status->float_infzeronan_rule = rule;
22
* memory_region_notify_iommu() (or, if necessary, by calling
23
* memory_region_notify_one() for each registered notifier).
24
+ *
25
+ * Conceptually an IOMMU provides a mapping from input address
26
+ * to an output TLB entry. If the IOMMU is aware of memory transaction
27
+ * attributes and the output TLB entry depends on the transaction
28
+ * attributes, we represent this using IOMMU indexes. Each index
29
+ * selects a particular translation table that the IOMMU has:
30
+ * @attrs_to_index returns the IOMMU index for a set of transaction attributes
31
+ * @translate takes an input address and an IOMMU index
32
+ * and the mapping returned can only depend on the input address and the
33
+ * IOMMU index.
34
+ *
35
+ * Most IOMMUs don't care about the transaction attributes and support
36
+ * only a single IOMMU index. A more complex IOMMU might have one index
37
+ * for secure transactions and one for non-secure transactions.
38
*/
39
typedef struct IOMMUMemoryRegionClass {
40
/* private */
41
@@ -XXX,XX +XXX,XX @@ typedef struct IOMMUMemoryRegionClass {
42
*/
43
int (*get_attr)(IOMMUMemoryRegion *iommu, enum IOMMUMemoryRegionAttr attr,
44
void *data);
45
+
46
+ /* Return the IOMMU index to use for a given set of transaction attributes.
47
+ *
48
+ * Optional method: if an IOMMU only supports a single IOMMU index then
49
+ * the default implementation of memory_region_iommu_attrs_to_index()
50
+ * will return 0.
51
+ *
52
+ * The indexes supported by an IOMMU must be contiguous, starting at 0.
53
+ *
54
+ * @iommu: the IOMMUMemoryRegion
55
+ * @attrs: memory transaction attributes
56
+ */
57
+ int (*attrs_to_index)(IOMMUMemoryRegion *iommu, MemTxAttrs attrs);
58
+
59
+ /* Return the number of IOMMU indexes this IOMMU supports.
60
+ *
61
+ * Optional method: if this method is not provided, then
62
+ * memory_region_iommu_num_indexes() will return 1, indicating that
63
+ * only a single IOMMU index is supported.
64
+ *
65
+ * @iommu: the IOMMUMemoryRegion
66
+ */
67
+ int (*num_indexes)(IOMMUMemoryRegion *iommu);
68
} IOMMUMemoryRegionClass;
69
70
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
71
@@ -XXX,XX +XXX,XX @@ int memory_region_iommu_get_attr(IOMMUMemoryRegion *iommu_mr,
72
enum IOMMUMemoryRegionAttr attr,
73
void *data);
74
75
+/**
76
+ * memory_region_iommu_attrs_to_index: return the IOMMU index to
77
+ * use for translations with the given memory transaction attributes.
78
+ *
79
+ * @iommu_mr: the memory region
80
+ * @attrs: the memory transaction attributes
81
+ */
82
+int memory_region_iommu_attrs_to_index(IOMMUMemoryRegion *iommu_mr,
83
+ MemTxAttrs attrs);
84
+
85
+/**
86
+ * memory_region_iommu_num_indexes: return the total number of IOMMU
87
+ * indexes that this IOMMU supports.
88
+ *
89
+ * @iommu_mr: the memory region
90
+ */
91
+int memory_region_iommu_num_indexes(IOMMUMemoryRegion *iommu_mr);
92
+
93
/**
94
* memory_region_name: get a memory region's name
95
*
96
diff --git a/memory.c b/memory.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/memory.c
99
+++ b/memory.c
100
@@ -XXX,XX +XXX,XX @@ int memory_region_iommu_get_attr(IOMMUMemoryRegion *iommu_mr,
101
return imrc->get_attr(iommu_mr, attr, data);
102
}
30
}
103
31
104
+int memory_region_iommu_attrs_to_index(IOMMUMemoryRegion *iommu_mr,
32
+static inline void set_float_default_nan_pattern(uint8_t dnan_pattern,
105
+ MemTxAttrs attrs)
33
+ float_status *status)
106
+{
34
+{
107
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
35
+ status->default_nan_pattern = dnan_pattern;
108
+
109
+ if (!imrc->attrs_to_index) {
110
+ return 0;
111
+ }
112
+
113
+ return imrc->attrs_to_index(iommu_mr, attrs);
114
+}
36
+}
115
+
37
+
116
+int memory_region_iommu_num_indexes(IOMMUMemoryRegion *iommu_mr)
38
static inline void set_flush_to_zero(bool val, float_status *status)
39
{
40
status->flush_to_zero = val;
41
@@ -XXX,XX +XXX,XX @@ static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status
42
return status->float_infzeronan_rule;
43
}
44
45
+static inline uint8_t get_float_default_nan_pattern(float_status *status)
117
+{
46
+{
118
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
47
+ return status->default_nan_pattern;
119
+
120
+ if (!imrc->num_indexes) {
121
+ return 1;
122
+ }
123
+
124
+ return imrc->num_indexes(iommu_mr);
125
+}
48
+}
126
+
49
+
127
void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
50
static inline bool get_flush_to_zero(float_status *status)
128
{
51
{
129
uint8_t mask = 1 << client;
52
return status->flush_to_zero;
53
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/include/fpu/softfloat-types.h
56
+++ b/include/fpu/softfloat-types.h
57
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
58
/* should denormalised inputs go to zero and set the input_denormal flag? */
59
bool flush_inputs_to_zero;
60
bool default_nan_mode;
61
+ /*
62
+ * The pattern to use for the default NaN. Here the high bit specifies
63
+ * the default NaN's sign bit, and bits 6..0 specify the high bits of the
64
+ * fractional part. The low bits of the fractional part are copies of bit 0.
65
+ * The exponent of the default NaN is (as for any NaN) always all 1s.
66
+ * Note that a value of 0 here is not a valid NaN. The target must set
67
+ * this to the correct non-zero value, or we will assert when trying to
68
+ * create a default NaN.
69
+ */
70
+ uint8_t default_nan_pattern;
71
/*
72
* The flags below are not used on all specializations and may
73
* constant fold away (see snan_bit_is_one()/no_signalling_nans() in
74
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
75
index XXXXXXX..XXXXXXX 100644
76
--- a/fpu/softfloat-specialize.c.inc
77
+++ b/fpu/softfloat-specialize.c.inc
78
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
79
{
80
bool sign = 0;
81
uint64_t frac;
82
+ uint8_t dnan_pattern = status->default_nan_pattern;
83
84
+ if (dnan_pattern == 0) {
85
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
86
- /* !snan_bit_is_one, set all bits */
87
- frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
88
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
89
+ /* Sign bit clear, all frac bits set */
90
+ dnan_pattern = 0b01111111;
91
+#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
92
|| defined(TARGET_MICROBLAZE)
93
- /* !snan_bit_is_one, set sign and msb */
94
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
95
- sign = 1;
96
+ /* Sign bit set, most significant frac bit set */
97
+ dnan_pattern = 0b11000000;
98
#elif defined(TARGET_HPPA)
99
- /* snan_bit_is_one, set msb-1. */
100
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
101
+ /* Sign bit clear, msb-1 frac bit set */
102
+ dnan_pattern = 0b00100000;
103
#elif defined(TARGET_HEXAGON)
104
- sign = 1;
105
- frac = ~0ULL;
106
+ /* Sign bit set, all frac bits set. */
107
+ dnan_pattern = 0b11111111;
108
#else
109
- /*
110
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
111
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
112
- * do not have floating-point.
113
- */
114
- if (snan_bit_is_one(status)) {
115
- /* set all bits other than msb */
116
- frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1;
117
- } else {
118
- /* set msb */
119
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
120
- }
121
+ /*
122
+ * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
123
+ * S390, SH4, TriCore, and Xtensa. Our other supported targets
124
+ * do not have floating-point.
125
+ */
126
+ if (snan_bit_is_one(status)) {
127
+ /* sign bit clear, set all frac bits other than msb */
128
+ dnan_pattern = 0b00111111;
129
+ } else {
130
+ /* sign bit clear, set frac msb */
131
+ dnan_pattern = 0b01000000;
132
+ }
133
#endif
134
+ }
135
+ assert(dnan_pattern != 0);
136
+
137
+ sign = dnan_pattern >> 7;
138
+ /*
139
+ * Place default_nan_pattern [6:0] into bits [62:56],
140
+ * and replecate bit [0] down into [55:0]
141
+ */
142
+ frac = deposit64(0, DECOMPOSED_BINARY_POINT - 7, 7, dnan_pattern);
143
+ frac = deposit64(frac, 0, DECOMPOSED_BINARY_POINT - 7, -(dnan_pattern & 1));
144
145
*p = (FloatParts64) {
146
.cls = float_class_qnan,
130
--
147
--
131
2.17.1
148
2.34.1
132
133
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
1
The stellaris board is still using the legacy armv7m_init() function,
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
which predates conversion of the ARMv7M into a proper QOM container
2
parts64_default_nan().
3
object. Make the board code directly create the ARMv7M object instead.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Message-id: 20241202131347.498124-38-peter.maydell@linaro.org
8
Message-id: 20180601144328.23817-2-peter.maydell@linaro.org
9
---
7
---
10
hw/arm/stellaris.c | 12 ++++++++++--
8
target/i386/tcg/fpu_helper.c | 4 ++++
11
1 file changed, 10 insertions(+), 2 deletions(-)
9
fpu/softfloat-specialize.c.inc | 3 ---
10
2 files changed, 4 insertions(+), 3 deletions(-)
12
11
13
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
12
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/stellaris.c
14
--- a/target/i386/tcg/fpu_helper.c
16
+++ b/hw/arm/stellaris.c
15
+++ b/target/i386/tcg/fpu_helper.c
17
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
18
#include "qemu/log.h"
17
*/
19
#include "exec/address-spaces.h"
18
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
20
#include "sysemu/sysemu.h"
19
set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
21
+#include "hw/arm/armv7m.h"
20
+ /* Default NaN: sign bit set, most significant frac bit set */
22
#include "hw/char/pl011.h"
21
+ set_float_default_nan_pattern(0b11000000, &env->fp_status);
23
#include "hw/misc/unimp.h"
22
+ set_float_default_nan_pattern(0b11000000, &env->mmx_status);
24
#include "cpu.h"
23
+ set_float_default_nan_pattern(0b11000000, &env->sse_status);
25
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
26
&error_fatal);
27
memory_region_add_subregion(system_memory, 0x20000000, sram);
28
29
- nvic = armv7m_init(system_memory, flash_size, NUM_IRQ_LINES,
30
- ms->kernel_filename, ms->cpu_type);
31
+ nvic = qdev_create(NULL, TYPE_ARMV7M);
32
+ qdev_prop_set_uint32(nvic, "num-irq", NUM_IRQ_LINES);
33
+ qdev_prop_set_string(nvic, "cpu-type", ms->cpu_type);
34
+ object_property_set_link(OBJECT(nvic), OBJECT(get_system_memory()),
35
+ "memory", &error_abort);
36
+ /* This will exit with an error if the user passed us a bad cpu_type */
37
+ qdev_init_nofail(nvic);
38
39
qdev_connect_gpio_out_named(nvic, "SYSRESETREQ", 0,
40
qemu_allocate_irq(&do_sys_reset, NULL, 0));
41
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
42
create_unimplemented_device("analogue-comparator", 0x4003c000, 0x1000);
43
create_unimplemented_device("hibernation", 0x400fc000, 0x1000);
44
create_unimplemented_device("flash-control", 0x400fd000, 0x1000);
45
+
46
+ armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, flash_size);
47
}
24
}
48
25
49
/* FIXME: Figure out how to generate these from stellaris_boards. */
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;
50
--
41
--
51
2.17.1
42
2.34.1
52
53
diff view generated by jsdifflib
1
Convert the pckbd device away from using the old_mmio field
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
of MemoryRegionOps. This change only affects the memory-mapped
2
parts64_default_nan().
3
variant of the i8042, which is used by the Unicore32 'puv3'
4
board and the MIPS Jazz boards 'magnum' and 'pica61'.
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180601141223.26630-6-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-39-peter.maydell@linaro.org
9
---
7
---
10
hw/input/pckbd.c | 14 ++++++++------
8
target/hppa/fpu_helper.c | 2 ++
11
1 file changed, 8 insertions(+), 6 deletions(-)
9
fpu/softfloat-specialize.c.inc | 3 ---
10
2 files changed, 2 insertions(+), 3 deletions(-)
12
11
13
diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c
12
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/input/pckbd.c
14
--- a/target/hppa/fpu_helper.c
16
+++ b/hw/input/pckbd.c
15
+++ b/target/hppa/fpu_helper.c
17
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_kbd = {
16
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
18
};
17
set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
19
18
/* For inf * 0 + NaN, return the input NaN */
20
/* Memory mapped interface */
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
21
-static uint32_t kbd_mm_readb (void *opaque, hwaddr addr)
20
+ /* Default NaN: sign bit clear, msb-1 frac bit set */
22
+static uint64_t kbd_mm_readfn(void *opaque, hwaddr addr, unsigned size)
21
+ set_float_default_nan_pattern(0b00100000, &env->fp_status);
23
{
24
KBDState *s = opaque;
25
26
@@ -XXX,XX +XXX,XX @@ static uint32_t kbd_mm_readb (void *opaque, hwaddr addr)
27
return kbd_read_data(s, 0, 1) & 0xff;
28
}
22
}
29
23
30
-static void kbd_mm_writeb (void *opaque, hwaddr addr, uint32_t value)
24
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
31
+static void kbd_mm_writefn(void *opaque, hwaddr addr,
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
+ uint64_t value, unsigned size)
26
index XXXXXXX..XXXXXXX 100644
33
{
27
--- a/fpu/softfloat-specialize.c.inc
34
KBDState *s = opaque;
28
+++ b/fpu/softfloat-specialize.c.inc
35
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
36
@@ -XXX,XX +XXX,XX @@ static void kbd_mm_writeb (void *opaque, hwaddr addr, uint32_t value)
30
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
37
kbd_write_data(s, 0, value & 0xff, 1);
31
/* Sign bit clear, all frac bits set */
38
}
32
dnan_pattern = 0b01111111;
39
33
-#elif defined(TARGET_HPPA)
40
+
34
- /* Sign bit clear, msb-1 frac bit set */
41
static const MemoryRegionOps i8042_mmio_ops = {
35
- dnan_pattern = 0b00100000;
42
+ .read = kbd_mm_readfn,
36
#elif defined(TARGET_HEXAGON)
43
+ .write = kbd_mm_writefn,
37
/* Sign bit set, all frac bits set. */
44
+ .valid.min_access_size = 1,
38
dnan_pattern = 0b11111111;
45
+ .valid.max_access_size = 4,
46
.endianness = DEVICE_NATIVE_ENDIAN,
47
- .old_mmio = {
48
- .read = { kbd_mm_readb, kbd_mm_readb, kbd_mm_readb },
49
- .write = { kbd_mm_writeb, kbd_mm_writeb, kbd_mm_writeb },
50
- },
51
};
52
53
void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
54
--
39
--
55
2.17.1
40
2.34.1
56
57
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
Now we have stn_p() and ldn_p() we can use them in various
1
Set the default NaN pattern explicitly for the arm target.
2
functions in exec.c that used to have their own switch-on-size code.
2
This includes setting it for the old linux-user nwfpe emulation.
3
For nwfpe, our default doesn't match the real kernel, but we
4
avoid making a behaviour change in this commit.
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180611171007.4165-4-peter.maydell@linaro.org
8
Message-id: 20241202131347.498124-41-peter.maydell@linaro.org
8
---
9
---
9
exec.c | 112 +++++----------------------------------------------------
10
linux-user/arm/nwfpe/fpa11.c | 5 +++++
10
1 file changed, 8 insertions(+), 104 deletions(-)
11
target/arm/cpu.c | 2 ++
12
2 files changed, 7 insertions(+)
11
13
12
diff --git a/exec.c b/exec.c
14
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/exec.c
16
--- a/linux-user/arm/nwfpe/fpa11.c
15
+++ b/exec.c
17
+++ b/linux-user/arm/nwfpe/fpa11.c
16
@@ -XXX,XX +XXX,XX @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
18
@@ -XXX,XX +XXX,XX @@ void resetFPA11(void)
17
memory_notdirty_write_prepare(&ndi, current_cpu, current_cpu->mem_io_vaddr,
19
* this late date.
18
ram_addr, size);
20
*/
19
21
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &fpa11->fp_status);
20
- switch (size) {
22
+ /*
21
- case 1:
23
+ * Use the same default NaN value as Arm VFP. This doesn't match
22
- stb_p(qemu_map_ram_ptr(NULL, ram_addr), val);
24
+ * the Linux kernel's nwfpe emulation, which uses an all-1s value.
23
- break;
25
+ */
24
- case 2:
26
+ set_float_default_nan_pattern(0b01000000, &fpa11->fp_status);
25
- stw_p(qemu_map_ram_ptr(NULL, ram_addr), val);
26
- break;
27
- case 4:
28
- stl_p(qemu_map_ram_ptr(NULL, ram_addr), val);
29
- break;
30
- case 8:
31
- stq_p(qemu_map_ram_ptr(NULL, ram_addr), val);
32
- break;
33
- default:
34
- abort();
35
- }
36
+ stn_p(qemu_map_ram_ptr(NULL, ram_addr), size, val);
37
memory_notdirty_write_complete(&ndi);
38
}
27
}
39
28
40
@@ -XXX,XX +XXX,XX @@ static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
29
void SetRoundingMode(const unsigned int opcode)
41
if (res) {
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
42
return res;
31
index XXXXXXX..XXXXXXX 100644
43
}
32
--- a/target/arm/cpu.c
44
- switch (len) {
33
+++ b/target/arm/cpu.c
45
- case 1:
34
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
46
- *data = ldub_p(buf);
35
* the pseudocode function the arguments are in the order c, a, b.
47
- return MEMTX_OK;
36
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
48
- case 2:
37
* and the input NaN if it is signalling
49
- *data = lduw_p(buf);
38
+ * * Default NaN has sign bit clear, msb frac bit set
50
- return MEMTX_OK;
39
*/
51
- case 4:
40
static void arm_set_default_fp_behaviours(float_status *s)
52
- *data = (uint32_t)ldl_p(buf);
41
{
53
- return MEMTX_OK;
42
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
54
- case 8:
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
55
- *data = ldq_p(buf);
44
set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
56
- return MEMTX_OK;
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
57
- default:
46
+ set_float_default_nan_pattern(0b01000000, s);
58
- abort();
59
- }
60
+ *data = ldn_p(buf, len);
61
+ return MEMTX_OK;
62
}
47
}
63
48
64
static MemTxResult subpage_write(void *opaque, hwaddr addr,
49
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
65
@@ -XXX,XX +XXX,XX @@ static MemTxResult subpage_write(void *opaque, hwaddr addr,
66
" value %"PRIx64"\n",
67
__func__, subpage, len, addr, value);
68
#endif
69
- switch (len) {
70
- case 1:
71
- stb_p(buf, value);
72
- break;
73
- case 2:
74
- stw_p(buf, value);
75
- break;
76
- case 4:
77
- stl_p(buf, value);
78
- break;
79
- case 8:
80
- stq_p(buf, value);
81
- break;
82
- default:
83
- abort();
84
- }
85
+ stn_p(buf, len, value);
86
return flatview_write(subpage->fv, addr + subpage->base, attrs, buf, len);
87
}
88
89
@@ -XXX,XX +XXX,XX @@ static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr,
90
l = memory_access_size(mr, l, addr1);
91
/* XXX: could force current_cpu to NULL to avoid
92
potential bugs */
93
- switch (l) {
94
- case 8:
95
- /* 64 bit write access */
96
- val = ldq_p(buf);
97
- result |= memory_region_dispatch_write(mr, addr1, val, 8,
98
- attrs);
99
- break;
100
- case 4:
101
- /* 32 bit write access */
102
- val = (uint32_t)ldl_p(buf);
103
- result |= memory_region_dispatch_write(mr, addr1, val, 4,
104
- attrs);
105
- break;
106
- case 2:
107
- /* 16 bit write access */
108
- val = lduw_p(buf);
109
- result |= memory_region_dispatch_write(mr, addr1, val, 2,
110
- attrs);
111
- break;
112
- case 1:
113
- /* 8 bit write access */
114
- val = ldub_p(buf);
115
- result |= memory_region_dispatch_write(mr, addr1, val, 1,
116
- attrs);
117
- break;
118
- default:
119
- abort();
120
- }
121
+ val = ldn_p(buf, l);
122
+ result |= memory_region_dispatch_write(mr, addr1, val, l, attrs);
123
} else {
124
/* RAM case */
125
ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
126
@@ -XXX,XX +XXX,XX @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
127
/* I/O case */
128
release_lock |= prepare_mmio_access(mr);
129
l = memory_access_size(mr, l, addr1);
130
- switch (l) {
131
- case 8:
132
- /* 64 bit read access */
133
- result |= memory_region_dispatch_read(mr, addr1, &val, 8,
134
- attrs);
135
- stq_p(buf, val);
136
- break;
137
- case 4:
138
- /* 32 bit read access */
139
- result |= memory_region_dispatch_read(mr, addr1, &val, 4,
140
- attrs);
141
- stl_p(buf, val);
142
- break;
143
- case 2:
144
- /* 16 bit read access */
145
- result |= memory_region_dispatch_read(mr, addr1, &val, 2,
146
- attrs);
147
- stw_p(buf, val);
148
- break;
149
- case 1:
150
- /* 8 bit read access */
151
- result |= memory_region_dispatch_read(mr, addr1, &val, 1,
152
- attrs);
153
- stb_p(buf, val);
154
- break;
155
- default:
156
- abort();
157
- }
158
+ result |= memory_region_dispatch_read(mr, addr1, &val, l, attrs);
159
+ stn_p(buf, l, val);
160
} else {
161
/* RAM case */
162
ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
163
--
50
--
164
2.17.1
51
2.34.1
165
166
diff view generated by jsdifflib
1
Add an IOMMU index argument to the translate method of
1
Set the default NaN pattern explicitly for loongarch.
2
IOMMUs. Since all of our current IOMMU implementations
3
support only a single IOMMU index, this has no effect
4
on the behaviour.
5
2
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Message-id: 20241202131347.498124-42-peter.maydell@linaro.org
9
Message-id: 20180604152941.20374-4-peter.maydell@linaro.org
10
---
6
---
11
include/exec/memory.h | 3 ++-
7
target/loongarch/tcg/fpu_helper.c | 2 ++
12
exec.c | 11 +++++++++--
8
1 file changed, 2 insertions(+)
13
hw/alpha/typhoon.c | 3 ++-
14
hw/arm/smmuv3.c | 2 +-
15
hw/dma/rc4030.c | 2 +-
16
hw/i386/amd_iommu.c | 2 +-
17
hw/i386/intel_iommu.c | 2 +-
18
hw/ppc/spapr_iommu.c | 3 ++-
19
hw/s390x/s390-pci-bus.c | 2 +-
20
hw/sparc/sun4m_iommu.c | 3 ++-
21
hw/sparc64/sun4u_iommu.c | 2 +-
22
memory.c | 2 +-
23
12 files changed, 24 insertions(+), 13 deletions(-)
24
9
25
diff --git a/include/exec/memory.h b/include/exec/memory.h
10
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
26
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
27
--- a/include/exec/memory.h
12
--- a/target/loongarch/tcg/fpu_helper.c
28
+++ b/include/exec/memory.h
13
+++ b/target/loongarch/tcg/fpu_helper.c
29
@@ -XXX,XX +XXX,XX @@ typedef struct IOMMUMemoryRegionClass {
14
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
30
* @iommu: the IOMMUMemoryRegion
31
* @hwaddr: address to be translated within the memory region
32
* @flag: requested access permissions
33
+ * @iommu_idx: IOMMU index for the translation
34
*/
15
*/
35
IOMMUTLBEntry (*translate)(IOMMUMemoryRegion *iommu, hwaddr addr,
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
36
- IOMMUAccessFlags flag);
17
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
37
+ IOMMUAccessFlags flag, int iommu_idx);
18
+ /* Default NaN: sign bit clear, msb frac bit set */
38
/* Returns minimum supported page size in bytes.
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
39
* If this method is not provided then the minimum is assumed to
40
* be TARGET_PAGE_SIZE.
41
diff --git a/exec.c b/exec.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/exec.c
44
+++ b/exec.c
45
@@ -XXX,XX +XXX,XX @@ static MemoryRegionSection address_space_translate_iommu(IOMMUMemoryRegion *iomm
46
do {
47
hwaddr addr = *xlat;
48
IOMMUMemoryRegionClass *imrc = memory_region_get_iommu_class_nocheck(iommu_mr);
49
- IOMMUTLBEntry iotlb = imrc->translate(iommu_mr, addr, is_write ?
50
- IOMMU_WO : IOMMU_RO);
51
+ int iommu_idx = 0;
52
+ IOMMUTLBEntry iotlb;
53
+
54
+ if (imrc->attrs_to_index) {
55
+ iommu_idx = imrc->attrs_to_index(iommu_mr, attrs);
56
+ }
57
+
58
+ iotlb = imrc->translate(iommu_mr, addr, is_write ?
59
+ IOMMU_WO : IOMMU_RO, iommu_idx);
60
61
if (!(iotlb.perm & (1 << is_write))) {
62
goto unassigned;
63
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/alpha/typhoon.c
66
+++ b/hw/alpha/typhoon.c
67
@@ -XXX,XX +XXX,XX @@ static bool window_translate(TyphoonWindow *win, hwaddr addr,
68
Pchip and generate a machine check interrupt. */
69
static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu,
70
hwaddr addr,
71
- IOMMUAccessFlags flag)
72
+ IOMMUAccessFlags flag,
73
+ int iommu_idx)
74
{
75
TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
76
IOMMUTLBEntry ret;
77
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/arm/smmuv3.c
80
+++ b/hw/arm/smmuv3.c
81
@@ -XXX,XX +XXX,XX @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg,
82
}
20
}
83
21
84
static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
22
int ieee_ex_to_loongarch(int xcpt)
85
- IOMMUAccessFlags flag)
86
+ IOMMUAccessFlags flag, int iommu_idx)
87
{
88
SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
89
SMMUv3State *s = sdev->smmu;
90
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/hw/dma/rc4030.c
93
+++ b/hw/dma/rc4030.c
94
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps jazzio_ops = {
95
};
96
97
static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
98
- IOMMUAccessFlags flag)
99
+ IOMMUAccessFlags flag, int iommu_idx)
100
{
101
rc4030State *s = container_of(iommu, rc4030State, dma_mr);
102
IOMMUTLBEntry ret = {
103
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/hw/i386/amd_iommu.c
106
+++ b/hw/i386/amd_iommu.c
107
@@ -XXX,XX +XXX,XX @@ static inline bool amdvi_is_interrupt_addr(hwaddr addr)
108
}
109
110
static IOMMUTLBEntry amdvi_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
111
- IOMMUAccessFlags flag)
112
+ IOMMUAccessFlags flag, int iommu_idx)
113
{
114
AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu);
115
AMDVIState *s = as->iommu_state;
116
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/hw/i386/intel_iommu.c
119
+++ b/hw/i386/intel_iommu.c
120
@@ -XXX,XX +XXX,XX @@ static void vtd_mem_write(void *opaque, hwaddr addr,
121
}
122
123
static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
124
- IOMMUAccessFlags flag)
125
+ IOMMUAccessFlags flag, int iommu_idx)
126
{
127
VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
128
IntelIOMMUState *s = vtd_as->iommu_state;
129
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/ppc/spapr_iommu.c
132
+++ b/hw/ppc/spapr_iommu.c
133
@@ -XXX,XX +XXX,XX @@ static void spapr_tce_free_table(uint64_t *table, int fd, uint32_t nb_table)
134
/* Called from RCU critical section */
135
static IOMMUTLBEntry spapr_tce_translate_iommu(IOMMUMemoryRegion *iommu,
136
hwaddr addr,
137
- IOMMUAccessFlags flag)
138
+ IOMMUAccessFlags flag,
139
+ int iommu_idx)
140
{
141
sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
142
uint64_t tce;
143
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/hw/s390x/s390-pci-bus.c
146
+++ b/hw/s390x/s390-pci-bus.c
147
@@ -XXX,XX +XXX,XX @@ uint16_t s390_guest_io_table_walk(uint64_t g_iota, hwaddr addr,
148
}
149
150
static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr,
151
- IOMMUAccessFlags flag)
152
+ IOMMUAccessFlags flag, int iommu_idx)
153
{
154
S390PCIIOMMU *iommu = container_of(mr, S390PCIIOMMU, iommu_mr);
155
S390IOTLBEntry *entry;
156
diff --git a/hw/sparc/sun4m_iommu.c b/hw/sparc/sun4m_iommu.c
157
index XXXXXXX..XXXXXXX 100644
158
--- a/hw/sparc/sun4m_iommu.c
159
+++ b/hw/sparc/sun4m_iommu.c
160
@@ -XXX,XX +XXX,XX @@ static void iommu_bad_addr(IOMMUState *s, hwaddr addr,
161
/* Called from RCU critical section */
162
static IOMMUTLBEntry sun4m_translate_iommu(IOMMUMemoryRegion *iommu,
163
hwaddr addr,
164
- IOMMUAccessFlags flags)
165
+ IOMMUAccessFlags flags,
166
+ int iommu_idx)
167
{
168
IOMMUState *is = container_of(iommu, IOMMUState, iommu);
169
hwaddr page, pa;
170
diff --git a/hw/sparc64/sun4u_iommu.c b/hw/sparc64/sun4u_iommu.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/hw/sparc64/sun4u_iommu.c
173
+++ b/hw/sparc64/sun4u_iommu.c
174
@@ -XXX,XX +XXX,XX @@
175
/* Called from RCU critical section */
176
static IOMMUTLBEntry sun4u_translate_iommu(IOMMUMemoryRegion *iommu,
177
hwaddr addr,
178
- IOMMUAccessFlags flag)
179
+ IOMMUAccessFlags flag, int iommu_idx)
180
{
181
IOMMUState *is = container_of(iommu, IOMMUState, iommu);
182
hwaddr baseaddr, offset;
183
diff --git a/memory.c b/memory.c
184
index XXXXXXX..XXXXXXX 100644
185
--- a/memory.c
186
+++ b/memory.c
187
@@ -XXX,XX +XXX,XX @@ void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
188
granularity = memory_region_iommu_get_min_page_size(iommu_mr);
189
190
for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
191
- iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE);
192
+ iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE, n->iommu_idx);
193
if (iotlb.perm != IOMMU_NONE) {
194
n->notify(n, &iotlb);
195
}
196
--
23
--
197
2.17.1
24
2.34.1
198
199
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
1
Convert the wdt_i6300esb device away from using the old_mmio field
1
Set the default NaN pattern explicitly for MIPS. Note that this
2
of MemoryRegionOps.
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).
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180601141223.26630-5-peter.maydell@linaro.org
8
Message-id: 20241202131347.498124-44-peter.maydell@linaro.org
7
---
9
---
8
hw/watchdog/wdt_i6300esb.c | 48 ++++++++++++++++++++++++++++----------
10
target/mips/fpu_helper.h | 7 +++++++
9
1 file changed, 36 insertions(+), 12 deletions(-)
11
target/mips/msa.c | 3 +++
12
2 files changed, 10 insertions(+)
10
13
11
diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c
14
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/watchdog/wdt_i6300esb.c
16
--- a/target/mips/fpu_helper.h
14
+++ b/hw/watchdog/wdt_i6300esb.c
17
+++ b/target/mips/fpu_helper.h
15
@@ -XXX,XX +XXX,XX @@ static void i6300esb_mem_writel(void *vp, hwaddr addr, uint32_t val)
18
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
16
}
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
17
}
30
}
18
31
19
+static uint64_t i6300esb_mem_readfn(void *opaque, hwaddr addr, unsigned size)
32
diff --git a/target/mips/msa.c b/target/mips/msa.c
20
+{
33
index XXXXXXX..XXXXXXX 100644
21
+ switch (size) {
34
--- a/target/mips/msa.c
22
+ case 1:
35
+++ b/target/mips/msa.c
23
+ return i6300esb_mem_readb(opaque, addr);
36
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
24
+ case 2:
37
/* Inf * 0 + NaN returns the input NaN */
25
+ return i6300esb_mem_readw(opaque, addr);
38
set_float_infzeronan_rule(float_infzeronan_dnan_never,
26
+ case 4:
39
&env->active_tc.msa_fp_status);
27
+ return i6300esb_mem_readl(opaque, addr);
40
+ /* Default NaN: sign bit clear, frac msb set */
28
+ default:
41
+ set_float_default_nan_pattern(0b01000000,
29
+ g_assert_not_reached();
42
+ &env->active_tc.msa_fp_status);
30
+ }
43
}
31
+}
32
+
33
+static void i6300esb_mem_writefn(void *opaque, hwaddr addr,
34
+ uint64_t value, unsigned size)
35
+{
36
+ switch (size) {
37
+ case 1:
38
+ i6300esb_mem_writeb(opaque, addr, value);
39
+ break;
40
+ case 2:
41
+ i6300esb_mem_writew(opaque, addr, value);
42
+ break;
43
+ case 4:
44
+ i6300esb_mem_writel(opaque, addr, value);
45
+ break;
46
+ default:
47
+ g_assert_not_reached();
48
+ }
49
+}
50
+
51
static const MemoryRegionOps i6300esb_ops = {
52
- .old_mmio = {
53
- .read = {
54
- i6300esb_mem_readb,
55
- i6300esb_mem_readw,
56
- i6300esb_mem_readl,
57
- },
58
- .write = {
59
- i6300esb_mem_writeb,
60
- i6300esb_mem_writew,
61
- i6300esb_mem_writel,
62
- },
63
- },
64
+ .read = i6300esb_mem_readfn,
65
+ .write = i6300esb_mem_writefn,
66
+ .valid.min_access_size = 1,
67
+ .valid.max_access_size = 4,
68
.endianness = DEVICE_LITTLE_ENDIAN,
69
};
70
71
--
44
--
72
2.17.1
45
2.34.1
73
74
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
The 'addr' field in the CPUIOTLBEntry struct has a rather non-obvious
1
Set the default NaN pattern explicitly for ppc.
2
use; add a comment documenting it (reverse-engineered from what
3
the code that sets it is doing).
4
2
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180611125633.32755-2-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-46-peter.maydell@linaro.org
9
---
6
---
10
include/exec/cpu-defs.h | 9 +++++++++
7
target/ppc/cpu_init.c | 4 ++++
11
accel/tcg/cputlb.c | 12 ++++++++++++
8
1 file changed, 4 insertions(+)
12
2 files changed, 21 insertions(+)
13
9
14
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
10
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
15
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/cpu-defs.h
12
--- a/target/ppc/cpu_init.c
17
+++ b/include/exec/cpu-defs.h
13
+++ b/target/ppc/cpu_init.c
18
@@ -XXX,XX +XXX,XX @@ QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
14
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
19
* structs into one.)
15
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
*/
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
21
typedef struct CPUIOTLBEntry {
17
22
+ /*
18
+ /* Default NaN: sign bit clear, set frac msb */
23
+ * @addr contains:
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
24
+ * - in the lower TARGET_PAGE_BITS, a physical section number
20
+ set_float_default_nan_pattern(0b01000000, &env->vec_status);
25
+ * - with the lower TARGET_PAGE_BITS masked off, an offset which
21
+
26
+ * must be added to the virtual address to obtain:
22
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
27
+ * + the ram_addr_t of the target RAM (if the physical section
23
ppc_spr_t *spr = &env->spr_cb[i];
28
+ * number is PHYS_SECTION_NOTDIRTY or PHYS_SECTION_ROM)
29
+ * + the offset within the target MemoryRegion (otherwise)
30
+ */
31
hwaddr addr;
32
MemTxAttrs attrs;
33
} CPUIOTLBEntry;
34
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/accel/tcg/cputlb.c
37
+++ b/accel/tcg/cputlb.c
38
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
39
env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index];
40
41
/* refill the tlb */
42
+ /*
43
+ * At this point iotlb contains a physical section number in the lower
44
+ * TARGET_PAGE_BITS, and either
45
+ * + the ram_addr_t of the page base of the target RAM (if NOTDIRTY or ROM)
46
+ * + the offset within section->mr of the page base (otherwise)
47
+ * We subtract the vaddr (which is page aligned and thus won't
48
+ * disturb the low bits) to give an offset which can be added to the
49
+ * (non-page-aligned) vaddr of the eventual memory access to get
50
+ * the MemoryRegion offset for the access. Note that the vaddr we
51
+ * subtract here is that of the page base, and not the same as the
52
+ * vaddr we add back in io_readx()/io_writex()/get_page_addr_code().
53
+ */
54
env->iotlb[mmu_idx][index].addr = iotlb - vaddr;
55
env->iotlb[mmu_idx][index].attrs = attrs;
56
24
57
--
25
--
58
2.17.1
26
2.34.1
59
60
diff view generated by jsdifflib
1
Convert the sh7750 device away from using the old_mmio field
1
Set the default NaN pattern explicitly for sh4. Note that sh4
2
of MemoryRegionOps. This device is used by the sh4 r2d board.
2
is one of the only three targets (the others being HPPA and
3
sometimes MIPS) that has snan_bit_is_one set.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180601141223.26630-2-peter.maydell@linaro.org
7
Message-id: 20241202131347.498124-47-peter.maydell@linaro.org
7
---
8
---
8
hw/sh4/sh7750.c | 44 ++++++++++++++++++++++++++++++++++++--------
9
target/sh4/cpu.c | 2 ++
9
1 file changed, 36 insertions(+), 8 deletions(-)
10
1 file changed, 2 insertions(+)
10
11
11
diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c
12
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
12
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/sh4/sh7750.c
14
--- a/target/sh4/cpu.c
14
+++ b/hw/sh4/sh7750.c
15
+++ b/target/sh4/cpu.c
15
@@ -XXX,XX +XXX,XX @@ static void sh7750_mem_writel(void *opaque, hwaddr addr,
16
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
16
}
17
set_flush_to_zero(1, &env->fp_status);
18
#endif
19
set_default_nan_mode(1, &env->fp_status);
20
+ /* sign bit clear, set all frac bits other than msb */
21
+ set_float_default_nan_pattern(0b00111111, &env->fp_status);
17
}
22
}
18
23
19
+static uint64_t sh7750_mem_readfn(void *opaque, hwaddr addr, unsigned size)
24
static void superh_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
20
+{
21
+ switch (size) {
22
+ case 1:
23
+ return sh7750_mem_readb(opaque, addr);
24
+ case 2:
25
+ return sh7750_mem_readw(opaque, addr);
26
+ case 4:
27
+ return sh7750_mem_readl(opaque, addr);
28
+ default:
29
+ g_assert_not_reached();
30
+ }
31
+}
32
+
33
+static void sh7750_mem_writefn(void *opaque, hwaddr addr,
34
+ uint64_t value, unsigned size)
35
+{
36
+ switch (size) {
37
+ case 1:
38
+ sh7750_mem_writeb(opaque, addr, value);
39
+ break;
40
+ case 2:
41
+ sh7750_mem_writew(opaque, addr, value);
42
+ break;
43
+ case 4:
44
+ sh7750_mem_writel(opaque, addr, value);
45
+ break;
46
+ default:
47
+ g_assert_not_reached();
48
+ }
49
+}
50
+
51
static const MemoryRegionOps sh7750_mem_ops = {
52
- .old_mmio = {
53
- .read = {sh7750_mem_readb,
54
- sh7750_mem_readw,
55
- sh7750_mem_readl },
56
- .write = {sh7750_mem_writeb,
57
- sh7750_mem_writew,
58
- sh7750_mem_writel },
59
- },
60
+ .read = sh7750_mem_readfn,
61
+ .write = sh7750_mem_writefn,
62
+ .valid.min_access_size = 1,
63
+ .valid.max_access_size = 4,
64
.endianness = DEVICE_NATIVE_ENDIAN,
65
};
66
67
--
25
--
68
2.17.1
26
2.34.1
69
70
diff view generated by jsdifflib
1
There's a common pattern in QEMU where a function needs to perform
1
Set the default NaN pattern explicitly for rx.
2
a data load or store of an N byte integer in a particular endianness.
3
At the moment this is handled by doing a switch() on the size and
4
calling the appropriate ld*_p or st*_p function for each size.
5
6
Provide a new family of functions ldn_*_p() and stn_*_p() which
7
take the size as an argument and do the switch() themselves.
8
2
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20180611171007.4165-2-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-48-peter.maydell@linaro.org
13
---
6
---
14
include/exec/cpu-all.h | 4 +++
7
target/rx/cpu.c | 2 ++
15
include/qemu/bswap.h | 52 +++++++++++++++++++++++++++++++++++++
8
1 file changed, 2 insertions(+)
16
docs/devel/loads-stores.rst | 15 +++++++++++
17
3 files changed, 71 insertions(+)
18
9
19
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
10
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
20
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
21
--- a/include/exec/cpu-all.h
12
--- a/target/rx/cpu.c
22
+++ b/include/exec/cpu-all.h
13
+++ b/target/rx/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static inline void tswap64s(uint64_t *s)
14
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_reset_hold(Object *obj, ResetType type)
24
#define stq_p(p, v) stq_be_p(p, v)
15
* then prefer dest over source", which is float_2nan_prop_s_ab.
25
#define stfl_p(p, v) stfl_be_p(p, v)
16
*/
26
#define stfq_p(p, v) stfq_be_p(p, v)
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
27
+#define ldn_p(p, sz) ldn_be_p(p, sz)
18
+ /* Default NaN value: sign bit clear, set frac msb */
28
+#define stn_p(p, sz, v) stn_be_p(p, sz, v)
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
29
#else
30
#define lduw_p(p) lduw_le_p(p)
31
#define ldsw_p(p) ldsw_le_p(p)
32
@@ -XXX,XX +XXX,XX @@ static inline void tswap64s(uint64_t *s)
33
#define stq_p(p, v) stq_le_p(p, v)
34
#define stfl_p(p, v) stfl_le_p(p, v)
35
#define stfq_p(p, v) stfq_le_p(p, v)
36
+#define ldn_p(p, sz) ldn_le_p(p, sz)
37
+#define stn_p(p, sz, v) stn_le_p(p, sz, v)
38
#endif
39
40
/* MMU memory access macros */
41
diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/include/qemu/bswap.h
44
+++ b/include/qemu/bswap.h
45
@@ -XXX,XX +XXX,XX @@ typedef union {
46
* For accessors that take a guest address rather than a
47
* host address, see the cpu_{ld,st}_* accessors defined in
48
* cpu_ldst.h.
49
+ *
50
+ * For cases where the size to be used is not fixed at compile time,
51
+ * there are
52
+ * stn{endian}_p(ptr, sz, val)
53
+ * which stores @val to @ptr as an @endian-order number @sz bytes in size
54
+ * and
55
+ * ldn{endian}_p(ptr, sz)
56
+ * which loads @sz bytes from @ptr as an unsigned @endian-order number
57
+ * and returns it in a uint64_t.
58
*/
59
60
static inline int ldub_p(const void *ptr)
61
@@ -XXX,XX +XXX,XX @@ static inline unsigned long leul_to_cpu(unsigned long v)
62
#endif
63
}
20
}
64
21
65
+/* Store v to p as a sz byte value in host order */
22
static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
66
+#define DO_STN_LDN_P(END) \
67
+ static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v) \
68
+ { \
69
+ switch (sz) { \
70
+ case 1: \
71
+ stb_p(ptr, v); \
72
+ break; \
73
+ case 2: \
74
+ stw_ ## END ## _p(ptr, v); \
75
+ break; \
76
+ case 4: \
77
+ stl_ ## END ## _p(ptr, v); \
78
+ break; \
79
+ case 8: \
80
+ stq_ ## END ## _p(ptr, v); \
81
+ break; \
82
+ default: \
83
+ g_assert_not_reached(); \
84
+ } \
85
+ } \
86
+ static inline uint64_t ldn_## END ## _p(const void *ptr, int sz) \
87
+ { \
88
+ switch (sz) { \
89
+ case 1: \
90
+ return ldub_p(ptr); \
91
+ case 2: \
92
+ return lduw_ ## END ## _p(ptr); \
93
+ case 4: \
94
+ return (uint32_t)ldl_ ## END ## _p(ptr); \
95
+ case 8: \
96
+ return ldq_ ## END ## _p(ptr); \
97
+ default: \
98
+ g_assert_not_reached(); \
99
+ } \
100
+ }
101
+
102
+DO_STN_LDN_P(he)
103
+DO_STN_LDN_P(le)
104
+DO_STN_LDN_P(be)
105
+
106
+#undef DO_STN_LDN_P
107
+
108
#undef le_bswap
109
#undef be_bswap
110
#undef le_bswaps
111
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
112
index XXXXXXX..XXXXXXX 100644
113
--- a/docs/devel/loads-stores.rst
114
+++ b/docs/devel/loads-stores.rst
115
@@ -XXX,XX +XXX,XX @@ The ``_{endian}`` infix is omitted for target-endian accesses.
116
The target endian accessors are only available to source
117
files which are built per-target.
118
119
+There are also functions which take the size as an argument:
120
+
121
+load: ``ldn{endian}_p(ptr, sz)``
122
+
123
+which performs an unsigned load of ``sz`` bytes from ``ptr``
124
+as an ``{endian}`` order value and returns it in a uint64_t.
125
+
126
+store: ``stn{endian}_p(ptr, sz, val)``
127
+
128
+which stores ``val`` to ``ptr`` as an ``{endian}`` order value
129
+of size ``sz`` bytes.
130
+
131
+
132
Regexes for git grep
133
- ``\<ldf\?[us]\?[bwlq]\(_[hbl]e\)\?_p\>``
134
- ``\<stf\?[bwlq]\(_[hbl]e\)\?_p\>``
135
+ - ``\<ldn_\([hbl]e\)?_p\>``
136
+ - ``\<stn_\([hbl]e\)?_p\>``
137
138
``cpu_{ld,st}_*``
139
~~~~~~~~~~~~~~~~~
140
--
23
--
141
2.17.1
24
2.34.1
142
143
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for s390x.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-49-peter.maydell@linaro.org
6
---
7
target/s390x/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/s390x/cpu.c
13
+++ b/target/s390x/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
15
set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
16
set_float_infzeronan_rule(float_infzeronan_dnan_always,
17
&env->fpu_status);
18
+ /* Default NaN value: sign bit clear, frac msb set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fpu_status);
20
/* fall through */
21
case RESET_TYPE_S390_CPU_NORMAL:
22
env->psw.mask &= ~PSW_MASK_RI;
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for SPARC, and remove
2
the ifdef from parts64_default_nan.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-50-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 5 +----
10
2 files changed, 3 insertions(+), 4 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
18
/* For inf * 0 + NaN, return the input NaN */
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ /* Default NaN value: sign bit clear, all frac bits set */
21
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
22
23
cpu_exec_realizefn(cs, &local_err);
24
if (local_err != NULL) {
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
30
uint8_t dnan_pattern = status->default_nan_pattern;
31
32
if (dnan_pattern == 0) {
33
-#if defined(TARGET_SPARC)
34
- /* Sign bit clear, all frac bits set */
35
- dnan_pattern = 0b01111111;
36
-#elif defined(TARGET_HEXAGON)
37
+#if defined(TARGET_HEXAGON)
38
/* Sign bit set, all frac bits set. */
39
dnan_pattern = 0b11111111;
40
#else
41
--
42
2.34.1
diff view generated by jsdifflib
1
The API for cpu_transaction_failed() says that it takes the physical
1
Set the default NaN pattern explicitly for xtensa.
2
address for the failed transaction. However we were actually passing
3
it the offset within the target MemoryRegion. We don't currently
4
have any target CPU implementations of this hook that require the
5
physical address; fix this bug so we don't get confused if we ever
6
do add one.
7
2
8
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20180611125633.32755-3-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-51-peter.maydell@linaro.org
13
---
6
---
14
include/exec/exec-all.h | 13 ++++++++++--
7
target/xtensa/cpu.c | 2 ++
15
accel/tcg/cputlb.c | 44 +++++++++++++++++++++++++++++------------
8
1 file changed, 2 insertions(+)
16
exec.c | 5 +++--
17
3 files changed, 45 insertions(+), 17 deletions(-)
18
9
19
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
10
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
20
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
21
--- a/include/exec/exec-all.h
12
--- a/target/xtensa/cpu.c
22
+++ b/include/exec/exec-all.h
13
+++ b/target/xtensa/cpu.c
23
@@ -XXX,XX +XXX,XX @@ void tb_lock_reset(void);
14
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
24
15
/* For inf * 0 + NaN, return the input NaN */
25
#if !defined(CONFIG_USER_ONLY)
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
17
set_no_signaling_nans(!dfpu, &env->fp_status);
27
-struct MemoryRegion *iotlb_to_region(CPUState *cpu,
18
+ /* Default NaN value: sign bit clear, set frac msb */
28
- hwaddr index, MemTxAttrs attrs);
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
29
+/**
20
xtensa_use_first_nan(env, !dfpu);
30
+ * iotlb_to_section:
31
+ * @cpu: CPU performing the access
32
+ * @index: TCG CPU IOTLB entry
33
+ *
34
+ * Given a TCG CPU IOTLB entry, return the MemoryRegionSection that
35
+ * it refers to. @index will have been initially created and returned
36
+ * by memory_region_section_get_iotlb().
37
+ */
38
+struct MemoryRegionSection *iotlb_to_section(CPUState *cpu,
39
+ hwaddr index, MemTxAttrs attrs);
40
41
void tlb_fill(CPUState *cpu, target_ulong addr, int size,
42
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr);
43
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/accel/tcg/cputlb.c
46
+++ b/accel/tcg/cputlb.c
47
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
48
target_ulong addr, uintptr_t retaddr, int size)
49
{
50
CPUState *cpu = ENV_GET_CPU(env);
51
- hwaddr physaddr = iotlbentry->addr;
52
- MemoryRegion *mr = iotlb_to_region(cpu, physaddr, iotlbentry->attrs);
53
+ hwaddr mr_offset;
54
+ MemoryRegionSection *section;
55
+ MemoryRegion *mr;
56
uint64_t val;
57
bool locked = false;
58
MemTxResult r;
59
60
- physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
61
+ section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
62
+ mr = section->mr;
63
+ mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
64
cpu->mem_io_pc = retaddr;
65
if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) {
66
cpu_io_recompile(cpu, retaddr);
67
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
68
qemu_mutex_lock_iothread();
69
locked = true;
70
}
71
- r = memory_region_dispatch_read(mr, physaddr,
72
+ r = memory_region_dispatch_read(mr, mr_offset,
73
&val, size, iotlbentry->attrs);
74
if (r != MEMTX_OK) {
75
+ hwaddr physaddr = mr_offset +
76
+ section->offset_within_address_space -
77
+ section->offset_within_region;
78
+
79
cpu_transaction_failed(cpu, physaddr, addr, size, MMU_DATA_LOAD,
80
mmu_idx, iotlbentry->attrs, r, retaddr);
81
}
82
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
83
uintptr_t retaddr, int size)
84
{
85
CPUState *cpu = ENV_GET_CPU(env);
86
- hwaddr physaddr = iotlbentry->addr;
87
- MemoryRegion *mr = iotlb_to_region(cpu, physaddr, iotlbentry->attrs);
88
+ hwaddr mr_offset;
89
+ MemoryRegionSection *section;
90
+ MemoryRegion *mr;
91
bool locked = false;
92
MemTxResult r;
93
94
- physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
95
+ section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
96
+ mr = section->mr;
97
+ mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
98
if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) {
99
cpu_io_recompile(cpu, retaddr);
100
}
101
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
102
qemu_mutex_lock_iothread();
103
locked = true;
104
}
105
- r = memory_region_dispatch_write(mr, physaddr,
106
+ r = memory_region_dispatch_write(mr, mr_offset,
107
val, size, iotlbentry->attrs);
108
if (r != MEMTX_OK) {
109
+ hwaddr physaddr = mr_offset +
110
+ section->offset_within_address_space -
111
+ section->offset_within_region;
112
+
113
cpu_transaction_failed(cpu, physaddr, addr, size, MMU_DATA_STORE,
114
mmu_idx, iotlbentry->attrs, r, retaddr);
115
}
116
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
117
*/
118
tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
119
{
120
- int mmu_idx, index, pd;
121
+ int mmu_idx, index;
122
void *p;
123
MemoryRegion *mr;
124
+ MemoryRegionSection *section;
125
CPUState *cpu = ENV_GET_CPU(env);
126
CPUIOTLBEntry *iotlbentry;
127
- hwaddr physaddr;
128
+ hwaddr physaddr, mr_offset;
129
130
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
131
mmu_idx = cpu_mmu_index(env, true);
132
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
133
}
134
}
135
iotlbentry = &env->iotlb[mmu_idx][index];
136
- pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
137
- mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
138
+ section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
139
+ mr = section->mr;
140
if (memory_region_is_unassigned(mr)) {
141
qemu_mutex_lock_iothread();
142
if (memory_region_request_mmio_ptr(mr, addr)) {
143
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
144
* and use the MemTXResult it produced). However it is the
145
* simplest place we have currently available for the check.
146
*/
147
- physaddr = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
148
+ mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
149
+ physaddr = mr_offset +
150
+ section->offset_within_address_space -
151
+ section->offset_within_region;
152
cpu_transaction_failed(cpu, physaddr, addr, 0, MMU_INST_FETCH, mmu_idx,
153
iotlbentry->attrs, MEMTX_DECODE_ERROR, 0);
154
155
diff --git a/exec.c b/exec.c
156
index XXXXXXX..XXXXXXX 100644
157
--- a/exec.c
158
+++ b/exec.c
159
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps readonly_mem_ops = {
160
},
161
};
162
163
-MemoryRegion *iotlb_to_region(CPUState *cpu, hwaddr index, MemTxAttrs attrs)
164
+MemoryRegionSection *iotlb_to_section(CPUState *cpu,
165
+ hwaddr index, MemTxAttrs attrs)
166
{
167
int asidx = cpu_asidx_from_attrs(cpu, attrs);
168
CPUAddressSpace *cpuas = &cpu->cpu_ases[asidx];
169
AddressSpaceDispatch *d = atomic_rcu_read(&cpuas->memory_dispatch);
170
MemoryRegionSection *sections = d->map.sections;
171
172
- return sections[index & ~TARGET_PAGE_MASK].mr;
173
+ return &sections[index & ~TARGET_PAGE_MASK];
174
}
21
}
175
22
176
static void io_mem_init(void)
177
--
23
--
178
2.17.1
24
2.34.1
179
180
diff view generated by jsdifflib
1
Convert the mcf5206 device away from using the old_mmio field
1
Set the default NaN pattern explicitly for hexagon.
2
of MemoryRegionOps. This device is used by the an5206 board.
2
Remove the ifdef from parts64_default_nan(); the only
3
remaining unconverted targets all use the default case.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Acked-by: Thomas Huth <huth@tuxfamily.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180601141223.26630-3-peter.maydell@linaro.org
7
Message-id: 20241202131347.498124-52-peter.maydell@linaro.org
7
---
8
---
8
hw/m68k/mcf5206.c | 48 +++++++++++++++++++++++++++++++++++------------
9
target/hexagon/cpu.c | 2 ++
9
1 file changed, 36 insertions(+), 12 deletions(-)
10
fpu/softfloat-specialize.c.inc | 5 -----
11
2 files changed, 2 insertions(+), 5 deletions(-)
10
12
11
diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c
13
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/m68k/mcf5206.c
15
--- a/target/hexagon/cpu.c
14
+++ b/hw/m68k/mcf5206.c
16
+++ b/target/hexagon/cpu.c
15
@@ -XXX,XX +XXX,XX @@ static void m5206_mbar_writel(void *opaque, hwaddr offset,
17
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
16
m5206_mbar_write(s, offset, value, 4);
18
19
set_default_nan_mode(1, &env->fp_status);
20
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
21
+ /* Default NaN value: sign bit set, all frac bits set */
22
+ set_float_default_nan_pattern(0b11111111, &env->fp_status);
17
}
23
}
18
24
19
+static uint64_t m5206_mbar_readfn(void *opaque, hwaddr addr, unsigned size)
25
static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
20
+{
26
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
21
+ switch (size) {
27
index XXXXXXX..XXXXXXX 100644
22
+ case 1:
28
--- a/fpu/softfloat-specialize.c.inc
23
+ return m5206_mbar_readb(opaque, addr);
29
+++ b/fpu/softfloat-specialize.c.inc
24
+ case 2:
30
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
25
+ return m5206_mbar_readw(opaque, addr);
31
uint8_t dnan_pattern = status->default_nan_pattern;
26
+ case 4:
32
27
+ return m5206_mbar_readl(opaque, addr);
33
if (dnan_pattern == 0) {
28
+ default:
34
-#if defined(TARGET_HEXAGON)
29
+ g_assert_not_reached();
35
- /* Sign bit set, all frac bits set. */
30
+ }
36
- dnan_pattern = 0b11111111;
31
+}
37
-#else
32
+
38
/*
33
+static void m5206_mbar_writefn(void *opaque, hwaddr addr,
39
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
34
+ uint64_t value, unsigned size)
40
* S390, SH4, TriCore, and Xtensa. Our other supported targets
35
+{
41
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
36
+ switch (size) {
42
/* sign bit clear, set frac msb */
37
+ case 1:
43
dnan_pattern = 0b01000000;
38
+ m5206_mbar_writeb(opaque, addr, value);
44
}
39
+ break;
45
-#endif
40
+ case 2:
46
}
41
+ m5206_mbar_writew(opaque, addr, value);
47
assert(dnan_pattern != 0);
42
+ break;
43
+ case 4:
44
+ m5206_mbar_writel(opaque, addr, value);
45
+ break;
46
+ default:
47
+ g_assert_not_reached();
48
+ }
49
+}
50
+
51
static const MemoryRegionOps m5206_mbar_ops = {
52
- .old_mmio = {
53
- .read = {
54
- m5206_mbar_readb,
55
- m5206_mbar_readw,
56
- m5206_mbar_readl,
57
- },
58
- .write = {
59
- m5206_mbar_writeb,
60
- m5206_mbar_writew,
61
- m5206_mbar_writel,
62
- },
63
- },
64
+ .read = m5206_mbar_readfn,
65
+ .write = m5206_mbar_writefn,
66
+ .valid.min_access_size = 1,
67
+ .valid.max_access_size = 4,
68
.endianness = DEVICE_NATIVE_ENDIAN,
69
};
70
48
71
--
49
--
72
2.17.1
50
2.34.1
73
74
diff view generated by jsdifflib
1
In subpage_read() we perform a load of the data into a local buffer
1
Set the default NaN pattern explicitly for riscv.
2
which we then access using ldub_p(), lduw_p(), ldl_p() or ldq_p()
3
depending on its size, storing the result into the uint64_t *data.
4
Since ldl_p() returns an 'int', this means that for the 4-byte
5
case we will sign-extend the data, whereas for 1 and 2 byte
6
reads we zero-extend it.
7
8
This ought not to matter since the caller will likely ignore values in
9
the high bytes of the data, but add a cast so that we're consistent.
10
2
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20180611171007.4165-3-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-53-peter.maydell@linaro.org
14
---
6
---
15
exec.c | 2 +-
7
target/riscv/cpu.c | 2 ++
16
1 file changed, 1 insertion(+), 1 deletion(-)
8
1 file changed, 2 insertions(+)
17
9
18
diff --git a/exec.c b/exec.c
10
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
19
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
20
--- a/exec.c
12
--- a/target/riscv/cpu.c
21
+++ b/exec.c
13
+++ b/target/riscv/cpu.c
22
@@ -XXX,XX +XXX,XX @@ static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
14
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
23
*data = lduw_p(buf);
15
cs->exception_index = RISCV_EXCP_NONE;
24
return MEMTX_OK;
16
env->load_res = -1;
25
case 4:
17
set_default_nan_mode(1, &env->fp_status);
26
- *data = ldl_p(buf);
18
+ /* Default NaN value: sign bit clear, frac msb set */
27
+ *data = (uint32_t)ldl_p(buf);
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
28
return MEMTX_OK;
20
env->vill = true;
29
case 8:
21
30
*data = ldq_p(buf);
22
#ifndef CONFIG_USER_ONLY
31
--
23
--
32
2.17.1
24
2.34.1
33
34
diff view generated by jsdifflib
1
For the IoTKit MPC support, we need to wire together the
1
Set the default NaN pattern explicitly for tricore.
2
interrupt outputs of 17 MPCs; this exceeds the current
3
value of MAX_OR_LINES. Increase MAX_OR_LINES to 32 (which
4
should be enough for anyone).
5
6
The tricky part is retaining the migration compatibility for
7
existing OR gates; we add a subsection which is only used
8
for larger OR gates, and define it such that we can freely
9
increase MAX_OR_LINES in future (or even move to a dynamically
10
allocated levels[] array without an upper size limit) without
11
breaking compatibility.
12
2
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20180604152941.20374-10-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-54-peter.maydell@linaro.org
16
---
6
---
17
include/hw/or-irq.h | 5 ++++-
7
target/tricore/helper.c | 2 ++
18
hw/core/or-irq.c | 39 +++++++++++++++++++++++++++++++++++++--
8
1 file changed, 2 insertions(+)
19
2 files changed, 41 insertions(+), 3 deletions(-)
20
9
21
diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h
10
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
22
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/or-irq.h
12
--- a/target/tricore/helper.c
24
+++ b/include/hw/or-irq.h
13
+++ b/target/tricore/helper.c
25
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ void fpu_set_state(CPUTriCoreState *env)
26
15
set_flush_to_zero(1, &env->fp_status);
27
#define TYPE_OR_IRQ "or-irq"
16
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
28
17
set_default_nan_mode(1, &env->fp_status);
29
-#define MAX_OR_LINES 16
18
+ /* Default NaN pattern: sign bit clear, frac msb set */
30
+/* This can safely be increased if necessary without breaking
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
31
+ * migration compatibility (as long as it remains greater than 15).
32
+ */
33
+#define MAX_OR_LINES 32
34
35
typedef struct OrIRQState qemu_or_irq;
36
37
diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/core/or-irq.c
40
+++ b/hw/core/or-irq.c
41
@@ -XXX,XX +XXX,XX @@ static void or_irq_init(Object *obj)
42
qdev_init_gpio_out(DEVICE(obj), &s->out_irq, 1);
43
}
20
}
44
21
45
+/* The original version of this device had a fixed 16 entries in its
22
uint32_t psw_read(CPUTriCoreState *env)
46
+ * VMState array; devices with more inputs than this need to
47
+ * migrate the extra lines via a subsection.
48
+ * The subsection migrates as much of the levels[] array as is needed
49
+ * (including repeating the first 16 elements), to avoid the awkwardness
50
+ * of splitting it in two to meet the requirements of VMSTATE_VARRAY_UINT16.
51
+ */
52
+#define OLD_MAX_OR_LINES 16
53
+#if MAX_OR_LINES < OLD_MAX_OR_LINES
54
+#error MAX_OR_LINES must be at least 16 for migration compatibility
55
+#endif
56
+
57
+static bool vmstate_extras_needed(void *opaque)
58
+{
59
+ qemu_or_irq *s = OR_IRQ(opaque);
60
+
61
+ return s->num_lines >= OLD_MAX_OR_LINES;
62
+}
63
+
64
+static const VMStateDescription vmstate_or_irq_extras = {
65
+ .name = "or-irq-extras",
66
+ .version_id = 1,
67
+ .minimum_version_id = 1,
68
+ .needed = vmstate_extras_needed,
69
+ .fields = (VMStateField[]) {
70
+ VMSTATE_VARRAY_UINT16_UNSAFE(levels, qemu_or_irq, num_lines, 0,
71
+ vmstate_info_bool, bool),
72
+ VMSTATE_END_OF_LIST(),
73
+ },
74
+};
75
+
76
static const VMStateDescription vmstate_or_irq = {
77
.name = TYPE_OR_IRQ,
78
.version_id = 1,
79
.minimum_version_id = 1,
80
.fields = (VMStateField[]) {
81
- VMSTATE_BOOL_ARRAY(levels, qemu_or_irq, MAX_OR_LINES),
82
+ VMSTATE_BOOL_SUB_ARRAY(levels, qemu_or_irq, 0, OLD_MAX_OR_LINES),
83
VMSTATE_END_OF_LIST(),
84
- }
85
+ },
86
+ .subsections = (const VMStateDescription*[]) {
87
+ &vmstate_or_irq_extras,
88
+ NULL
89
+ },
90
};
91
92
static Property or_irq_properties[] = {
93
--
23
--
94
2.17.1
24
2.34.1
95
96
diff view generated by jsdifflib
1
The codebase has a bit of a mix of different multiline
1
Now that all our targets have bene converted to explicitly specify
2
comment styles. State a preference for the Linux kernel
2
their pattern for the default NaN value we can remove the remaining
3
style:
3
fallback code in parts64_default_nan().
4
/*
5
* Star on the left for each line.
6
* Leading slash-star and trailing star-slash
7
* each go on a line of their own.
8
*/
9
4
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
7
Message-id: 20241202131347.498124-55-peter.maydell@linaro.org
13
Reviewed-by: Markus Armbruster <armbru@redhat.com>
14
Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
15
Reviewed-by: Thomas Huth <thuth@redhat.com>
16
Reviewed-by: John Snow <jsnow@redhat.com>
17
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
18
Message-id: 20180611141716.3813-1-peter.maydell@linaro.org
19
---
8
---
20
CODING_STYLE | 17 +++++++++++++++++
9
fpu/softfloat-specialize.c.inc | 14 --------------
21
1 file changed, 17 insertions(+)
10
1 file changed, 14 deletions(-)
22
11
23
diff --git a/CODING_STYLE b/CODING_STYLE
12
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
24
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
25
--- a/CODING_STYLE
14
--- a/fpu/softfloat-specialize.c.inc
26
+++ b/CODING_STYLE
15
+++ b/fpu/softfloat-specialize.c.inc
27
@@ -XXX,XX +XXX,XX @@ We use traditional C-style /* */ comments and avoid // comments.
16
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
28
Rationale: The // form is valid in C99, so this is purely a matter of
17
uint64_t frac;
29
consistency of style. The checkpatch script will warn you about this.
18
uint8_t dnan_pattern = status->default_nan_pattern;
30
19
31
+Multiline comment blocks should have a row of stars on the left,
20
- if (dnan_pattern == 0) {
32
+and the initial /* and terminating */ both on their own lines:
21
- /*
33
+ /*
22
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
34
+ * like
23
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
35
+ * this
24
- * do not have floating-point.
36
+ */
25
- */
37
+This is the same format required by the Linux kernel coding style.
26
- if (snan_bit_is_one(status)) {
38
+
27
- /* sign bit clear, set all frac bits other than msb */
39
+(Some of the existing comments in the codebase use the GNU Coding
28
- dnan_pattern = 0b00111111;
40
+Standards form which does not have stars on the left, or other
29
- } else {
41
+variations; avoid these when writing new comments, but don't worry
30
- /* sign bit clear, set frac msb */
42
+about converting to the preferred form unless you're editing that
31
- dnan_pattern = 0b01000000;
43
+comment anyway.)
32
- }
44
+
33
- }
45
+Rationale: Consistency, and ease of visually picking out a multiline
34
assert(dnan_pattern != 0);
46
+comment from the surrounding code.
35
47
+
36
sign = dnan_pattern >> 7;
48
8. trace-events style
49
50
8.1 0x prefix
51
--
37
--
52
2.17.1
38
2.34.1
53
54
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Inline pickNaNMulAdd into its only caller. This makes
4
one assert redundant with the immediately preceding IF.
5
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180613015641.5667-9-richard.henderson@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-3-richard.henderson@linaro.org
9
[PMM: keep comment from old code in new location]
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
target/arm/helper-sve.h | 14 +++++++++++++
12
fpu/softfloat-parts.c.inc | 41 +++++++++++++++++++++++++-
9
target/arm/sve_helper.c | 41 +++++++++++++++++++++++++++++++-------
13
fpu/softfloat-specialize.c.inc | 54 ----------------------------------
10
target/arm/translate-sve.c | 38 +++++++++++++++++++++++++++++++++++
14
2 files changed, 40 insertions(+), 55 deletions(-)
11
target/arm/sve.decode | 7 +++++++
12
4 files changed, 93 insertions(+), 7 deletions(-)
13
15
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
18
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/helper-sve.h
19
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_compact_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
21
}
20
DEF_HELPER_FLAGS_2(sve_last_active_element, TCG_CALL_NO_RWG, s32, ptr, i32)
22
21
23
if (s->default_nan_mode) {
22
+DEF_HELPER_FLAGS_4(sve_revb_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+ /*
23
+DEF_HELPER_FLAGS_4(sve_revb_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+ * We guarantee not to require the target to tell us how to
24
+DEF_HELPER_FLAGS_4(sve_revb_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
+ * pick a NaN if we're always returning the default NaN.
27
+ * But if we're not in default-NaN mode then the target must
28
+ * specify.
29
+ */
30
which = 3;
31
+ } else if (infzero) {
32
+ /*
33
+ * Inf * 0 + NaN -- some implementations return the
34
+ * default NaN here, and some return the input NaN.
35
+ */
36
+ switch (s->float_infzeronan_rule) {
37
+ case float_infzeronan_dnan_never:
38
+ which = 2;
39
+ break;
40
+ case float_infzeronan_dnan_always:
41
+ which = 3;
42
+ break;
43
+ case float_infzeronan_dnan_if_qnan:
44
+ which = is_qnan(c->cls) ? 3 : 2;
45
+ break;
46
+ default:
47
+ g_assert_not_reached();
48
+ }
49
} else {
50
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
51
+ FloatClass cls[3] = { a->cls, b->cls, c->cls };
52
+ Float3NaNPropRule rule = s->float_3nan_prop_rule;
25
+
53
+
26
+DEF_HELPER_FLAGS_4(sve_revh_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
54
+ assert(rule != float_3nan_prop_none);
27
+DEF_HELPER_FLAGS_4(sve_revh_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
55
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
28
+
56
+ /* We have at least one SNaN input and should prefer it */
29
+DEF_HELPER_FLAGS_4(sve_revw_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
57
+ do {
30
+
58
+ which = rule & R_3NAN_1ST_MASK;
31
+DEF_HELPER_FLAGS_4(sve_rbit_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
59
+ rule >>= R_3NAN_1ST_LENGTH;
32
+DEF_HELPER_FLAGS_4(sve_rbit_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
60
+ } while (!is_snan(cls[which]));
33
+DEF_HELPER_FLAGS_4(sve_rbit_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
61
+ } else {
34
+DEF_HELPER_FLAGS_4(sve_rbit_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
62
+ do {
35
+
63
+ which = rule & R_3NAN_1ST_MASK;
36
DEF_HELPER_FLAGS_5(sve_and_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
64
+ rule >>= R_3NAN_1ST_LENGTH;
37
DEF_HELPER_FLAGS_5(sve_bic_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
65
+ } while (!is_nan(cls[which]));
38
DEF_HELPER_FLAGS_5(sve_eor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
66
+ }
39
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
67
}
68
69
if (which == 3) {
70
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
40
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/sve_helper.c
72
--- a/fpu/softfloat-specialize.c.inc
42
+++ b/target/arm/sve_helper.c
73
+++ b/fpu/softfloat-specialize.c.inc
43
@@ -XXX,XX +XXX,XX @@ static inline uint64_t expand_pred_s(uint8_t byte)
74
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
44
return word[byte & 0x11];
45
}
46
47
+/* Swap 16-bit words within a 32-bit word. */
48
+static inline uint32_t hswap32(uint32_t h)
49
+{
50
+ return rol32(h, 16);
51
+}
52
+
53
+/* Swap 16-bit words within a 64-bit word. */
54
+static inline uint64_t hswap64(uint64_t h)
55
+{
56
+ uint64_t m = 0x0000ffff0000ffffull;
57
+ h = rol64(h, 32);
58
+ return ((h & m) << 16) | ((h >> 16) & m);
59
+}
60
+
61
+/* Swap 32-bit words within a 64-bit word. */
62
+static inline uint64_t wswap64(uint64_t h)
63
+{
64
+ return rol64(h, 32);
65
+}
66
+
67
#define LOGICAL_PPPP(NAME, FUNC) \
68
void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \
69
{ \
70
@@ -XXX,XX +XXX,XX @@ DO_ZPZ(sve_neg_h, uint16_t, H1_2, DO_NEG)
71
DO_ZPZ(sve_neg_s, uint32_t, H1_4, DO_NEG)
72
DO_ZPZ_D(sve_neg_d, uint64_t, DO_NEG)
73
74
+DO_ZPZ(sve_revb_h, uint16_t, H1_2, bswap16)
75
+DO_ZPZ(sve_revb_s, uint32_t, H1_4, bswap32)
76
+DO_ZPZ_D(sve_revb_d, uint64_t, bswap64)
77
+
78
+DO_ZPZ(sve_revh_s, uint32_t, H1_4, hswap32)
79
+DO_ZPZ_D(sve_revh_d, uint64_t, hswap64)
80
+
81
+DO_ZPZ_D(sve_revw_d, uint64_t, wswap64)
82
+
83
+DO_ZPZ(sve_rbit_b, uint8_t, H1, revbit8)
84
+DO_ZPZ(sve_rbit_h, uint16_t, H1_2, revbit16)
85
+DO_ZPZ(sve_rbit_s, uint32_t, H1_4, revbit32)
86
+DO_ZPZ_D(sve_rbit_d, uint64_t, revbit64)
87
+
88
/* Three-operand expander, unpredicated, in which the third operand is "wide".
89
*/
90
#define DO_ZZW(NAME, TYPE, TYPEW, H, OP) \
91
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_rev_b)(void *vd, void *vn, uint32_t desc)
92
}
75
}
93
}
76
}
94
77
95
-static inline uint64_t hswap64(uint64_t h)
78
-/*----------------------------------------------------------------------------
79
-| Select which NaN to propagate for a three-input operation.
80
-| For the moment we assume that no CPU needs the 'larger significand'
81
-| information.
82
-| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
83
-*----------------------------------------------------------------------------*/
84
-static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
85
- bool infzero, bool have_snan, float_status *status)
96
-{
86
-{
97
- uint64_t m = 0x0000ffff0000ffffull;
87
- FloatClass cls[3] = { a_cls, b_cls, c_cls };
98
- h = rol64(h, 32);
88
- Float3NaNPropRule rule = status->float_3nan_prop_rule;
99
- return ((h & m) << 16) | ((h >> 16) & m);
89
- int which;
90
-
91
- /*
92
- * We guarantee not to require the target to tell us how to
93
- * pick a NaN if we're always returning the default NaN.
94
- * But if we're not in default-NaN mode then the target must
95
- * specify.
96
- */
97
- assert(!status->default_nan_mode);
98
-
99
- if (infzero) {
100
- /*
101
- * Inf * 0 + NaN -- some implementations return the default NaN here,
102
- * and some return the input NaN.
103
- */
104
- switch (status->float_infzeronan_rule) {
105
- case float_infzeronan_dnan_never:
106
- return 2;
107
- case float_infzeronan_dnan_always:
108
- return 3;
109
- case float_infzeronan_dnan_if_qnan:
110
- return is_qnan(c_cls) ? 3 : 2;
111
- default:
112
- g_assert_not_reached();
113
- }
114
- }
115
-
116
- assert(rule != float_3nan_prop_none);
117
- if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
118
- /* We have at least one SNaN input and should prefer it */
119
- do {
120
- which = rule & R_3NAN_1ST_MASK;
121
- rule >>= R_3NAN_1ST_LENGTH;
122
- } while (!is_snan(cls[which]));
123
- } else {
124
- do {
125
- which = rule & R_3NAN_1ST_MASK;
126
- rule >>= R_3NAN_1ST_LENGTH;
127
- } while (!is_nan(cls[which]));
128
- }
129
- return which;
100
-}
130
-}
101
-
131
-
102
void HELPER(sve_rev_h)(void *vd, void *vn, uint32_t desc)
132
/*----------------------------------------------------------------------------
103
{
133
| Returns 1 if the double-precision floating-point value `a' is a quiet
104
intptr_t i, j, opr_sz = simd_oprsz(desc);
134
| NaN; otherwise returns 0.
105
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/translate-sve.c
108
+++ b/target/arm/translate-sve.c
109
@@ -XXX,XX +XXX,XX @@ static bool trans_CPY_m_v(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
110
return true;
111
}
112
113
+static bool trans_REVB(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
114
+{
115
+ static gen_helper_gvec_3 * const fns[4] = {
116
+ NULL,
117
+ gen_helper_sve_revb_h,
118
+ gen_helper_sve_revb_s,
119
+ gen_helper_sve_revb_d,
120
+ };
121
+ return do_zpz_ool(s, a, fns[a->esz]);
122
+}
123
+
124
+static bool trans_REVH(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
125
+{
126
+ static gen_helper_gvec_3 * const fns[4] = {
127
+ NULL,
128
+ NULL,
129
+ gen_helper_sve_revh_s,
130
+ gen_helper_sve_revh_d,
131
+ };
132
+ return do_zpz_ool(s, a, fns[a->esz]);
133
+}
134
+
135
+static bool trans_REVW(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
136
+{
137
+ return do_zpz_ool(s, a, a->esz == 3 ? gen_helper_sve_revw_d : NULL);
138
+}
139
+
140
+static bool trans_RBIT(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
141
+{
142
+ static gen_helper_gvec_3 * const fns[4] = {
143
+ gen_helper_sve_rbit_b,
144
+ gen_helper_sve_rbit_h,
145
+ gen_helper_sve_rbit_s,
146
+ gen_helper_sve_rbit_d,
147
+ };
148
+ return do_zpz_ool(s, a, fns[a->esz]);
149
+}
150
+
151
/*
152
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
153
*/
154
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
155
index XXXXXXX..XXXXXXX 100644
156
--- a/target/arm/sve.decode
157
+++ b/target/arm/sve.decode
158
@@ -XXX,XX +XXX,XX @@ CPY_m_v 00000101 .. 100000 100 ... ..... ..... @rd_pg_rn
159
# SVE copy element from general register to vector (predicated)
160
CPY_m_r 00000101 .. 101000 101 ... ..... ..... @rd_pg_rn
161
162
+# SVE reverse within elements
163
+# Note esz >= operation size
164
+REVB 00000101 .. 1001 00 100 ... ..... ..... @rd_pg_rn
165
+REVH 00000101 .. 1001 01 100 ... ..... ..... @rd_pg_rn
166
+REVW 00000101 .. 1001 10 100 ... ..... ..... @rd_pg_rn
167
+RBIT 00000101 .. 1001 11 100 ... ..... ..... @rd_pg_rn
168
+
169
### SVE Predicate Logical Operations Group
170
171
# SVE predicate logical operations
172
--
135
--
173
2.17.1
136
2.34.1
174
137
175
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
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Remove "3" as a special case for which and simply
4
branch to return the desired value.
5
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180613015641.5667-11-richard.henderson@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-4-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 9 +++++++
11
fpu/softfloat-parts.c.inc | 20 ++++++++++----------
9
target/arm/sve_helper.c | 55 ++++++++++++++++++++++++++++++++++++++
12
1 file changed, 10 insertions(+), 10 deletions(-)
10
target/arm/translate-sve.c | 2 ++
11
target/arm/sve.decode | 6 +++++
12
4 files changed, 72 insertions(+)
13
13
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
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/target/arm/helper-sve.h
16
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/helper-sve.h
17
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_lsl_zpzz_s, TCG_CALL_NO_RWG,
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
DEF_HELPER_FLAGS_5(sve_lsl_zpzz_d, TCG_CALL_NO_RWG,
19
* But if we're not in default-NaN mode then the target must
20
void, ptr, ptr, ptr, ptr, i32)
20
* specify.
21
21
*/
22
+DEF_HELPER_FLAGS_5(sve_sel_zpzz_b, TCG_CALL_NO_RWG,
22
- which = 3;
23
+ void, ptr, ptr, ptr, ptr, i32)
23
+ goto default_nan;
24
+DEF_HELPER_FLAGS_5(sve_sel_zpzz_h, TCG_CALL_NO_RWG,
24
} else if (infzero) {
25
+ void, ptr, ptr, ptr, ptr, i32)
25
/*
26
+DEF_HELPER_FLAGS_5(sve_sel_zpzz_s, TCG_CALL_NO_RWG,
26
* Inf * 0 + NaN -- some implementations return the
27
+ void, ptr, ptr, ptr, ptr, i32)
27
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
28
+DEF_HELPER_FLAGS_5(sve_sel_zpzz_d, TCG_CALL_NO_RWG,
28
*/
29
+ void, ptr, ptr, ptr, ptr, i32)
29
switch (s->float_infzeronan_rule) {
30
case float_infzeronan_dnan_never:
31
- which = 2;
32
break;
33
case float_infzeronan_dnan_always:
34
- which = 3;
35
- break;
36
+ goto default_nan;
37
case float_infzeronan_dnan_if_qnan:
38
- which = is_qnan(c->cls) ? 3 : 2;
39
+ if (is_qnan(c->cls)) {
40
+ goto default_nan;
41
+ }
42
break;
43
default:
44
g_assert_not_reached();
45
}
46
+ which = 2;
47
} else {
48
FloatClass cls[3] = { a->cls, b->cls, c->cls };
49
Float3NaNPropRule rule = s->float_3nan_prop_rule;
50
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
51
}
52
}
53
54
- if (which == 3) {
55
- parts_default_nan(a, s);
56
- return a;
57
- }
58
-
59
switch (which) {
60
case 0:
61
break;
62
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
63
parts_silence_nan(a, s);
64
}
65
return a;
30
+
66
+
31
DEF_HELPER_FLAGS_5(sve_asr_zpzw_b, TCG_CALL_NO_RWG,
67
+ default_nan:
32
void, ptr, ptr, ptr, ptr, i32)
68
+ parts_default_nan(a, s);
33
DEF_HELPER_FLAGS_5(sve_asr_zpzw_h, TCG_CALL_NO_RWG,
69
+ return a;
34
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/sve_helper.c
37
+++ b/target/arm/sve_helper.c
38
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_splice)(void *vd, void *vn, void *vm, void *vg, uint32_t desc)
39
}
40
swap_memmove(vd + len, vm, opr_sz * 8 - len);
41
}
70
}
42
+
43
+void HELPER(sve_sel_zpzz_b)(void *vd, void *vn, void *vm,
44
+ void *vg, uint32_t desc)
45
+{
46
+ intptr_t i, opr_sz = simd_oprsz(desc) / 8;
47
+ uint64_t *d = vd, *n = vn, *m = vm;
48
+ uint8_t *pg = vg;
49
+
50
+ for (i = 0; i < opr_sz; i += 1) {
51
+ uint64_t nn = n[i], mm = m[i];
52
+ uint64_t pp = expand_pred_b(pg[H1(i)]);
53
+ d[i] = (nn & pp) | (mm & ~pp);
54
+ }
55
+}
56
+
57
+void HELPER(sve_sel_zpzz_h)(void *vd, void *vn, void *vm,
58
+ void *vg, uint32_t desc)
59
+{
60
+ intptr_t i, opr_sz = simd_oprsz(desc) / 8;
61
+ uint64_t *d = vd, *n = vn, *m = vm;
62
+ uint8_t *pg = vg;
63
+
64
+ for (i = 0; i < opr_sz; i += 1) {
65
+ uint64_t nn = n[i], mm = m[i];
66
+ uint64_t pp = expand_pred_h(pg[H1(i)]);
67
+ d[i] = (nn & pp) | (mm & ~pp);
68
+ }
69
+}
70
+
71
+void HELPER(sve_sel_zpzz_s)(void *vd, void *vn, void *vm,
72
+ void *vg, uint32_t desc)
73
+{
74
+ intptr_t i, opr_sz = simd_oprsz(desc) / 8;
75
+ uint64_t *d = vd, *n = vn, *m = vm;
76
+ uint8_t *pg = vg;
77
+
78
+ for (i = 0; i < opr_sz; i += 1) {
79
+ uint64_t nn = n[i], mm = m[i];
80
+ uint64_t pp = expand_pred_s(pg[H1(i)]);
81
+ d[i] = (nn & pp) | (mm & ~pp);
82
+ }
83
+}
84
+
85
+void HELPER(sve_sel_zpzz_d)(void *vd, void *vn, void *vm,
86
+ void *vg, uint32_t desc)
87
+{
88
+ intptr_t i, opr_sz = simd_oprsz(desc) / 8;
89
+ uint64_t *d = vd, *n = vn, *m = vm;
90
+ uint8_t *pg = vg;
91
+
92
+ for (i = 0; i < opr_sz; i += 1) {
93
+ uint64_t nn = n[i], mm = m[i];
94
+ d[i] = (pg[H1(i)] & 1 ? nn : mm);
95
+ }
96
+}
97
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
98
index XXXXXXX..XXXXXXX 100644
99
--- a/target/arm/translate-sve.c
100
+++ b/target/arm/translate-sve.c
101
@@ -XXX,XX +XXX,XX @@ static bool trans_UDIV_zpzz(DisasContext *s, arg_rprr_esz *a, uint32_t insn)
102
return do_zpzz_ool(s, a, fns[a->esz]);
103
}
104
105
+DO_ZPZZ(SEL, sel)
106
+
107
#undef DO_ZPZZ
108
71
109
/*
72
/*
110
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
111
index XXXXXXX..XXXXXXX 100644
112
--- a/target/arm/sve.decode
113
+++ b/target/arm/sve.decode
114
@@ -XXX,XX +XXX,XX @@
115
&rprr_esz rn=%reg_movprfx
116
@rdm_pg_rn ........ esz:2 ... ... ... pg:3 rn:5 rd:5 \
117
&rprr_esz rm=%reg_movprfx
118
+@rd_pg4_rn_rm ........ esz:2 . rm:5 .. pg:4 rn:5 rd:5 &rprr_esz
119
120
# Three register operand, with governing predicate, vector element size
121
@rda_pg_rn_rm ........ esz:2 . rm:5 ... pg:3 rn:5 rd:5 \
122
@@ -XXX,XX +XXX,XX @@ RBIT 00000101 .. 1001 11 100 ... ..... ..... @rd_pg_rn
123
# SVE vector splice (predicated)
124
SPLICE 00000101 .. 101 100 100 ... ..... ..... @rdn_pg_rm
125
126
+### SVE Select Vectors Group
127
+
128
+# SVE select vector elements (predicated)
129
+SEL_zpzz 00000101 .. 1 ..... 11 .... ..... ..... @rd_pg4_rn_rm
130
+
131
### SVE Predicate Logical Operations Group
132
133
# SVE predicate logical operations
134
--
73
--
135
2.17.1
74
2.34.1
136
75
137
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
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Assign the pointer return value to 'a' directly,
4
rather than going through an intermediary index.
5
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180613015641.5667-5-richard.henderson@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-5-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 15 ++++++++
11
fpu/softfloat-parts.c.inc | 32 ++++++++++----------------------
9
target/arm/sve_helper.c | 72 ++++++++++++++++++++++++++++++++++++
12
1 file changed, 10 insertions(+), 22 deletions(-)
10
target/arm/translate-sve.c | 75 ++++++++++++++++++++++++++++++++++++++
11
target/arm/sve.decode | 10 +++++
12
4 files changed, 172 insertions(+)
13
13
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
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/target/arm/helper-sve.h
16
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/helper-sve.h
17
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_trn_p, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
DEF_HELPER_FLAGS_3(sve_rev_p, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
19
FloatPartsN *c, float_status *s,
20
DEF_HELPER_FLAGS_3(sve_punpk_p, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
20
int ab_mask, int abc_mask)
21
21
{
22
+DEF_HELPER_FLAGS_4(sve_zip_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
- int which;
23
+DEF_HELPER_FLAGS_4(sve_zip_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
bool infzero = (ab_mask == float_cmask_infzero);
24
+DEF_HELPER_FLAGS_4(sve_zip_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
bool have_snan = (abc_mask & float_cmask_snan);
25
+DEF_HELPER_FLAGS_4(sve_zip_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+ FloatPartsN *ret;
26
+
26
27
+DEF_HELPER_FLAGS_4(sve_uzp_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
if (unlikely(have_snan)) {
28
+DEF_HELPER_FLAGS_4(sve_uzp_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
29
+DEF_HELPER_FLAGS_4(sve_uzp_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
30
+DEF_HELPER_FLAGS_4(sve_uzp_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
30
default:
31
+
31
g_assert_not_reached();
32
+DEF_HELPER_FLAGS_4(sve_trn_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
32
}
33
+DEF_HELPER_FLAGS_4(sve_trn_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
- which = 2;
34
+DEF_HELPER_FLAGS_4(sve_trn_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
+ ret = c;
35
+DEF_HELPER_FLAGS_4(sve_trn_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
35
} else {
36
+
36
- FloatClass cls[3] = { a->cls, b->cls, c->cls };
37
DEF_HELPER_FLAGS_5(sve_and_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
37
+ FloatPartsN *val[3] = { a, b, c };
38
DEF_HELPER_FLAGS_5(sve_bic_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
38
Float3NaNPropRule rule = s->float_3nan_prop_rule;
39
DEF_HELPER_FLAGS_5(sve_eor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
39
40
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
40
assert(rule != float_3nan_prop_none);
41
index XXXXXXX..XXXXXXX 100644
41
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
42
--- a/target/arm/sve_helper.c
42
/* We have at least one SNaN input and should prefer it */
43
+++ b/target/arm/sve_helper.c
43
do {
44
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_punpk_p)(void *vd, void *vn, uint32_t pred_desc)
44
- which = rule & R_3NAN_1ST_MASK;
45
+ ret = val[rule & R_3NAN_1ST_MASK];
46
rule >>= R_3NAN_1ST_LENGTH;
47
- } while (!is_snan(cls[which]));
48
+ } while (!is_snan(ret->cls));
49
} else {
50
do {
51
- which = rule & R_3NAN_1ST_MASK;
52
+ ret = val[rule & R_3NAN_1ST_MASK];
53
rule >>= R_3NAN_1ST_LENGTH;
54
- } while (!is_nan(cls[which]));
55
+ } while (!is_nan(ret->cls));
45
}
56
}
46
}
57
}
47
}
58
48
+
59
- switch (which) {
49
+#define DO_ZIP(NAME, TYPE, H) \
60
- case 0:
50
+void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
61
- break;
51
+{ \
62
- case 1:
52
+ intptr_t oprsz = simd_oprsz(desc); \
63
- a = b;
53
+ intptr_t i, oprsz_2 = oprsz / 2; \
64
- break;
54
+ ARMVectorReg tmp_n, tmp_m; \
65
- case 2:
55
+ /* We produce output faster than we consume input. \
66
- a = c;
56
+ Therefore we must be mindful of possible overlap. */ \
67
- break;
57
+ if (unlikely((vn - vd) < (uintptr_t)oprsz)) { \
68
- default:
58
+ vn = memcpy(&tmp_n, vn, oprsz_2); \
69
- g_assert_not_reached();
59
+ } \
70
+ if (is_snan(ret->cls)) {
60
+ if (unlikely((vm - vd) < (uintptr_t)oprsz)) { \
71
+ parts_silence_nan(ret, s);
61
+ vm = memcpy(&tmp_m, vm, oprsz_2); \
72
}
62
+ } \
73
- if (is_snan(a->cls)) {
63
+ for (i = 0; i < oprsz_2; i += sizeof(TYPE)) { \
74
- parts_silence_nan(a, s);
64
+ *(TYPE *)(vd + H(2 * i + 0)) = *(TYPE *)(vn + H(i)); \
75
- }
65
+ *(TYPE *)(vd + H(2 * i + sizeof(TYPE))) = *(TYPE *)(vm + H(i)); \
76
- return a;
66
+ } \
77
+ return ret;
67
+}
78
68
+
79
default_nan:
69
+DO_ZIP(sve_zip_b, uint8_t, H1)
80
parts_default_nan(a, s);
70
+DO_ZIP(sve_zip_h, uint16_t, H1_2)
71
+DO_ZIP(sve_zip_s, uint32_t, H1_4)
72
+DO_ZIP(sve_zip_d, uint64_t, )
73
+
74
+#define DO_UZP(NAME, TYPE, H) \
75
+void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
76
+{ \
77
+ intptr_t oprsz = simd_oprsz(desc); \
78
+ intptr_t oprsz_2 = oprsz / 2; \
79
+ intptr_t odd_ofs = simd_data(desc); \
80
+ intptr_t i; \
81
+ ARMVectorReg tmp_m; \
82
+ if (unlikely((vm - vd) < (uintptr_t)oprsz)) { \
83
+ vm = memcpy(&tmp_m, vm, oprsz); \
84
+ } \
85
+ for (i = 0; i < oprsz_2; i += sizeof(TYPE)) { \
86
+ *(TYPE *)(vd + H(i)) = *(TYPE *)(vn + H(2 * i + odd_ofs)); \
87
+ } \
88
+ for (i = 0; i < oprsz_2; i += sizeof(TYPE)) { \
89
+ *(TYPE *)(vd + H(oprsz_2 + i)) = *(TYPE *)(vm + H(2 * i + odd_ofs)); \
90
+ } \
91
+}
92
+
93
+DO_UZP(sve_uzp_b, uint8_t, H1)
94
+DO_UZP(sve_uzp_h, uint16_t, H1_2)
95
+DO_UZP(sve_uzp_s, uint32_t, H1_4)
96
+DO_UZP(sve_uzp_d, uint64_t, )
97
+
98
+#define DO_TRN(NAME, TYPE, H) \
99
+void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
100
+{ \
101
+ intptr_t oprsz = simd_oprsz(desc); \
102
+ intptr_t odd_ofs = simd_data(desc); \
103
+ intptr_t i; \
104
+ for (i = 0; i < oprsz; i += 2 * sizeof(TYPE)) { \
105
+ TYPE ae = *(TYPE *)(vn + H(i + odd_ofs)); \
106
+ TYPE be = *(TYPE *)(vm + H(i + odd_ofs)); \
107
+ *(TYPE *)(vd + H(i + 0)) = ae; \
108
+ *(TYPE *)(vd + H(i + sizeof(TYPE))) = be; \
109
+ } \
110
+}
111
+
112
+DO_TRN(sve_trn_b, uint8_t, H1)
113
+DO_TRN(sve_trn_h, uint16_t, H1_2)
114
+DO_TRN(sve_trn_s, uint32_t, H1_4)
115
+DO_TRN(sve_trn_d, uint64_t, )
116
+
117
+#undef DO_ZIP
118
+#undef DO_UZP
119
+#undef DO_TRN
120
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/target/arm/translate-sve.c
123
+++ b/target/arm/translate-sve.c
124
@@ -XXX,XX +XXX,XX @@ static bool trans_PUNPKHI(DisasContext *s, arg_PUNPKHI *a, uint32_t insn)
125
return do_perm_pred2(s, a, 1, gen_helper_sve_punpk_p);
126
}
127
128
+/*
129
+ *** SVE Permute - Interleaving Group
130
+ */
131
+
132
+static bool do_zip(DisasContext *s, arg_rrr_esz *a, bool high)
133
+{
134
+ static gen_helper_gvec_3 * const fns[4] = {
135
+ gen_helper_sve_zip_b, gen_helper_sve_zip_h,
136
+ gen_helper_sve_zip_s, gen_helper_sve_zip_d,
137
+ };
138
+
139
+ if (sve_access_check(s)) {
140
+ unsigned vsz = vec_full_reg_size(s);
141
+ unsigned high_ofs = high ? vsz / 2 : 0;
142
+ tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd),
143
+ vec_full_reg_offset(s, a->rn) + high_ofs,
144
+ vec_full_reg_offset(s, a->rm) + high_ofs,
145
+ vsz, vsz, 0, fns[a->esz]);
146
+ }
147
+ return true;
148
+}
149
+
150
+static bool do_zzz_data_ool(DisasContext *s, arg_rrr_esz *a, int data,
151
+ gen_helper_gvec_3 *fn)
152
+{
153
+ if (sve_access_check(s)) {
154
+ unsigned vsz = vec_full_reg_size(s);
155
+ tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd),
156
+ vec_full_reg_offset(s, a->rn),
157
+ vec_full_reg_offset(s, a->rm),
158
+ vsz, vsz, data, fn);
159
+ }
160
+ return true;
161
+}
162
+
163
+static bool trans_ZIP1_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
164
+{
165
+ return do_zip(s, a, false);
166
+}
167
+
168
+static bool trans_ZIP2_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
169
+{
170
+ return do_zip(s, a, true);
171
+}
172
+
173
+static gen_helper_gvec_3 * const uzp_fns[4] = {
174
+ gen_helper_sve_uzp_b, gen_helper_sve_uzp_h,
175
+ gen_helper_sve_uzp_s, gen_helper_sve_uzp_d,
176
+};
177
+
178
+static bool trans_UZP1_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
179
+{
180
+ return do_zzz_data_ool(s, a, 0, uzp_fns[a->esz]);
181
+}
182
+
183
+static bool trans_UZP2_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
184
+{
185
+ return do_zzz_data_ool(s, a, 1 << a->esz, uzp_fns[a->esz]);
186
+}
187
+
188
+static gen_helper_gvec_3 * const trn_fns[4] = {
189
+ gen_helper_sve_trn_b, gen_helper_sve_trn_h,
190
+ gen_helper_sve_trn_s, gen_helper_sve_trn_d,
191
+};
192
+
193
+static bool trans_TRN1_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
194
+{
195
+ return do_zzz_data_ool(s, a, 0, trn_fns[a->esz]);
196
+}
197
+
198
+static bool trans_TRN2_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
199
+{
200
+ return do_zzz_data_ool(s, a, 1 << a->esz, trn_fns[a->esz]);
201
+}
202
+
203
/*
204
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
205
*/
206
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
207
index XXXXXXX..XXXXXXX 100644
208
--- a/target/arm/sve.decode
209
+++ b/target/arm/sve.decode
210
@@ -XXX,XX +XXX,XX @@ REV_p 00000101 .. 11 0100 010 000 0 .... 0 .... @pd_pn
211
PUNPKLO 00000101 00 11 0000 010 000 0 .... 0 .... @pd_pn_e0
212
PUNPKHI 00000101 00 11 0001 010 000 0 .... 0 .... @pd_pn_e0
213
214
+### SVE Permute - Interleaving Group
215
+
216
+# SVE permute vector elements
217
+ZIP1_z 00000101 .. 1 ..... 011 000 ..... ..... @rd_rn_rm
218
+ZIP2_z 00000101 .. 1 ..... 011 001 ..... ..... @rd_rn_rm
219
+UZP1_z 00000101 .. 1 ..... 011 010 ..... ..... @rd_rn_rm
220
+UZP2_z 00000101 .. 1 ..... 011 011 ..... ..... @rd_rn_rm
221
+TRN1_z 00000101 .. 1 ..... 011 100 ..... ..... @rd_rn_rm
222
+TRN2_z 00000101 .. 1 ..... 011 101 ..... ..... @rd_rn_rm
223
+
224
### SVE Predicate Logical Operations Group
225
226
# SVE predicate logical operations
227
--
81
--
228
2.17.1
82
2.34.1
229
83
230
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
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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.
7
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180613015641.5667-14-richard.henderson@linaro.org
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Message-id: 20241203203949.483774-6-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
12
---
8
target/arm/helper-sve.h | 18 +++
13
fpu/softfloat-parts.c.inc | 2 +-
9
target/arm/sve_helper.c | 248 +++++++++++++++++++++++++++++++++++++
14
1 file changed, 1 insertion(+), 1 deletion(-)
10
target/arm/translate-sve.c | 106 ++++++++++++++++
11
target/arm/sve.decode | 19 +++
12
4 files changed, 391 insertions(+)
13
15
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
18
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/helper-sve.h
19
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_orn_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
DEF_HELPER_FLAGS_5(sve_nor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
}
20
DEF_HELPER_FLAGS_5(sve_nand_pppp, TCG_CALL_NO_RWG,
22
ret = c;
21
void, ptr, ptr, ptr, ptr, i32)
23
} else {
22
+
24
- FloatPartsN *val[3] = { a, b, c };
23
+DEF_HELPER_FLAGS_5(sve_brkpa, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
+ FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
24
+DEF_HELPER_FLAGS_5(sve_brkpb, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
Float3NaNPropRule rule = s->float_3nan_prop_rule;
25
+DEF_HELPER_FLAGS_5(sve_brkpas, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, ptr, i32)
27
26
+DEF_HELPER_FLAGS_5(sve_brkpbs, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, ptr, i32)
28
assert(rule != float_3nan_prop_none);
27
+
28
+DEF_HELPER_FLAGS_4(sve_brka_z, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_4(sve_brkb_z, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
30
+DEF_HELPER_FLAGS_4(sve_brka_m, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_4(sve_brkb_m, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
32
+
33
+DEF_HELPER_FLAGS_4(sve_brkas_z, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(sve_brkbs_z, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_4(sve_brkas_m, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
36
+DEF_HELPER_FLAGS_4(sve_brkbs_m, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
37
+
38
+DEF_HELPER_FLAGS_4(sve_brkn, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_4(sve_brkns, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
40
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/sve_helper.c
43
+++ b/target/arm/sve_helper.c
44
@@ -XXX,XX +XXX,XX @@ DO_CMP_PPZI_D(sve_cmpls_ppzi_d, uint64_t, <=)
45
#undef DO_CMP_PPZI_S
46
#undef DO_CMP_PPZI_D
47
#undef DO_CMP_PPZI
48
+
49
+/* Similar to the ARM LastActive pseudocode function. */
50
+static bool last_active_pred(void *vd, void *vg, intptr_t oprsz)
51
+{
52
+ intptr_t i;
53
+
54
+ for (i = QEMU_ALIGN_UP(oprsz, 8) - 8; i >= 0; i -= 8) {
55
+ uint64_t pg = *(uint64_t *)(vg + i);
56
+ if (pg) {
57
+ return (pow2floor(pg) & *(uint64_t *)(vd + i)) != 0;
58
+ }
59
+ }
60
+ return 0;
61
+}
62
+
63
+/* Compute a mask into RETB that is true for all G, up to and including
64
+ * (if after) or excluding (if !after) the first G & N.
65
+ * Return true if BRK found.
66
+ */
67
+static bool compute_brk(uint64_t *retb, uint64_t n, uint64_t g,
68
+ bool brk, bool after)
69
+{
70
+ uint64_t b;
71
+
72
+ if (brk) {
73
+ b = 0;
74
+ } else if ((g & n) == 0) {
75
+ /* For all G, no N are set; break not found. */
76
+ b = g;
77
+ } else {
78
+ /* Break somewhere in N. Locate it. */
79
+ b = g & n; /* guard true, pred true */
80
+ b = b & -b; /* first such */
81
+ if (after) {
82
+ b = b | (b - 1); /* break after same */
83
+ } else {
84
+ b = b - 1; /* break before same */
85
+ }
86
+ brk = true;
87
+ }
88
+
89
+ *retb = b;
90
+ return brk;
91
+}
92
+
93
+/* Compute a zeroing BRK. */
94
+static void compute_brk_z(uint64_t *d, uint64_t *n, uint64_t *g,
95
+ intptr_t oprsz, bool after)
96
+{
97
+ bool brk = false;
98
+ intptr_t i;
99
+
100
+ for (i = 0; i < DIV_ROUND_UP(oprsz, 8); ++i) {
101
+ uint64_t this_b, this_g = g[i];
102
+
103
+ brk = compute_brk(&this_b, n[i], this_g, brk, after);
104
+ d[i] = this_b & this_g;
105
+ }
106
+}
107
+
108
+/* Likewise, but also compute flags. */
109
+static uint32_t compute_brks_z(uint64_t *d, uint64_t *n, uint64_t *g,
110
+ intptr_t oprsz, bool after)
111
+{
112
+ uint32_t flags = PREDTEST_INIT;
113
+ bool brk = false;
114
+ intptr_t i;
115
+
116
+ for (i = 0; i < DIV_ROUND_UP(oprsz, 8); ++i) {
117
+ uint64_t this_b, this_d, this_g = g[i];
118
+
119
+ brk = compute_brk(&this_b, n[i], this_g, brk, after);
120
+ d[i] = this_d = this_b & this_g;
121
+ flags = iter_predtest_fwd(this_d, this_g, flags);
122
+ }
123
+ return flags;
124
+}
125
+
126
+/* Compute a merging BRK. */
127
+static void compute_brk_m(uint64_t *d, uint64_t *n, uint64_t *g,
128
+ intptr_t oprsz, bool after)
129
+{
130
+ bool brk = false;
131
+ intptr_t i;
132
+
133
+ for (i = 0; i < DIV_ROUND_UP(oprsz, 8); ++i) {
134
+ uint64_t this_b, this_g = g[i];
135
+
136
+ brk = compute_brk(&this_b, n[i], this_g, brk, after);
137
+ d[i] = (this_b & this_g) | (d[i] & ~this_g);
138
+ }
139
+}
140
+
141
+/* Likewise, but also compute flags. */
142
+static uint32_t compute_brks_m(uint64_t *d, uint64_t *n, uint64_t *g,
143
+ intptr_t oprsz, bool after)
144
+{
145
+ uint32_t flags = PREDTEST_INIT;
146
+ bool brk = false;
147
+ intptr_t i;
148
+
149
+ for (i = 0; i < oprsz / 8; ++i) {
150
+ uint64_t this_b, this_d = d[i], this_g = g[i];
151
+
152
+ brk = compute_brk(&this_b, n[i], this_g, brk, after);
153
+ d[i] = this_d = (this_b & this_g) | (this_d & ~this_g);
154
+ flags = iter_predtest_fwd(this_d, this_g, flags);
155
+ }
156
+ return flags;
157
+}
158
+
159
+static uint32_t do_zero(ARMPredicateReg *d, intptr_t oprsz)
160
+{
161
+ /* It is quicker to zero the whole predicate than loop on OPRSZ.
162
+ * The compiler should turn this into 4 64-bit integer stores.
163
+ */
164
+ memset(d, 0, sizeof(ARMPredicateReg));
165
+ return PREDTEST_INIT;
166
+}
167
+
168
+void HELPER(sve_brkpa)(void *vd, void *vn, void *vm, void *vg,
169
+ uint32_t pred_desc)
170
+{
171
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
172
+ if (last_active_pred(vn, vg, oprsz)) {
173
+ compute_brk_z(vd, vm, vg, oprsz, true);
174
+ } else {
175
+ do_zero(vd, oprsz);
176
+ }
177
+}
178
+
179
+uint32_t HELPER(sve_brkpas)(void *vd, void *vn, void *vm, void *vg,
180
+ uint32_t pred_desc)
181
+{
182
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
183
+ if (last_active_pred(vn, vg, oprsz)) {
184
+ return compute_brks_z(vd, vm, vg, oprsz, true);
185
+ } else {
186
+ return do_zero(vd, oprsz);
187
+ }
188
+}
189
+
190
+void HELPER(sve_brkpb)(void *vd, void *vn, void *vm, void *vg,
191
+ uint32_t pred_desc)
192
+{
193
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
194
+ if (last_active_pred(vn, vg, oprsz)) {
195
+ compute_brk_z(vd, vm, vg, oprsz, false);
196
+ } else {
197
+ do_zero(vd, oprsz);
198
+ }
199
+}
200
+
201
+uint32_t HELPER(sve_brkpbs)(void *vd, void *vn, void *vm, void *vg,
202
+ uint32_t pred_desc)
203
+{
204
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
205
+ if (last_active_pred(vn, vg, oprsz)) {
206
+ return compute_brks_z(vd, vm, vg, oprsz, false);
207
+ } else {
208
+ return do_zero(vd, oprsz);
209
+ }
210
+}
211
+
212
+void HELPER(sve_brka_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
213
+{
214
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
215
+ compute_brk_z(vd, vn, vg, oprsz, true);
216
+}
217
+
218
+uint32_t HELPER(sve_brkas_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
219
+{
220
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
221
+ return compute_brks_z(vd, vn, vg, oprsz, true);
222
+}
223
+
224
+void HELPER(sve_brkb_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
225
+{
226
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
227
+ compute_brk_z(vd, vn, vg, oprsz, false);
228
+}
229
+
230
+uint32_t HELPER(sve_brkbs_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
231
+{
232
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
233
+ return compute_brks_z(vd, vn, vg, oprsz, false);
234
+}
235
+
236
+void HELPER(sve_brka_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
237
+{
238
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
239
+ compute_brk_m(vd, vn, vg, oprsz, true);
240
+}
241
+
242
+uint32_t HELPER(sve_brkas_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
243
+{
244
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
245
+ return compute_brks_m(vd, vn, vg, oprsz, true);
246
+}
247
+
248
+void HELPER(sve_brkb_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
249
+{
250
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
251
+ compute_brk_m(vd, vn, vg, oprsz, false);
252
+}
253
+
254
+uint32_t HELPER(sve_brkbs_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
255
+{
256
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
257
+ return compute_brks_m(vd, vn, vg, oprsz, false);
258
+}
259
+
260
+void HELPER(sve_brkn)(void *vd, void *vn, void *vg, uint32_t pred_desc)
261
+{
262
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
263
+
264
+ if (!last_active_pred(vn, vg, oprsz)) {
265
+ do_zero(vd, oprsz);
266
+ }
267
+}
268
+
269
+/* As if PredTest(Ones(PL), D, esz). */
270
+static uint32_t predtest_ones(ARMPredicateReg *d, intptr_t oprsz,
271
+ uint64_t esz_mask)
272
+{
273
+ uint32_t flags = PREDTEST_INIT;
274
+ intptr_t i;
275
+
276
+ for (i = 0; i < oprsz / 8; i++) {
277
+ flags = iter_predtest_fwd(d->p[i], esz_mask, flags);
278
+ }
279
+ if (oprsz & 7) {
280
+ uint64_t mask = ~(-1ULL << (8 * (oprsz & 7)));
281
+ flags = iter_predtest_fwd(d->p[i], esz_mask & mask, flags);
282
+ }
283
+ return flags;
284
+}
285
+
286
+uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc)
287
+{
288
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
289
+
290
+ if (last_active_pred(vn, vg, oprsz)) {
291
+ return predtest_ones(vd, oprsz, -1);
292
+ } else {
293
+ return do_zero(vd, oprsz);
294
+ }
295
+}
296
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
297
index XXXXXXX..XXXXXXX 100644
298
--- a/target/arm/translate-sve.c
299
+++ b/target/arm/translate-sve.c
300
@@ -XXX,XX +XXX,XX @@ DO_PPZI(CMPLS, cmpls)
301
302
#undef DO_PPZI
303
304
+/*
305
+ *** SVE Partition Break Group
306
+ */
307
+
308
+static bool do_brk3(DisasContext *s, arg_rprr_s *a,
309
+ gen_helper_gvec_4 *fn, gen_helper_gvec_flags_4 *fn_s)
310
+{
311
+ if (!sve_access_check(s)) {
312
+ return true;
313
+ }
314
+
315
+ unsigned vsz = pred_full_reg_size(s);
316
+
317
+ /* Predicate sizes may be smaller and cannot use simd_desc. */
318
+ TCGv_ptr d = tcg_temp_new_ptr();
319
+ TCGv_ptr n = tcg_temp_new_ptr();
320
+ TCGv_ptr m = tcg_temp_new_ptr();
321
+ TCGv_ptr g = tcg_temp_new_ptr();
322
+ TCGv_i32 t = tcg_const_i32(vsz - 2);
323
+
324
+ tcg_gen_addi_ptr(d, cpu_env, pred_full_reg_offset(s, a->rd));
325
+ tcg_gen_addi_ptr(n, cpu_env, pred_full_reg_offset(s, a->rn));
326
+ tcg_gen_addi_ptr(m, cpu_env, pred_full_reg_offset(s, a->rm));
327
+ tcg_gen_addi_ptr(g, cpu_env, pred_full_reg_offset(s, a->pg));
328
+
329
+ if (a->s) {
330
+ fn_s(t, d, n, m, g, t);
331
+ do_pred_flags(t);
332
+ } else {
333
+ fn(d, n, m, g, t);
334
+ }
335
+ tcg_temp_free_ptr(d);
336
+ tcg_temp_free_ptr(n);
337
+ tcg_temp_free_ptr(m);
338
+ tcg_temp_free_ptr(g);
339
+ tcg_temp_free_i32(t);
340
+ return true;
341
+}
342
+
343
+static bool do_brk2(DisasContext *s, arg_rpr_s *a,
344
+ gen_helper_gvec_3 *fn, gen_helper_gvec_flags_3 *fn_s)
345
+{
346
+ if (!sve_access_check(s)) {
347
+ return true;
348
+ }
349
+
350
+ unsigned vsz = pred_full_reg_size(s);
351
+
352
+ /* Predicate sizes may be smaller and cannot use simd_desc. */
353
+ TCGv_ptr d = tcg_temp_new_ptr();
354
+ TCGv_ptr n = tcg_temp_new_ptr();
355
+ TCGv_ptr g = tcg_temp_new_ptr();
356
+ TCGv_i32 t = tcg_const_i32(vsz - 2);
357
+
358
+ tcg_gen_addi_ptr(d, cpu_env, pred_full_reg_offset(s, a->rd));
359
+ tcg_gen_addi_ptr(n, cpu_env, pred_full_reg_offset(s, a->rn));
360
+ tcg_gen_addi_ptr(g, cpu_env, pred_full_reg_offset(s, a->pg));
361
+
362
+ if (a->s) {
363
+ fn_s(t, d, n, g, t);
364
+ do_pred_flags(t);
365
+ } else {
366
+ fn(d, n, g, t);
367
+ }
368
+ tcg_temp_free_ptr(d);
369
+ tcg_temp_free_ptr(n);
370
+ tcg_temp_free_ptr(g);
371
+ tcg_temp_free_i32(t);
372
+ return true;
373
+}
374
+
375
+static bool trans_BRKPA(DisasContext *s, arg_rprr_s *a, uint32_t insn)
376
+{
377
+ return do_brk3(s, a, gen_helper_sve_brkpa, gen_helper_sve_brkpas);
378
+}
379
+
380
+static bool trans_BRKPB(DisasContext *s, arg_rprr_s *a, uint32_t insn)
381
+{
382
+ return do_brk3(s, a, gen_helper_sve_brkpb, gen_helper_sve_brkpbs);
383
+}
384
+
385
+static bool trans_BRKA_m(DisasContext *s, arg_rpr_s *a, uint32_t insn)
386
+{
387
+ return do_brk2(s, a, gen_helper_sve_brka_m, gen_helper_sve_brkas_m);
388
+}
389
+
390
+static bool trans_BRKB_m(DisasContext *s, arg_rpr_s *a, uint32_t insn)
391
+{
392
+ return do_brk2(s, a, gen_helper_sve_brkb_m, gen_helper_sve_brkbs_m);
393
+}
394
+
395
+static bool trans_BRKA_z(DisasContext *s, arg_rpr_s *a, uint32_t insn)
396
+{
397
+ return do_brk2(s, a, gen_helper_sve_brka_z, gen_helper_sve_brkas_z);
398
+}
399
+
400
+static bool trans_BRKB_z(DisasContext *s, arg_rpr_s *a, uint32_t insn)
401
+{
402
+ return do_brk2(s, a, gen_helper_sve_brkb_z, gen_helper_sve_brkbs_z);
403
+}
404
+
405
+static bool trans_BRKN(DisasContext *s, arg_rpr_s *a, uint32_t insn)
406
+{
407
+ return do_brk2(s, a, gen_helper_sve_brkn, gen_helper_sve_brkns);
408
+}
409
+
410
/*
411
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
412
*/
413
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
414
index XXXXXXX..XXXXXXX 100644
415
--- a/target/arm/sve.decode
416
+++ b/target/arm/sve.decode
417
@@ -XXX,XX +XXX,XX @@
418
&rri_esz rd rn imm esz
419
&rrr_esz rd rn rm esz
420
&rpr_esz rd pg rn esz
421
+&rpr_s rd pg rn s
422
&rprr_s rd pg rn rm s
423
&rprr_esz rd pg rn rm esz
424
&rprrr_esz rd pg rn rm ra esz
425
@@ -XXX,XX +XXX,XX @@
426
@pd_pn ........ esz:2 .. .... ....... rn:4 . rd:4 &rr_esz
427
@rd_rn ........ esz:2 ...... ...... rn:5 rd:5 &rr_esz
428
429
+# Two operand with governing predicate, flags setting
430
+@pd_pg_pn_s ........ . s:1 ...... .. pg:4 . rn:4 . rd:4 &rpr_s
431
+
432
# Three operand with unused vector element size
433
@rd_rn_rm_e0 ........ ... rm:5 ... ... rn:5 rd:5 &rrr_esz esz=0
434
435
@@ -XXX,XX +XXX,XX @@ PFIRST 00100101 01 011 000 11000 00 .... 0 .... @pd_pn_e0
436
# SVE predicate next active
437
PNEXT 00100101 .. 011 001 11000 10 .... 0 .... @pd_pn
438
439
+### SVE Partition Break Group
440
+
441
+# SVE propagate break from previous partition
442
+BRKPA 00100101 0. 00 .... 11 .... 0 .... 0 .... @pd_pg_pn_pm_s
443
+BRKPB 00100101 0. 00 .... 11 .... 0 .... 1 .... @pd_pg_pn_pm_s
444
+
445
+# SVE partition break condition
446
+BRKA_z 00100101 0. 01000001 .... 0 .... 0 .... @pd_pg_pn_s
447
+BRKB_z 00100101 1. 01000001 .... 0 .... 0 .... @pd_pg_pn_s
448
+BRKA_m 00100101 0. 01000001 .... 0 .... 1 .... @pd_pg_pn_s
449
+BRKB_m 00100101 1. 01000001 .... 0 .... 1 .... @pd_pg_pn_s
450
+
451
+# SVE propagate break to next partition
452
+BRKN 00100101 0. 01100001 .... 0 .... 0 .... @pd_pg_pn_s
453
+
454
### SVE Memory - 32-bit Gather and Unsized Contiguous Group
455
456
# SVE load predicate register
457
--
29
--
458
2.17.1
30
2.34.1
459
31
460
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 function is part of the public interface and
4
is not "specialized" to any target in any way.
5
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20180613015641.5667-16-richard.henderson@linaro.org
5
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
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 2 +
11
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++++++++
9
target/arm/sve_helper.c | 31 ++++++++++++
12
fpu/softfloat-specialize.c.inc | 52 ----------------------------------
10
target/arm/translate-sve.c | 99 ++++++++++++++++++++++++++++++++++++++
13
2 files changed, 52 insertions(+), 52 deletions(-)
11
target/arm/sve.decode | 8 +++
12
4 files changed, 140 insertions(+)
13
14
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
17
--- a/fpu/softfloat.c
17
+++ b/target/arm/helper-sve.h
18
+++ b/fpu/softfloat.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_brkn, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
19
DEF_HELPER_FLAGS_4(sve_brkns, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
20
*zExpPtr = 1 - shiftCount;
20
21
}
21
DEF_HELPER_FLAGS_3(sve_cntp, TCG_CALL_NO_RWG, i64, ptr, ptr, i32)
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
+DEF_HELPER_FLAGS_3(sve_while, TCG_CALL_NO_RWG, i32, ptr, i32, i32)
29
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
24
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
30
+{
25
index XXXXXXX..XXXXXXX 100644
31
+ bool aIsLargerSignificand;
26
--- a/target/arm/sve_helper.c
32
+ FloatClass a_cls, b_cls;
27
+++ b/target/arm/sve_helper.c
28
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
29
}
30
return sum;
31
}
32
+
33
+
33
+uint32_t HELPER(sve_while)(void *vd, uint32_t count, uint32_t pred_desc)
34
+ /* This is not complete, but is good enough for pickNaN. */
34
+{
35
+ a_cls = (!floatx80_is_any_nan(a)
35
+ uintptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
36
+ ? float_class_normal
36
+ intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
37
+ : floatx80_is_signaling_nan(a, status)
37
+ uint64_t esz_mask = pred_esz_masks[esz];
38
+ ? float_class_snan
38
+ ARMPredicateReg *d = vd;
39
+ : float_class_qnan);
39
+ uint32_t flags;
40
+ b_cls = (!floatx80_is_any_nan(b)
40
+ intptr_t i;
41
+ ? float_class_normal
42
+ : floatx80_is_signaling_nan(b, status)
43
+ ? float_class_snan
44
+ : float_class_qnan);
41
+
45
+
42
+ /* Begin with a zero predicate register. */
46
+ if (is_snan(a_cls) || is_snan(b_cls)) {
43
+ flags = do_zero(d, oprsz);
47
+ float_raise(float_flag_invalid, status);
44
+ if (count == 0) {
45
+ return flags;
46
+ }
48
+ }
47
+
49
+
48
+ /* Scale from predicate element count to bits. */
50
+ if (status->default_nan_mode) {
49
+ count <<= esz;
51
+ return floatx80_default_nan(status);
50
+ /* Bound to the bits in the predicate. */
51
+ count = MIN(count, oprsz * 8);
52
+
53
+ /* Set all of the requested bits. */
54
+ for (i = 0; i < count / 64; ++i) {
55
+ d->p[i] = esz_mask;
56
+ }
57
+ if (count & 63) {
58
+ d->p[i] = MAKE_64BIT_MASK(0, count & 63) & esz_mask;
59
+ }
52
+ }
60
+
53
+
61
+ return predtest_ones(d, oprsz, esz_mask);
54
+ if (a.low < b.low) {
62
+}
55
+ aIsLargerSignificand = 0;
63
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
56
+ } else if (b.low < a.low) {
64
index XXXXXXX..XXXXXXX 100644
57
+ aIsLargerSignificand = 1;
65
--- a/target/arm/translate-sve.c
58
+ } else {
66
+++ b/target/arm/translate-sve.c
59
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
67
@@ -XXX,XX +XXX,XX @@ static bool trans_SINCDECP_z(DisasContext *s, arg_incdec2_pred *a,
68
return true;
69
}
70
71
+/*
72
+ *** SVE Integer Compare Scalars Group
73
+ */
74
+
75
+static bool trans_CTERM(DisasContext *s, arg_CTERM *a, uint32_t insn)
76
+{
77
+ if (!sve_access_check(s)) {
78
+ return true;
79
+ }
60
+ }
80
+
61
+
81
+ TCGCond cond = (a->ne ? TCG_COND_NE : TCG_COND_EQ);
62
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
82
+ TCGv_i64 rn = read_cpu_reg(s, a->rn, a->sf);
63
+ if (is_snan(b_cls)) {
83
+ TCGv_i64 rm = read_cpu_reg(s, a->rm, a->sf);
64
+ return floatx80_silence_nan(b, status);
84
+ TCGv_i64 cmp = tcg_temp_new_i64();
65
+ }
85
+
66
+ return b;
86
+ tcg_gen_setcond_i64(cond, cmp, rn, rm);
67
+ } else {
87
+ tcg_gen_extrl_i64_i32(cpu_NF, cmp);
68
+ if (is_snan(a_cls)) {
88
+ tcg_temp_free_i64(cmp);
69
+ return floatx80_silence_nan(a, status);
89
+
70
+ }
90
+ /* VF = !NF & !CF. */
71
+ return a;
91
+ tcg_gen_xori_i32(cpu_VF, cpu_NF, 1);
72
+ }
92
+ tcg_gen_andc_i32(cpu_VF, cpu_VF, cpu_CF);
93
+
94
+ /* Both NF and VF actually look at bit 31. */
95
+ tcg_gen_neg_i32(cpu_NF, cpu_NF);
96
+ tcg_gen_neg_i32(cpu_VF, cpu_VF);
97
+ return true;
98
+}
73
+}
99
+
74
+
100
+static bool trans_WHILE(DisasContext *s, arg_WHILE *a, uint32_t insn)
75
/*----------------------------------------------------------------------------
101
+{
76
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
102
+ if (!sve_access_check(s)) {
77
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
103
+ return true;
78
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
104
+ }
105
+
106
+ TCGv_i64 op0 = read_cpu_reg(s, a->rn, 1);
107
+ TCGv_i64 op1 = read_cpu_reg(s, a->rm, 1);
108
+ TCGv_i64 t0 = tcg_temp_new_i64();
109
+ TCGv_i64 t1 = tcg_temp_new_i64();
110
+ TCGv_i32 t2, t3;
111
+ TCGv_ptr ptr;
112
+ unsigned desc, vsz = vec_full_reg_size(s);
113
+ TCGCond cond;
114
+
115
+ if (!a->sf) {
116
+ if (a->u) {
117
+ tcg_gen_ext32u_i64(op0, op0);
118
+ tcg_gen_ext32u_i64(op1, op1);
119
+ } else {
120
+ tcg_gen_ext32s_i64(op0, op0);
121
+ tcg_gen_ext32s_i64(op1, op1);
122
+ }
123
+ }
124
+
125
+ /* For the helper, compress the different conditions into a computation
126
+ * of how many iterations for which the condition is true.
127
+ *
128
+ * This is slightly complicated by 0 <= UINT64_MAX, which is nominally
129
+ * 2**64 iterations, overflowing to 0. Of course, predicate registers
130
+ * aren't that large, so any value >= predicate size is sufficient.
131
+ */
132
+ tcg_gen_sub_i64(t0, op1, op0);
133
+
134
+ /* t0 = MIN(op1 - op0, vsz). */
135
+ tcg_gen_movi_i64(t1, vsz);
136
+ tcg_gen_umin_i64(t0, t0, t1);
137
+ if (a->eq) {
138
+ /* Equality means one more iteration. */
139
+ tcg_gen_addi_i64(t0, t0, 1);
140
+ }
141
+
142
+ /* t0 = (condition true ? t0 : 0). */
143
+ cond = (a->u
144
+ ? (a->eq ? TCG_COND_LEU : TCG_COND_LTU)
145
+ : (a->eq ? TCG_COND_LE : TCG_COND_LT));
146
+ tcg_gen_movi_i64(t1, 0);
147
+ tcg_gen_movcond_i64(cond, t0, op0, op1, t0, t1);
148
+
149
+ t2 = tcg_temp_new_i32();
150
+ tcg_gen_extrl_i64_i32(t2, t0);
151
+ tcg_temp_free_i64(t0);
152
+ tcg_temp_free_i64(t1);
153
+
154
+ desc = (vsz / 8) - 2;
155
+ desc = deposit32(desc, SIMD_DATA_SHIFT, 2, a->esz);
156
+ t3 = tcg_const_i32(desc);
157
+
158
+ ptr = tcg_temp_new_ptr();
159
+ tcg_gen_addi_ptr(ptr, cpu_env, pred_full_reg_offset(s, a->rd));
160
+
161
+ gen_helper_sve_while(t2, ptr, t2, t3);
162
+ do_pred_flags(t2);
163
+
164
+ tcg_temp_free_ptr(ptr);
165
+ tcg_temp_free_i32(t2);
166
+ tcg_temp_free_i32(t3);
167
+ return true;
168
+}
169
+
170
/*
171
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
172
*/
173
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
174
index XXXXXXX..XXXXXXX 100644
79
index XXXXXXX..XXXXXXX 100644
175
--- a/target/arm/sve.decode
80
--- a/fpu/softfloat-specialize.c.inc
176
+++ b/target/arm/sve.decode
81
+++ b/fpu/softfloat-specialize.c.inc
177
@@ -XXX,XX +XXX,XX @@ SINCDECP_r_64 00100101 .. 1010 d:1 u:1 10001 10 .... ..... @incdec_pred
82
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
178
# SVE saturating inc/dec vector by predicate count
83
return a;
179
SINCDECP_z 00100101 .. 1010 d:1 u:1 10000 00 .... ..... @incdec2_pred
84
}
180
85
181
+### SVE Integer Compare - Scalars Group
86
-/*----------------------------------------------------------------------------
182
+
87
-| Takes two extended double-precision floating-point values `a' and `b', one
183
+# SVE conditionally terminate scalars
88
-| of which is a NaN, and returns the appropriate NaN result. If either `a' or
184
+CTERM 00100101 1 sf:1 1 rm:5 001000 rn:5 ne:1 0000
89
-| `b' is a signaling NaN, the invalid exception is raised.
185
+
90
-*----------------------------------------------------------------------------*/
186
+# SVE integer compare scalar count and limit
91
-
187
+WHILE 00100101 esz:2 1 rm:5 000 sf:1 u:1 1 rn:5 eq:1 rd:4
92
-floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
188
+
93
-{
189
### SVE Memory - 32-bit Gather and Unsized Contiguous Group
94
- bool aIsLargerSignificand;
190
95
- FloatClass a_cls, b_cls;
191
# SVE load predicate register
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.
192
--
141
--
193
2.17.1
142
2.34.1
194
195
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Unpacking and repacking the parts may be slightly more work
4
than we did before, but we get to reuse more code. For a
5
code path handling exceptional values, this is an improvement.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241203203949.483774-8-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180613015641.5667-8-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
target/arm/translate-sve.c | 19 +++++++++++++++++++
12
fpu/softfloat.c | 43 +++++--------------------------------------
9
target/arm/sve.decode | 6 ++++++
13
1 file changed, 5 insertions(+), 38 deletions(-)
10
2 files changed, 25 insertions(+)
11
14
12
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-sve.c
17
--- a/fpu/softfloat.c
15
+++ b/target/arm/translate-sve.c
18
+++ b/fpu/softfloat.c
16
@@ -XXX,XX +XXX,XX @@ static bool trans_LASTB_r(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
17
return do_last_general(s, a, true);
20
21
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
22
{
23
- bool aIsLargerSignificand;
24
- FloatClass a_cls, b_cls;
25
+ FloatParts128 pa, pb, *pr;
26
27
- /* This is not complete, but is good enough for pickNaN. */
28
- a_cls = (!floatx80_is_any_nan(a)
29
- ? float_class_normal
30
- : floatx80_is_signaling_nan(a, status)
31
- ? float_class_snan
32
- : float_class_qnan);
33
- b_cls = (!floatx80_is_any_nan(b)
34
- ? float_class_normal
35
- : floatx80_is_signaling_nan(b, status)
36
- ? float_class_snan
37
- : float_class_qnan);
38
-
39
- if (is_snan(a_cls) || is_snan(b_cls)) {
40
- float_raise(float_flag_invalid, status);
41
- }
42
-
43
- if (status->default_nan_mode) {
44
+ if (!floatx80_unpack_canonical(&pa, a, status) ||
45
+ !floatx80_unpack_canonical(&pb, b, status)) {
46
return floatx80_default_nan(status);
47
}
48
49
- if (a.low < b.low) {
50
- aIsLargerSignificand = 0;
51
- } else if (b.low < a.low) {
52
- aIsLargerSignificand = 1;
53
- } else {
54
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
55
- }
56
-
57
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
58
- if (is_snan(b_cls)) {
59
- return floatx80_silence_nan(b, status);
60
- }
61
- return b;
62
- } else {
63
- if (is_snan(a_cls)) {
64
- return floatx80_silence_nan(a, status);
65
- }
66
- return a;
67
- }
68
+ pr = parts_pick_nan(&pa, &pb, status);
69
+ return floatx80_round_pack_canonical(pr, status);
18
}
70
}
19
71
20
+static bool trans_CPY_m_r(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
72
/*----------------------------------------------------------------------------
21
+{
22
+ if (sve_access_check(s)) {
23
+ do_cpy_m(s, a->esz, a->rd, a->rd, a->pg, cpu_reg_sp(s, a->rn));
24
+ }
25
+ return true;
26
+}
27
+
28
+static bool trans_CPY_m_v(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
29
+{
30
+ if (sve_access_check(s)) {
31
+ int ofs = vec_reg_offset(s, a->rn, 0, a->esz);
32
+ TCGv_i64 t = load_esz(cpu_env, ofs, a->esz);
33
+ do_cpy_m(s, a->esz, a->rd, a->rd, a->pg, t);
34
+ tcg_temp_free_i64(t);
35
+ }
36
+ return true;
37
+}
38
+
39
/*
40
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
41
*/
42
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/sve.decode
45
+++ b/target/arm/sve.decode
46
@@ -XXX,XX +XXX,XX @@ LASTB_v 00000101 .. 10001 1 100 ... ..... ..... @rd_pg_rn
47
LASTA_r 00000101 .. 10000 0 101 ... ..... ..... @rd_pg_rn
48
LASTB_r 00000101 .. 10000 1 101 ... ..... ..... @rd_pg_rn
49
50
+# SVE copy element from SIMD&FP scalar register
51
+CPY_m_v 00000101 .. 100000 100 ... ..... ..... @rd_pg_rn
52
+
53
+# SVE copy element from general register to vector (predicated)
54
+CPY_m_r 00000101 .. 101000 101 ... ..... ..... @rd_pg_rn
55
+
56
### SVE Predicate Logical Operations Group
57
58
# SVE predicate logical operations
59
--
73
--
60
2.17.1
74
2.34.1
61
62
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Inline pickNaN into its only caller. This makes one assert
4
redundant with the immediately preceding IF.
5
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180613015641.5667-4-richard.henderson@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-9-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 6 +
11
fpu/softfloat-parts.c.inc | 82 +++++++++++++++++++++++++----
9
target/arm/sve_helper.c | 290 +++++++++++++++++++++++++++++++++++++
12
fpu/softfloat-specialize.c.inc | 96 ----------------------------------
10
target/arm/translate-sve.c | 120 +++++++++++++++
13
2 files changed, 73 insertions(+), 105 deletions(-)
11
target/arm/sve.decode | 18 +++
14
12
4 files changed, 434 insertions(+)
15
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
13
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
17
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/helper-sve.h
18
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(sve_uunpk_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
19
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
19
DEF_HELPER_FLAGS_3(sve_uunpk_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
20
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
20
DEF_HELPER_FLAGS_3(sve_uunpk_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
21
float_status *s)
21
22
{
22
+DEF_HELPER_FLAGS_4(sve_zip_p, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
+ int cmp, which;
23
+DEF_HELPER_FLAGS_4(sve_uzp_p, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_4(sve_trn_p, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_3(sve_rev_p, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_3(sve_punpk_p, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
27
+
24
+
28
DEF_HELPER_FLAGS_5(sve_and_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
if (is_snan(a->cls) || is_snan(b->cls)) {
29
DEF_HELPER_FLAGS_5(sve_bic_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
30
DEF_HELPER_FLAGS_5(sve_eor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
}
31
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
28
32
index XXXXXXX..XXXXXXX 100644
29
if (s->default_nan_mode) {
33
--- a/target/arm/sve_helper.c
30
parts_default_nan(a, s);
34
+++ b/target/arm/sve_helper.c
31
- } else {
35
@@ -XXX,XX +XXX,XX @@ DO_UNPK(sve_uunpk_s, uint32_t, uint16_t, H4, H2)
32
- int cmp = frac_cmp(a, b);
36
DO_UNPK(sve_uunpk_d, uint64_t, uint32_t, , H4)
33
- if (cmp == 0) {
37
34
- cmp = a->sign < b->sign;
38
#undef DO_UNPK
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
+ }
39
+
46
+
40
+/* Mask of bits included in the even numbered predicates of width esz.
47
+ switch (s->float_2nan_prop_rule) {
41
+ * We also use this for expand_bits/compress_bits, and so extend the
48
+ case float_2nan_prop_s_ab:
42
+ * same pattern out to 16-bit units.
49
if (is_snan(a->cls)) {
43
+ */
50
- parts_silence_nan(a, s);
44
+static const uint64_t even_bit_esz_masks[5] = {
51
+ which = 0;
45
+ 0x5555555555555555ull,
52
+ } else if (is_snan(b->cls)) {
46
+ 0x3333333333333333ull,
53
+ which = 1;
47
+ 0x0f0f0f0f0f0f0f0full,
54
+ } else if (is_qnan(a->cls)) {
48
+ 0x00ff00ff00ff00ffull,
55
+ which = 0;
49
+ 0x0000ffff0000ffffull,
56
+ } else {
50
+};
57
+ which = 1;
51
+
58
}
52
+/* Zero-extend units of 2**N bits to units of 2**(N+1) bits.
59
+ break;
53
+ * For N==0, this corresponds to the operation that in qemu/bitops.h
60
+ case float_2nan_prop_s_ba:
54
+ * we call half_shuffle64; this algorithm is from Hacker's Delight,
61
+ if (is_snan(b->cls)) {
55
+ * section 7-2 Shuffling Bits.
62
+ which = 1;
56
+ */
63
+ } else if (is_snan(a->cls)) {
57
+static uint64_t expand_bits(uint64_t x, int n)
64
+ which = 0;
58
+{
65
+ } else if (is_qnan(b->cls)) {
59
+ int i;
66
+ which = 1;
60
+
67
+ } else {
61
+ x &= 0xffffffffu;
68
+ which = 0;
62
+ for (i = 4; i >= n; i--) {
63
+ int sh = 1 << i;
64
+ x = ((x << sh) | x) & even_bit_esz_masks[i];
65
+ }
66
+ return x;
67
+}
68
+
69
+/* Compress units of 2**(N+1) bits to units of 2**N bits.
70
+ * For N==0, this corresponds to the operation that in qemu/bitops.h
71
+ * we call half_unshuffle64; this algorithm is from Hacker's Delight,
72
+ * section 7-2 Shuffling Bits, where it is called an inverse half shuffle.
73
+ */
74
+static uint64_t compress_bits(uint64_t x, int n)
75
+{
76
+ int i;
77
+
78
+ for (i = n; i <= 4; i++) {
79
+ int sh = 1 << i;
80
+ x &= even_bit_esz_masks[i];
81
+ x = (x >> sh) | x;
82
+ }
83
+ return x & 0xffffffffu;
84
+}
85
+
86
+void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
87
+{
88
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
89
+ int esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
90
+ intptr_t high = extract32(pred_desc, SIMD_DATA_SHIFT + 2, 1);
91
+ uint64_t *d = vd;
92
+ intptr_t i;
93
+
94
+ if (oprsz <= 8) {
95
+ uint64_t nn = *(uint64_t *)vn;
96
+ uint64_t mm = *(uint64_t *)vm;
97
+ int half = 4 * oprsz;
98
+
99
+ nn = extract64(nn, high * half, half);
100
+ mm = extract64(mm, high * half, half);
101
+ nn = expand_bits(nn, esz);
102
+ mm = expand_bits(mm, esz);
103
+ d[0] = nn + (mm << (1 << esz));
104
+ } else {
105
+ ARMPredicateReg tmp_n, tmp_m;
106
+
107
+ /* We produce output faster than we consume input.
108
+ Therefore we must be mindful of possible overlap. */
109
+ if ((vn - vd) < (uintptr_t)oprsz) {
110
+ vn = memcpy(&tmp_n, vn, oprsz);
111
+ }
69
+ }
112
+ if ((vm - vd) < (uintptr_t)oprsz) {
70
+ break;
113
+ vm = memcpy(&tmp_m, vm, oprsz);
71
+ case float_2nan_prop_ab:
114
+ }
72
+ which = is_nan(a->cls) ? 0 : 1;
115
+ if (high) {
73
+ break;
116
+ high = oprsz >> 1;
74
+ case float_2nan_prop_ba:
117
+ }
75
+ which = is_nan(b->cls) ? 1 : 0;
118
+
76
+ break;
119
+ if ((high & 3) == 0) {
77
+ case float_2nan_prop_x87:
120
+ uint32_t *n = vn, *m = vm;
78
+ /*
121
+ high >>= 2;
79
+ * This implements x87 NaN propagation rules:
122
+
80
+ * SNaN + QNaN => return the QNaN
123
+ for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
81
+ * two SNaNs => return the one with the larger significand, silenced
124
+ uint64_t nn = n[H4(high + i)];
82
+ * two QNaNs => return the one with the larger significand
125
+ uint64_t mm = m[H4(high + i)];
83
+ * SNaN and a non-NaN => return the SNaN, silenced
126
+
84
+ * QNaN and a non-NaN => return the QNaN
127
+ nn = expand_bits(nn, esz);
85
+ *
128
+ mm = expand_bits(mm, esz);
86
+ * If we get down to comparing significands and they are the same,
129
+ d[i] = nn + (mm << (1 << esz));
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;
130
+ }
100
+ }
131
+ } else {
101
+ } else {
132
+ uint8_t *n = vn, *m = vm;
102
+ which = 1;
133
+ uint16_t *d16 = vd;
103
+ }
104
+ break;
105
+ default:
106
+ g_assert_not_reached();
107
+ }
134
+
108
+
135
+ for (i = 0; i < oprsz / 2; i++) {
109
+ if (which) {
136
+ uint16_t nn = n[H1(high + i)];
110
+ a = b;
137
+ uint16_t mm = m[H1(high + i)];
111
+ }
138
+
112
+ if (is_snan(a->cls)) {
139
+ nn = expand_bits(nn, esz);
113
+ parts_silence_nan(a, s);
140
+ mm = expand_bits(mm, esz);
114
}
141
+ d16[H2(i)] = nn + (mm << (1 << esz));
115
return a;
142
+ }
116
}
143
+ }
117
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
144
+ }
145
+}
146
+
147
+void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
148
+{
149
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
150
+ int esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
151
+ int odd = extract32(pred_desc, SIMD_DATA_SHIFT + 2, 1) << esz;
152
+ uint64_t *d = vd, *n = vn, *m = vm;
153
+ uint64_t l, h;
154
+ intptr_t i;
155
+
156
+ if (oprsz <= 8) {
157
+ l = compress_bits(n[0] >> odd, esz);
158
+ h = compress_bits(m[0] >> odd, esz);
159
+ d[0] = extract64(l + (h << (4 * oprsz)), 0, 8 * oprsz);
160
+ } else {
161
+ ARMPredicateReg tmp_m;
162
+ intptr_t oprsz_16 = oprsz / 16;
163
+
164
+ if ((vm - vd) < (uintptr_t)oprsz) {
165
+ m = memcpy(&tmp_m, vm, oprsz);
166
+ }
167
+
168
+ for (i = 0; i < oprsz_16; i++) {
169
+ l = n[2 * i + 0];
170
+ h = n[2 * i + 1];
171
+ l = compress_bits(l >> odd, esz);
172
+ h = compress_bits(h >> odd, esz);
173
+ d[i] = l + (h << 32);
174
+ }
175
+
176
+ /* For VL which is not a power of 2, the results from M do not
177
+ align nicely with the uint64_t for D. Put the aligned results
178
+ from M into TMP_M and then copy it into place afterward. */
179
+ if (oprsz & 15) {
180
+ d[i] = compress_bits(n[2 * i] >> odd, esz);
181
+
182
+ for (i = 0; i < oprsz_16; i++) {
183
+ l = m[2 * i + 0];
184
+ h = m[2 * i + 1];
185
+ l = compress_bits(l >> odd, esz);
186
+ h = compress_bits(h >> odd, esz);
187
+ tmp_m.p[i] = l + (h << 32);
188
+ }
189
+ tmp_m.p[i] = compress_bits(m[2 * i] >> odd, esz);
190
+
191
+ swap_memmove(vd + oprsz / 2, &tmp_m, oprsz / 2);
192
+ } else {
193
+ for (i = 0; i < oprsz_16; i++) {
194
+ l = m[2 * i + 0];
195
+ h = m[2 * i + 1];
196
+ l = compress_bits(l >> odd, esz);
197
+ h = compress_bits(h >> odd, esz);
198
+ d[oprsz_16 + i] = l + (h << 32);
199
+ }
200
+ }
201
+ }
202
+}
203
+
204
+void HELPER(sve_trn_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
205
+{
206
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
207
+ uintptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
208
+ bool odd = extract32(pred_desc, SIMD_DATA_SHIFT + 2, 1);
209
+ uint64_t *d = vd, *n = vn, *m = vm;
210
+ uint64_t mask;
211
+ int shr, shl;
212
+ intptr_t i;
213
+
214
+ shl = 1 << esz;
215
+ shr = 0;
216
+ mask = even_bit_esz_masks[esz];
217
+ if (odd) {
218
+ mask <<= shl;
219
+ shr = shl;
220
+ shl = 0;
221
+ }
222
+
223
+ for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
224
+ uint64_t nn = (n[i] & mask) >> shr;
225
+ uint64_t mm = (m[i] & mask) << shl;
226
+ d[i] = nn + mm;
227
+ }
228
+}
229
+
230
+/* Reverse units of 2**N bits. */
231
+static uint64_t reverse_bits_64(uint64_t x, int n)
232
+{
233
+ int i, sh;
234
+
235
+ x = bswap64(x);
236
+ for (i = 2, sh = 4; i >= n; i--, sh >>= 1) {
237
+ uint64_t mask = even_bit_esz_masks[i];
238
+ x = ((x & mask) << sh) | ((x >> sh) & mask);
239
+ }
240
+ return x;
241
+}
242
+
243
+static uint8_t reverse_bits_8(uint8_t x, int n)
244
+{
245
+ static const uint8_t mask[3] = { 0x55, 0x33, 0x0f };
246
+ int i, sh;
247
+
248
+ for (i = 2, sh = 4; i >= n; i--, sh >>= 1) {
249
+ x = ((x & mask[i]) << sh) | ((x >> sh) & mask[i]);
250
+ }
251
+ return x;
252
+}
253
+
254
+void HELPER(sve_rev_p)(void *vd, void *vn, uint32_t pred_desc)
255
+{
256
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
257
+ int esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
258
+ intptr_t i, oprsz_2 = oprsz / 2;
259
+
260
+ if (oprsz <= 8) {
261
+ uint64_t l = *(uint64_t *)vn;
262
+ l = reverse_bits_64(l << (64 - 8 * oprsz), esz);
263
+ *(uint64_t *)vd = l;
264
+ } else if ((oprsz & 15) == 0) {
265
+ for (i = 0; i < oprsz_2; i += 8) {
266
+ intptr_t ih = oprsz - 8 - i;
267
+ uint64_t l = reverse_bits_64(*(uint64_t *)(vn + i), esz);
268
+ uint64_t h = reverse_bits_64(*(uint64_t *)(vn + ih), esz);
269
+ *(uint64_t *)(vd + i) = h;
270
+ *(uint64_t *)(vd + ih) = l;
271
+ }
272
+ } else {
273
+ for (i = 0; i < oprsz_2; i += 1) {
274
+ intptr_t il = H1(i);
275
+ intptr_t ih = H1(oprsz - 1 - i);
276
+ uint8_t l = reverse_bits_8(*(uint8_t *)(vn + il), esz);
277
+ uint8_t h = reverse_bits_8(*(uint8_t *)(vn + ih), esz);
278
+ *(uint8_t *)(vd + il) = h;
279
+ *(uint8_t *)(vd + ih) = l;
280
+ }
281
+ }
282
+}
283
+
284
+void HELPER(sve_punpk_p)(void *vd, void *vn, uint32_t pred_desc)
285
+{
286
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
287
+ intptr_t high = extract32(pred_desc, SIMD_DATA_SHIFT + 2, 1);
288
+ uint64_t *d = vd;
289
+ intptr_t i;
290
+
291
+ if (oprsz <= 8) {
292
+ uint64_t nn = *(uint64_t *)vn;
293
+ int half = 4 * oprsz;
294
+
295
+ nn = extract64(nn, high * half, half);
296
+ nn = expand_bits(nn, 0);
297
+ d[0] = nn;
298
+ } else {
299
+ ARMPredicateReg tmp_n;
300
+
301
+ /* We produce output faster than we consume input.
302
+ Therefore we must be mindful of possible overlap. */
303
+ if ((vn - vd) < (uintptr_t)oprsz) {
304
+ vn = memcpy(&tmp_n, vn, oprsz);
305
+ }
306
+ if (high) {
307
+ high = oprsz >> 1;
308
+ }
309
+
310
+ if ((high & 3) == 0) {
311
+ uint32_t *n = vn;
312
+ high >>= 2;
313
+
314
+ for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
315
+ uint64_t nn = n[H4(high + i)];
316
+ d[i] = expand_bits(nn, 0);
317
+ }
318
+ } else {
319
+ uint16_t *d16 = vd;
320
+ uint8_t *n = vn;
321
+
322
+ for (i = 0; i < oprsz / 2; i++) {
323
+ uint16_t nn = n[H1(high + i)];
324
+ d16[H2(i)] = expand_bits(nn, 0);
325
+ }
326
+ }
327
+ }
328
+}
329
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
330
index XXXXXXX..XXXXXXX 100644
118
index XXXXXXX..XXXXXXX 100644
331
--- a/target/arm/translate-sve.c
119
--- a/fpu/softfloat-specialize.c.inc
332
+++ b/target/arm/translate-sve.c
120
+++ b/fpu/softfloat-specialize.c.inc
333
@@ -XXX,XX +XXX,XX @@ static bool trans_UNPK(DisasContext *s, arg_UNPK *a, uint32_t insn)
121
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
334
return true;
122
}
335
}
123
}
336
124
337
+/*
125
-/*----------------------------------------------------------------------------
338
+ *** SVE Permute - Predicates Group
126
-| Select which NaN to propagate for a two-input operation.
339
+ */
127
-| IEEE754 doesn't specify all the details of this, so the
340
+
128
-| algorithm is target-specific.
341
+static bool do_perm_pred3(DisasContext *s, arg_rrr_esz *a, bool high_odd,
129
-| The routine is passed various bits of information about the
342
+ gen_helper_gvec_3 *fn)
130
-| two NaNs and should return 0 to select NaN a and 1 for NaN b.
343
+{
131
-| Note that signalling NaNs are always squashed to quiet NaNs
344
+ if (!sve_access_check(s)) {
132
-| by the caller, by calling floatXX_silence_nan() before
345
+ return true;
133
-| returning them.
346
+ }
134
-|
347
+
135
-| aIsLargerSignificand is only valid if both a and b are NaNs
348
+ unsigned vsz = pred_full_reg_size(s);
136
-| of some kind, and is true if a has the larger significand,
349
+
137
-| or if both a and b have the same significand but a is
350
+ /* Predicate sizes may be smaller and cannot use simd_desc.
138
-| positive but b is negative. It is only needed for the x87
351
+ We cannot round up, as we do elsewhere, because we need
139
-| tie-break rule.
352
+ the exact size for ZIP2 and REV. We retain the style for
140
-*----------------------------------------------------------------------------*/
353
+ the other helpers for consistency. */
141
-
354
+ TCGv_ptr t_d = tcg_temp_new_ptr();
142
-static int pickNaN(FloatClass a_cls, FloatClass b_cls,
355
+ TCGv_ptr t_n = tcg_temp_new_ptr();
143
- bool aIsLargerSignificand, float_status *status)
356
+ TCGv_ptr t_m = tcg_temp_new_ptr();
144
-{
357
+ TCGv_i32 t_desc;
145
- /*
358
+ int desc;
146
- * We guarantee not to require the target to tell us how to
359
+
147
- * pick a NaN if we're always returning the default NaN.
360
+ desc = vsz - 2;
148
- * But if we're not in default-NaN mode then the target must
361
+ desc = deposit32(desc, SIMD_DATA_SHIFT, 2, a->esz);
149
- * specify via set_float_2nan_prop_rule().
362
+ desc = deposit32(desc, SIMD_DATA_SHIFT + 2, 2, high_odd);
150
- */
363
+
151
- assert(!status->default_nan_mode);
364
+ tcg_gen_addi_ptr(t_d, cpu_env, pred_full_reg_offset(s, a->rd));
152
-
365
+ tcg_gen_addi_ptr(t_n, cpu_env, pred_full_reg_offset(s, a->rn));
153
- switch (status->float_2nan_prop_rule) {
366
+ tcg_gen_addi_ptr(t_m, cpu_env, pred_full_reg_offset(s, a->rm));
154
- case float_2nan_prop_s_ab:
367
+ t_desc = tcg_const_i32(desc);
155
- if (is_snan(a_cls)) {
368
+
156
- return 0;
369
+ fn(t_d, t_n, t_m, t_desc);
157
- } else if (is_snan(b_cls)) {
370
+
158
- return 1;
371
+ tcg_temp_free_ptr(t_d);
159
- } else if (is_qnan(a_cls)) {
372
+ tcg_temp_free_ptr(t_n);
160
- return 0;
373
+ tcg_temp_free_ptr(t_m);
161
- } else {
374
+ tcg_temp_free_i32(t_desc);
162
- return 1;
375
+ return true;
163
- }
376
+}
164
- break;
377
+
165
- case float_2nan_prop_s_ba:
378
+static bool do_perm_pred2(DisasContext *s, arg_rr_esz *a, bool high_odd,
166
- if (is_snan(b_cls)) {
379
+ gen_helper_gvec_2 *fn)
167
- return 1;
380
+{
168
- } else if (is_snan(a_cls)) {
381
+ if (!sve_access_check(s)) {
169
- return 0;
382
+ return true;
170
- } else if (is_qnan(b_cls)) {
383
+ }
171
- return 1;
384
+
172
- } else {
385
+ unsigned vsz = pred_full_reg_size(s);
173
- return 0;
386
+ TCGv_ptr t_d = tcg_temp_new_ptr();
174
- }
387
+ TCGv_ptr t_n = tcg_temp_new_ptr();
175
- break;
388
+ TCGv_i32 t_desc;
176
- case float_2nan_prop_ab:
389
+ int desc;
177
- if (is_nan(a_cls)) {
390
+
178
- return 0;
391
+ tcg_gen_addi_ptr(t_d, cpu_env, pred_full_reg_offset(s, a->rd));
179
- } else {
392
+ tcg_gen_addi_ptr(t_n, cpu_env, pred_full_reg_offset(s, a->rn));
180
- return 1;
393
+
181
- }
394
+ /* Predicate sizes may be smaller and cannot use simd_desc.
182
- break;
395
+ We cannot round up, as we do elsewhere, because we need
183
- case float_2nan_prop_ba:
396
+ the exact size for ZIP2 and REV. We retain the style for
184
- if (is_nan(b_cls)) {
397
+ the other helpers for consistency. */
185
- return 1;
398
+
186
- } else {
399
+ desc = vsz - 2;
187
- return 0;
400
+ desc = deposit32(desc, SIMD_DATA_SHIFT, 2, a->esz);
188
- }
401
+ desc = deposit32(desc, SIMD_DATA_SHIFT + 2, 2, high_odd);
189
- break;
402
+ t_desc = tcg_const_i32(desc);
190
- case float_2nan_prop_x87:
403
+
191
- /*
404
+ fn(t_d, t_n, t_desc);
192
- * This implements x87 NaN propagation rules:
405
+
193
- * SNaN + QNaN => return the QNaN
406
+ tcg_temp_free_i32(t_desc);
194
- * two SNaNs => return the one with the larger significand, silenced
407
+ tcg_temp_free_ptr(t_d);
195
- * two QNaNs => return the one with the larger significand
408
+ tcg_temp_free_ptr(t_n);
196
- * SNaN and a non-NaN => return the SNaN, silenced
409
+ return true;
197
- * QNaN and a non-NaN => return the QNaN
410
+}
198
- *
411
+
199
- * If we get down to comparing significands and they are the same,
412
+static bool trans_ZIP1_p(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
200
- * return the NaN with the positive sign bit (if any).
413
+{
201
- */
414
+ return do_perm_pred3(s, a, 0, gen_helper_sve_zip_p);
202
- if (is_snan(a_cls)) {
415
+}
203
- if (is_snan(b_cls)) {
416
+
204
- return aIsLargerSignificand ? 0 : 1;
417
+static bool trans_ZIP2_p(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
205
- }
418
+{
206
- return is_qnan(b_cls) ? 1 : 0;
419
+ return do_perm_pred3(s, a, 1, gen_helper_sve_zip_p);
207
- } else if (is_qnan(a_cls)) {
420
+}
208
- if (is_snan(b_cls) || !is_qnan(b_cls)) {
421
+
209
- return 0;
422
+static bool trans_UZP1_p(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
210
- } else {
423
+{
211
- return aIsLargerSignificand ? 0 : 1;
424
+ return do_perm_pred3(s, a, 0, gen_helper_sve_uzp_p);
212
- }
425
+}
213
- } else {
426
+
214
- return 1;
427
+static bool trans_UZP2_p(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
215
- }
428
+{
216
- default:
429
+ return do_perm_pred3(s, a, 1, gen_helper_sve_uzp_p);
217
- g_assert_not_reached();
430
+}
218
- }
431
+
219
-}
432
+static bool trans_TRN1_p(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
220
-
433
+{
221
/*----------------------------------------------------------------------------
434
+ return do_perm_pred3(s, a, 0, gen_helper_sve_trn_p);
222
| Returns 1 if the double-precision floating-point value `a' is a quiet
435
+}
223
| NaN; otherwise returns 0.
436
+
437
+static bool trans_TRN2_p(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
438
+{
439
+ return do_perm_pred3(s, a, 1, gen_helper_sve_trn_p);
440
+}
441
+
442
+static bool trans_REV_p(DisasContext *s, arg_rr_esz *a, uint32_t insn)
443
+{
444
+ return do_perm_pred2(s, a, 0, gen_helper_sve_rev_p);
445
+}
446
+
447
+static bool trans_PUNPKLO(DisasContext *s, arg_PUNPKLO *a, uint32_t insn)
448
+{
449
+ return do_perm_pred2(s, a, 0, gen_helper_sve_punpk_p);
450
+}
451
+
452
+static bool trans_PUNPKHI(DisasContext *s, arg_PUNPKHI *a, uint32_t insn)
453
+{
454
+ return do_perm_pred2(s, a, 1, gen_helper_sve_punpk_p);
455
+}
456
+
457
/*
458
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
459
*/
460
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
461
index XXXXXXX..XXXXXXX 100644
462
--- a/target/arm/sve.decode
463
+++ b/target/arm/sve.decode
464
@@ -XXX,XX +XXX,XX @@
465
466
# Three operand, vector element size
467
@rd_rn_rm ........ esz:2 . rm:5 ... ... rn:5 rd:5 &rrr_esz
468
+@pd_pn_pm ........ esz:2 .. rm:4 ....... rn:4 . rd:4 &rrr_esz
469
@rdn_rm ........ esz:2 ...... ...... rm:5 rd:5 \
470
&rrr_esz rn=%reg_movprfx
471
472
@@ -XXX,XX +XXX,XX @@ TBL 00000101 .. 1 ..... 001100 ..... ..... @rd_rn_rm
473
# SVE unpack vector elements
474
UNPK 00000101 esz:2 1100 u:1 h:1 001110 rn:5 rd:5
475
476
+### SVE Permute - Predicates Group
477
+
478
+# SVE permute predicate elements
479
+ZIP1_p 00000101 .. 10 .... 010 000 0 .... 0 .... @pd_pn_pm
480
+ZIP2_p 00000101 .. 10 .... 010 001 0 .... 0 .... @pd_pn_pm
481
+UZP1_p 00000101 .. 10 .... 010 010 0 .... 0 .... @pd_pn_pm
482
+UZP2_p 00000101 .. 10 .... 010 011 0 .... 0 .... @pd_pn_pm
483
+TRN1_p 00000101 .. 10 .... 010 100 0 .... 0 .... @pd_pn_pm
484
+TRN2_p 00000101 .. 10 .... 010 101 0 .... 0 .... @pd_pn_pm
485
+
486
+# SVE reverse predicate elements
487
+REV_p 00000101 .. 11 0100 010 000 0 .... 0 .... @pd_pn
488
+
489
+# SVE unpack predicate elements
490
+PUNPKLO 00000101 00 11 0000 010 000 0 .... 0 .... @pd_pn_e0
491
+PUNPKHI 00000101 00 11 0001 010 000 0 .... 0 .... @pd_pn_e0
492
+
493
### SVE Predicate Logical Operations Group
494
495
# SVE predicate logical operations
496
--
224
--
497
2.17.1
225
2.34.1
498
226
499
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
Remember if there was an SNaN, and use that to simplify
4
float_2nan_prop_s_{ab,ba} to only the snan component.
5
Then, fall through to the corresponding
6
float_2nan_prop_{ab,ba} case to handle any remaining
7
nans, which must be quiet.
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20241203203949.483774-10-richard.henderson@linaro.org
5
Message-id: 20180613015641.5667-13-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
13
---
8
target/arm/helper-sve.h | 44 +++++++++++++++++++
14
fpu/softfloat-parts.c.inc | 32 ++++++++++++--------------------
9
target/arm/sve_helper.c | 88 ++++++++++++++++++++++++++++++++++++++
15
1 file changed, 12 insertions(+), 20 deletions(-)
10
target/arm/translate-sve.c | 66 ++++++++++++++++++++++++++++
11
target/arm/sve.decode | 23 ++++++++++
12
4 files changed, 221 insertions(+)
13
16
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
19
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/helper-sve.h
20
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_cmplo_ppzw_s, TCG_CALL_NO_RWG,
21
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
19
DEF_HELPER_FLAGS_5(sve_cmpls_ppzw_s, TCG_CALL_NO_RWG,
22
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
20
i32, ptr, ptr, ptr, ptr, i32)
23
float_status *s)
21
24
{
22
+DEF_HELPER_FLAGS_4(sve_cmpeq_ppzi_b, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
25
+ bool have_snan = false;
23
+DEF_HELPER_FLAGS_4(sve_cmpne_ppzi_b, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
26
int cmp, which;
24
+DEF_HELPER_FLAGS_4(sve_cmpgt_ppzi_b, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
27
25
+DEF_HELPER_FLAGS_4(sve_cmpge_ppzi_b, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
28
if (is_snan(a->cls) || is_snan(b->cls)) {
26
+DEF_HELPER_FLAGS_4(sve_cmplt_ppzi_b, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
29
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
27
+DEF_HELPER_FLAGS_4(sve_cmple_ppzi_b, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
30
+ have_snan = true;
28
+DEF_HELPER_FLAGS_4(sve_cmphs_ppzi_b, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
31
}
29
+DEF_HELPER_FLAGS_4(sve_cmphi_ppzi_b, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
32
30
+DEF_HELPER_FLAGS_4(sve_cmplo_ppzi_b, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
33
if (s->default_nan_mode) {
31
+DEF_HELPER_FLAGS_4(sve_cmpls_ppzi_b, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
34
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
32
+
35
33
+DEF_HELPER_FLAGS_4(sve_cmpeq_ppzi_h, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
36
switch (s->float_2nan_prop_rule) {
34
+DEF_HELPER_FLAGS_4(sve_cmpne_ppzi_h, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
37
case float_2nan_prop_s_ab:
35
+DEF_HELPER_FLAGS_4(sve_cmpgt_ppzi_h, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
38
- if (is_snan(a->cls)) {
36
+DEF_HELPER_FLAGS_4(sve_cmpge_ppzi_h, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
39
- which = 0;
37
+DEF_HELPER_FLAGS_4(sve_cmplt_ppzi_h, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
40
- } else if (is_snan(b->cls)) {
38
+DEF_HELPER_FLAGS_4(sve_cmple_ppzi_h, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
41
- which = 1;
39
+DEF_HELPER_FLAGS_4(sve_cmphs_ppzi_h, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
42
- } else if (is_qnan(a->cls)) {
40
+DEF_HELPER_FLAGS_4(sve_cmphi_ppzi_h, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
43
- which = 0;
41
+DEF_HELPER_FLAGS_4(sve_cmplo_ppzi_h, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
44
- } else {
42
+DEF_HELPER_FLAGS_4(sve_cmpls_ppzi_h, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
45
- which = 1;
43
+
46
+ if (have_snan) {
44
+DEF_HELPER_FLAGS_4(sve_cmpeq_ppzi_s, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
47
+ which = is_snan(a->cls) ? 0 : 1;
45
+DEF_HELPER_FLAGS_4(sve_cmpne_ppzi_s, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
48
+ break;
46
+DEF_HELPER_FLAGS_4(sve_cmpgt_ppzi_s, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
49
}
47
+DEF_HELPER_FLAGS_4(sve_cmpge_ppzi_s, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
50
- break;
48
+DEF_HELPER_FLAGS_4(sve_cmplt_ppzi_s, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
51
- case float_2nan_prop_s_ba:
49
+DEF_HELPER_FLAGS_4(sve_cmple_ppzi_s, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
52
- if (is_snan(b->cls)) {
50
+DEF_HELPER_FLAGS_4(sve_cmphs_ppzi_s, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
53
- which = 1;
51
+DEF_HELPER_FLAGS_4(sve_cmphi_ppzi_s, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
54
- } else if (is_snan(a->cls)) {
52
+DEF_HELPER_FLAGS_4(sve_cmplo_ppzi_s, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
55
- which = 0;
53
+DEF_HELPER_FLAGS_4(sve_cmpls_ppzi_s, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
56
- } else if (is_qnan(b->cls)) {
54
+
57
- which = 1;
55
+DEF_HELPER_FLAGS_4(sve_cmpeq_ppzi_d, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
58
- } else {
56
+DEF_HELPER_FLAGS_4(sve_cmpne_ppzi_d, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
59
- which = 0;
57
+DEF_HELPER_FLAGS_4(sve_cmpgt_ppzi_d, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
60
- }
58
+DEF_HELPER_FLAGS_4(sve_cmpge_ppzi_d, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
61
- break;
59
+DEF_HELPER_FLAGS_4(sve_cmplt_ppzi_d, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
62
+ /* fall through */
60
+DEF_HELPER_FLAGS_4(sve_cmple_ppzi_d, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
63
case float_2nan_prop_ab:
61
+DEF_HELPER_FLAGS_4(sve_cmphs_ppzi_d, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
64
which = is_nan(a->cls) ? 0 : 1;
62
+DEF_HELPER_FLAGS_4(sve_cmphi_ppzi_d, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
65
break;
63
+DEF_HELPER_FLAGS_4(sve_cmplo_ppzi_d, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
66
+ case float_2nan_prop_s_ba:
64
+DEF_HELPER_FLAGS_4(sve_cmpls_ppzi_d, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32)
67
+ if (have_snan) {
65
+
68
+ which = is_snan(b->cls) ? 1 : 0;
66
DEF_HELPER_FLAGS_5(sve_and_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
69
+ break;
67
DEF_HELPER_FLAGS_5(sve_bic_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
70
+ }
68
DEF_HELPER_FLAGS_5(sve_eor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
71
+ /* fall through */
69
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
72
case float_2nan_prop_ba:
70
index XXXXXXX..XXXXXXX 100644
73
which = is_nan(b->cls) ? 1 : 0;
71
--- a/target/arm/sve_helper.c
74
break;
72
+++ b/target/arm/sve_helper.c
73
@@ -XXX,XX +XXX,XX @@ DO_CMP_PPZW_S(sve_cmpls_ppzw_s, uint32_t, uint64_t, <=)
74
#undef DO_CMP_PPZW_H
75
#undef DO_CMP_PPZW_S
76
#undef DO_CMP_PPZW
77
+
78
+/* Similar, but the second source is immediate. */
79
+#define DO_CMP_PPZI(NAME, TYPE, OP, H, MASK) \
80
+uint32_t HELPER(NAME)(void *vd, void *vn, void *vg, uint32_t desc) \
81
+{ \
82
+ intptr_t opr_sz = simd_oprsz(desc); \
83
+ uint32_t flags = PREDTEST_INIT; \
84
+ TYPE mm = simd_data(desc); \
85
+ intptr_t i = opr_sz; \
86
+ do { \
87
+ uint64_t out = 0, pg; \
88
+ do { \
89
+ i -= sizeof(TYPE), out <<= sizeof(TYPE); \
90
+ TYPE nn = *(TYPE *)(vn + H(i)); \
91
+ out |= nn OP mm; \
92
+ } while (i & 63); \
93
+ pg = *(uint64_t *)(vg + (i >> 3)) & MASK; \
94
+ out &= pg; \
95
+ *(uint64_t *)(vd + (i >> 3)) = out; \
96
+ flags = iter_predtest_bwd(out, pg, flags); \
97
+ } while (i > 0); \
98
+ return flags; \
99
+}
100
+
101
+#define DO_CMP_PPZI_B(NAME, TYPE, OP) \
102
+ DO_CMP_PPZI(NAME, TYPE, OP, H1, 0xffffffffffffffffull)
103
+#define DO_CMP_PPZI_H(NAME, TYPE, OP) \
104
+ DO_CMP_PPZI(NAME, TYPE, OP, H1_2, 0x5555555555555555ull)
105
+#define DO_CMP_PPZI_S(NAME, TYPE, OP) \
106
+ DO_CMP_PPZI(NAME, TYPE, OP, H1_4, 0x1111111111111111ull)
107
+#define DO_CMP_PPZI_D(NAME, TYPE, OP) \
108
+ DO_CMP_PPZI(NAME, TYPE, OP, , 0x0101010101010101ull)
109
+
110
+DO_CMP_PPZI_B(sve_cmpeq_ppzi_b, uint8_t, ==)
111
+DO_CMP_PPZI_H(sve_cmpeq_ppzi_h, uint16_t, ==)
112
+DO_CMP_PPZI_S(sve_cmpeq_ppzi_s, uint32_t, ==)
113
+DO_CMP_PPZI_D(sve_cmpeq_ppzi_d, uint64_t, ==)
114
+
115
+DO_CMP_PPZI_B(sve_cmpne_ppzi_b, uint8_t, !=)
116
+DO_CMP_PPZI_H(sve_cmpne_ppzi_h, uint16_t, !=)
117
+DO_CMP_PPZI_S(sve_cmpne_ppzi_s, uint32_t, !=)
118
+DO_CMP_PPZI_D(sve_cmpne_ppzi_d, uint64_t, !=)
119
+
120
+DO_CMP_PPZI_B(sve_cmpgt_ppzi_b, int8_t, >)
121
+DO_CMP_PPZI_H(sve_cmpgt_ppzi_h, int16_t, >)
122
+DO_CMP_PPZI_S(sve_cmpgt_ppzi_s, int32_t, >)
123
+DO_CMP_PPZI_D(sve_cmpgt_ppzi_d, int64_t, >)
124
+
125
+DO_CMP_PPZI_B(sve_cmpge_ppzi_b, int8_t, >=)
126
+DO_CMP_PPZI_H(sve_cmpge_ppzi_h, int16_t, >=)
127
+DO_CMP_PPZI_S(sve_cmpge_ppzi_s, int32_t, >=)
128
+DO_CMP_PPZI_D(sve_cmpge_ppzi_d, int64_t, >=)
129
+
130
+DO_CMP_PPZI_B(sve_cmphi_ppzi_b, uint8_t, >)
131
+DO_CMP_PPZI_H(sve_cmphi_ppzi_h, uint16_t, >)
132
+DO_CMP_PPZI_S(sve_cmphi_ppzi_s, uint32_t, >)
133
+DO_CMP_PPZI_D(sve_cmphi_ppzi_d, uint64_t, >)
134
+
135
+DO_CMP_PPZI_B(sve_cmphs_ppzi_b, uint8_t, >=)
136
+DO_CMP_PPZI_H(sve_cmphs_ppzi_h, uint16_t, >=)
137
+DO_CMP_PPZI_S(sve_cmphs_ppzi_s, uint32_t, >=)
138
+DO_CMP_PPZI_D(sve_cmphs_ppzi_d, uint64_t, >=)
139
+
140
+DO_CMP_PPZI_B(sve_cmplt_ppzi_b, int8_t, <)
141
+DO_CMP_PPZI_H(sve_cmplt_ppzi_h, int16_t, <)
142
+DO_CMP_PPZI_S(sve_cmplt_ppzi_s, int32_t, <)
143
+DO_CMP_PPZI_D(sve_cmplt_ppzi_d, int64_t, <)
144
+
145
+DO_CMP_PPZI_B(sve_cmple_ppzi_b, int8_t, <=)
146
+DO_CMP_PPZI_H(sve_cmple_ppzi_h, int16_t, <=)
147
+DO_CMP_PPZI_S(sve_cmple_ppzi_s, int32_t, <=)
148
+DO_CMP_PPZI_D(sve_cmple_ppzi_d, int64_t, <=)
149
+
150
+DO_CMP_PPZI_B(sve_cmplo_ppzi_b, uint8_t, <)
151
+DO_CMP_PPZI_H(sve_cmplo_ppzi_h, uint16_t, <)
152
+DO_CMP_PPZI_S(sve_cmplo_ppzi_s, uint32_t, <)
153
+DO_CMP_PPZI_D(sve_cmplo_ppzi_d, uint64_t, <)
154
+
155
+DO_CMP_PPZI_B(sve_cmpls_ppzi_b, uint8_t, <=)
156
+DO_CMP_PPZI_H(sve_cmpls_ppzi_h, uint16_t, <=)
157
+DO_CMP_PPZI_S(sve_cmpls_ppzi_s, uint32_t, <=)
158
+DO_CMP_PPZI_D(sve_cmpls_ppzi_d, uint64_t, <=)
159
+
160
+#undef DO_CMP_PPZI_B
161
+#undef DO_CMP_PPZI_H
162
+#undef DO_CMP_PPZI_S
163
+#undef DO_CMP_PPZI_D
164
+#undef DO_CMP_PPZI
165
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/target/arm/translate-sve.c
168
+++ b/target/arm/translate-sve.c
169
@@ -XXX,XX +XXX,XX @@
170
#include "translate-a64.h"
171
172
173
+typedef void gen_helper_gvec_flags_3(TCGv_i32, TCGv_ptr, TCGv_ptr,
174
+ TCGv_ptr, TCGv_i32);
175
typedef void gen_helper_gvec_flags_4(TCGv_i32, TCGv_ptr, TCGv_ptr,
176
TCGv_ptr, TCGv_ptr, TCGv_i32);
177
178
@@ -XXX,XX +XXX,XX @@ DO_PPZW(CMPLS, cmpls)
179
180
#undef DO_PPZW
181
182
+/*
183
+ *** SVE Integer Compare - Immediate Groups
184
+ */
185
+
186
+static bool do_ppzi_flags(DisasContext *s, arg_rpri_esz *a,
187
+ gen_helper_gvec_flags_3 *gen_fn)
188
+{
189
+ TCGv_ptr pd, zn, pg;
190
+ unsigned vsz;
191
+ TCGv_i32 t;
192
+
193
+ if (gen_fn == NULL) {
194
+ return false;
195
+ }
196
+ if (!sve_access_check(s)) {
197
+ return true;
198
+ }
199
+
200
+ vsz = vec_full_reg_size(s);
201
+ t = tcg_const_i32(simd_desc(vsz, vsz, a->imm));
202
+ pd = tcg_temp_new_ptr();
203
+ zn = tcg_temp_new_ptr();
204
+ pg = tcg_temp_new_ptr();
205
+
206
+ tcg_gen_addi_ptr(pd, cpu_env, pred_full_reg_offset(s, a->rd));
207
+ tcg_gen_addi_ptr(zn, cpu_env, vec_full_reg_offset(s, a->rn));
208
+ tcg_gen_addi_ptr(pg, cpu_env, pred_full_reg_offset(s, a->pg));
209
+
210
+ gen_fn(t, pd, zn, pg, t);
211
+
212
+ tcg_temp_free_ptr(pd);
213
+ tcg_temp_free_ptr(zn);
214
+ tcg_temp_free_ptr(pg);
215
+
216
+ do_pred_flags(t);
217
+
218
+ tcg_temp_free_i32(t);
219
+ return true;
220
+}
221
+
222
+#define DO_PPZI(NAME, name) \
223
+static bool trans_##NAME##_ppzi(DisasContext *s, arg_rpri_esz *a, \
224
+ uint32_t insn) \
225
+{ \
226
+ static gen_helper_gvec_flags_3 * const fns[4] = { \
227
+ gen_helper_sve_##name##_ppzi_b, gen_helper_sve_##name##_ppzi_h, \
228
+ gen_helper_sve_##name##_ppzi_s, gen_helper_sve_##name##_ppzi_d, \
229
+ }; \
230
+ return do_ppzi_flags(s, a, fns[a->esz]); \
231
+}
232
+
233
+DO_PPZI(CMPEQ, cmpeq)
234
+DO_PPZI(CMPNE, cmpne)
235
+DO_PPZI(CMPGT, cmpgt)
236
+DO_PPZI(CMPGE, cmpge)
237
+DO_PPZI(CMPHI, cmphi)
238
+DO_PPZI(CMPHS, cmphs)
239
+DO_PPZI(CMPLT, cmplt)
240
+DO_PPZI(CMPLE, cmple)
241
+DO_PPZI(CMPLO, cmplo)
242
+DO_PPZI(CMPLS, cmpls)
243
+
244
+#undef DO_PPZI
245
+
246
/*
247
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
248
*/
249
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
250
index XXXXXXX..XXXXXXX 100644
251
--- a/target/arm/sve.decode
252
+++ b/target/arm/sve.decode
253
@@ -XXX,XX +XXX,XX @@
254
@rdn_dbm ........ .. .... dbm:13 rd:5 \
255
&rr_dbm rn=%reg_movprfx
256
257
+# Predicate output, vector and immediate input,
258
+# controlling predicate, element size.
259
+@pd_pg_rn_i7 ........ esz:2 . imm:7 . pg:3 rn:5 . rd:4 &rpri_esz
260
+@pd_pg_rn_i5 ........ esz:2 . imm:s5 ... pg:3 rn:5 . rd:4 &rpri_esz
261
+
262
# Basic Load/Store with 9-bit immediate offset
263
@pd_rn_i9 ........ ........ ...... rn:5 . rd:4 \
264
&rri imm=%imm9_16_10
265
@@ -XXX,XX +XXX,XX @@ CMPHI_ppzw 00100100 .. 0 ..... 110 ... ..... 1 .... @pd_pg_rn_rm
266
CMPLO_ppzw 00100100 .. 0 ..... 111 ... ..... 0 .... @pd_pg_rn_rm
267
CMPLS_ppzw 00100100 .. 0 ..... 111 ... ..... 1 .... @pd_pg_rn_rm
268
269
+### SVE Integer Compare - Unsigned Immediate Group
270
+
271
+# SVE integer compare with unsigned immediate
272
+CMPHS_ppzi 00100100 .. 1 ....... 0 ... ..... 0 .... @pd_pg_rn_i7
273
+CMPHI_ppzi 00100100 .. 1 ....... 0 ... ..... 1 .... @pd_pg_rn_i7
274
+CMPLO_ppzi 00100100 .. 1 ....... 1 ... ..... 0 .... @pd_pg_rn_i7
275
+CMPLS_ppzi 00100100 .. 1 ....... 1 ... ..... 1 .... @pd_pg_rn_i7
276
+
277
+### SVE Integer Compare - Signed Immediate Group
278
+
279
+# SVE integer compare with signed immediate
280
+CMPGE_ppzi 00100101 .. 0 ..... 000 ... ..... 0 .... @pd_pg_rn_i5
281
+CMPGT_ppzi 00100101 .. 0 ..... 000 ... ..... 1 .... @pd_pg_rn_i5
282
+CMPLT_ppzi 00100101 .. 0 ..... 001 ... ..... 0 .... @pd_pg_rn_i5
283
+CMPLE_ppzi 00100101 .. 0 ..... 001 ... ..... 1 .... @pd_pg_rn_i5
284
+CMPEQ_ppzi 00100101 .. 0 ..... 100 ... ..... 0 .... @pd_pg_rn_i5
285
+CMPNE_ppzi 00100101 .. 0 ..... 100 ... ..... 1 .... @pd_pg_rn_i5
286
+
287
### SVE Predicate Logical Operations Group
288
289
# SVE predicate logical operations
290
--
75
--
291
2.17.1
76
2.34.1
292
293
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Move the fractional comparison to the end of the
4
float_2nan_prop_x87 case. This is not required for
5
any other 2nan propagation rule. Reorganize the
6
x87 case itself to break out of the switch when the
7
fractional comparison is not required.
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20241203203949.483774-11-richard.henderson@linaro.org
5
Message-id: 20180613015641.5667-7-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
13
---
8
target/arm/helper-sve.h | 2 +
14
fpu/softfloat-parts.c.inc | 19 +++++++++----------
9
target/arm/sve_helper.c | 12 ++
15
1 file changed, 9 insertions(+), 10 deletions(-)
10
target/arm/translate-sve.c | 328 +++++++++++++++++++++++++++++++++++++
11
target/arm/sve.decode | 20 +++
12
4 files changed, 362 insertions(+)
13
16
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
19
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/helper-sve.h
20
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_trn_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
21
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
19
DEF_HELPER_FLAGS_4(sve_compact_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
return a;
20
DEF_HELPER_FLAGS_4(sve_compact_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
21
22
+DEF_HELPER_FLAGS_2(sve_last_active_element, TCG_CALL_NO_RWG, s32, ptr, i32)
23
+
24
DEF_HELPER_FLAGS_5(sve_and_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
DEF_HELPER_FLAGS_5(sve_bic_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
DEF_HELPER_FLAGS_5(sve_eor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/sve_helper.c
30
+++ b/target/arm/sve_helper.c
31
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_compact_d)(void *vd, void *vn, void *vg, uint32_t desc)
32
d[j] = 0;
33
}
23
}
34
}
24
35
+
25
- cmp = frac_cmp(a, b);
36
+/* Similar to the ARM LastActiveElement pseudocode function, except the
26
- if (cmp == 0) {
37
+ * result is multiplied by the element size. This includes the not found
27
- cmp = a->sign < b->sign;
38
+ * indication; e.g. not found for esz=3 is -8.
28
- }
39
+ */
29
-
40
+int32_t HELPER(sve_last_active_element)(void *vg, uint32_t pred_desc)
30
switch (s->float_2nan_prop_rule) {
41
+{
31
case float_2nan_prop_s_ab:
42
+ intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
32
if (have_snan) {
43
+ intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
33
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
44
+
34
* return the NaN with the positive sign bit (if any).
45
+ return last_active_element(vg, DIV_ROUND_UP(oprsz, 8), esz);
35
*/
46
+}
36
if (is_snan(a->cls)) {
47
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
37
- if (is_snan(b->cls)) {
48
index XXXXXXX..XXXXXXX 100644
38
- which = cmp > 0 ? 0 : 1;
49
--- a/target/arm/translate-sve.c
39
- } else {
50
+++ b/target/arm/translate-sve.c
40
+ if (!is_snan(b->cls)) {
51
@@ -XXX,XX +XXX,XX @@ static bool trans_COMPACT(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
41
which = is_qnan(b->cls) ? 1 : 0;
52
return do_zpz_ool(s, a, fns[a->esz]);
42
+ break;
53
}
43
}
54
44
} else if (is_qnan(a->cls)) {
55
+/* Call the helper that computes the ARM LastActiveElement pseudocode
45
if (is_snan(b->cls) || !is_qnan(b->cls)) {
56
+ * function, scaled by the element size. This includes the not found
46
which = 0;
57
+ * indication; e.g. not found for esz=3 is -8.
47
- } else {
58
+ */
48
- which = cmp > 0 ? 0 : 1;
59
+static void find_last_active(DisasContext *s, TCGv_i32 ret, int esz, int pg)
49
+ break;
60
+{
50
}
61
+ /* Predicate sizes may be smaller and cannot use simd_desc. We cannot
51
} else {
62
+ * round up, as we do elsewhere, because we need the exact size.
52
which = 1;
63
+ */
53
+ break;
64
+ TCGv_ptr t_p = tcg_temp_new_ptr();
54
}
65
+ TCGv_i32 t_desc;
55
+ cmp = frac_cmp(a, b);
66
+ unsigned vsz = pred_full_reg_size(s);
56
+ if (cmp == 0) {
67
+ unsigned desc;
57
+ cmp = a->sign < b->sign;
68
+
58
+ }
69
+ desc = vsz - 2;
59
+ which = cmp > 0 ? 0 : 1;
70
+ desc = deposit32(desc, SIMD_DATA_SHIFT, 2, esz);
60
break;
71
+
61
default:
72
+ tcg_gen_addi_ptr(t_p, cpu_env, pred_full_reg_offset(s, pg));
62
g_assert_not_reached();
73
+ t_desc = tcg_const_i32(desc);
74
+
75
+ gen_helper_sve_last_active_element(ret, t_p, t_desc);
76
+
77
+ tcg_temp_free_i32(t_desc);
78
+ tcg_temp_free_ptr(t_p);
79
+}
80
+
81
+/* Increment LAST to the offset of the next element in the vector,
82
+ * wrapping around to 0.
83
+ */
84
+static void incr_last_active(DisasContext *s, TCGv_i32 last, int esz)
85
+{
86
+ unsigned vsz = vec_full_reg_size(s);
87
+
88
+ tcg_gen_addi_i32(last, last, 1 << esz);
89
+ if (is_power_of_2(vsz)) {
90
+ tcg_gen_andi_i32(last, last, vsz - 1);
91
+ } else {
92
+ TCGv_i32 max = tcg_const_i32(vsz);
93
+ TCGv_i32 zero = tcg_const_i32(0);
94
+ tcg_gen_movcond_i32(TCG_COND_GEU, last, last, max, zero, last);
95
+ tcg_temp_free_i32(max);
96
+ tcg_temp_free_i32(zero);
97
+ }
98
+}
99
+
100
+/* If LAST < 0, set LAST to the offset of the last element in the vector. */
101
+static void wrap_last_active(DisasContext *s, TCGv_i32 last, int esz)
102
+{
103
+ unsigned vsz = vec_full_reg_size(s);
104
+
105
+ if (is_power_of_2(vsz)) {
106
+ tcg_gen_andi_i32(last, last, vsz - 1);
107
+ } else {
108
+ TCGv_i32 max = tcg_const_i32(vsz - (1 << esz));
109
+ TCGv_i32 zero = tcg_const_i32(0);
110
+ tcg_gen_movcond_i32(TCG_COND_LT, last, last, zero, max, last);
111
+ tcg_temp_free_i32(max);
112
+ tcg_temp_free_i32(zero);
113
+ }
114
+}
115
+
116
+/* Load an unsigned element of ESZ from BASE+OFS. */
117
+static TCGv_i64 load_esz(TCGv_ptr base, int ofs, int esz)
118
+{
119
+ TCGv_i64 r = tcg_temp_new_i64();
120
+
121
+ switch (esz) {
122
+ case 0:
123
+ tcg_gen_ld8u_i64(r, base, ofs);
124
+ break;
125
+ case 1:
126
+ tcg_gen_ld16u_i64(r, base, ofs);
127
+ break;
128
+ case 2:
129
+ tcg_gen_ld32u_i64(r, base, ofs);
130
+ break;
131
+ case 3:
132
+ tcg_gen_ld_i64(r, base, ofs);
133
+ break;
134
+ default:
135
+ g_assert_not_reached();
136
+ }
137
+ return r;
138
+}
139
+
140
+/* Load an unsigned element of ESZ from RM[LAST]. */
141
+static TCGv_i64 load_last_active(DisasContext *s, TCGv_i32 last,
142
+ int rm, int esz)
143
+{
144
+ TCGv_ptr p = tcg_temp_new_ptr();
145
+ TCGv_i64 r;
146
+
147
+ /* Convert offset into vector into offset into ENV.
148
+ * The final adjustment for the vector register base
149
+ * is added via constant offset to the load.
150
+ */
151
+#ifdef HOST_WORDS_BIGENDIAN
152
+ /* Adjust for element ordering. See vec_reg_offset. */
153
+ if (esz < 3) {
154
+ tcg_gen_xori_i32(last, last, 8 - (1 << esz));
155
+ }
156
+#endif
157
+ tcg_gen_ext_i32_ptr(p, last);
158
+ tcg_gen_add_ptr(p, p, cpu_env);
159
+
160
+ r = load_esz(p, vec_full_reg_offset(s, rm), esz);
161
+ tcg_temp_free_ptr(p);
162
+
163
+ return r;
164
+}
165
+
166
+/* Compute CLAST for a Zreg. */
167
+static bool do_clast_vector(DisasContext *s, arg_rprr_esz *a, bool before)
168
+{
169
+ TCGv_i32 last;
170
+ TCGLabel *over;
171
+ TCGv_i64 ele;
172
+ unsigned vsz, esz = a->esz;
173
+
174
+ if (!sve_access_check(s)) {
175
+ return true;
176
+ }
177
+
178
+ last = tcg_temp_local_new_i32();
179
+ over = gen_new_label();
180
+
181
+ find_last_active(s, last, esz, a->pg);
182
+
183
+ /* There is of course no movcond for a 2048-bit vector,
184
+ * so we must branch over the actual store.
185
+ */
186
+ tcg_gen_brcondi_i32(TCG_COND_LT, last, 0, over);
187
+
188
+ if (!before) {
189
+ incr_last_active(s, last, esz);
190
+ }
191
+
192
+ ele = load_last_active(s, last, a->rm, esz);
193
+ tcg_temp_free_i32(last);
194
+
195
+ vsz = vec_full_reg_size(s);
196
+ tcg_gen_gvec_dup_i64(esz, vec_full_reg_offset(s, a->rd), vsz, vsz, ele);
197
+ tcg_temp_free_i64(ele);
198
+
199
+ /* If this insn used MOVPRFX, we may need a second move. */
200
+ if (a->rd != a->rn) {
201
+ TCGLabel *done = gen_new_label();
202
+ tcg_gen_br(done);
203
+
204
+ gen_set_label(over);
205
+ do_mov_z(s, a->rd, a->rn);
206
+
207
+ gen_set_label(done);
208
+ } else {
209
+ gen_set_label(over);
210
+ }
211
+ return true;
212
+}
213
+
214
+static bool trans_CLASTA_z(DisasContext *s, arg_rprr_esz *a, uint32_t insn)
215
+{
216
+ return do_clast_vector(s, a, false);
217
+}
218
+
219
+static bool trans_CLASTB_z(DisasContext *s, arg_rprr_esz *a, uint32_t insn)
220
+{
221
+ return do_clast_vector(s, a, true);
222
+}
223
+
224
+/* Compute CLAST for a scalar. */
225
+static void do_clast_scalar(DisasContext *s, int esz, int pg, int rm,
226
+ bool before, TCGv_i64 reg_val)
227
+{
228
+ TCGv_i32 last = tcg_temp_new_i32();
229
+ TCGv_i64 ele, cmp, zero;
230
+
231
+ find_last_active(s, last, esz, pg);
232
+
233
+ /* Extend the original value of last prior to incrementing. */
234
+ cmp = tcg_temp_new_i64();
235
+ tcg_gen_ext_i32_i64(cmp, last);
236
+
237
+ if (!before) {
238
+ incr_last_active(s, last, esz);
239
+ }
240
+
241
+ /* The conceit here is that while last < 0 indicates not found, after
242
+ * adjusting for cpu_env->vfp.zregs[rm], it is still a valid address
243
+ * from which we can load garbage. We then discard the garbage with
244
+ * a conditional move.
245
+ */
246
+ ele = load_last_active(s, last, rm, esz);
247
+ tcg_temp_free_i32(last);
248
+
249
+ zero = tcg_const_i64(0);
250
+ tcg_gen_movcond_i64(TCG_COND_GE, reg_val, cmp, zero, ele, reg_val);
251
+
252
+ tcg_temp_free_i64(zero);
253
+ tcg_temp_free_i64(cmp);
254
+ tcg_temp_free_i64(ele);
255
+}
256
+
257
+/* Compute CLAST for a Vreg. */
258
+static bool do_clast_fp(DisasContext *s, arg_rpr_esz *a, bool before)
259
+{
260
+ if (sve_access_check(s)) {
261
+ int esz = a->esz;
262
+ int ofs = vec_reg_offset(s, a->rd, 0, esz);
263
+ TCGv_i64 reg = load_esz(cpu_env, ofs, esz);
264
+
265
+ do_clast_scalar(s, esz, a->pg, a->rn, before, reg);
266
+ write_fp_dreg(s, a->rd, reg);
267
+ tcg_temp_free_i64(reg);
268
+ }
269
+ return true;
270
+}
271
+
272
+static bool trans_CLASTA_v(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
273
+{
274
+ return do_clast_fp(s, a, false);
275
+}
276
+
277
+static bool trans_CLASTB_v(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
278
+{
279
+ return do_clast_fp(s, a, true);
280
+}
281
+
282
+/* Compute CLAST for a Xreg. */
283
+static bool do_clast_general(DisasContext *s, arg_rpr_esz *a, bool before)
284
+{
285
+ TCGv_i64 reg;
286
+
287
+ if (!sve_access_check(s)) {
288
+ return true;
289
+ }
290
+
291
+ reg = cpu_reg(s, a->rd);
292
+ switch (a->esz) {
293
+ case 0:
294
+ tcg_gen_ext8u_i64(reg, reg);
295
+ break;
296
+ case 1:
297
+ tcg_gen_ext16u_i64(reg, reg);
298
+ break;
299
+ case 2:
300
+ tcg_gen_ext32u_i64(reg, reg);
301
+ break;
302
+ case 3:
303
+ break;
304
+ default:
305
+ g_assert_not_reached();
306
+ }
307
+
308
+ do_clast_scalar(s, a->esz, a->pg, a->rn, before, reg);
309
+ return true;
310
+}
311
+
312
+static bool trans_CLASTA_r(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
313
+{
314
+ return do_clast_general(s, a, false);
315
+}
316
+
317
+static bool trans_CLASTB_r(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
318
+{
319
+ return do_clast_general(s, a, true);
320
+}
321
+
322
+/* Compute LAST for a scalar. */
323
+static TCGv_i64 do_last_scalar(DisasContext *s, int esz,
324
+ int pg, int rm, bool before)
325
+{
326
+ TCGv_i32 last = tcg_temp_new_i32();
327
+ TCGv_i64 ret;
328
+
329
+ find_last_active(s, last, esz, pg);
330
+ if (before) {
331
+ wrap_last_active(s, last, esz);
332
+ } else {
333
+ incr_last_active(s, last, esz);
334
+ }
335
+
336
+ ret = load_last_active(s, last, rm, esz);
337
+ tcg_temp_free_i32(last);
338
+ return ret;
339
+}
340
+
341
+/* Compute LAST for a Vreg. */
342
+static bool do_last_fp(DisasContext *s, arg_rpr_esz *a, bool before)
343
+{
344
+ if (sve_access_check(s)) {
345
+ TCGv_i64 val = do_last_scalar(s, a->esz, a->pg, a->rn, before);
346
+ write_fp_dreg(s, a->rd, val);
347
+ tcg_temp_free_i64(val);
348
+ }
349
+ return true;
350
+}
351
+
352
+static bool trans_LASTA_v(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
353
+{
354
+ return do_last_fp(s, a, false);
355
+}
356
+
357
+static bool trans_LASTB_v(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
358
+{
359
+ return do_last_fp(s, a, true);
360
+}
361
+
362
+/* Compute LAST for a Xreg. */
363
+static bool do_last_general(DisasContext *s, arg_rpr_esz *a, bool before)
364
+{
365
+ if (sve_access_check(s)) {
366
+ TCGv_i64 val = do_last_scalar(s, a->esz, a->pg, a->rn, before);
367
+ tcg_gen_mov_i64(cpu_reg(s, a->rd), val);
368
+ tcg_temp_free_i64(val);
369
+ }
370
+ return true;
371
+}
372
+
373
+static bool trans_LASTA_r(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
374
+{
375
+ return do_last_general(s, a, false);
376
+}
377
+
378
+static bool trans_LASTB_r(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
379
+{
380
+ return do_last_general(s, a, true);
381
+}
382
+
383
/*
384
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
385
*/
386
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
387
index XXXXXXX..XXXXXXX 100644
388
--- a/target/arm/sve.decode
389
+++ b/target/arm/sve.decode
390
@@ -XXX,XX +XXX,XX @@ TRN2_z 00000101 .. 1 ..... 011 101 ..... ..... @rd_rn_rm
391
# Note esz >= 2
392
COMPACT 00000101 .. 100001 100 ... ..... ..... @rd_pg_rn
393
394
+# SVE conditionally broadcast element to vector
395
+CLASTA_z 00000101 .. 10100 0 100 ... ..... ..... @rdn_pg_rm
396
+CLASTB_z 00000101 .. 10100 1 100 ... ..... ..... @rdn_pg_rm
397
+
398
+# SVE conditionally copy element to SIMD&FP scalar
399
+CLASTA_v 00000101 .. 10101 0 100 ... ..... ..... @rd_pg_rn
400
+CLASTB_v 00000101 .. 10101 1 100 ... ..... ..... @rd_pg_rn
401
+
402
+# SVE conditionally copy element to general register
403
+CLASTA_r 00000101 .. 11000 0 101 ... ..... ..... @rd_pg_rn
404
+CLASTB_r 00000101 .. 11000 1 101 ... ..... ..... @rd_pg_rn
405
+
406
+# SVE copy element to SIMD&FP scalar register
407
+LASTA_v 00000101 .. 10001 0 100 ... ..... ..... @rd_pg_rn
408
+LASTB_v 00000101 .. 10001 1 100 ... ..... ..... @rd_pg_rn
409
+
410
+# SVE copy element to general register
411
+LASTA_r 00000101 .. 10000 0 101 ... ..... ..... @rd_pg_rn
412
+LASTB_r 00000101 .. 10000 1 101 ... ..... ..... @rd_pg_rn
413
+
414
### SVE Predicate Logical Operations Group
415
416
# SVE predicate logical operations
417
--
63
--
418
2.17.1
64
2.34.1
419
420
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Replace the "index" selecting between A and B with a result variable
4
of the proper type. This improves clarity within the function.
5
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180613015641.5667-6-richard.henderson@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-12-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 3 +++
11
fpu/softfloat-parts.c.inc | 28 +++++++++++++---------------
9
target/arm/sve_helper.c | 34 ++++++++++++++++++++++++++++++++++
12
1 file changed, 13 insertions(+), 15 deletions(-)
10
target/arm/translate-sve.c | 12 ++++++++++++
11
target/arm/sve.decode | 6 ++++++
12
4 files changed, 55 insertions(+)
13
13
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
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/target/arm/helper-sve.h
16
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/helper-sve.h
17
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_trn_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
19
DEF_HELPER_FLAGS_4(sve_trn_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
19
float_status *s)
20
DEF_HELPER_FLAGS_4(sve_trn_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
20
{
21
21
bool have_snan = false;
22
+DEF_HELPER_FLAGS_4(sve_compact_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
- int cmp, which;
23
+DEF_HELPER_FLAGS_4(sve_compact_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
+ FloatPartsN *ret;
24
+
24
+ int cmp;
25
DEF_HELPER_FLAGS_5(sve_and_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
26
DEF_HELPER_FLAGS_5(sve_bic_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
if (is_snan(a->cls) || is_snan(b->cls)) {
27
DEF_HELPER_FLAGS_5(sve_eor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
28
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
28
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
29
index XXXXXXX..XXXXXXX 100644
29
switch (s->float_2nan_prop_rule) {
30
--- a/target/arm/sve_helper.c
30
case float_2nan_prop_s_ab:
31
+++ b/target/arm/sve_helper.c
31
if (have_snan) {
32
@@ -XXX,XX +XXX,XX @@ DO_TRN(sve_trn_d, uint64_t, )
32
- which = is_snan(a->cls) ? 0 : 1;
33
#undef DO_ZIP
33
+ ret = is_snan(a->cls) ? a : b;
34
#undef DO_UZP
34
break;
35
#undef DO_TRN
35
}
36
+
36
/* fall through */
37
+void HELPER(sve_compact_s)(void *vd, void *vn, void *vg, uint32_t desc)
37
case float_2nan_prop_ab:
38
+{
38
- which = is_nan(a->cls) ? 0 : 1;
39
+ intptr_t i, j, opr_sz = simd_oprsz(desc) / 4;
39
+ ret = is_nan(a->cls) ? a : b;
40
+ uint32_t *d = vd, *n = vn;
40
break;
41
+ uint8_t *pg = vg;
41
case float_2nan_prop_s_ba:
42
+
42
if (have_snan) {
43
+ for (i = j = 0; i < opr_sz; i++) {
43
- which = is_snan(b->cls) ? 1 : 0;
44
+ if (pg[H1(i / 2)] & (i & 1 ? 0x10 : 0x01)) {
44
+ ret = is_snan(b->cls) ? b : a;
45
+ d[H4(j)] = n[H4(i)];
45
break;
46
+ j++;
46
}
47
+ }
47
/* fall through */
48
+ }
48
case float_2nan_prop_ba:
49
+ for (; j < opr_sz; j++) {
49
- which = is_nan(b->cls) ? 1 : 0;
50
+ d[H4(j)] = 0;
50
+ ret = is_nan(b->cls) ? b : a;
51
+ }
51
break;
52
+}
52
case float_2nan_prop_x87:
53
+
53
/*
54
+void HELPER(sve_compact_d)(void *vd, void *vn, void *vg, uint32_t desc)
54
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
55
+{
55
*/
56
+ intptr_t i, j, opr_sz = simd_oprsz(desc) / 8;
56
if (is_snan(a->cls)) {
57
+ uint64_t *d = vd, *n = vn;
57
if (!is_snan(b->cls)) {
58
+ uint8_t *pg = vg;
58
- which = is_qnan(b->cls) ? 1 : 0;
59
+
59
+ ret = is_qnan(b->cls) ? b : a;
60
+ for (i = j = 0; i < opr_sz; i++) {
60
break;
61
+ if (pg[H1(i)] & 1) {
61
}
62
+ d[j] = n[i];
62
} else if (is_qnan(a->cls)) {
63
+ j++;
63
if (is_snan(b->cls) || !is_qnan(b->cls)) {
64
+ }
64
- which = 0;
65
+ }
65
+ ret = a;
66
+ for (; j < opr_sz; j++) {
66
break;
67
+ d[j] = 0;
67
}
68
+ }
68
} else {
69
+}
69
- which = 1;
70
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
70
+ ret = b;
71
index XXXXXXX..XXXXXXX 100644
71
break;
72
--- a/target/arm/translate-sve.c
72
}
73
+++ b/target/arm/translate-sve.c
73
cmp = frac_cmp(a, b);
74
@@ -XXX,XX +XXX,XX @@ static bool trans_TRN2_z(DisasContext *s, arg_rrr_esz *a, uint32_t insn)
74
if (cmp == 0) {
75
return do_zzz_data_ool(s, a, 1 << a->esz, trn_fns[a->esz]);
75
cmp = a->sign < b->sign;
76
}
77
- which = cmp > 0 ? 0 : 1;
78
+ ret = cmp > 0 ? a : b;
79
break;
80
default:
81
g_assert_not_reached();
82
}
83
84
- if (which) {
85
- a = b;
86
+ if (is_snan(ret->cls)) {
87
+ parts_silence_nan(ret, s);
88
}
89
- if (is_snan(a->cls)) {
90
- parts_silence_nan(a, s);
91
- }
92
- return a;
93
+ return ret;
76
}
94
}
77
95
78
+/*
96
static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
79
+ *** SVE Permute Vector - Predicated Group
80
+ */
81
+
82
+static bool trans_COMPACT(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
83
+{
84
+ static gen_helper_gvec_3 * const fns[4] = {
85
+ NULL, NULL, gen_helper_sve_compact_s, gen_helper_sve_compact_d
86
+ };
87
+ return do_zpz_ool(s, a, fns[a->esz]);
88
+}
89
+
90
/*
91
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
92
*/
93
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/sve.decode
96
+++ b/target/arm/sve.decode
97
@@ -XXX,XX +XXX,XX @@ UZP2_z 00000101 .. 1 ..... 011 011 ..... ..... @rd_rn_rm
98
TRN1_z 00000101 .. 1 ..... 011 100 ..... ..... @rd_rn_rm
99
TRN2_z 00000101 .. 1 ..... 011 101 ..... ..... @rd_rn_rm
100
101
+### SVE Permute - Predicated Group
102
+
103
+# SVE compress active elements
104
+# Note esz >= 2
105
+COMPACT 00000101 .. 100001 100 ... ..... ..... @rd_pg_rn
106
+
107
### SVE Predicate Logical Operations Group
108
109
# SVE predicate logical operations
110
--
97
--
111
2.17.1
98
2.34.1
112
99
113
100
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
Rearrange the arithmetic so that we are agnostic about the total size
3
I'm migrating to Qualcomm's new open source email infrastructure, so
4
of the vector and the size of the element. This will allow us to index
4
update my email address, and update the mailmap to match.
5
up to the 32nd byte and with 16-byte elements.
6
5
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
9
Message-id: 20180613015641.5667-2-richard.henderson@linaro.org
8
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20241205114047.1125842-1-leif.lindholm@oss.qualcomm.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
target/arm/translate-a64.h | 26 +++++++++++++++++---------
14
MAINTAINERS | 2 +-
13
1 file changed, 17 insertions(+), 9 deletions(-)
15
.mailmap | 5 +++--
16
2 files changed, 4 insertions(+), 3 deletions(-)
14
17
15
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
18
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.h
20
--- a/MAINTAINERS
18
+++ b/target/arm/translate-a64.h
21
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ static inline void assert_fp_access_checked(DisasContext *s)
22
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
20
static inline int vec_reg_offset(DisasContext *s, int regno,
23
SBSA-REF
21
int element, TCGMemOp size)
24
M: Radoslaw Biernacki <rad@semihalf.com>
22
{
25
M: Peter Maydell <peter.maydell@linaro.org>
23
- int offs = 0;
26
-R: Leif Lindholm <quic_llindhol@quicinc.com>
24
+ int element_size = 1 << size;
27
+R: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
25
+ int offs = element * element_size;
28
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
26
#ifdef HOST_WORDS_BIGENDIAN
29
L: qemu-arm@nongnu.org
27
/* This is complicated slightly because vfp.zregs[n].d[0] is
30
S: Maintained
28
- * still the low half and vfp.zregs[n].d[1] the high half
31
diff --git a/.mailmap b/.mailmap
29
- * of the 128 bit vector, even on big endian systems.
32
index XXXXXXX..XXXXXXX 100644
30
- * Calculate the offset assuming a fully bigendian 128 bits,
33
--- a/.mailmap
31
- * then XOR to account for the order of the two 64 bit halves.
34
+++ b/.mailmap
32
+ * still the lowest and vfp.zregs[n].d[15] the highest of the
35
@@ -XXX,XX +XXX,XX @@ Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
33
+ * 256 byte vector, even on big endian systems.
36
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
34
+ *
37
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
35
+ * Calculate the offset assuming fully little-endian,
38
Juan Quintela <quintela@trasno.org> <quintela@redhat.com>
36
+ * then XOR to account for the order of the 8-byte units.
39
-Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
37
+ *
40
-Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
38
+ * For 16 byte elements, the two 8 byte halves will not form a
41
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <quic_llindhol@quicinc.com>
39
+ * host int128 if the host is bigendian, since they're in the
42
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif.lindholm@linaro.org>
40
+ * wrong order. However the only 16 byte operation we have is
43
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif@nuviainc.com>
41
+ * a move, so we can ignore this for the moment. More complicated
44
Luc Michel <luc@lmichel.fr> <luc.michel@git.antfield.fr>
42
+ * operations will have to special case loading and storing from
45
Luc Michel <luc@lmichel.fr> <luc.michel@greensocs.com>
43
+ * the zregs array.
46
Luc Michel <luc@lmichel.fr> <lmichel@kalray.eu>
44
*/
45
- offs += (16 - ((element + 1) * (1 << size)));
46
- offs ^= 8;
47
-#else
48
- offs += element * (1 << size);
49
+ if (element_size < 8) {
50
+ offs ^= 8 - element_size;
51
+ }
52
#endif
53
offs += offsetof(CPUARMState, vfp.zregs[regno]);
54
assert_fp_access_checked(s);
55
--
47
--
56
2.17.1
48
2.34.1
57
49
58
50
diff view generated by jsdifflib
1
From: Shannon Zhao <zhaoshenglong@huawei.com>
1
From: Vikram Garhwal <vikram.garhwal@bytedance.com>
2
2
3
While for_each_dist_irq_reg loop starts from GIC_INTERNAL, it forgot to
3
Previously, maintainer role was paused due to inactive email id. Commit id:
4
offset the date array and index. This will overlap the GICR registers
4
c009d715721861984c4987bcc78b7ee183e86d75.
5
value and leave the last GIC_INTERNAL irq's registers out of update.
6
5
7
Fixes: 367b9f527becdd20ddf116e17a3c0c2bbc486920
6
Signed-off-by: Vikram Garhwal <vikram.garhwal@bytedance.com>
8
Cc: qemu-stable@nongnu.org
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241204184205.12952-1-vikram.garhwal@bytedance.com
10
Reviewed-by: Eric Auger <eric.auger@redhat.com>
11
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
hw/intc/arm_gicv3_kvm.c | 18 ++++++++++++++++--
11
MAINTAINERS | 2 ++
15
1 file changed, 16 insertions(+), 2 deletions(-)
12
1 file changed, 2 insertions(+)
16
13
17
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
14
diff --git a/MAINTAINERS b/MAINTAINERS
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/intc/arm_gicv3_kvm.c
16
--- a/MAINTAINERS
20
+++ b/hw/intc/arm_gicv3_kvm.c
17
+++ b/MAINTAINERS
21
@@ -XXX,XX +XXX,XX @@ static void kvm_dist_get_priority(GICv3State *s, uint32_t offset, uint8_t *bmp)
18
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-sb16-test.c
22
uint32_t reg, *field;
19
23
int irq;
20
Xilinx CAN
24
21
M: Francisco Iglesias <francisco.iglesias@amd.com>
25
- field = (uint32_t *)bmp;
22
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
26
+ /* For the KVM GICv3, affinity routing is always enabled, and the first 8
23
S: Maintained
27
+ * GICD_IPRIORITYR<n> registers are always RAZ/WI. The corresponding
24
F: hw/net/can/xlnx-*
28
+ * functionality is replaced by GICR_IPRIORITYR<n>. It doesn't need to
25
F: include/hw/net/xlnx-*
29
+ * sync them. So it needs to skip the field of GIC_INTERNAL irqs in bmp and
26
@@ -XXX,XX +XXX,XX @@ F: include/hw/rx/
30
+ * offset.
27
CAN bus subsystem and hardware
31
+ */
28
M: Pavel Pisa <pisa@cmp.felk.cvut.cz>
32
+ field = (uint32_t *)(bmp + GIC_INTERNAL);
29
M: Francisco Iglesias <francisco.iglesias@amd.com>
33
+ offset += (GIC_INTERNAL * 8) / 8;
30
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
34
for_each_dist_irq_reg(irq, s->num_irq, 8) {
31
S: Maintained
35
kvm_gicd_access(s, offset, &reg, false);
32
W: https://canbus.pages.fel.cvut.cz/
36
*field = reg;
33
F: net/can/*
37
@@ -XXX,XX +XXX,XX @@ static void kvm_dist_put_priority(GICv3State *s, uint32_t offset, uint8_t *bmp)
38
uint32_t reg, *field;
39
int irq;
40
41
- field = (uint32_t *)bmp;
42
+ /* For the KVM GICv3, affinity routing is always enabled, and the first 8
43
+ * GICD_IPRIORITYR<n> registers are always RAZ/WI. The corresponding
44
+ * functionality is replaced by GICR_IPRIORITYR<n>. It doesn't need to
45
+ * sync them. So it needs to skip the field of GIC_INTERNAL irqs in bmp and
46
+ * offset.
47
+ */
48
+ field = (uint32_t *)(bmp + GIC_INTERNAL);
49
+ offset += (GIC_INTERNAL * 8) / 8;
50
for_each_dist_irq_reg(irq, s->num_irq, 8) {
51
reg = *field;
52
kvm_gicd_access(s, offset, &reg, true);
53
--
34
--
54
2.17.1
35
2.34.1
55
56
diff view generated by jsdifflib