1
Just my fp16 work, plus some small stuff for the sbsa-ref board;
1
First arm pullreq of the cycle; this is mostly my softfloat NaN
2
but my rule of thumb is to send a pullreq once I get over about
2
handling series. (Lots more in my to-review queue, but I don't
3
30 patches...
3
like pullreqs growing too close to a hundred patches at a time :-))
4
4
5
thanks
5
-- PMM
6
-- PMM
6
7
7
The following changes since commit 2f4c51c0f384d7888a04b4815861e6d5fd244d75:
8
The following changes since commit 97f2796a3736ed37a1b85dc1c76a6c45b829dd17:
8
9
9
Merge remote-tracking branch 'remotes/kraxel/tags/usb-20200831-pull-request' into staging (2020-08-31 19:39:13 +0100)
10
Open 10.0 development tree (2024-12-10 17:41:17 +0000)
10
11
11
are available in the Git repository at:
12
are available in the Git repository at:
12
13
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200901
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20241211
14
15
15
for you to fetch changes up to 3f462bf0f6ea6382dd1502d4eb1fcd33c8e774f5:
16
for you to fetch changes up to 1abe28d519239eea5cf9620bb13149423e5665f8:
16
17
17
hw/arm/sbsa-ref : Add embedded controller in secure memory (2020-09-01 14:01:34 +0100)
18
MAINTAINERS: Add correct email address for Vikram Garhwal (2024-12-11 15:31:09 +0000)
18
19
19
----------------------------------------------------------------
20
----------------------------------------------------------------
20
target-arm queue:
21
target-arm queue:
21
* Implement fp16 support for AArch32 VFP and Neon
22
* hw/net/lan9118: Extract PHY model, reuse with imx_fec, fix bugs
22
* hw/arm/sbsa-ref: add "reg" property to DT cpu nodes
23
* fpu: Make muladd NaN handling runtime-selected, not compile-time
23
* hw/arm/sbsa-ref : Add embedded controller in secure memory
24
* fpu: Make default NaN pattern runtime-selected, not compile-time
25
* fpu: Minor NaN-related cleanups
26
* MAINTAINERS: email address updates
24
27
25
----------------------------------------------------------------
28
----------------------------------------------------------------
26
Graeme Gregory (2):
29
Bernhard Beschow (5):
27
hw/misc/sbsa_ec : Add an embedded controller for sbsa-ref
30
hw/net/lan9118: Extract lan9118_phy
28
hw/arm/sbsa-ref : Add embedded controller in secure memory
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
29
35
30
Leif Lindholm (1):
36
Leif Lindholm (1):
31
hw/arm/sbsa-ref: add "reg" property to DT cpu nodes
37
MAINTAINERS: update email address for Leif Lindholm
32
38
33
Peter Maydell (44):
39
Peter Maydell (54):
34
target/arm: Remove local definitions of float constants
40
fpu: handle raising Invalid for infzero in pick_nan_muladd
35
target/arm: Use correct ID register check for aa32_fp16_arith
41
fpu: Check for default_nan_mode before calling pickNaNMulAdd
36
target/arm: Implement VFP fp16 for VFP_BINOP operations
42
softfloat: Allow runtime choice of inf * 0 + NaN result
37
target/arm: Implement VFP fp16 VMLA, VMLS, VNMLS, VNMLA, VNMUL
43
tests/fp: Explicitly set inf-zero-nan rule
38
target/arm: Macroify trans functions for VFMA, VFMS, VFNMA, VFNMS
44
target/arm: Set FloatInfZeroNaNRule explicitly
39
target/arm: Implement VFP fp16 for fused-multiply-add
45
target/s390: Set FloatInfZeroNaNRule explicitly
40
target/arm: Macroify uses of do_vfp_2op_sp() and do_vfp_2op_dp()
46
target/ppc: Set FloatInfZeroNaNRule explicitly
41
target/arm: Implement VFP fp16 for VABS, VNEG, VSQRT
47
target/mips: Set FloatInfZeroNaNRule explicitly
42
target/arm: Implement VFP fp16 for VMOV immediate
48
target/sparc: Set FloatInfZeroNaNRule explicitly
43
target/arm: Implement VFP fp16 VCMP
49
target/xtensa: Set FloatInfZeroNaNRule explicitly
44
target/arm: Implement VFP fp16 VLDR and VSTR
50
target/x86: Set FloatInfZeroNaNRule explicitly
45
target/arm: Implement VFP fp16 VCVT between float and integer
51
target/loongarch: Set FloatInfZeroNaNRule explicitly
46
target/arm: Make VFP_CONV_FIX macros take separate float type and float size
52
target/hppa: Set FloatInfZeroNaNRule explicitly
47
target/arm: Use macros instead of open-coding fp16 conversion helpers
53
softfloat: Pass have_snan to pickNaNMulAdd
48
target/arm: Implement VFP fp16 VCVT between float and fixed-point
54
softfloat: Allow runtime choice of NaN propagation for muladd
49
target/arm: Implement VFP vp16 VCVT-with-specified-rounding-mode
55
tests/fp: Explicitly set 3-NaN propagation rule
50
target/arm: Implement VFP fp16 VSEL
56
target/arm: Set Float3NaNPropRule explicitly
51
target/arm: Implement VFP fp16 VRINT*
57
target/loongarch: Set Float3NaNPropRule explicitly
52
target/arm: Implement new VFP fp16 insn VINS
58
target/ppc: Set Float3NaNPropRule explicitly
53
target/arm: Implement new VFP fp16 insn VMOVX
59
target/s390x: Set Float3NaNPropRule explicitly
54
target/arm: Implement VFP fp16 VMOV between gp and halfprec registers
60
target/sparc: Set Float3NaNPropRule explicitly
55
target/arm: Implement FP16 for Neon VADD, VSUB, VABD, VMUL
61
target/mips: Set Float3NaNPropRule explicitly
56
target/arm: Implement fp16 for Neon VRECPE, VRSQRTE using gvec
62
target/xtensa: Set Float3NaNPropRule explicitly
57
target/arm: Implement fp16 for Neon VABS, VNEG of floats
63
target/i386: Set Float3NaNPropRule explicitly
58
target/arm: Implement fp16 for VCEQ, VCGE, VCGT comparisons
64
target/hppa: Set Float3NaNPropRule explicitly
59
target/arm: Implement fp16 for VACGE, VACGT
65
fpu: Remove use_first_nan field from float_status
60
target/arm: Implement fp16 for Neon VMAX, VMIN
66
target/m68k: Don't pass NULL float_status to floatx80_default_nan()
61
target/arm: Implement fp16 for Neon VMAXNM, VMINNM
67
softfloat: Create floatx80 default NaN from parts64_default_nan
62
target/arm: Implement fp16 for Neon VMLA, VMLS operations
68
target/loongarch: Use normal float_status in fclass_s and fclass_d helpers
63
target/arm: Implement fp16 for Neon VFMA, VMFS
69
target/m68k: In frem helper, initialize local float_status from env->fp_status
64
target/arm: Implement fp16 for Neon fp compare-vs-0
70
target/m68k: Init local float_status from env fp_status in gdb get/set reg
65
target/arm: Implement fp16 for Neon VRECPS
71
target/sparc: Initialize local scratch float_status from env->fp_status
66
target/arm: Implement fp16 for Neon VRSQRTS
72
target/ppc: Use env->fp_status in helper_compute_fprf functions
67
target/arm: Implement fp16 for Neon pairwise fp ops
73
fpu: Allow runtime choice of default NaN value
68
target/arm: Implement fp16 for Neon float-integer VCVT
74
tests/fp: Set default NaN pattern explicitly
69
target/arm: Convert Neon VCVT fixed-point to gvec
75
target/microblaze: Set default NaN pattern explicitly
70
target/arm: Implement fp16 for Neon VCVT fixed-point
76
target/i386: Set default NaN pattern explicitly
71
target/arm: Implement fp16 for Neon VCVT with rounding modes
77
target/hppa: Set default NaN pattern explicitly
72
target/arm: Implement fp16 for Neon VRINT-with-specified-rounding-mode
78
target/alpha: Set default NaN pattern explicitly
73
target/arm: Implement fp16 for Neon VRINTX
79
target/arm: Set default NaN pattern explicitly
74
target/arm/vec_helper: Handle oprsz less than 16 bytes in indexed operations
80
target/loongarch: Set default NaN pattern explicitly
75
target/arm/vec_helper: Add gvec fp indexed multiply-and-add operations
81
target/m68k: Set default NaN pattern explicitly
76
target/arm: Implement fp16 for Neon VMUL, VMLA, VMLS
82
target/mips: Set default NaN pattern explicitly
77
target/arm: Enable FP16 in '-cpu max'
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
78
94
79
target/arm/cpu.h | 7 +-
95
Richard Henderson (11):
80
target/arm/helper.h | 133 ++++++-
96
target/arm: Copy entire float_status in is_ebf
81
target/arm/neon-dp.decode | 8 +-
97
softfloat: Inline pickNaNMulAdd
82
target/arm/vfp-uncond.decode | 27 +-
98
softfloat: Use goto for default nan case in pick_nan_muladd
83
target/arm/vfp.decode | 34 +-
99
softfloat: Remove which from parts_pick_nan_muladd
84
hw/arm/sbsa-ref.c | 43 ++-
100
softfloat: Pad array size in pick_nan_muladd
85
hw/misc/sbsa_ec.c | 98 +++++
101
softfloat: Move propagateFloatx80NaN to softfloat.c
86
target/arm/cpu.c | 3 +-
102
softfloat: Use parts_pick_nan in propagateFloatx80NaN
87
target/arm/cpu64.c | 10 +-
103
softfloat: Inline pickNaN
88
target/arm/helper-a64.c | 11 -
104
softfloat: Share code between parts_pick_nan cases
89
target/arm/translate-sve.c | 4 -
105
softfloat: Sink frac_cmp in parts_pick_nan until needed
90
target/arm/vec_helper.c | 431 ++++++++++++++++++++-
106
softfloat: Replace WHICH with RET in parts_pick_nan
91
target/arm/vfp_helper.c | 244 +++++-------
92
hw/misc/meson.build | 2 +
93
target/arm/translate-neon.c.inc | 755 +++++++++++++------------------------
94
target/arm/translate-vfp.c.inc | 810 ++++++++++++++++++++++++++++++++++++----
95
16 files changed, 1819 insertions(+), 801 deletions(-)
96
create mode 100644 hw/misc/sbsa_ec.c
97
107
108
Vikram Garhwal (1):
109
MAINTAINERS: Add correct email address for Vikram Garhwal
110
111
MAINTAINERS | 4 +-
112
include/fpu/softfloat-helpers.h | 38 +++-
113
include/fpu/softfloat-types.h | 89 +++++++-
114
include/hw/net/imx_fec.h | 9 +-
115
include/hw/net/lan9118_phy.h | 37 ++++
116
include/hw/net/mii.h | 6 +
117
target/mips/fpu_helper.h | 20 ++
118
target/sparc/helper.h | 4 +-
119
fpu/softfloat.c | 19 ++
120
hw/net/imx_fec.c | 146 ++------------
121
hw/net/lan9118.c | 137 ++-----------
122
hw/net/lan9118_phy.c | 222 ++++++++++++++++++++
123
linux-user/arm/nwfpe/fpa11.c | 5 +
124
target/alpha/cpu.c | 2 +
125
target/arm/cpu.c | 10 +
126
target/arm/tcg/vec_helper.c | 20 +-
127
target/hexagon/cpu.c | 2 +
128
target/hppa/fpu_helper.c | 12 ++
129
target/i386/tcg/fpu_helper.c | 12 ++
130
target/loongarch/tcg/fpu_helper.c | 14 +-
131
target/m68k/cpu.c | 14 +-
132
target/m68k/fpu_helper.c | 6 +-
133
target/m68k/helper.c | 6 +-
134
target/microblaze/cpu.c | 2 +
135
target/mips/msa.c | 10 +
136
target/openrisc/cpu.c | 2 +
137
target/ppc/cpu_init.c | 19 ++
138
target/ppc/fpu_helper.c | 3 +-
139
target/riscv/cpu.c | 2 +
140
target/rx/cpu.c | 2 +
141
target/s390x/cpu.c | 5 +
142
target/sh4/cpu.c | 2 +
143
target/sparc/cpu.c | 6 +
144
target/sparc/fop_helper.c | 8 +-
145
target/sparc/translate.c | 4 +-
146
target/tricore/helper.c | 2 +
147
target/xtensa/cpu.c | 4 +
148
target/xtensa/fpu_helper.c | 3 +-
149
tests/fp/fp-bench.c | 7 +
150
tests/fp/fp-test-log2.c | 1 +
151
tests/fp/fp-test.c | 7 +
152
fpu/softfloat-parts.c.inc | 152 +++++++++++---
153
fpu/softfloat-specialize.c.inc | 412 ++------------------------------------
154
.mailmap | 5 +-
155
hw/net/Kconfig | 5 +
156
hw/net/meson.build | 1 +
157
hw/net/trace-events | 10 +-
158
47 files changed, 778 insertions(+), 730 deletions(-)
159
create mode 100644 include/hw/net/lan9118_phy.h
160
create mode 100644 hw/net/lan9118_phy.c
diff view generated by jsdifflib
1
From: Graeme Gregory <graeme@nuviainc.com>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
A difference between sbsa platform and the virt platform is PSCI is
3
A very similar implementation of the same device exists in imx_fec. Prepare for
4
handled by ARM-TF in the sbsa platform. This means that the PSCI code
4
a common implementation by extracting a device model into its own files.
5
there needs to communicate some of the platform power changes down
6
to the qemu code for things like shutdown/reset control.
7
5
8
Space has been left to extend the EC if we find other use cases in
6
Some migration state has been moved into the new device model which breaks
9
future where ARM-TF and qemu need to communicate.
7
migration compatibility for the following machines:
8
* smdkc210
9
* realview-*
10
* vexpress-*
11
* kzm
12
* mps2-*
10
13
11
Signed-off-by: Graeme Gregory <graeme@nuviainc.com>
14
While breaking migration ABI, fix the size of the MII registers to be 16 bit,
12
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
15
as defined by IEEE 802.3u.
13
Tested-by: Leif Lindholm <leif@nuviainc.com>
16
14
Message-id: 20200826141952.136164-2-graeme@nuviainc.com
17
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
18
Tested-by: Guenter Roeck <linux@roeck-us.net>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Message-id: 20241102125724.532843-2-shentey@gmail.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
22
---
18
hw/misc/sbsa_ec.c | 98 +++++++++++++++++++++++++++++++++++++++++++++
23
include/hw/net/lan9118_phy.h | 37 ++++++++
19
hw/misc/meson.build | 2 +
24
hw/net/lan9118.c | 137 +++++-----------------------
20
2 files changed, 100 insertions(+)
25
hw/net/lan9118_phy.c | 169 +++++++++++++++++++++++++++++++++++
21
create mode 100644 hw/misc/sbsa_ec.c
26
hw/net/Kconfig | 4 +
27
hw/net/meson.build | 1 +
28
5 files changed, 233 insertions(+), 115 deletions(-)
29
create mode 100644 include/hw/net/lan9118_phy.h
30
create mode 100644 hw/net/lan9118_phy.c
22
31
23
diff --git a/hw/misc/sbsa_ec.c b/hw/misc/sbsa_ec.c
32
diff --git a/include/hw/net/lan9118_phy.h b/include/hw/net/lan9118_phy.h
24
new file mode 100644
33
new file mode 100644
25
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
26
--- /dev/null
35
--- /dev/null
27
+++ b/hw/misc/sbsa_ec.c
36
+++ b/include/hw/net/lan9118_phy.h
28
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
29
+/*
38
+/*
30
+ * ARM SBSA Reference Platform Embedded Controller
39
+ * SMSC LAN9118 PHY emulation
31
+ *
40
+ *
32
+ * A device to allow PSCI running in the secure side of sbsa-ref machine
41
+ * Copyright (c) 2009 CodeSourcery, LLC.
33
+ * to communicate platform power states to qemu.
42
+ * Written by Paul Brook
34
+ *
43
+ *
35
+ * Copyright (c) 2020 Nuvia Inc
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
36
+ * Written by Graeme Gregory <graeme@nuviainc.com>
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
76
index XXXXXXX..XXXXXXX 100644
77
--- a/hw/net/lan9118.c
78
+++ b/hw/net/lan9118.c
79
@@ -XXX,XX +XXX,XX @@
80
#include "net/net.h"
81
#include "net/eth.h"
82
#include "hw/irq.h"
83
+#include "hw/net/lan9118_phy.h"
84
#include "hw/net/lan9118.h"
85
#include "hw/ptimer.h"
86
#include "hw/qdev-properties.h"
87
@@ -XXX,XX +XXX,XX @@ do { printf("lan9118: " fmt , ## __VA_ARGS__); } while (0)
88
#define MAC_CR_RXEN 0x00000004
89
#define MAC_CR_RESERVED 0x7f404213
90
91
-#define PHY_INT_ENERGYON 0x80
92
-#define PHY_INT_AUTONEG_COMPLETE 0x40
93
-#define PHY_INT_FAULT 0x20
94
-#define PHY_INT_DOWN 0x10
95
-#define PHY_INT_AUTONEG_LP 0x08
96
-#define PHY_INT_PARFAULT 0x04
97
-#define PHY_INT_AUTONEG_PAGE 0x02
98
-
99
#define GPT_TIMER_EN 0x20000000
100
101
/*
102
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
103
uint32_t mac_mii_data;
104
uint32_t mac_flow;
105
106
- uint32_t phy_status;
107
- uint32_t phy_control;
108
- uint32_t phy_advertise;
109
- uint32_t phy_int;
110
- uint32_t phy_int_mask;
111
+ Lan9118PhyState mii;
112
+ IRQState mii_irq;
113
114
int32_t eeprom_writable;
115
uint8_t eeprom[128];
116
@@ -XXX,XX +XXX,XX @@ struct lan9118_state {
117
118
static const VMStateDescription vmstate_lan9118 = {
119
.name = "lan9118",
120
- .version_id = 2,
121
- .minimum_version_id = 1,
122
+ .version_id = 3,
123
+ .minimum_version_id = 3,
124
.fields = (const VMStateField[]) {
125
VMSTATE_PTIMER(timer, lan9118_state),
126
VMSTATE_UINT32(irq_cfg, lan9118_state),
127
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118 = {
128
VMSTATE_UINT32(mac_mii_acc, lan9118_state),
129
VMSTATE_UINT32(mac_mii_data, lan9118_state),
130
VMSTATE_UINT32(mac_flow, lan9118_state),
131
- VMSTATE_UINT32(phy_status, lan9118_state),
132
- VMSTATE_UINT32(phy_control, lan9118_state),
133
- VMSTATE_UINT32(phy_advertise, lan9118_state),
134
- VMSTATE_UINT32(phy_int, lan9118_state),
135
- VMSTATE_UINT32(phy_int_mask, lan9118_state),
136
VMSTATE_INT32(eeprom_writable, lan9118_state),
137
VMSTATE_UINT8_ARRAY(eeprom, lan9118_state, 128),
138
VMSTATE_INT32(tx_fifo_size, lan9118_state),
139
@@ -XXX,XX +XXX,XX @@ static void lan9118_reload_eeprom(lan9118_state *s)
140
lan9118_mac_changed(s);
141
}
142
143
-static void phy_update_irq(lan9118_state *s)
144
+static void lan9118_update_irq(void *opaque, int n, int level)
145
{
146
- if (s->phy_int & s->phy_int_mask) {
147
+ lan9118_state *s = opaque;
148
+
149
+ if (level) {
150
s->int_sts |= PHY_INT;
151
} else {
152
s->int_sts &= ~PHY_INT;
153
@@ -XXX,XX +XXX,XX @@ static void phy_update_irq(lan9118_state *s)
154
lan9118_update(s);
155
}
156
157
-static void phy_update_link(lan9118_state *s)
158
-{
159
- /* Autonegotiation status mirrors link status. */
160
- if (qemu_get_queue(s->nic)->link_down) {
161
- s->phy_status &= ~0x0024;
162
- s->phy_int |= PHY_INT_DOWN;
163
- } else {
164
- s->phy_status |= 0x0024;
165
- s->phy_int |= PHY_INT_ENERGYON;
166
- s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
167
- }
168
- phy_update_irq(s);
169
-}
170
-
171
static void lan9118_set_link(NetClientState *nc)
172
{
173
- phy_update_link(qemu_get_nic_opaque(nc));
174
-}
175
-
176
-static void phy_reset(lan9118_state *s)
177
-{
178
- s->phy_status = 0x7809;
179
- s->phy_control = 0x3000;
180
- s->phy_advertise = 0x01e1;
181
- s->phy_int_mask = 0;
182
- s->phy_int = 0;
183
- phy_update_link(s);
184
+ lan9118_phy_update_link(&LAN9118(qemu_get_nic_opaque(nc))->mii,
185
+ nc->link_down);
186
}
187
188
static void lan9118_reset(DeviceState *d)
189
@@ -XXX,XX +XXX,XX @@ static void lan9118_reset(DeviceState *d)
190
s->read_word_n = 0;
191
s->write_word_n = 0;
192
193
- phy_reset(s);
194
-
195
s->eeprom_writable = 0;
196
lan9118_reload_eeprom(s);
197
}
198
@@ -XXX,XX +XXX,XX @@ static void do_tx_packet(lan9118_state *s)
199
uint32_t status;
200
201
/* FIXME: Honor TX disable, and allow queueing of packets. */
202
- if (s->phy_control & 0x4000) {
203
+ if (s->mii.control & 0x4000) {
204
/* This assumes the receive routine doesn't touch the VLANClient. */
205
qemu_receive_packet(qemu_get_queue(s->nic), s->txp->data, s->txp->len);
206
} else {
207
@@ -XXX,XX +XXX,XX @@ static void tx_fifo_push(lan9118_state *s, uint32_t val)
208
}
209
}
210
211
-static uint32_t do_phy_read(lan9118_state *s, int reg)
212
-{
213
- uint32_t val;
214
-
215
- switch (reg) {
216
- case 0: /* Basic Control */
217
- return s->phy_control;
218
- case 1: /* Basic Status */
219
- return s->phy_status;
220
- case 2: /* ID1 */
221
- return 0x0007;
222
- case 3: /* ID2 */
223
- return 0xc0d1;
224
- case 4: /* Auto-neg advertisement */
225
- return s->phy_advertise;
226
- case 5: /* Auto-neg Link Partner Ability */
227
- return 0x0f71;
228
- case 6: /* Auto-neg Expansion */
229
- return 1;
230
- /* TODO 17, 18, 27, 29, 30, 31 */
231
- case 29: /* Interrupt source. */
232
- val = s->phy_int;
233
- s->phy_int = 0;
234
- phy_update_irq(s);
235
- return val;
236
- case 30: /* Interrupt mask */
237
- return s->phy_int_mask;
238
- default:
239
- qemu_log_mask(LOG_GUEST_ERROR,
240
- "do_phy_read: PHY read reg %d\n", reg);
241
- return 0;
242
- }
243
-}
244
-
245
-static void do_phy_write(lan9118_state *s, int reg, uint32_t val)
246
-{
247
- switch (reg) {
248
- case 0: /* Basic Control */
249
- if (val & 0x8000) {
250
- phy_reset(s);
251
- break;
252
- }
253
- s->phy_control = val & 0x7980;
254
- /* Complete autonegotiation immediately. */
255
- if (val & 0x1000) {
256
- s->phy_status |= 0x0020;
257
- }
258
- break;
259
- case 4: /* Auto-neg advertisement */
260
- s->phy_advertise = (val & 0x2d7f) | 0x80;
261
- break;
262
- /* TODO 17, 18, 27, 31 */
263
- case 30: /* Interrupt mask */
264
- s->phy_int_mask = val & 0xff;
265
- phy_update_irq(s);
266
- break;
267
- default:
268
- qemu_log_mask(LOG_GUEST_ERROR,
269
- "do_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
270
- }
271
-}
272
-
273
static void do_mac_write(lan9118_state *s, int reg, uint32_t val)
274
{
275
switch (reg) {
276
@@ -XXX,XX +XXX,XX @@ static void do_mac_write(lan9118_state *s, int reg, uint32_t val)
277
if (val & 2) {
278
DPRINTF("PHY write %d = 0x%04x\n",
279
(val >> 6) & 0x1f, s->mac_mii_data);
280
- do_phy_write(s, (val >> 6) & 0x1f, s->mac_mii_data);
281
+ lan9118_phy_write(&s->mii, (val >> 6) & 0x1f, s->mac_mii_data);
282
} else {
283
- s->mac_mii_data = do_phy_read(s, (val >> 6) & 0x1f);
284
+ s->mac_mii_data = lan9118_phy_read(&s->mii, (val >> 6) & 0x1f);
285
DPRINTF("PHY read %d = 0x%04x\n",
286
(val >> 6) & 0x1f, s->mac_mii_data);
287
}
288
@@ -XXX,XX +XXX,XX @@ static void lan9118_writel(void *opaque, hwaddr offset,
289
break;
290
case CSR_PMT_CTRL:
291
if (val & 0x400) {
292
- phy_reset(s);
293
+ lan9118_phy_reset(&s->mii);
294
}
295
s->pmt_ctrl &= ~0x34e;
296
s->pmt_ctrl |= (val & 0x34e);
297
@@ -XXX,XX +XXX,XX @@ static void lan9118_realize(DeviceState *dev, Error **errp)
298
const MemoryRegionOps *mem_ops =
299
s->mode_16bit ? &lan9118_16bit_mem_ops : &lan9118_mem_ops;
300
301
+ qemu_init_irq(&s->mii_irq, lan9118_update_irq, s, 0);
302
+ object_initialize_child(OBJECT(s), "mii", &s->mii, TYPE_LAN9118_PHY);
303
+ if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->mii), errp)) {
304
+ return;
305
+ }
306
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
307
+
308
memory_region_init_io(&s->mmio, OBJECT(dev), mem_ops, s,
309
"lan9118-mmio", 0x100);
310
sysbus_init_mmio(sbd, &s->mmio);
311
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
312
new file mode 100644
313
index XXXXXXX..XXXXXXX
314
--- /dev/null
315
+++ b/hw/net/lan9118_phy.c
316
@@ -XXX,XX +XXX,XX @@
317
+/*
318
+ * SMSC LAN9118 PHY emulation
37
+ *
319
+ *
38
+ * SPDX-License-Identifer: GPL-2.0-or-later
320
+ * Copyright (c) 2009 CodeSourcery, LLC.
321
+ * Written by Paul Brook
322
+ *
323
+ * This code is licensed under the GNU GPL v2
324
+ *
325
+ * Contributions after 2012-01-13 are licensed under the terms of the
326
+ * GNU GPL, version 2 or (at your option) any later version.
39
+ */
327
+ */
40
+
328
+
41
+#include "qemu/osdep.h"
329
+#include "qemu/osdep.h"
42
+#include "qemu-common.h"
330
+#include "hw/net/lan9118_phy.h"
331
+#include "hw/irq.h"
332
+#include "hw/resettable.h"
333
+#include "migration/vmstate.h"
43
+#include "qemu/log.h"
334
+#include "qemu/log.h"
44
+#include "hw/sysbus.h"
335
+
45
+#include "sysemu/runstate.h"
336
+#define PHY_INT_ENERGYON (1 << 7)
46
+
337
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
47
+typedef struct {
338
+#define PHY_INT_FAULT (1 << 5)
48
+ SysBusDevice parent_obj;
339
+#define PHY_INT_DOWN (1 << 4)
49
+ MemoryRegion iomem;
340
+#define PHY_INT_AUTONEG_LP (1 << 3)
50
+} SECUREECState;
341
+#define PHY_INT_PARFAULT (1 << 2)
51
+
342
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
52
+#define TYPE_SBSA_EC "sbsa-ec"
343
+
53
+#define SECURE_EC(obj) OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_EC)
344
+static void lan9118_phy_update_irq(Lan9118PhyState *s)
54
+
345
+{
55
+enum sbsa_ec_powerstates {
346
+ qemu_set_irq(s->irq, !!(s->ints & s->int_mask));
56
+ SBSA_EC_CMD_POWEROFF = 0x01,
347
+}
57
+ SBSA_EC_CMD_REBOOT = 0x02,
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;
380
+ }
381
+}
382
+
383
+void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
384
+{
385
+ switch (reg) {
386
+ case 0: /* Basic Control */
387
+ if (val & 0x8000) {
388
+ lan9118_phy_reset(s);
389
+ break;
390
+ }
391
+ s->control = val & 0x7980;
392
+ /* Complete autonegotiation immediately. */
393
+ if (val & 0x1000) {
394
+ s->status |= 0x0020;
395
+ }
396
+ break;
397
+ case 4: /* Auto-neg advertisement */
398
+ s->advertise = (val & 0x2d7f) | 0x80;
399
+ break;
400
+ /* TODO 17, 18, 27, 31 */
401
+ case 30: /* Interrupt mask */
402
+ s->int_mask = val & 0xff;
403
+ lan9118_phy_update_irq(s);
404
+ break;
405
+ default:
406
+ qemu_log_mask(LOG_GUEST_ERROR,
407
+ "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
408
+ }
409
+}
410
+
411
+void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
412
+{
413
+ s->link_down = link_down;
414
+
415
+ /* Autonegotiation status mirrors link status. */
416
+ if (link_down) {
417
+ s->status &= ~0x0024;
418
+ s->ints |= PHY_INT_DOWN;
419
+ } else {
420
+ s->status |= 0x0024;
421
+ s->ints |= PHY_INT_ENERGYON;
422
+ s->ints |= PHY_INT_AUTONEG_COMPLETE;
423
+ }
424
+ lan9118_phy_update_irq(s);
425
+}
426
+
427
+void lan9118_phy_reset(Lan9118PhyState *s)
428
+{
429
+ s->control = 0x3000;
430
+ s->status = 0x7809;
431
+ s->advertise = 0x01e1;
432
+ s->int_mask = 0;
433
+ s->ints = 0;
434
+ lan9118_phy_update_link(s, s->link_down);
435
+}
436
+
437
+static void lan9118_phy_reset_hold(Object *obj, ResetType type)
438
+{
439
+ Lan9118PhyState *s = LAN9118_PHY(obj);
440
+
441
+ lan9118_phy_reset(s);
442
+}
443
+
444
+static void lan9118_phy_init(Object *obj)
445
+{
446
+ Lan9118PhyState *s = LAN9118_PHY(obj);
447
+
448
+ qdev_init_gpio_out(DEVICE(s), &s->irq, 1);
449
+}
450
+
451
+static const VMStateDescription vmstate_lan9118_phy = {
452
+ .name = "lan9118-phy",
453
+ .version_id = 1,
454
+ .minimum_version_id = 1,
455
+ .fields = (const VMStateField[]) {
456
+ VMSTATE_UINT16(control, Lan9118PhyState),
457
+ VMSTATE_UINT16(status, Lan9118PhyState),
458
+ VMSTATE_UINT16(advertise, Lan9118PhyState),
459
+ VMSTATE_UINT16(ints, Lan9118PhyState),
460
+ VMSTATE_UINT16(int_mask, Lan9118PhyState),
461
+ VMSTATE_BOOL(link_down, Lan9118PhyState),
462
+ VMSTATE_END_OF_LIST()
463
+ }
58
+};
464
+};
59
+
465
+
60
+static uint64_t sbsa_ec_read(void *opaque, hwaddr offset, unsigned size)
466
+static void lan9118_phy_class_init(ObjectClass *klass, void *data)
61
+{
467
+{
62
+ /* No use for this currently */
468
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
63
+ qemu_log_mask(LOG_GUEST_ERROR, "sbsa-ec: no readable registers");
469
+ DeviceClass *dc = DEVICE_CLASS(klass);
64
+ return 0;
470
+
65
+}
471
+ rc->phases.hold = lan9118_phy_reset_hold;
66
+
472
+ dc->vmsd = &vmstate_lan9118_phy;
67
+static void sbsa_ec_write(void *opaque, hwaddr offset,
473
+}
68
+ uint64_t value, unsigned size)
474
+
69
+{
475
+static const TypeInfo types[] = {
70
+ if (offset == 0) { /* PSCI machine power command register */
476
+ {
71
+ switch (value) {
477
+ .name = TYPE_LAN9118_PHY,
72
+ case SBSA_EC_CMD_POWEROFF:
478
+ .parent = TYPE_SYS_BUS_DEVICE,
73
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
479
+ .instance_size = sizeof(Lan9118PhyState),
74
+ break;
480
+ .instance_init = lan9118_phy_init,
75
+ case SBSA_EC_CMD_REBOOT:
481
+ .class_init = lan9118_phy_class_init,
76
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
77
+ break;
78
+ default:
79
+ qemu_log_mask(LOG_GUEST_ERROR,
80
+ "sbsa-ec: unknown power command");
81
+ }
82
+ } else {
83
+ qemu_log_mask(LOG_GUEST_ERROR, "sbsa-ec: unknown EC register");
84
+ }
482
+ }
85
+}
86
+
87
+static const MemoryRegionOps sbsa_ec_ops = {
88
+ .read = sbsa_ec_read,
89
+ .write = sbsa_ec_write,
90
+ .endianness = DEVICE_NATIVE_ENDIAN,
91
+ .valid.min_access_size = 4,
92
+ .valid.max_access_size = 4,
93
+};
483
+};
94
+
484
+
95
+static void sbsa_ec_init(Object *obj)
485
+DEFINE_TYPES(types)
96
+{
486
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
97
+ SECUREECState *s = SECURE_EC(obj);
98
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
99
+
100
+ memory_region_init_io(&s->iomem, obj, &sbsa_ec_ops, s, "sbsa-ec",
101
+ 0x1000);
102
+ sysbus_init_mmio(dev, &s->iomem);
103
+}
104
+
105
+static void sbsa_ec_class_init(ObjectClass *klass, void *data)
106
+{
107
+ DeviceClass *dc = DEVICE_CLASS(klass);
108
+
109
+ /* No vmstate or reset required: device has no internal state */
110
+ dc->user_creatable = false;
111
+}
112
+
113
+static const TypeInfo sbsa_ec_info = {
114
+ .name = TYPE_SBSA_EC,
115
+ .parent = TYPE_SYS_BUS_DEVICE,
116
+ .instance_size = sizeof(SECUREECState),
117
+ .instance_init = sbsa_ec_init,
118
+ .class_init = sbsa_ec_class_init,
119
+};
120
+
121
+static void sbsa_ec_register_type(void)
122
+{
123
+ type_register_static(&sbsa_ec_info);
124
+}
125
+
126
+type_init(sbsa_ec_register_type);
127
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
128
index XXXXXXX..XXXXXXX 100644
487
index XXXXXXX..XXXXXXX 100644
129
--- a/hw/misc/meson.build
488
--- a/hw/net/Kconfig
130
+++ b/hw/misc/meson.build
489
+++ b/hw/net/Kconfig
131
@@ -XXX,XX +XXX,XX @@ specific_ss.add(when: 'CONFIG_MAC_VIA', if_true: files('mac_via.c'))
490
@@ -XXX,XX +XXX,XX @@ config VMXNET3_PCI
132
491
config SMC91C111
133
specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_cmgcr.c', 'mips_cpc.c'))
492
bool
134
specific_ss.add(when: 'CONFIG_MIPS_ITU', if_true: files('mips_itu.c'))
493
135
+
494
+config LAN9118_PHY
136
+specific_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c'))
495
+ bool
496
+
497
config LAN9118
498
bool
499
+ select LAN9118_PHY
500
select PTIMER
501
502
config NE2000_ISA
503
diff --git a/hw/net/meson.build b/hw/net/meson.build
504
index XXXXXXX..XXXXXXX 100644
505
--- a/hw/net/meson.build
506
+++ b/hw/net/meson.build
507
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_VMXNET3_PCI', if_true: files('vmxnet3.c'))
508
509
system_ss.add(when: 'CONFIG_SMC91C111', if_true: files('smc91c111.c'))
510
system_ss.add(when: 'CONFIG_LAN9118', if_true: files('lan9118.c'))
511
+system_ss.add(when: 'CONFIG_LAN9118_PHY', if_true: files('lan9118_phy.c'))
512
system_ss.add(when: 'CONFIG_NE2000_ISA', if_true: files('ne2000-isa.c'))
513
system_ss.add(when: 'CONFIG_OPENCORES_ETH', if_true: files('opencores_eth.c'))
514
system_ss.add(when: 'CONFIG_XGMAC', if_true: files('xgmac.c'))
137
--
515
--
138
2.20.1
516
2.34.1
139
140
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
imx_fec models the same PHY as lan9118_phy. The code is almost the same with
4
imx_fec having more logging and tracing. Merge these improvements into
5
lan9118_phy and reuse in imx_fec to fix the code duplication.
6
7
Some migration state how resides in the new device model which breaks migration
8
compatibility for the following machines:
9
* imx25-pdk
10
* sabrelite
11
* mcimx7d-sabre
12
* mcimx6ul-evk
13
14
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
15
Tested-by: Guenter Roeck <linux@roeck-us.net>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Message-id: 20241102125724.532843-3-shentey@gmail.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
include/hw/net/imx_fec.h | 9 ++-
21
hw/net/imx_fec.c | 146 ++++-----------------------------------
22
hw/net/lan9118_phy.c | 82 ++++++++++++++++------
23
hw/net/Kconfig | 1 +
24
hw/net/trace-events | 10 +--
25
5 files changed, 85 insertions(+), 163 deletions(-)
26
27
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/net/imx_fec.h
30
+++ b/include/hw/net/imx_fec.h
31
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC)
32
#define TYPE_IMX_ENET "imx.enet"
33
34
#include "hw/sysbus.h"
35
+#include "hw/net/lan9118_phy.h"
36
+#include "hw/irq.h"
37
#include "net/net.h"
38
39
#define ENET_EIR 1
40
@@ -XXX,XX +XXX,XX @@ struct IMXFECState {
41
uint32_t tx_descriptor[ENET_TX_RING_NUM];
42
uint32_t tx_ring_num;
43
44
- uint32_t phy_status;
45
- uint32_t phy_control;
46
- uint32_t phy_advertise;
47
- uint32_t phy_int;
48
- uint32_t phy_int_mask;
49
+ Lan9118PhyState mii;
50
+ IRQState mii_irq;
51
uint32_t phy_num;
52
bool phy_connected;
53
struct IMXFECState *phy_consumer;
54
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/net/imx_fec.c
57
+++ b/hw/net/imx_fec.c
58
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_eth_txdescs = {
59
60
static const VMStateDescription vmstate_imx_eth = {
61
.name = TYPE_IMX_FEC,
62
- .version_id = 2,
63
- .minimum_version_id = 2,
64
+ .version_id = 3,
65
+ .minimum_version_id = 3,
66
.fields = (const VMStateField[]) {
67
VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
68
VMSTATE_UINT32(rx_descriptor, IMXFECState),
69
VMSTATE_UINT32(tx_descriptor[0], IMXFECState),
70
- VMSTATE_UINT32(phy_status, IMXFECState),
71
- VMSTATE_UINT32(phy_control, IMXFECState),
72
- VMSTATE_UINT32(phy_advertise, IMXFECState),
73
- VMSTATE_UINT32(phy_int, IMXFECState),
74
- VMSTATE_UINT32(phy_int_mask, IMXFECState),
75
VMSTATE_END_OF_LIST()
76
},
77
.subsections = (const VMStateDescription * const []) {
78
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_eth = {
79
},
80
};
81
82
-#define PHY_INT_ENERGYON (1 << 7)
83
-#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
84
-#define PHY_INT_FAULT (1 << 5)
85
-#define PHY_INT_DOWN (1 << 4)
86
-#define PHY_INT_AUTONEG_LP (1 << 3)
87
-#define PHY_INT_PARFAULT (1 << 2)
88
-#define PHY_INT_AUTONEG_PAGE (1 << 1)
89
-
90
static void imx_eth_update(IMXFECState *s);
91
92
/*
93
@@ -XXX,XX +XXX,XX @@ static void imx_eth_update(IMXFECState *s);
94
* For now we don't handle any GPIO/interrupt line, so the OS will
95
* have to poll for the PHY status.
96
*/
97
-static void imx_phy_update_irq(IMXFECState *s)
98
+static void imx_phy_update_irq(void *opaque, int n, int level)
99
{
100
- imx_eth_update(s);
101
-}
102
-
103
-static void imx_phy_update_link(IMXFECState *s)
104
-{
105
- /* Autonegotiation status mirrors link status. */
106
- if (qemu_get_queue(s->nic)->link_down) {
107
- trace_imx_phy_update_link("down");
108
- s->phy_status &= ~0x0024;
109
- s->phy_int |= PHY_INT_DOWN;
110
- } else {
111
- trace_imx_phy_update_link("up");
112
- s->phy_status |= 0x0024;
113
- s->phy_int |= PHY_INT_ENERGYON;
114
- s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
115
- }
116
- imx_phy_update_irq(s);
117
+ imx_eth_update(opaque);
118
}
119
120
static void imx_eth_set_link(NetClientState *nc)
121
{
122
- imx_phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
123
-}
124
-
125
-static void imx_phy_reset(IMXFECState *s)
126
-{
127
- trace_imx_phy_reset();
128
-
129
- s->phy_status = 0x7809;
130
- s->phy_control = 0x3000;
131
- s->phy_advertise = 0x01e1;
132
- s->phy_int_mask = 0;
133
- s->phy_int = 0;
134
- imx_phy_update_link(s);
135
+ lan9118_phy_update_link(&IMX_FEC(qemu_get_nic_opaque(nc))->mii,
136
+ nc->link_down);
137
}
138
139
static uint32_t imx_phy_read(IMXFECState *s, int reg)
140
{
141
- uint32_t val;
142
uint32_t phy = reg / 32;
143
144
if (!s->phy_connected) {
145
@@ -XXX,XX +XXX,XX @@ static uint32_t imx_phy_read(IMXFECState *s, int reg)
146
147
reg %= 32;
148
149
- switch (reg) {
150
- case 0: /* Basic Control */
151
- val = s->phy_control;
152
- break;
153
- case 1: /* Basic Status */
154
- val = s->phy_status;
155
- break;
156
- case 2: /* ID1 */
157
- val = 0x0007;
158
- break;
159
- case 3: /* ID2 */
160
- val = 0xc0d1;
161
- break;
162
- case 4: /* Auto-neg advertisement */
163
- val = s->phy_advertise;
164
- break;
165
- case 5: /* Auto-neg Link Partner Ability */
166
- val = 0x0f71;
167
- break;
168
- case 6: /* Auto-neg Expansion */
169
- val = 1;
170
- break;
171
- case 29: /* Interrupt source. */
172
- val = s->phy_int;
173
- s->phy_int = 0;
174
- imx_phy_update_irq(s);
175
- break;
176
- case 30: /* Interrupt mask */
177
- val = s->phy_int_mask;
178
- break;
179
- case 17:
180
- case 18:
181
- case 27:
182
- case 31:
183
- qemu_log_mask(LOG_UNIMP, "[%s.phy]%s: reg %d not implemented\n",
184
- TYPE_IMX_FEC, __func__, reg);
185
- val = 0;
186
- break;
187
- default:
188
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
189
- TYPE_IMX_FEC, __func__, reg);
190
- val = 0;
191
- break;
192
- }
193
-
194
- trace_imx_phy_read(val, phy, reg);
195
-
196
- return val;
197
+ return lan9118_phy_read(&s->mii, reg);
198
}
199
200
static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
201
@@ -XXX,XX +XXX,XX @@ static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
202
203
reg %= 32;
204
205
- trace_imx_phy_write(val, phy, reg);
206
-
207
- switch (reg) {
208
- case 0: /* Basic Control */
209
- if (val & 0x8000) {
210
- imx_phy_reset(s);
211
- } else {
212
- s->phy_control = val & 0x7980;
213
- /* Complete autonegotiation immediately. */
214
- if (val & 0x1000) {
215
- s->phy_status |= 0x0020;
216
- }
217
- }
218
- break;
219
- case 4: /* Auto-neg advertisement */
220
- s->phy_advertise = (val & 0x2d7f) | 0x80;
221
- break;
222
- case 30: /* Interrupt mask */
223
- s->phy_int_mask = val & 0xff;
224
- imx_phy_update_irq(s);
225
- break;
226
- case 17:
227
- case 18:
228
- case 27:
229
- case 31:
230
- qemu_log_mask(LOG_UNIMP, "[%s.phy)%s: reg %d not implemented\n",
231
- TYPE_IMX_FEC, __func__, reg);
232
- break;
233
- default:
234
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
235
- TYPE_IMX_FEC, __func__, reg);
236
- break;
237
- }
238
+ lan9118_phy_write(&s->mii, reg, val);
239
}
240
241
static void imx_fec_read_bd(IMXFECBufDesc *bd, dma_addr_t addr)
242
@@ -XXX,XX +XXX,XX @@ static void imx_eth_reset(DeviceState *d)
243
244
s->rx_descriptor = 0;
245
memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor));
246
-
247
- /* We also reset the PHY */
248
- imx_phy_reset(s);
249
}
250
251
static uint32_t imx_default_read(IMXFECState *s, uint32_t index)
252
@@ -XXX,XX +XXX,XX @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
253
sysbus_init_irq(sbd, &s->irq[0]);
254
sysbus_init_irq(sbd, &s->irq[1]);
255
256
+ qemu_init_irq(&s->mii_irq, imx_phy_update_irq, s, 0);
257
+ object_initialize_child(OBJECT(s), "mii", &s->mii, TYPE_LAN9118_PHY);
258
+ if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->mii), errp)) {
259
+ return;
260
+ }
261
+ qdev_connect_gpio_out(DEVICE(&s->mii), 0, &s->mii_irq);
262
+
263
qemu_macaddr_default_if_unset(&s->conf.macaddr);
264
265
s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
266
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
267
index XXXXXXX..XXXXXXX 100644
268
--- a/hw/net/lan9118_phy.c
269
+++ b/hw/net/lan9118_phy.c
270
@@ -XXX,XX +XXX,XX @@
271
* Copyright (c) 2009 CodeSourcery, LLC.
272
* Written by Paul Brook
273
*
274
+ * Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
275
+ *
276
* This code is licensed under the GNU GPL v2
277
*
278
* Contributions after 2012-01-13 are licensed under the terms of the
279
@@ -XXX,XX +XXX,XX @@
280
#include "hw/resettable.h"
281
#include "migration/vmstate.h"
282
#include "qemu/log.h"
283
+#include "trace.h"
284
285
#define PHY_INT_ENERGYON (1 << 7)
286
#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
287
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
288
289
switch (reg) {
290
case 0: /* Basic Control */
291
- return s->control;
292
+ val = s->control;
293
+ break;
294
case 1: /* Basic Status */
295
- return s->status;
296
+ val = s->status;
297
+ break;
298
case 2: /* ID1 */
299
- return 0x0007;
300
+ val = 0x0007;
301
+ break;
302
case 3: /* ID2 */
303
- return 0xc0d1;
304
+ val = 0xc0d1;
305
+ break;
306
case 4: /* Auto-neg advertisement */
307
- return s->advertise;
308
+ val = s->advertise;
309
+ break;
310
case 5: /* Auto-neg Link Partner Ability */
311
- return 0x0f71;
312
+ val = 0x0f71;
313
+ break;
314
case 6: /* Auto-neg Expansion */
315
- return 1;
316
- /* TODO 17, 18, 27, 29, 30, 31 */
317
+ val = 1;
318
+ break;
319
case 29: /* Interrupt source. */
320
val = s->ints;
321
s->ints = 0;
322
lan9118_phy_update_irq(s);
323
- return val;
324
+ break;
325
case 30: /* Interrupt mask */
326
- return s->int_mask;
327
+ val = s->int_mask;
328
+ break;
329
+ case 17:
330
+ case 18:
331
+ case 27:
332
+ case 31:
333
+ qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
334
+ __func__, reg);
335
+ val = 0;
336
+ break;
337
default:
338
- qemu_log_mask(LOG_GUEST_ERROR,
339
- "lan9118_phy_read: PHY read reg %d\n", reg);
340
- return 0;
341
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
342
+ __func__, reg);
343
+ val = 0;
344
+ break;
345
}
346
+
347
+ trace_lan9118_phy_read(val, reg);
348
+
349
+ return val;
350
}
351
352
void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
353
{
354
+ trace_lan9118_phy_write(val, reg);
355
+
356
switch (reg) {
357
case 0: /* Basic Control */
358
if (val & 0x8000) {
359
lan9118_phy_reset(s);
360
- break;
361
- }
362
- s->control = val & 0x7980;
363
- /* Complete autonegotiation immediately. */
364
- if (val & 0x1000) {
365
- s->status |= 0x0020;
366
+ } else {
367
+ s->control = val & 0x7980;
368
+ /* Complete autonegotiation immediately. */
369
+ if (val & 0x1000) {
370
+ s->status |= 0x0020;
371
+ }
372
}
373
break;
374
case 4: /* Auto-neg advertisement */
375
s->advertise = (val & 0x2d7f) | 0x80;
376
break;
377
- /* TODO 17, 18, 27, 31 */
378
case 30: /* Interrupt mask */
379
s->int_mask = val & 0xff;
380
lan9118_phy_update_irq(s);
381
break;
382
+ case 17:
383
+ case 18:
384
+ case 27:
385
+ case 31:
386
+ qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
387
+ __func__, reg);
388
+ break;
389
default:
390
- qemu_log_mask(LOG_GUEST_ERROR,
391
- "lan9118_phy_write: PHY write reg %d = 0x%04x\n", reg, val);
392
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
393
+ __func__, reg);
394
+ break;
395
}
396
}
397
398
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
399
400
/* Autonegotiation status mirrors link status. */
401
if (link_down) {
402
+ trace_lan9118_phy_update_link("down");
403
s->status &= ~0x0024;
404
s->ints |= PHY_INT_DOWN;
405
} else {
406
+ trace_lan9118_phy_update_link("up");
407
s->status |= 0x0024;
408
s->ints |= PHY_INT_ENERGYON;
409
s->ints |= PHY_INT_AUTONEG_COMPLETE;
410
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
411
412
void lan9118_phy_reset(Lan9118PhyState *s)
413
{
414
+ trace_lan9118_phy_reset();
415
+
416
s->control = 0x3000;
417
s->status = 0x7809;
418
s->advertise = 0x01e1;
419
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118_phy = {
420
.version_id = 1,
421
.minimum_version_id = 1,
422
.fields = (const VMStateField[]) {
423
- VMSTATE_UINT16(control, Lan9118PhyState),
424
VMSTATE_UINT16(status, Lan9118PhyState),
425
+ VMSTATE_UINT16(control, Lan9118PhyState),
426
VMSTATE_UINT16(advertise, Lan9118PhyState),
427
VMSTATE_UINT16(ints, Lan9118PhyState),
428
VMSTATE_UINT16(int_mask, Lan9118PhyState),
429
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
430
index XXXXXXX..XXXXXXX 100644
431
--- a/hw/net/Kconfig
432
+++ b/hw/net/Kconfig
433
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_SUN8I_EMAC
434
435
config IMX_FEC
436
bool
437
+ select LAN9118_PHY
438
439
config CADENCE
440
bool
441
diff --git a/hw/net/trace-events b/hw/net/trace-events
442
index XXXXXXX..XXXXXXX 100644
443
--- a/hw/net/trace-events
444
+++ b/hw/net/trace-events
445
@@ -XXX,XX +XXX,XX @@ allwinner_sun8i_emac_set_link(bool active) "Set link: active=%u"
446
allwinner_sun8i_emac_read(uint64_t offset, uint64_t val) "MMIO read: offset=0x%" PRIx64 " value=0x%" PRIx64
447
allwinner_sun8i_emac_write(uint64_t offset, uint64_t val) "MMIO write: offset=0x%" PRIx64 " value=0x%" PRIx64
448
449
+# lan9118_phy.c
450
+lan9118_phy_read(uint16_t val, int reg) "[0x%02x] -> 0x%04" PRIx16
451
+lan9118_phy_write(uint16_t val, int reg) "[0x%02x] <- 0x%04" PRIx16
452
+lan9118_phy_update_link(const char *s) "%s"
453
+lan9118_phy_reset(void) ""
454
+
455
# lance.c
456
lance_mem_readw(uint64_t addr, uint32_t ret) "addr=0x%"PRIx64"val=0x%04x"
457
lance_mem_writew(uint64_t addr, uint32_t val) "addr=0x%"PRIx64"val=0x%04x"
458
@@ -XXX,XX +XXX,XX @@ i82596_set_multicast(uint16_t count) "Added %d multicast entries"
459
i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION"
460
461
# imx_fec.c
462
-imx_phy_read(uint32_t val, int phy, int reg) "0x%04"PRIx32" <= phy[%d].reg[%d]"
463
imx_phy_read_num(int phy, int configured) "read request from unconfigured phy %d (configured %d)"
464
-imx_phy_write(uint32_t val, int phy, int reg) "0x%04"PRIx32" => phy[%d].reg[%d]"
465
imx_phy_write_num(int phy, int configured) "write request to unconfigured phy %d (configured %d)"
466
-imx_phy_update_link(const char *s) "%s"
467
-imx_phy_reset(void) ""
468
imx_fec_read_bd(uint64_t addr, int flags, int len, int data) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x"
469
imx_enet_read_bd(uint64_t addr, int flags, int len, int data, int options, int status) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x option 0x%04x status 0x%04x"
470
imx_eth_tx_bd_busy(void) "tx_bd ran out of descriptors to transmit"
471
--
472
2.34.1
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Turns 0x70 into 0xe0 (== 0x70 << 1) which adds the missing MII_ANLPAR_TX and
4
fixes the MSB of selector field to be zero, as specified in the datasheet.
5
6
Fixes: 2a424990170b "LAN9118 emulation"
7
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
8
Tested-by: Guenter Roeck <linux@roeck-us.net>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20241102125724.532843-4-shentey@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/net/lan9118_phy.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/lan9118_phy.c
19
+++ b/hw/net/lan9118_phy.c
20
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
21
val = s->advertise;
22
break;
23
case 5: /* Auto-neg Link Partner Ability */
24
- val = 0x0f71;
25
+ val = 0x0fe1;
26
break;
27
case 6: /* Auto-neg Expansion */
28
val = 1;
29
--
30
2.34.1
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
Prefer named constants over magic values for better readability.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
7
Tested-by: Guenter Roeck <linux@roeck-us.net>
8
Message-id: 20241102125724.532843-5-shentey@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/net/mii.h | 6 +++++
12
hw/net/lan9118_phy.c | 63 ++++++++++++++++++++++++++++----------------
13
2 files changed, 46 insertions(+), 23 deletions(-)
14
15
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/net/mii.h
18
+++ b/include/hw/net/mii.h
19
@@ -XXX,XX +XXX,XX @@
20
#define MII_BMSR_JABBER (1 << 1) /* Jabber detected */
21
#define MII_BMSR_EXTCAP (1 << 0) /* Ext-reg capability */
22
23
+#define MII_ANAR_RFAULT (1 << 13) /* Say we can detect faults */
24
#define MII_ANAR_PAUSE_ASYM (1 << 11) /* Try for asymmetric pause */
25
#define MII_ANAR_PAUSE (1 << 10) /* Try for pause */
26
#define MII_ANAR_TXFD (1 << 8)
27
@@ -XXX,XX +XXX,XX @@
28
#define MII_ANAR_10FD (1 << 6)
29
#define MII_ANAR_10 (1 << 5)
30
#define MII_ANAR_CSMACD (1 << 0)
31
+#define MII_ANAR_SELECT (0x001f) /* Selector bits */
32
33
#define MII_ANLPAR_ACK (1 << 14)
34
#define MII_ANLPAR_PAUSEASY (1 << 11) /* can pause asymmetrically */
35
@@ -XXX,XX +XXX,XX @@
36
#define RTL8201CP_PHYID1 0x0000
37
#define RTL8201CP_PHYID2 0x8201
38
39
+/* SMSC LAN9118 */
40
+#define SMSCLAN9118_PHYID1 0x0007
41
+#define SMSCLAN9118_PHYID2 0xc0d1
42
+
43
/* RealTek 8211E */
44
#define RTL8211E_PHYID1 0x001c
45
#define RTL8211E_PHYID2 0xc915
46
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/net/lan9118_phy.c
49
+++ b/hw/net/lan9118_phy.c
50
@@ -XXX,XX +XXX,XX @@
51
52
#include "qemu/osdep.h"
53
#include "hw/net/lan9118_phy.h"
54
+#include "hw/net/mii.h"
55
#include "hw/irq.h"
56
#include "hw/resettable.h"
57
#include "migration/vmstate.h"
58
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
59
uint16_t val;
60
61
switch (reg) {
62
- case 0: /* Basic Control */
63
+ case MII_BMCR:
64
val = s->control;
65
break;
66
- case 1: /* Basic Status */
67
+ case MII_BMSR:
68
val = s->status;
69
break;
70
- case 2: /* ID1 */
71
- val = 0x0007;
72
+ case MII_PHYID1:
73
+ val = SMSCLAN9118_PHYID1;
74
break;
75
- case 3: /* ID2 */
76
- val = 0xc0d1;
77
+ case MII_PHYID2:
78
+ val = SMSCLAN9118_PHYID2;
79
break;
80
- case 4: /* Auto-neg advertisement */
81
+ case MII_ANAR:
82
val = s->advertise;
83
break;
84
- case 5: /* Auto-neg Link Partner Ability */
85
- val = 0x0fe1;
86
+ case MII_ANLPAR:
87
+ val = MII_ANLPAR_PAUSEASY | MII_ANLPAR_PAUSE | MII_ANLPAR_T4 |
88
+ MII_ANLPAR_TXFD | MII_ANLPAR_TX | MII_ANLPAR_10FD |
89
+ MII_ANLPAR_10 | MII_ANLPAR_CSMACD;
90
break;
91
- case 6: /* Auto-neg Expansion */
92
- val = 1;
93
+ case MII_ANER:
94
+ val = MII_ANER_NWAY;
95
break;
96
case 29: /* Interrupt source. */
97
val = s->ints;
98
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
99
trace_lan9118_phy_write(val, reg);
100
101
switch (reg) {
102
- case 0: /* Basic Control */
103
- if (val & 0x8000) {
104
+ case MII_BMCR:
105
+ if (val & MII_BMCR_RESET) {
106
lan9118_phy_reset(s);
107
} else {
108
- s->control = val & 0x7980;
109
+ s->control = val & (MII_BMCR_LOOPBACK | MII_BMCR_SPEED100 |
110
+ MII_BMCR_AUTOEN | MII_BMCR_PDOWN | MII_BMCR_FD |
111
+ MII_BMCR_CTST);
112
/* Complete autonegotiation immediately. */
113
- if (val & 0x1000) {
114
- s->status |= 0x0020;
115
+ if (val & MII_BMCR_AUTOEN) {
116
+ s->status |= MII_BMSR_AN_COMP;
117
}
118
}
119
break;
120
- case 4: /* Auto-neg advertisement */
121
- s->advertise = (val & 0x2d7f) | 0x80;
122
+ case MII_ANAR:
123
+ s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
124
+ MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
125
+ MII_ANAR_SELECT))
126
+ | MII_ANAR_TX;
127
break;
128
case 30: /* Interrupt mask */
129
s->int_mask = val & 0xff;
130
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_update_link(Lan9118PhyState *s, bool link_down)
131
/* Autonegotiation status mirrors link status. */
132
if (link_down) {
133
trace_lan9118_phy_update_link("down");
134
- s->status &= ~0x0024;
135
+ s->status &= ~(MII_BMSR_AN_COMP | MII_BMSR_LINK_ST);
136
s->ints |= PHY_INT_DOWN;
137
} else {
138
trace_lan9118_phy_update_link("up");
139
- s->status |= 0x0024;
140
+ s->status |= MII_BMSR_AN_COMP | MII_BMSR_LINK_ST;
141
s->ints |= PHY_INT_ENERGYON;
142
s->ints |= PHY_INT_AUTONEG_COMPLETE;
143
}
144
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_reset(Lan9118PhyState *s)
145
{
146
trace_lan9118_phy_reset();
147
148
- s->control = 0x3000;
149
- s->status = 0x7809;
150
- s->advertise = 0x01e1;
151
+ s->control = MII_BMCR_AUTOEN | MII_BMCR_SPEED100;
152
+ s->status = MII_BMSR_100TX_FD
153
+ | MII_BMSR_100TX_HD
154
+ | MII_BMSR_10T_FD
155
+ | MII_BMSR_10T_HD
156
+ | MII_BMSR_AUTONEG
157
+ | MII_BMSR_EXTCAP;
158
+ s->advertise = MII_ANAR_TXFD
159
+ | MII_ANAR_TX
160
+ | MII_ANAR_10FD
161
+ | MII_ANAR_10
162
+ | MII_ANAR_CSMACD;
163
s->int_mask = 0;
164
s->ints = 0;
165
lan9118_phy_update_link(s, s->link_down);
166
--
167
2.34.1
diff view generated by jsdifflib
New patch
1
From: Bernhard Beschow <shentey@gmail.com>
1
2
3
The real device advertises this mode and the device model already advertises
4
100 mbps half duplex and 10 mbps full+half duplex. So advertise this mode to
5
make the model more realistic.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
9
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
Message-id: 20241102125724.532843-6-shentey@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/net/lan9118_phy.c | 4 ++--
14
1 file changed, 2 insertions(+), 2 deletions(-)
15
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/lan9118_phy.c
19
+++ b/hw/net/lan9118_phy.c
20
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
21
break;
22
case MII_ANAR:
23
s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
24
- MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
25
- MII_ANAR_SELECT))
26
+ MII_ANAR_PAUSE | MII_ANAR_TXFD | MII_ANAR_10FD |
27
+ MII_ANAR_10 | MII_ANAR_SELECT))
28
| MII_ANAR_TX;
29
break;
30
case 30: /* Interrupt mask */
31
--
32
2.34.1
diff view generated by jsdifflib
1
Implement the fp16 versions of the VFP VCVT instruction forms
1
For IEEE fused multiply-add, the (0 * inf) + NaN case should raise
2
which convert between floating point and integer with a specified
2
Invalid for the multiplication of 0 by infinity. Currently we handle
3
rounding mode.
3
this in the per-architecture ifdef ladder in pickNaNMulAdd().
4
However, since this isn't really architecture specific we can hoist
5
it up to the generic code.
6
7
For the cases where the infzero test in pickNaNMulAdd was
8
returning 2, we can delete the check entirely and allow the
9
code to fall into the normal pick-a-NaN handling, because this
10
will return 2 anyway (input 'c' being the only NaN in this case).
11
For the cases where infzero was returning 3 to indicate "return
12
the default NaN", we must retain that "return 3".
13
14
For Arm, this looks like it might be a behaviour change because we
15
used to set float_flag_invalid | float_flag_invalid_imz only if C is
16
a quiet NaN. However, it is not, because Arm target code never looks
17
at float_flag_invalid_imz, and for the (0 * inf) + SNaN case we
18
already raised float_flag_invalid via the "abc_mask &
19
float_cmask_snan" check in pick_nan_muladd.
20
21
For any target architecture using the "default implementation" at the
22
bottom of the ifdef, this is a behaviour change but will be fixing a
23
bug (where we failed to raise the Invalid exception for (0 * inf +
24
QNaN). The architectures using the default case are:
25
* hppa
26
* i386
27
* sh4
28
* tricore
29
30
The x86, Tricore and SH4 CPU architecture manuals are clear that this
31
should have raised Invalid; HPPA is a bit vaguer but still seems
32
clear enough.
4
33
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200828183354.27913-17-peter.maydell@linaro.org
36
Message-id: 20241202131347.498124-2-peter.maydell@linaro.org
8
---
37
---
9
target/arm/vfp-uncond.decode | 6 ++++--
38
fpu/softfloat-parts.c.inc | 13 +++++++------
10
target/arm/translate-vfp.c.inc | 32 ++++++++++++++++++++++++--------
39
fpu/softfloat-specialize.c.inc | 29 +----------------------------
11
2 files changed, 28 insertions(+), 10 deletions(-)
40
2 files changed, 8 insertions(+), 34 deletions(-)
12
41
13
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
42
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
14
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/vfp-uncond.decode
44
--- a/fpu/softfloat-parts.c.inc
16
+++ b/target/arm/vfp-uncond.decode
45
+++ b/fpu/softfloat-parts.c.inc
17
@@ -XXX,XX +XXX,XX @@ VRINT 1111 1110 1.11 10 rm:2 .... 1011 01.0 .... \
46
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
18
vm=%vm_dp vd=%vd_dp dp=1
47
int ab_mask, int abc_mask)
19
20
# VCVT float to int with specified rounding mode; Vd is always single-precision
21
+VCVT 1111 1110 1.11 11 rm:2 .... 1001 op:1 1.0 .... \
22
+ vm=%vm_sp vd=%vd_sp sz=1
23
VCVT 1111 1110 1.11 11 rm:2 .... 1010 op:1 1.0 .... \
24
- vm=%vm_sp vd=%vd_sp dp=0
25
+ vm=%vm_sp vd=%vd_sp sz=2
26
VCVT 1111 1110 1.11 11 rm:2 .... 1011 op:1 1.0 .... \
27
- vm=%vm_dp vd=%vd_sp dp=1
28
+ vm=%vm_dp vd=%vd_sp sz=3
29
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate-vfp.c.inc
32
+++ b/target/arm/translate-vfp.c.inc
33
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
34
static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
35
{
48
{
36
uint32_t rd, rm;
49
int which;
37
- bool dp = a->dp;
50
+ bool infzero = (ab_mask == float_cmask_infzero);
38
+ int sz = a->sz;
51
39
TCGv_ptr fpst;
52
if (unlikely(abc_mask & float_cmask_snan)) {
40
TCGv_i32 tcg_rmode, tcg_shift;
53
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
41
int rounding = fp_decode_rm[a->rm];
42
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
43
return false;
44
}
54
}
45
55
46
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
56
- which = pickNaNMulAdd(a->cls, b->cls, c->cls,
47
+ if (sz == 3 && !dc_isar_feature(aa32_fpdp_v2, s)) {
57
- ab_mask == float_cmask_infzero, s);
48
+ return false;
58
+ if (infzero) {
59
+ /* This is (0 * inf) + NaN or (inf * 0) + NaN */
60
+ float_raise(float_flag_invalid | float_flag_invalid_imz, s);
49
+ }
61
+ }
50
+
62
+
51
+ if (sz == 1 && !dc_isar_feature(aa32_fp16_arith, s)) {
63
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
52
return false;
64
65
if (s->default_nan_mode || which == 3) {
66
- /*
67
- * Note that this check is after pickNaNMulAdd so that function
68
- * has an opportunity to set the Invalid flag for infzero.
69
- */
70
parts_default_nan(a, s);
71
return a;
53
}
72
}
54
73
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
55
/* UNDEF accesses to D16-D31 if they don't exist */
74
index XXXXXXX..XXXXXXX 100644
56
- if (dp && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
75
--- a/fpu/softfloat-specialize.c.inc
57
+ if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
76
+++ b/fpu/softfloat-specialize.c.inc
58
return false;
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;
59
}
83
}
60
84
61
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
85
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
62
return true;
86
* case sets InvalidOp and returns the default NaN
87
*/
88
if (infzero) {
89
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
90
return 3;
91
}
92
/* Prefer sNaN over qNaN, in the a, b, c order. */
93
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
94
* For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
95
* case sets InvalidOp and returns the input value 'c'
96
*/
97
- if (infzero) {
98
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
99
- return 2;
100
- }
101
/* Prefer sNaN over qNaN, in the c, a, b order. */
102
if (is_snan(c_cls)) {
103
return 2;
104
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
105
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
106
* case sets InvalidOp and returns the input value 'c'
107
*/
108
- if (infzero) {
109
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
110
- return 2;
111
- }
112
+
113
/* Prefer sNaN over qNaN, in the c, a, b order. */
114
if (is_snan(c_cls)) {
115
return 2;
116
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
117
* to return an input NaN if we have one (ie c) rather than generating
118
* a default NaN
119
*/
120
- if (infzero) {
121
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
122
- return 2;
123
- }
124
125
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
126
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
127
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
128
return 1;
63
}
129
}
64
130
#elif defined(TARGET_RISCV)
65
- fpst = fpstatus_ptr(FPST_FPCR);
131
- /* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
66
+ if (sz == 1) {
132
- if (infzero) {
67
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
133
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
68
+ } else {
134
- }
69
+ fpst = fpstatus_ptr(FPST_FPCR);
135
return 3; /* default NaN */
70
+ }
136
#elif defined(TARGET_S390X)
71
137
if (infzero) {
72
tcg_shift = tcg_const_i32(0);
138
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
73
139
return 3;
74
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
140
}
75
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
141
76
142
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
77
- if (dp) {
143
return 2;
78
+ if (sz == 3) {
144
}
79
TCGv_i64 tcg_double, tcg_res;
145
#elif defined(TARGET_SPARC)
80
TCGv_i32 tcg_tmp;
146
- /* For (inf,0,nan) return c. */
81
tcg_double = tcg_temp_new_i64();
147
- if (infzero) {
82
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
148
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
83
tcg_single = tcg_temp_new_i32();
149
- return 2;
84
tcg_res = tcg_temp_new_i32();
150
- }
85
neon_load_reg32(tcg_single, rm);
151
/* Prefer SNaN over QNaN, order C, B, A. */
86
- if (is_signed) {
152
if (is_snan(c_cls)) {
87
- gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
153
return 2;
88
+ if (sz == 1) {
154
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
89
+ if (is_signed) {
155
* For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
90
+ gen_helper_vfp_toslh(tcg_res, tcg_single, tcg_shift, fpst);
156
* an input NaN if we have one (ie c).
91
+ } else {
157
*/
92
+ gen_helper_vfp_toulh(tcg_res, tcg_single, tcg_shift, fpst);
158
- if (infzero) {
93
+ }
159
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
94
} else {
160
- return 2;
95
- gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
161
- }
96
+ if (is_signed) {
162
if (status->use_first_nan) {
97
+ gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
163
if (is_nan(a_cls)) {
98
+ } else {
164
return 0;
99
+ gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
100
+ }
101
}
102
neon_store_reg32(tcg_res, rd);
103
tcg_temp_free_i32(tcg_res);
104
--
165
--
105
2.20.1
166
2.34.1
106
107
diff view generated by jsdifflib
1
Convert the Neon floating-point VMUL, VMLA and VMLS to use gvec,
1
If the target sets default_nan_mode then we're always going to return
2
and use this to implement fp16 support.
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().
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().
3
12
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-45-peter.maydell@linaro.org
15
Message-id: 20241202131347.498124-3-peter.maydell@linaro.org
7
---
16
---
8
target/arm/translate-neon.c.inc | 114 ++++++++++++++++----------------
17
fpu/softfloat-parts.c.inc | 8 ++++++--
9
1 file changed, 57 insertions(+), 57 deletions(-)
18
fpu/softfloat-specialize.c.inc | 9 +++++++--
19
2 files changed, 13 insertions(+), 4 deletions(-)
10
20
11
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
21
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
12
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-neon.c.inc
23
--- a/fpu/softfloat-parts.c.inc
14
+++ b/target/arm/translate-neon.c.inc
24
+++ b/fpu/softfloat-parts.c.inc
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLS_2sc(DisasContext *s, arg_2scalar *a)
25
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
16
return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
26
float_raise(float_flag_invalid | float_flag_invalid_imz, s);
17
}
18
19
-/*
20
- * Rather than have a float-specific version of do_2scalar just for
21
- * three insns, we wrap a NeonGenTwoSingleOpFn to turn it into
22
- * a NeonGenTwoOpFn.
23
- */
24
-#define WRAP_FP_FN(WRAPNAME, FUNC) \
25
- static void WRAPNAME(TCGv_i32 rd, TCGv_i32 rn, TCGv_i32 rm) \
26
- { \
27
- TCGv_ptr fpstatus = fpstatus_ptr(FPST_STD); \
28
- FUNC(rd, rn, rm, fpstatus); \
29
- tcg_temp_free_ptr(fpstatus); \
30
+static bool do_2scalar_fp_vec(DisasContext *s, arg_2scalar *a,
31
+ gen_helper_gvec_3_ptr *fn)
32
+{
33
+ /* Two registers and a scalar, using gvec */
34
+ int vec_size = a->q ? 16 : 8;
35
+ int rd_ofs = neon_reg_offset(a->vd, 0);
36
+ int rn_ofs = neon_reg_offset(a->vn, 0);
37
+ int rm_ofs;
38
+ int idx;
39
+ TCGv_ptr fpstatus;
40
+
41
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
42
+ return false;
43
}
27
}
44
28
45
-WRAP_FP_FN(gen_VMUL_F_mul, gen_helper_vfp_muls)
29
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
46
-WRAP_FP_FN(gen_VMUL_F_add, gen_helper_vfp_adds)
30
+ if (s->default_nan_mode) {
47
-WRAP_FP_FN(gen_VMUL_F_sub, gen_helper_vfp_subs)
31
+ which = 3;
48
+ /* UNDEF accesses to D16-D31 if they don't exist. */
32
+ } else {
49
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
33
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
50
+ ((a->vd | a->vn | a->vm) & 0x10)) {
51
+ return false;
52
+ }
34
+ }
53
35
54
-static bool trans_VMUL_F_2sc(DisasContext *s, arg_2scalar *a)
36
- if (s->default_nan_mode || which == 3) {
55
-{
37
+ if (which == 3) {
56
- static NeonGenTwoOpFn * const opfn[] = {
38
parts_default_nan(a, s);
57
- NULL,
39
return a;
58
- NULL, /* TODO: fp16 support */
40
}
59
- gen_VMUL_F_mul,
41
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
60
- NULL,
42
index XXXXXXX..XXXXXXX 100644
61
- };
43
--- a/fpu/softfloat-specialize.c.inc
62
+ if (!fn) {
44
+++ b/fpu/softfloat-specialize.c.inc
63
+ /* Bad size (including size == 3, which is a different insn group) */
45
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
64
+ return false;
46
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
65
+ }
47
bool infzero, float_status *status)
66
48
{
67
- return do_2scalar(s, a, opfn[a->size], NULL);
49
+ /*
68
+ if (a->q && ((a->vd | a->vn) & 1)) {
50
+ * We guarantee not to require the target to tell us how to
69
+ return false;
51
+ * pick a NaN if we're always returning the default NaN.
70
+ }
52
+ * But if we're not in default-NaN mode then the target must
71
+
53
+ * specify.
72
+ if (!vfp_access_check(s)) {
54
+ */
73
+ return true;
55
+ assert(!status->default_nan_mode);
74
+ }
56
#if defined(TARGET_ARM)
75
+
57
/* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
76
+ /* a->vm is M:Vm, which encodes both register and index */
58
* the default NaN
77
+ idx = extract32(a->vm, a->size + 2, 2);
59
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
78
+ a->vm = extract32(a->vm, 0, a->size + 2);
60
} else {
79
+ rm_ofs = neon_reg_offset(a->vm, 0);
61
return 1;
80
+
62
}
81
+ fpstatus = fpstatus_ptr(a->size == 1 ? FPST_STD_F16 : FPST_STD);
63
-#elif defined(TARGET_RISCV)
82
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpstatus,
64
- return 3; /* default NaN */
83
+ vec_size, vec_size, idx, fn);
65
#elif defined(TARGET_S390X)
84
+ tcg_temp_free_ptr(fpstatus);
66
if (infzero) {
85
+ return true;
67
return 3;
86
}
87
88
-static bool trans_VMLA_F_2sc(DisasContext *s, arg_2scalar *a)
89
-{
90
- static NeonGenTwoOpFn * const opfn[] = {
91
- NULL,
92
- NULL, /* TODO: fp16 support */
93
- gen_VMUL_F_mul,
94
- NULL,
95
- };
96
- static NeonGenTwoOpFn * const accfn[] = {
97
- NULL,
98
- NULL, /* TODO: fp16 support */
99
- gen_VMUL_F_add,
100
- NULL,
101
- };
102
+#define DO_VMUL_F_2sc(NAME, FUNC) \
103
+ static bool trans_##NAME##_F_2sc(DisasContext *s, arg_2scalar *a) \
104
+ { \
105
+ static gen_helper_gvec_3_ptr * const opfn[] = { \
106
+ NULL, \
107
+ gen_helper_##FUNC##_h, \
108
+ gen_helper_##FUNC##_s, \
109
+ NULL, \
110
+ }; \
111
+ if (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s)) { \
112
+ return false; \
113
+ } \
114
+ return do_2scalar_fp_vec(s, a, opfn[a->size]); \
115
+ }
116
117
- return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
118
-}
119
-
120
-static bool trans_VMLS_F_2sc(DisasContext *s, arg_2scalar *a)
121
-{
122
- static NeonGenTwoOpFn * const opfn[] = {
123
- NULL,
124
- NULL, /* TODO: fp16 support */
125
- gen_VMUL_F_mul,
126
- NULL,
127
- };
128
- static NeonGenTwoOpFn * const accfn[] = {
129
- NULL,
130
- NULL, /* TODO: fp16 support */
131
- gen_VMUL_F_sub,
132
- NULL,
133
- };
134
-
135
- return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
136
-}
137
+DO_VMUL_F_2sc(VMUL, gvec_fmul_idx)
138
+DO_VMUL_F_2sc(VMLA, gvec_fmla_nf_idx)
139
+DO_VMUL_F_2sc(VMLS, gvec_fmls_nf_idx)
140
141
WRAP_ENV_FN(gen_VQDMULH_16, gen_helper_neon_qdmulh_s16)
142
WRAP_ENV_FN(gen_VQDMULH_32, gen_helper_neon_qdmulh_s32)
143
--
68
--
144
2.20.1
69
2.34.1
145
146
diff view generated by jsdifflib
1
Convert the Neon VRINT-with-specified-rounding-mode insns to gvec,
1
IEEE 758 does not define a fixed rule for what NaN to return in
2
and use this to implement the fp16 versions.
2
the case of a fused multiply-add of inf * 0 + NaN. Different
3
architectures thus do different things:
4
* some return the default NaN
5
* some return the input NaN
6
* Arm returns the default NaN if the input NaN is quiet,
7
and the input NaN if it is signalling
8
9
We want to make this logic be runtime selected rather than
10
hardcoded into the binary, because:
11
* this will let us have multiple targets in one QEMU binary
12
* the Arm FEAT_AFP architectural feature includes letting
13
the guest select a NaN propagation rule at runtime
14
15
In this commit we add an enum for the propagation rule, the field in
16
float_status, and the corresponding getters and setters. We change
17
pickNaNMulAdd to honour this, but because all targets still leave
18
this field at its default 0 value, the fallback logic will pick the
19
rule type with the old ifdef ladder.
20
21
Note that four architectures both use the muladd softfloat functions
22
and did not have a branch of the ifdef ladder to specify their
23
behaviour (and so were ending up with the "default" case, probably
24
wrongly): i386, HPPA, SH4 and Tricore. SH4 and Tricore both set
25
default_nan_mode, and so will never get into pickNaNMulAdd(). For
26
HPPA and i386 we retain the same behaviour as the old default-case,
27
which is to not ever return the default NaN. This might not be
28
correct but it is not a behaviour change.
3
29
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-41-peter.maydell@linaro.org
32
Message-id: 20241202131347.498124-4-peter.maydell@linaro.org
7
---
33
---
8
target/arm/helper.h | 4 +-
34
include/fpu/softfloat-helpers.h | 11 ++++
9
target/arm/vec_helper.c | 21 +++++++++++
35
include/fpu/softfloat-types.h | 23 +++++++++
10
target/arm/vfp_helper.c | 17 ---------
36
fpu/softfloat-specialize.c.inc | 91 ++++++++++++++++++++++-----------
11
target/arm/translate-neon.c.inc | 67 +++------------------------------
37
3 files changed, 95 insertions(+), 30 deletions(-)
12
4 files changed, 30 insertions(+), 79 deletions(-)
38
13
39
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.h
41
--- a/include/fpu/softfloat-helpers.h
17
+++ b/target/arm/helper.h
42
+++ b/include/fpu/softfloat-helpers.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
43
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
19
DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
44
status->float_2nan_prop_rule = rule;
20
45
}
21
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
46
22
-DEF_HELPER_FLAGS_2(set_neon_rmode, TCG_CALL_NO_RWG, i32, i32, env)
47
+static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
23
48
+ float_status *status)
24
DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f32, TCG_CALL_NO_RWG, f32, f16, ptr, i32)
49
+{
25
DEF_HELPER_FLAGS_3(vfp_fcvt_f32_to_f16, TCG_CALL_NO_RWG, f16, f32, ptr, i32)
50
+ status->float_infzeronan_rule = rule;
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_vcvt_rm_us, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
51
+}
27
DEF_HELPER_FLAGS_4(gvec_vcvt_rm_sh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
52
+
28
DEF_HELPER_FLAGS_4(gvec_vcvt_rm_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
53
static inline void set_flush_to_zero(bool val, float_status *status)
29
54
{
30
+DEF_HELPER_FLAGS_4(gvec_vrint_rm_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
55
status->flush_to_zero = val;
31
+DEF_HELPER_FLAGS_4(gvec_vrint_rm_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
56
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
32
+
57
return status->float_2nan_prop_rule;
33
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
58
}
34
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
59
35
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
60
+static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
36
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
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
37
index XXXXXXX..XXXXXXX 100644
69
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/vec_helper.c
70
--- a/include/fpu/softfloat-types.h
39
+++ b/target/arm/vec_helper.c
71
+++ b/include/fpu/softfloat-types.h
40
@@ -XXX,XX +XXX,XX @@ DO_VCVT_RMODE(gvec_vcvt_rm_sh, helper_vfp_toshh, uint16_t)
72
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
41
DO_VCVT_RMODE(gvec_vcvt_rm_uh, helper_vfp_touhh, uint16_t)
73
float_2nan_prop_x87,
42
74
} Float2NaNPropRule;
43
#undef DO_VCVT_RMODE
75
44
+
76
+/*
45
+#define DO_VRINT_RMODE(NAME, FUNC, TYPE) \
77
+ * Rule for result of fused multiply-add 0 * Inf + NaN.
46
+ void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
78
+ * This must be a NaN, but implementations differ on whether this
47
+ { \
79
+ * is the input NaN or the default NaN.
48
+ float_status *fpst = stat; \
80
+ *
49
+ intptr_t i, oprsz = simd_oprsz(desc); \
81
+ * You don't need to set this if default_nan_mode is enabled.
50
+ uint32_t rmode = simd_data(desc); \
82
+ * When not in default-NaN mode, it is an error for the target
51
+ uint32_t prev_rmode = get_float_rounding_mode(fpst); \
83
+ * not to set the rule in float_status if it uses muladd, and we
52
+ TYPE *d = vd, *n = vn; \
84
+ * will assert if we need to handle an input NaN and no rule was
53
+ set_float_rounding_mode(rmode, fpst); \
85
+ * selected.
54
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
86
+ */
55
+ d[i] = FUNC(n[i], fpst); \
87
+typedef enum __attribute__((__packed__)) {
56
+ } \
88
+ /* No propagation rule specified */
57
+ set_float_rounding_mode(prev_rmode, fpst); \
89
+ float_infzeronan_none = 0,
58
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
90
+ /* Result is never the default NaN (so always the input NaN) */
91
+ float_infzeronan_dnan_never,
92
+ /* Result is always the default NaN */
93
+ float_infzeronan_dnan_always,
94
+ /* Result is the default NaN if the input NaN is quiet */
95
+ float_infzeronan_dnan_if_qnan,
96
+} FloatInfZeroNaNRule;
97
+
98
/*
99
* Floating Point Status. Individual architectures may maintain
100
* several versions of float_status for different functions. The
101
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
102
FloatRoundMode float_rounding_mode;
103
FloatX80RoundPrec floatx80_rounding_precision;
104
Float2NaNPropRule float_2nan_prop_rule;
105
+ FloatInfZeroNaNRule float_infzeronan_rule;
106
bool tininess_before_rounding;
107
/* should denormalised results go to zero and set the inexact flag? */
108
bool flush_to_zero;
109
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
110
index XXXXXXX..XXXXXXX 100644
111
--- a/fpu/softfloat-specialize.c.inc
112
+++ b/fpu/softfloat-specialize.c.inc
113
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
114
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
115
bool infzero, float_status *status)
116
{
117
+ FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
118
+
119
/*
120
* We guarantee not to require the target to tell us how to
121
* pick a NaN if we're always returning the default NaN.
122
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
123
* specify.
124
*/
125
assert(!status->default_nan_mode);
126
+
127
+ if (rule == float_infzeronan_none) {
128
+ /*
129
+ * Temporarily fall back to ifdef ladder
130
+ */
131
#if defined(TARGET_ARM)
132
- /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
133
- * the default NaN
134
- */
135
- if (infzero && is_qnan(c_cls)) {
136
- return 3;
137
+ /*
138
+ * For ARM, the (inf,zero,qnan) case returns the default NaN,
139
+ * but (inf,zero,snan) returns the input NaN.
140
+ */
141
+ rule = float_infzeronan_dnan_if_qnan;
142
+#elif defined(TARGET_MIPS)
143
+ if (snan_bit_is_one(status)) {
144
+ /*
145
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
146
+ * case sets InvalidOp and returns the default NaN
147
+ */
148
+ rule = float_infzeronan_dnan_always;
149
+ } else {
150
+ /*
151
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
152
+ * case sets InvalidOp and returns the input value 'c'
153
+ */
154
+ rule = float_infzeronan_dnan_never;
155
+ }
156
+#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
157
+ defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
158
+ defined(TARGET_I386) || defined(TARGET_LOONGARCH)
159
+ /*
160
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
161
+ * case sets InvalidOp and returns the input value 'c'
162
+ */
163
+ /*
164
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
165
+ * to return an input NaN if we have one (ie c) rather than generating
166
+ * a default NaN
167
+ */
168
+ rule = float_infzeronan_dnan_never;
169
+#elif defined(TARGET_S390X)
170
+ rule = float_infzeronan_dnan_always;
171
+#endif
172
}
173
174
+ if (infzero) {
175
+ /*
176
+ * Inf * 0 + NaN -- some implementations return the default NaN here,
177
+ * and some return the input NaN.
178
+ */
179
+ switch (rule) {
180
+ case float_infzeronan_dnan_never:
181
+ return 2;
182
+ case float_infzeronan_dnan_always:
183
+ return 3;
184
+ case float_infzeronan_dnan_if_qnan:
185
+ return is_qnan(c_cls) ? 3 : 2;
186
+ default:
187
+ g_assert_not_reached();
188
+ }
59
+ }
189
+ }
60
+
190
+
61
+DO_VRINT_RMODE(gvec_vrint_rm_h, helper_rinth, uint16_t)
191
+#if defined(TARGET_ARM)
62
+DO_VRINT_RMODE(gvec_vrint_rm_s, helper_rints, uint32_t)
192
+
63
+
193
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
64
+#undef DO_VRINT_RMODE
194
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
65
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
195
*/
66
index XXXXXXX..XXXXXXX 100644
196
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
67
--- a/target/arm/vfp_helper.c
197
}
68
+++ b/target/arm/vfp_helper.c
198
#elif defined(TARGET_MIPS)
69
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
199
if (snan_bit_is_one(status)) {
70
return prev_rmode;
200
- /*
71
}
201
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
72
202
- * case sets InvalidOp and returns the default NaN
73
-/* Set the current fp rounding mode in the standard fp status and return
203
- */
74
- * the old one. This is for NEON instructions that need to change the
204
- if (infzero) {
75
- * rounding mode but wish to use the standard FPSCR values for everything
205
- return 3;
76
- * else. Always set the rounding mode back to the correct value after
206
- }
77
- * modifying it.
207
/* Prefer sNaN over qNaN, in the a, b, c order. */
78
- * The argument is a softfloat float_round_ value.
208
if (is_snan(a_cls)) {
79
- */
209
return 0;
80
-uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
210
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
81
-{
211
return 2;
82
- float_status *fp_status = &env->vfp.standard_fp_status;
212
}
213
} else {
214
- /*
215
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
216
- * case sets InvalidOp and returns the input value 'c'
217
- */
218
/* Prefer sNaN over qNaN, in the c, a, b order. */
219
if (is_snan(c_cls)) {
220
return 2;
221
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
222
}
223
}
224
#elif defined(TARGET_LOONGARCH64)
225
- /*
226
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
227
- * case sets InvalidOp and returns the input value 'c'
228
- */
83
-
229
-
84
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
230
/* Prefer sNaN over qNaN, in the c, a, b order. */
85
- set_float_rounding_mode(rmode, fp_status);
231
if (is_snan(c_cls)) {
232
return 2;
233
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
234
return 1;
235
}
236
#elif defined(TARGET_PPC)
237
- /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
238
- * to return an input NaN if we have one (ie c) rather than generating
239
- * a default NaN
240
- */
86
-
241
-
87
- return prev_rmode;
242
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
88
-}
243
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
89
-
244
*/
90
/* Half precision conversions. */
245
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
91
float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode)
246
return 1;
92
{
247
}
93
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
248
#elif defined(TARGET_S390X)
94
index XXXXXXX..XXXXXXX 100644
249
- if (infzero) {
95
--- a/target/arm/translate-neon.c.inc
250
- return 3;
96
+++ b/target/arm/translate-neon.c.inc
97
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
98
return do_2misc_fp(s, a, gen_helper_rints_exact);
99
}
100
101
-static bool do_vrint(DisasContext *s, arg_2misc *a, int rmode)
102
-{
103
- /*
104
- * Handle a VRINT* operation by iterating 32 bits at a time,
105
- * with a specified rounding mode in operation.
106
- */
107
- int pass;
108
- TCGv_ptr fpst;
109
- TCGv_i32 tcg_rmode;
110
-
111
- if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
112
- !arm_dc_feature(s, ARM_FEATURE_V8)) {
113
- return false;
114
- }
251
- }
115
-
252
-
116
- /* UNDEF accesses to D16-D31 if they don't exist. */
253
if (is_snan(a_cls)) {
117
- if (!dc_isar_feature(aa32_simd_r32, s) &&
254
return 0;
118
- ((a->vd | a->vm) & 0x10)) {
255
} else if (is_snan(b_cls)) {
119
- return false;
120
- }
121
-
122
- if (a->size != 2) {
123
- /* TODO: FP16 will be the size == 1 case */
124
- return false;
125
- }
126
-
127
- if ((a->vd | a->vm) & a->q) {
128
- return false;
129
- }
130
-
131
- if (!vfp_access_check(s)) {
132
- return true;
133
- }
134
-
135
- fpst = fpstatus_ptr(FPST_STD);
136
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
137
- gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
138
- for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
139
- TCGv_i32 tmp = neon_load_reg(a->vm, pass);
140
- gen_helper_rints(tmp, tmp, fpst);
141
- neon_store_reg(a->vd, pass, tmp);
142
- }
143
- gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
144
- tcg_temp_free_i32(tcg_rmode);
145
- tcg_temp_free_ptr(fpst);
146
-
147
- return true;
148
-}
149
-
150
-#define DO_VRINT(INSN, RMODE) \
151
- static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
152
- { \
153
- return do_vrint(s, a, RMODE); \
154
- }
155
-
156
-DO_VRINT(VRINTN, FPROUNDING_TIEEVEN)
157
-DO_VRINT(VRINTA, FPROUNDING_TIEAWAY)
158
-DO_VRINT(VRINTZ, FPROUNDING_ZERO)
159
-DO_VRINT(VRINTM, FPROUNDING_NEGINF)
160
-DO_VRINT(VRINTP, FPROUNDING_POSINF)
161
-
162
#define DO_VEC_RMODE(INSN, RMODE, OP) \
163
static void gen_##INSN(unsigned vece, uint32_t rd_ofs, \
164
uint32_t rm_ofs, \
165
@@ -XXX,XX +XXX,XX @@ DO_VEC_RMODE(VCVTPS, FPROUNDING_POSINF, vcvt_rm_s)
166
DO_VEC_RMODE(VCVTMU, FPROUNDING_NEGINF, vcvt_rm_u)
167
DO_VEC_RMODE(VCVTMS, FPROUNDING_NEGINF, vcvt_rm_s)
168
169
+DO_VEC_RMODE(VRINTN, FPROUNDING_TIEEVEN, vrint_rm_)
170
+DO_VEC_RMODE(VRINTA, FPROUNDING_TIEAWAY, vrint_rm_)
171
+DO_VEC_RMODE(VRINTZ, FPROUNDING_ZERO, vrint_rm_)
172
+DO_VEC_RMODE(VRINTM, FPROUNDING_NEGINF, vrint_rm_)
173
+DO_VEC_RMODE(VRINTP, FPROUNDING_POSINF, vrint_rm_)
174
+
175
static bool trans_VSWP(DisasContext *s, arg_2misc *a)
176
{
177
TCGv_i64 rm, rd;
178
--
256
--
179
2.20.1
257
2.34.1
180
181
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
1
Convert the Neon VCVT float<->fixed-point insns to a
1
Set the FloatInfZeroNaNRule explicitly for the Arm target,
2
gvec style, in preparation for adding fp16 support.
2
so we can remove the ifdef from pickNaNMulAdd().
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-38-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-6-peter.maydell@linaro.org
7
---
7
---
8
target/arm/helper.h | 5 +++++
8
target/arm/cpu.c | 3 +++
9
target/arm/vec_helper.c | 20 +++++++++++++++++++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
target/arm/translate-neon.c.inc | 35 +++++++++++++++++----------------
10
2 files changed, 4 insertions(+), 7 deletions(-)
11
3 files changed, 43 insertions(+), 17 deletions(-)
12
11
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
14
--- a/target/arm/cpu.c
16
+++ b/target/arm/helper.h
15
+++ b/target/arm/cpu.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_tosizs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
18
DEF_HELPER_FLAGS_4(gvec_touszh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
17
* * tininess-before-rounding
19
DEF_HELPER_FLAGS_4(gvec_touizs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
20
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
21
+DEF_HELPER_FLAGS_4(gvec_vcvt_sf, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
20
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
22
+DEF_HELPER_FLAGS_4(gvec_vcvt_uf, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
21
+ * and the input NaN if it is signalling
23
+DEF_HELPER_FLAGS_4(gvec_vcvt_fs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
*/
24
+DEF_HELPER_FLAGS_4(gvec_vcvt_fu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
static void arm_set_default_fp_behaviours(float_status *s)
25
+
24
{
26
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
set_float_detect_tininess(float_tininess_before_rounding, s);
27
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
28
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
29
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
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
30
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/vec_helper.c
33
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/target/arm/vec_helper.c
34
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ DO_NEON_PAIRWISE(neon_pmax, max)
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
34
DO_NEON_PAIRWISE(neon_pmin, min)
36
/*
35
37
* Temporarily fall back to ifdef ladder
36
#undef DO_NEON_PAIRWISE
38
*/
37
+
39
-#if defined(TARGET_ARM)
38
+#define DO_VCVT_FIXED(NAME, FUNC, TYPE) \
40
- /*
39
+ void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
41
- * For ARM, the (inf,zero,qnan) case returns the default NaN,
40
+ { \
42
- * but (inf,zero,snan) returns the input NaN.
41
+ intptr_t i, oprsz = simd_oprsz(desc); \
43
- */
42
+ int shift = simd_data(desc); \
44
- rule = float_infzeronan_dnan_if_qnan;
43
+ TYPE *d = vd, *n = vn; \
45
-#elif defined(TARGET_MIPS)
44
+ float_status *fpst = stat; \
46
+#if defined(TARGET_MIPS)
45
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
47
if (snan_bit_is_one(status)) {
46
+ d[i] = FUNC(n[i], shift, fpst); \
48
/*
47
+ } \
49
* For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
48
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
49
+ }
50
+
51
+DO_VCVT_FIXED(gvec_vcvt_sf, helper_vfp_sltos, uint32_t)
52
+DO_VCVT_FIXED(gvec_vcvt_uf, helper_vfp_ultos, uint32_t)
53
+DO_VCVT_FIXED(gvec_vcvt_fs, helper_vfp_tosls_round_to_zero, uint32_t)
54
+DO_VCVT_FIXED(gvec_vcvt_fu, helper_vfp_touls_round_to_zero, uint32_t)
55
+
56
+#undef DO_VCVT_FIXED
57
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/translate-neon.c.inc
60
+++ b/target/arm/translate-neon.c.inc
61
@@ -XXX,XX +XXX,XX @@ static bool trans_VSHLL_U_2sh(DisasContext *s, arg_2reg_shift *a)
62
}
63
64
static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
65
- NeonGenTwoSingleOpFn *fn)
66
+ gen_helper_gvec_2_ptr *fn)
67
{
68
/* FP operations in 2-reg-and-shift group */
69
- TCGv_i32 tmp, shiftv;
70
- TCGv_ptr fpstatus;
71
- int pass;
72
+ int vec_size = a->q ? 16 : 8;
73
+ int rd_ofs = neon_reg_offset(a->vd, 0);
74
+ int rm_ofs = neon_reg_offset(a->vm, 0);
75
+ TCGv_ptr fpst;
76
77
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
78
return false;
79
}
80
81
+ if (a->size != 0) {
82
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
83
+ return false;
84
+ }
85
+ }
86
+
87
/* UNDEF accesses to D16-D31 if they don't exist. */
88
if (!dc_isar_feature(aa32_simd_r32, s) &&
89
((a->vd | a->vm) & 0x10)) {
90
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
91
return true;
92
}
93
94
- fpstatus = fpstatus_ptr(FPST_STD);
95
- shiftv = tcg_const_i32(a->shift);
96
- for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
97
- tmp = neon_load_reg(a->vm, pass);
98
- fn(tmp, tmp, shiftv, fpstatus);
99
- neon_store_reg(a->vd, pass, tmp);
100
- }
101
- tcg_temp_free_ptr(fpstatus);
102
- tcg_temp_free_i32(shiftv);
103
+ fpst = fpstatus_ptr(a->size ? FPST_STD_F16 : FPST_STD);
104
+ tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, vec_size, vec_size, a->shift, fn);
105
+ tcg_temp_free_ptr(fpst);
106
return true;
107
}
108
109
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
110
return do_fp_2sh(s, a, FUNC); \
111
}
112
113
-DO_FP_2SH(VCVT_SF, gen_helper_vfp_sltos)
114
-DO_FP_2SH(VCVT_UF, gen_helper_vfp_ultos)
115
-DO_FP_2SH(VCVT_FS, gen_helper_vfp_tosls_round_to_zero)
116
-DO_FP_2SH(VCVT_FU, gen_helper_vfp_touls_round_to_zero)
117
+DO_FP_2SH(VCVT_SF, gen_helper_gvec_vcvt_sf)
118
+DO_FP_2SH(VCVT_UF, gen_helper_gvec_vcvt_uf)
119
+DO_FP_2SH(VCVT_FS, gen_helper_gvec_vcvt_fs)
120
+DO_FP_2SH(VCVT_FU, gen_helper_gvec_vcvt_fu)
121
122
static uint64_t asimd_imm_const(uint32_t imm, int cmode, int op)
123
{
124
--
50
--
125
2.20.1
51
2.34.1
126
127
diff view generated by jsdifflib
1
Convert the Neon pairwise fp ops to use a single gvic-style
1
Set the FloatInfZeroNaNRule explicitly for s390, so we
2
helper to do the full operation instead of one helper call
2
can remove the ifdef from pickNaNMulAdd().
3
for each 32-bit part. This allows us to use the same
4
framework to implement the fp16.
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: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200828183354.27913-36-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-7-peter.maydell@linaro.org
9
---
7
---
10
target/arm/helper.h | 7 +++++
8
target/s390x/cpu.c | 2 ++
11
target/arm/vec_helper.c | 45 +++++++++++++++++++++++++++++++++
9
fpu/softfloat-specialize.c.inc | 2 --
12
target/arm/translate-neon.c.inc | 42 ++++++++++++------------------
10
2 files changed, 2 insertions(+), 2 deletions(-)
13
3 files changed, 68 insertions(+), 26 deletions(-)
14
11
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
14
--- a/target/s390x/cpu.c
18
+++ b/target/arm/helper.h
15
+++ b/target/s390x/cpu.c
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fcmlas_idx, TCG_CALL_NO_RWG,
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
20
DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG,
17
set_float_detect_tininess(float_tininess_before_rounding,
21
void, ptr, ptr, ptr, ptr, i32)
18
&env->fpu_status);
22
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
23
+DEF_HELPER_FLAGS_5(neon_paddh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
+ set_float_infzeronan_rule(float_infzeronan_dnan_always,
24
+DEF_HELPER_FLAGS_5(neon_pmaxh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
+ &env->fpu_status);
25
+DEF_HELPER_FLAGS_5(neon_pminh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
22
/* fall through */
26
+DEF_HELPER_FLAGS_5(neon_padds, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
23
case RESET_TYPE_S390_CPU_NORMAL:
27
+DEF_HELPER_FLAGS_5(neon_pmaxs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
env->psw.mask &= ~PSW_MASK_RI;
28
+DEF_HELPER_FLAGS_5(neon_pmins, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
29
+
30
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
34
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/vec_helper.c
27
--- a/fpu/softfloat-specialize.c.inc
36
+++ b/target/arm/vec_helper.c
28
+++ b/fpu/softfloat-specialize.c.inc
37
@@ -XXX,XX +XXX,XX @@ DO_ABA(gvec_uaba_s, uint32_t)
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
38
DO_ABA(gvec_uaba_d, uint64_t)
30
* a default NaN
39
31
*/
40
#undef DO_ABA
32
rule = float_infzeronan_dnan_never;
41
+
33
-#elif defined(TARGET_S390X)
42
+#define DO_NEON_PAIRWISE(NAME, OP) \
34
- rule = float_infzeronan_dnan_always;
43
+ void HELPER(NAME##s)(void *vd, void *vn, void *vm, \
35
#endif
44
+ void *stat, uint32_t oprsz) \
45
+ { \
46
+ float_status *fpst = stat; \
47
+ float32 *d = vd; \
48
+ float32 *n = vn; \
49
+ float32 *m = vm; \
50
+ float32 r0, r1; \
51
+ \
52
+ /* Read all inputs before writing outputs in case vm == vd */ \
53
+ r0 = float32_##OP(n[H4(0)], n[H4(1)], fpst); \
54
+ r1 = float32_##OP(m[H4(0)], m[H4(1)], fpst); \
55
+ \
56
+ d[H4(0)] = r0; \
57
+ d[H4(1)] = r1; \
58
+ } \
59
+ \
60
+ void HELPER(NAME##h)(void *vd, void *vn, void *vm, \
61
+ void *stat, uint32_t oprsz) \
62
+ { \
63
+ float_status *fpst = stat; \
64
+ float16 *d = vd; \
65
+ float16 *n = vn; \
66
+ float16 *m = vm; \
67
+ float16 r0, r1, r2, r3; \
68
+ \
69
+ /* Read all inputs before writing outputs in case vm == vd */ \
70
+ r0 = float16_##OP(n[H2(0)], n[H2(1)], fpst); \
71
+ r1 = float16_##OP(n[H2(2)], n[H2(3)], fpst); \
72
+ r2 = float16_##OP(m[H2(0)], m[H2(1)], fpst); \
73
+ r3 = float16_##OP(m[H2(2)], m[H2(3)], fpst); \
74
+ \
75
+ d[H4(0)] = r0; \
76
+ d[H4(1)] = r1; \
77
+ d[H4(2)] = r2; \
78
+ d[H4(3)] = r3; \
79
+ }
80
+
81
+DO_NEON_PAIRWISE(neon_padd, add)
82
+DO_NEON_PAIRWISE(neon_pmax, max)
83
+DO_NEON_PAIRWISE(neon_pmin, min)
84
+
85
+#undef DO_NEON_PAIRWISE
86
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
87
index XXXXXXX..XXXXXXX 100644
88
--- a/target/arm/translate-neon.c.inc
89
+++ b/target/arm/translate-neon.c.inc
90
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
91
return do_3same(s, a, gen_VMINNM_fp32_3s);
92
}
93
94
-static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
95
+static bool do_3same_fp_pair(DisasContext *s, arg_3same *a,
96
+ gen_helper_gvec_3_ptr *fn)
97
{
98
- /* FP operations handled pairwise 32 bits at a time */
99
- TCGv_i32 tmp, tmp2, tmp3;
100
+ /* FP pairwise operations */
101
TCGv_ptr fpstatus;
102
103
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
104
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
105
106
assert(a->q == 0); /* enforced by decode patterns */
107
108
- /*
109
- * Note that we have to be careful not to clobber the source operands
110
- * in the "vm == vd" case by storing the result of the first pass too
111
- * early. Since Q is 0 there are always just two passes, so instead
112
- * of a complicated loop over each pass we just unroll.
113
- */
114
- fpstatus = fpstatus_ptr(FPST_STD);
115
- tmp = neon_load_reg(a->vn, 0);
116
- tmp2 = neon_load_reg(a->vn, 1);
117
- fn(tmp, tmp, tmp2, fpstatus);
118
- tcg_temp_free_i32(tmp2);
119
120
- tmp3 = neon_load_reg(a->vm, 0);
121
- tmp2 = neon_load_reg(a->vm, 1);
122
- fn(tmp3, tmp3, tmp2, fpstatus);
123
- tcg_temp_free_i32(tmp2);
124
+ fpstatus = fpstatus_ptr(a->size != 0 ? FPST_STD_F16 : FPST_STD);
125
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
126
+ vfp_reg_offset(1, a->vn),
127
+ vfp_reg_offset(1, a->vm),
128
+ fpstatus, 8, 8, 0, fn);
129
tcg_temp_free_ptr(fpstatus);
130
131
- neon_store_reg(a->vd, 0, tmp);
132
- neon_store_reg(a->vd, 1, tmp3);
133
return true;
134
}
135
136
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
137
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
138
{ \
139
if (a->size != 0) { \
140
- /* TODO fp16 support */ \
141
- return false; \
142
+ if (!dc_isar_feature(aa32_fp16_arith, s)) { \
143
+ return false; \
144
+ } \
145
+ return do_3same_fp_pair(s, a, FUNC##h); \
146
} \
147
- return do_3same_fp_pair(s, a, FUNC); \
148
+ return do_3same_fp_pair(s, a, FUNC##s); \
149
}
36
}
150
37
151
-DO_3S_FP_PAIR(VPADD, gen_helper_vfp_adds)
152
-DO_3S_FP_PAIR(VPMAX, gen_helper_vfp_maxs)
153
-DO_3S_FP_PAIR(VPMIN, gen_helper_vfp_mins)
154
+DO_3S_FP_PAIR(VPADD, gen_helper_neon_padd)
155
+DO_3S_FP_PAIR(VPMAX, gen_helper_neon_pmax)
156
+DO_3S_FP_PAIR(VPMIN, gen_helper_neon_pmin)
157
158
static bool do_vector_2sh(DisasContext *s, arg_2reg_shift *a, GVecGen2iFn *fn)
159
{
160
--
38
--
161
2.20.1
39
2.34.1
162
163
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
1
Convert the Neon float-integer VCVT insns to gvec, and use this
1
Set the FloatInfZeroNaNRule explicitly for the HPPA target,
2
to implement fp16 support for them.
2
so we can remove the ifdef from pickNaNMulAdd().
3
3
4
Note that unlike the VFP int<->fp16 VCVT insns we converted
4
As this is the last target to be converted to explicitly setting
5
earlier and which convert to/from a 32-bit integer, these
5
the rule, we can remove the fallback code in pickNaNMulAdd()
6
Neon insns convert to/from 16-bit integers. So we can use
6
entirely.
7
the existing vfp conversion helpers for the f32<->u32/i32
8
case but need to provide our own for f16<->u16/i16.
9
7
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200828183354.27913-37-peter.maydell@linaro.org
10
Message-id: 20241202131347.498124-14-peter.maydell@linaro.org
13
---
11
---
14
target/arm/helper.h | 9 +++++++++
12
target/hppa/fpu_helper.c | 2 ++
15
target/arm/vec_helper.c | 29 +++++++++++++++++++++++++++++
13
fpu/softfloat-specialize.c.inc | 13 +------------
16
target/arm/translate-neon.c.inc | 15 ++++-----------
14
2 files changed, 3 insertions(+), 12 deletions(-)
17
3 files changed, 42 insertions(+), 11 deletions(-)
18
15
19
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.h
18
--- a/target/hppa/fpu_helper.c
22
+++ b/target/arm/helper.h
19
+++ b/target/hppa/fpu_helper.c
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(neon_padds, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
24
DEF_HELPER_FLAGS_5(neon_pmaxs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
* HPPA does note implement a CPU reset method at all...
25
DEF_HELPER_FLAGS_5(neon_pmins, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
22
*/
26
23
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
27
+DEF_HELPER_FLAGS_4(gvec_sstoh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+ /* For inf * 0 + NaN, return the input NaN */
28
+DEF_HELPER_FLAGS_4(gvec_sitos, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
29
+DEF_HELPER_FLAGS_4(gvec_ustoh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
}
30
+DEF_HELPER_FLAGS_4(gvec_uitos, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
31
+DEF_HELPER_FLAGS_4(gvec_tosszh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
32
+DEF_HELPER_FLAGS_4(gvec_tosizs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
33
+DEF_HELPER_FLAGS_4(gvec_touszh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(gvec_touizs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
35
+
36
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
38
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
40
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/vec_helper.c
31
--- a/fpu/softfloat-specialize.c.inc
42
+++ b/target/arm/vec_helper.c
32
+++ b/fpu/softfloat-specialize.c.inc
43
@@ -XXX,XX +XXX,XX @@ static uint32_t float32_acgt(float32 op1, float32 op2, float_status *stat)
33
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
44
return -float32_lt(float32_abs(op2), float32_abs(op1), stat);
34
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
45
}
35
bool infzero, float_status *status)
46
36
{
47
+static int16_t vfp_tosszh(float16 x, void *fpstp)
37
- FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
48
+{
38
-
49
+ float_status *fpst = fpstp;
39
/*
50
+ if (float16_is_any_nan(x)) {
40
* We guarantee not to require the target to tell us how to
51
+ float_raise(float_flag_invalid, fpst);
41
* pick a NaN if we're always returning the default NaN.
52
+ return 0;
42
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
53
+ }
43
*/
54
+ return float16_to_int16_round_to_zero(x, fpst);
44
assert(!status->default_nan_mode);
55
+}
45
56
+
46
- if (rule == float_infzeronan_none) {
57
+static uint16_t vfp_touszh(float16 x, void *fpstp)
47
- /*
58
+{
48
- * Temporarily fall back to ifdef ladder
59
+ float_status *fpst = fpstp;
49
- */
60
+ if (float16_is_any_nan(x)) {
50
-#if defined(TARGET_HPPA)
61
+ float_raise(float_flag_invalid, fpst);
51
- rule = float_infzeronan_dnan_never;
62
+ return 0;
52
-#endif
63
+ }
64
+ return float16_to_uint16_round_to_zero(x, fpst);
65
+}
66
+
67
#define DO_2OP(NAME, FUNC, TYPE) \
68
void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
69
{ \
70
@@ -XXX,XX +XXX,XX @@ DO_2OP(gvec_frsqrte_h, helper_rsqrte_f16, float16)
71
DO_2OP(gvec_frsqrte_s, helper_rsqrte_f32, float32)
72
DO_2OP(gvec_frsqrte_d, helper_rsqrte_f64, float64)
73
74
+DO_2OP(gvec_sitos, helper_vfp_sitos, int32_t)
75
+DO_2OP(gvec_uitos, helper_vfp_uitos, uint32_t)
76
+DO_2OP(gvec_tosizs, helper_vfp_tosizs, float32)
77
+DO_2OP(gvec_touizs, helper_vfp_touizs, float32)
78
+DO_2OP(gvec_sstoh, int16_to_float16, int16_t)
79
+DO_2OP(gvec_ustoh, uint16_to_float16, uint16_t)
80
+DO_2OP(gvec_tosszh, vfp_tosszh, float16)
81
+DO_2OP(gvec_touszh, vfp_touszh, float16)
82
+
83
#define WRAP_CMP0_FWD(FN, CMPOP, TYPE) \
84
static TYPE TYPE##_##FN##0(TYPE op, float_status *stat) \
85
{ \
86
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
87
index XXXXXXX..XXXXXXX 100644
88
--- a/target/arm/translate-neon.c.inc
89
+++ b/target/arm/translate-neon.c.inc
90
@@ -XXX,XX +XXX,XX @@ static bool do_2misc_fp(DisasContext *s, arg_2misc *a,
91
return true;
92
}
93
94
-#define DO_2MISC_FP(INSN, FUNC) \
95
- static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
96
- { \
97
- return do_2misc_fp(s, a, FUNC); \
98
- }
53
- }
99
-
54
-
100
-DO_2MISC_FP(VCVT_FS, gen_helper_vfp_sitos)
55
if (infzero) {
101
-DO_2MISC_FP(VCVT_FU, gen_helper_vfp_uitos)
56
/*
102
-DO_2MISC_FP(VCVT_SF, gen_helper_vfp_tosizs)
57
* Inf * 0 + NaN -- some implementations return the default NaN here,
103
-DO_2MISC_FP(VCVT_UF, gen_helper_vfp_touizs)
58
* and some return the input NaN.
104
-
59
*/
105
#define DO_2MISC_FP_VEC(INSN, HFUNC, SFUNC) \
60
- switch (rule) {
106
static void gen_##INSN(unsigned vece, uint32_t rd_ofs, \
61
+ switch (status->float_infzeronan_rule) {
107
uint32_t rm_ofs, \
62
case float_infzeronan_dnan_never:
108
@@ -XXX,XX +XXX,XX @@ DO_2MISC_FP_VEC(VCGE0_F, gen_helper_gvec_fcge0_h, gen_helper_gvec_fcge0_s)
63
return 2;
109
DO_2MISC_FP_VEC(VCEQ0_F, gen_helper_gvec_fceq0_h, gen_helper_gvec_fceq0_s)
64
case float_infzeronan_dnan_always:
110
DO_2MISC_FP_VEC(VCLT0_F, gen_helper_gvec_fclt0_h, gen_helper_gvec_fclt0_s)
111
DO_2MISC_FP_VEC(VCLE0_F, gen_helper_gvec_fcle0_h, gen_helper_gvec_fcle0_s)
112
+DO_2MISC_FP_VEC(VCVT_FS, gen_helper_gvec_sstoh, gen_helper_gvec_sitos)
113
+DO_2MISC_FP_VEC(VCVT_FU, gen_helper_gvec_ustoh, gen_helper_gvec_uitos)
114
+DO_2MISC_FP_VEC(VCVT_SF, gen_helper_gvec_tosszh, gen_helper_gvec_tosizs)
115
+DO_2MISC_FP_VEC(VCVT_UF, gen_helper_gvec_touszh, gen_helper_gvec_touizs)
116
117
static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
118
{
119
--
65
--
120
2.20.1
66
2.34.1
121
122
diff view generated by jsdifflib
1
Implement fp16 for the Neon VCVT insns which convert between
1
The new implementation of pickNaNMulAdd() will find it convenient
2
float and fixed-point.
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.
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: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-39-peter.maydell@linaro.org
8
Message-id: 20241202131347.498124-15-peter.maydell@linaro.org
7
---
9
---
8
target/arm/helper.h | 5 +++++
10
fpu/softfloat-parts.c.inc | 5 +++--
9
target/arm/neon-dp.decode | 8 +++++++-
11
fpu/softfloat-specialize.c.inc | 2 +-
10
target/arm/vec_helper.c | 4 ++++
12
2 files changed, 4 insertions(+), 3 deletions(-)
11
target/arm/translate-neon.c.inc | 5 +++++
12
4 files changed, 21 insertions(+), 1 deletion(-)
13
13
14
diff --git a/target/arm/helper.h b/target/arm/helper.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.h
16
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/helper.h
17
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_vcvt_uf, 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_4(gvec_vcvt_fs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
19
{
20
DEF_HELPER_FLAGS_4(gvec_vcvt_fu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
20
int which;
21
21
bool infzero = (ab_mask == float_cmask_infzero);
22
+DEF_HELPER_FLAGS_4(gvec_vcvt_sh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
+ bool have_snan = (abc_mask & float_cmask_snan);
23
+DEF_HELPER_FLAGS_4(gvec_vcvt_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
24
+DEF_HELPER_FLAGS_4(gvec_vcvt_hs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
- if (unlikely(abc_mask & float_cmask_snan)) {
25
+DEF_HELPER_FLAGS_4(gvec_vcvt_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+ if (unlikely(have_snan)) {
26
+
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
27
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
}
28
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
29
DEF_HELPER_FLAGS_4(gvec_frecpe_d, 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
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
30
if (s->default_nan_mode) {
31
which = 3;
32
} else {
33
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
34
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
35
}
36
37
if (which == 3) {
38
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/neon-dp.decode
40
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/target/arm/neon-dp.decode
41
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
42
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
35
# We use size=0 for fp32 and size=1 for fp16 to match the 3-same encodings.
43
| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
36
@2reg_vcvt .... ... . . . 1 ..... .... .... . q:1 . . .... \
44
*----------------------------------------------------------------------------*/
37
&2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i5
45
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
38
+@2reg_vcvt_f16 .... ... . . . 11 .... .... .... . q:1 . . .... \
46
- bool infzero, float_status *status)
39
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4
47
+ bool infzero, bool have_snan, float_status *status)
40
41
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
42
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
43
@@ -XXX,XX +XXX,XX @@ VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_h
44
VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b
45
46
# VCVT fixed<->float conversions
47
-# TODO: FP16 fixed<->float conversions are opc==0b1100 and 0b1101
48
+VCVT_SH_2sh 1111 001 0 1 . ...... .... 1100 0 . . 1 .... @2reg_vcvt_f16
49
+VCVT_UH_2sh 1111 001 1 1 . ...... .... 1100 0 . . 1 .... @2reg_vcvt_f16
50
+VCVT_HS_2sh 1111 001 0 1 . ...... .... 1101 0 . . 1 .... @2reg_vcvt_f16
51
+VCVT_HU_2sh 1111 001 1 1 . ...... .... 1101 0 . . 1 .... @2reg_vcvt_f16
52
+
53
VCVT_SF_2sh 1111 001 0 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
54
VCVT_UF_2sh 1111 001 1 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
55
VCVT_FS_2sh 1111 001 0 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
56
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/vec_helper.c
59
+++ b/target/arm/vec_helper.c
60
@@ -XXX,XX +XXX,XX @@ DO_VCVT_FIXED(gvec_vcvt_sf, helper_vfp_sltos, uint32_t)
61
DO_VCVT_FIXED(gvec_vcvt_uf, helper_vfp_ultos, uint32_t)
62
DO_VCVT_FIXED(gvec_vcvt_fs, helper_vfp_tosls_round_to_zero, uint32_t)
63
DO_VCVT_FIXED(gvec_vcvt_fu, helper_vfp_touls_round_to_zero, uint32_t)
64
+DO_VCVT_FIXED(gvec_vcvt_sh, helper_vfp_shtoh, uint16_t)
65
+DO_VCVT_FIXED(gvec_vcvt_uh, helper_vfp_uhtoh, uint16_t)
66
+DO_VCVT_FIXED(gvec_vcvt_hs, helper_vfp_toshh_round_to_zero, uint16_t)
67
+DO_VCVT_FIXED(gvec_vcvt_hu, helper_vfp_touhh_round_to_zero, uint16_t)
68
69
#undef DO_VCVT_FIXED
70
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/translate-neon.c.inc
73
+++ b/target/arm/translate-neon.c.inc
74
@@ -XXX,XX +XXX,XX @@ DO_FP_2SH(VCVT_UF, gen_helper_gvec_vcvt_uf)
75
DO_FP_2SH(VCVT_FS, gen_helper_gvec_vcvt_fs)
76
DO_FP_2SH(VCVT_FU, gen_helper_gvec_vcvt_fu)
77
78
+DO_FP_2SH(VCVT_SH, gen_helper_gvec_vcvt_sh)
79
+DO_FP_2SH(VCVT_UH, gen_helper_gvec_vcvt_uh)
80
+DO_FP_2SH(VCVT_HS, gen_helper_gvec_vcvt_hs)
81
+DO_FP_2SH(VCVT_HU, gen_helper_gvec_vcvt_hu)
82
+
83
static uint64_t asimd_imm_const(uint32_t imm, int cmode, int op)
84
{
48
{
85
/*
49
/*
50
* We guarantee not to require the target to tell us how to
86
--
51
--
87
2.20.1
52
2.34.1
88
89
diff view generated by jsdifflib
1
Rewrite Neon VABS/VNEG of floats to use gvec logical AND and XOR, so
1
IEEE 758 does not define a fixed rule for which NaN to pick as the
2
that we can implement the fp16 version of the insns.
2
result if both operands of a 3-operand fused multiply-add operation
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.
3
23
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-26-peter.maydell@linaro.org
26
Message-id: 20241202131347.498124-16-peter.maydell@linaro.org
7
---
27
---
8
target/arm/translate-neon.c.inc | 34 +++++++++++++++++++++++++++------
28
include/fpu/softfloat-helpers.h | 11 +++
9
1 file changed, 28 insertions(+), 6 deletions(-)
29
include/fpu/softfloat-types.h | 55 +++++++++++
10
30
fpu/softfloat-specialize.c.inc | 167 ++++++++------------------------
11
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
31
3 files changed, 107 insertions(+), 126 deletions(-)
32
33
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
12
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-neon.c.inc
35
--- a/include/fpu/softfloat-helpers.h
14
+++ b/target/arm/translate-neon.c.inc
36
+++ b/include/fpu/softfloat-helpers.h
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VCNT(DisasContext *s, arg_2misc *a)
37
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
16
return do_2misc(s, a, gen_helper_neon_cnt_u8);
38
status->float_2nan_prop_rule = rule;
17
}
39
}
18
40
19
+static void gen_VABS_F(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
41
+static inline void set_float_3nan_prop_rule(Float3NaNPropRule rule,
20
+ uint32_t oprsz, uint32_t maxsz)
42
+ float_status *status)
21
+{
43
+{
22
+ tcg_gen_gvec_andi(vece, rd_ofs, rm_ofs,
44
+ status->float_3nan_prop_rule = rule;
23
+ vece == MO_16 ? 0x7fff : 0x7fffffff,
24
+ oprsz, maxsz);
25
+}
45
+}
26
+
46
+
27
static bool trans_VABS_F(DisasContext *s, arg_2misc *a)
47
static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
float_status *status)
28
{
49
{
29
- if (a->size != 2) {
50
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
30
+ if (a->size == MO_16) {
51
return status->float_2nan_prop_rule;
31
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
52
}
32
+ return false;
53
33
+ }
54
+static inline Float3NaNPropRule get_float_3nan_prop_rule(float_status *status)
34
+ } else if (a->size != MO_32) {
55
+{
35
return false;
56
+ return status->float_3nan_prop_rule;
57
+}
58
+
59
static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
60
{
61
return status->float_infzeronan_rule;
62
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
63
index XXXXXXX..XXXXXXX 100644
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
}
36
}
159
}
37
- /* TODO: FP16 : size == 1 */
160
38
- return do_2misc(s, a, gen_helper_vfp_abss);
161
+ if (rule == float_3nan_prop_none) {
39
+ return do_2misc_vec(s, a, gen_VABS_F);
162
#if defined(TARGET_ARM)
40
+}
163
-
41
+
164
- /* This looks different from the ARM ARM pseudocode, because the ARM ARM
42
+static void gen_VNEG_F(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
165
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
43
+ uint32_t oprsz, uint32_t maxsz)
166
- */
44
+{
167
- if (is_snan(c_cls)) {
45
+ tcg_gen_gvec_xori(vece, rd_ofs, rm_ofs,
168
- return 2;
46
+ vece == MO_16 ? 0x8000 : 0x80000000,
169
- } else if (is_snan(a_cls)) {
47
+ oprsz, maxsz);
170
- return 0;
171
- } else if (is_snan(b_cls)) {
172
- return 1;
173
- } else if (is_qnan(c_cls)) {
174
- return 2;
175
- } else if (is_qnan(a_cls)) {
176
- return 0;
177
- } else {
178
- return 1;
179
- }
180
+ /*
181
+ * This looks different from the ARM ARM pseudocode, because the ARM ARM
182
+ * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
183
+ */
184
+ rule = float_3nan_prop_s_cab;
185
#elif defined(TARGET_MIPS)
186
- if (snan_bit_is_one(status)) {
187
- /* Prefer sNaN over qNaN, in the a, b, c order. */
188
- if (is_snan(a_cls)) {
189
- return 0;
190
- } else if (is_snan(b_cls)) {
191
- return 1;
192
- } else if (is_snan(c_cls)) {
193
- return 2;
194
- } else if (is_qnan(a_cls)) {
195
- return 0;
196
- } else if (is_qnan(b_cls)) {
197
- return 1;
198
+ if (snan_bit_is_one(status)) {
199
+ rule = float_3nan_prop_s_abc;
200
} else {
201
- return 2;
202
+ rule = float_3nan_prop_s_cab;
203
}
204
- } else {
205
- /* Prefer sNaN over qNaN, in the c, a, b order. */
206
- if (is_snan(c_cls)) {
207
- return 2;
208
- } else if (is_snan(a_cls)) {
209
- return 0;
210
- } else if (is_snan(b_cls)) {
211
- return 1;
212
- } else if (is_qnan(c_cls)) {
213
- return 2;
214
- } else if (is_qnan(a_cls)) {
215
- return 0;
216
- } else {
217
- return 1;
218
- }
219
- }
220
#elif defined(TARGET_LOONGARCH64)
221
- /* Prefer sNaN over qNaN, in the c, a, b order. */
222
- if (is_snan(c_cls)) {
223
- return 2;
224
- } else if (is_snan(a_cls)) {
225
- return 0;
226
- } else if (is_snan(b_cls)) {
227
- return 1;
228
- } else if (is_qnan(c_cls)) {
229
- return 2;
230
- } else if (is_qnan(a_cls)) {
231
- return 0;
232
- } else {
233
- return 1;
234
- }
235
+ rule = float_3nan_prop_s_cab;
236
#elif defined(TARGET_PPC)
237
- /* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
238
- * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
239
- */
240
- if (is_nan(a_cls)) {
241
- return 0;
242
- } else if (is_nan(c_cls)) {
243
- return 2;
244
- } else {
245
- return 1;
246
- }
247
+ /*
248
+ * If fRA is a NaN return it; otherwise if fRB is a NaN return it;
249
+ * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
250
+ */
251
+ rule = float_3nan_prop_acb;
252
#elif defined(TARGET_S390X)
253
- if (is_snan(a_cls)) {
254
- return 0;
255
- } else if (is_snan(b_cls)) {
256
- return 1;
257
- } else if (is_snan(c_cls)) {
258
- return 2;
259
- } else if (is_qnan(a_cls)) {
260
- return 0;
261
- } else if (is_qnan(b_cls)) {
262
- return 1;
263
- } else {
264
- return 2;
265
- }
266
+ rule = float_3nan_prop_s_abc;
267
#elif defined(TARGET_SPARC)
268
- /* Prefer SNaN over QNaN, order C, B, A. */
269
- if (is_snan(c_cls)) {
270
- return 2;
271
- } else if (is_snan(b_cls)) {
272
- return 1;
273
- } else if (is_snan(a_cls)) {
274
- return 0;
275
- } else if (is_qnan(c_cls)) {
276
- return 2;
277
- } else if (is_qnan(b_cls)) {
278
- return 1;
279
- } else {
280
- return 0;
281
- }
282
+ rule = float_3nan_prop_s_cba;
283
#elif defined(TARGET_XTENSA)
284
- /*
285
- * For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
286
- * an input NaN if we have one (ie c).
287
- */
288
- if (status->use_first_nan) {
289
- if (is_nan(a_cls)) {
290
- return 0;
291
- } else if (is_nan(b_cls)) {
292
- return 1;
293
+ if (status->use_first_nan) {
294
+ rule = float_3nan_prop_abc;
295
} else {
296
- return 2;
297
+ rule = float_3nan_prop_cba;
298
}
299
- } else {
300
- if (is_nan(c_cls)) {
301
- return 2;
302
- } else if (is_nan(b_cls)) {
303
- return 1;
304
- } else {
305
- return 0;
306
- }
307
- }
308
#else
309
- /* A default implementation: prefer a to b to c.
310
- * This is unlikely to actually match any real implementation.
311
- */
312
- if (is_nan(a_cls)) {
313
- return 0;
314
- } else if (is_nan(b_cls)) {
315
- return 1;
316
- } else {
317
- return 2;
318
- }
319
+ rule = float_3nan_prop_abc;
320
#endif
321
+ }
322
+
323
+ assert(rule != float_3nan_prop_none);
324
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
325
+ /* We have at least one SNaN input and should prefer it */
326
+ do {
327
+ which = rule & R_3NAN_1ST_MASK;
328
+ rule >>= R_3NAN_1ST_LENGTH;
329
+ } while (!is_snan(cls[which]));
330
+ } else {
331
+ do {
332
+ which = rule & R_3NAN_1ST_MASK;
333
+ rule >>= R_3NAN_1ST_LENGTH;
334
+ } while (!is_nan(cls[which]));
335
+ }
336
+ return which;
48
}
337
}
49
338
50
static bool trans_VNEG_F(DisasContext *s, arg_2misc *a)
339
/*----------------------------------------------------------------------------
51
{
52
- if (a->size != 2) {
53
+ if (a->size == MO_16) {
54
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
55
+ return false;
56
+ }
57
+ } else if (a->size != MO_32) {
58
return false;
59
}
60
- /* TODO: FP16 : size == 1 */
61
- return do_2misc(s, a, gen_helper_vfp_negs);
62
+ return do_2misc_vec(s, a, gen_VNEG_F);
63
}
64
65
static bool trans_VRECPE(DisasContext *s, arg_2misc *a)
66
--
340
--
67
2.20.1
341
2.34.1
68
69
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
Set the MVFR1 ID register FPHP and SIMDHP fields to indicate
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
that our "-cpu max" has v8.2-FP16.
2
ifdef from pickNaNMulAdd().
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-46-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-18-peter.maydell@linaro.org
7
---
7
---
8
target/arm/cpu.c | 3 ++-
8
target/arm/cpu.c | 5 +++++
9
target/arm/cpu64.c | 10 ++++------
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 6 insertions(+), 7 deletions(-)
10
2 files changed, 6 insertions(+), 7 deletions(-)
11
11
12
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
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
17
cpu->isar.id_isar6 = t;
17
* * tininess-before-rounding
18
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
t = cpu->isar.mvfr1;
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
- t = FIELD_DP32(t, MVFR1, FPHP, 2); /* v8.0 FP support */
20
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
21
+ t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
21
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
22
+ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
22
+ * but note that for QEMU muladd is a * b + c, whereas for
23
cpu->isar.mvfr1 = t;
23
+ * the pseudocode function the arguments are in the order c, a, b.
24
24
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
25
t = cpu->isar.mvfr2;
25
* and the input NaN if it is signalling
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
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
27
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu64.c
37
--- a/fpu/softfloat-specialize.c.inc
29
+++ b/target/arm/cpu64.c
38
+++ b/fpu/softfloat-specialize.c.inc
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
39
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
31
u = FIELD_DP32(u, ID_DFR0, PERFMON, 5); /* v8.4-PMU */
40
}
32
cpu->isar.id_dfr0 = u;
41
33
42
if (rule == float_3nan_prop_none) {
43
-#if defined(TARGET_ARM)
34
- /*
44
- /*
35
- * FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet,
45
- * This looks different from the ARM ARM pseudocode, because the ARM ARM
36
- * so do not set MVFR1.FPHP. Strictly speaking this is not legal,
46
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
37
- * but it is also not legal to enable SVE without support for FP16,
38
- * and enabling SVE in system mode is more useful in the short term.
39
- */
47
- */
40
+ u = cpu->isar.mvfr1;
48
- rule = float_3nan_prop_s_cab;
41
+ u = FIELD_DP32(u, MVFR1, FPHP, 3); /* v8.2-FP16 */
49
-#elif defined(TARGET_MIPS)
42
+ u = FIELD_DP32(u, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
50
+#if defined(TARGET_MIPS)
43
+ cpu->isar.mvfr1 = u;
51
if (snan_bit_is_one(status)) {
44
52
rule = float_3nan_prop_s_abc;
45
#ifdef CONFIG_USER_ONLY
53
} else {
46
/* For usermode -cpu max we can use a larger and more efficient DCZ
47
--
54
--
48
2.20.1
55
2.34.1
49
50
diff view generated by jsdifflib
1
Convert the Neon VRSQRTS insn to using a gvec helper,
1
Set the Float3NaNPropRule explicitly for loongarch, and remove the
2
and use this to implement the fp16 case.
2
ifdef from pickNaNMulAdd().
3
4
As with VRECPS, we adjust the phrasing of the new implementation
5
slightly so that the fp32 version parallels the fp16 one.
6
3
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200828183354.27913-35-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-19-peter.maydell@linaro.org
10
---
7
---
11
target/arm/helper.h | 4 +++-
8
target/loongarch/tcg/fpu_helper.c | 1 +
12
target/arm/vec_helper.c | 30 ++++++++++++++++++++++++++++++
9
fpu/softfloat-specialize.c.inc | 2 --
13
target/arm/vfp_helper.c | 15 ---------------
10
2 files changed, 1 insertion(+), 2 deletions(-)
14
target/arm/translate-neon.c.inc | 21 +--------------------
15
4 files changed, 34 insertions(+), 36 deletions(-)
16
11
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
12
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
14
--- a/target/loongarch/tcg/fpu_helper.c
20
+++ b/target/arm/helper.h
15
+++ b/target/loongarch/tcg/fpu_helper.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
16
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
22
DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
17
* case sets InvalidOp and returns the input value 'c'
23
DEF_HELPER_4(vfp_muladdh, f16, f16, f16, f16, ptr)
18
*/
24
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
25
-DEF_HELPER_3(rsqrts_f32, f32, env, f32, f32)
20
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
26
DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
21
}
27
DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
22
28
DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
23
int ieee_ex_to_loongarch(int xcpt)
29
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fminnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i3
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
DEF_HELPER_FLAGS_5(gvec_recps_nf_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_5(gvec_recps_nf_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
32
33
+DEF_HELPER_FLAGS_5(gvec_rsqrts_nf_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_5(gvec_rsqrts_nf_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
35
+
36
DEF_HELPER_FLAGS_5(gvec_fmla_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
37
DEF_HELPER_FLAGS_5(gvec_fmla_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
38
39
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
40
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/vec_helper.c
26
--- a/fpu/softfloat-specialize.c.inc
42
+++ b/target/arm/vec_helper.c
27
+++ b/fpu/softfloat-specialize.c.inc
43
@@ -XXX,XX +XXX,XX @@ static float32 float32_recps_nf(float32 op1, float32 op2, float_status *stat)
28
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
44
return float32_sub(float32_two, float32_mul(op1, op2, stat), stat);
29
} else {
45
}
30
rule = float_3nan_prop_s_cab;
46
31
}
47
+/* Reciprocal square-root step. AArch32 non-fused semantics. */
32
-#elif defined(TARGET_LOONGARCH64)
48
+static float16 float16_rsqrts_nf(float16 op1, float16 op2, float_status *stat)
33
- rule = float_3nan_prop_s_cab;
49
+{
34
#elif defined(TARGET_PPC)
50
+ op1 = float16_squash_input_denormal(op1, stat);
35
/*
51
+ op2 = float16_squash_input_denormal(op2, stat);
36
* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
52
+
53
+ if ((float16_is_infinity(op1) && float16_is_zero(op2)) ||
54
+ (float16_is_infinity(op2) && float16_is_zero(op1))) {
55
+ return float16_one_point_five;
56
+ }
57
+ op1 = float16_sub(float16_three, float16_mul(op1, op2, stat), stat);
58
+ return float16_div(op1, float16_two, stat);
59
+}
60
+
61
+static float32 float32_rsqrts_nf(float32 op1, float32 op2, float_status *stat)
62
+{
63
+ op1 = float32_squash_input_denormal(op1, stat);
64
+ op2 = float32_squash_input_denormal(op2, stat);
65
+
66
+ if ((float32_is_infinity(op1) && float32_is_zero(op2)) ||
67
+ (float32_is_infinity(op2) && float32_is_zero(op1))) {
68
+ return float32_one_point_five;
69
+ }
70
+ op1 = float32_sub(float32_three, float32_mul(op1, op2, stat), stat);
71
+ return float32_div(op1, float32_two, stat);
72
+}
73
+
74
#define DO_3OP(NAME, FUNC, TYPE) \
75
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
76
{ \
77
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_fminnum_s, float32_minnum, float32)
78
DO_3OP(gvec_recps_nf_h, float16_recps_nf, float16)
79
DO_3OP(gvec_recps_nf_s, float32_recps_nf, float32)
80
81
+DO_3OP(gvec_rsqrts_nf_h, float16_rsqrts_nf, float16)
82
+DO_3OP(gvec_rsqrts_nf_s, float32_rsqrts_nf, float32)
83
+
84
#ifdef TARGET_AARCH64
85
86
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
87
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/vfp_helper.c
90
+++ b/target/arm/vfp_helper.c
91
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
92
return r;
93
}
94
95
-float32 HELPER(rsqrts_f32)(CPUARMState *env, float32 a, float32 b)
96
-{
97
- float_status *s = &env->vfp.standard_fp_status;
98
- float32 product;
99
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
100
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
101
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
102
- float_raise(float_flag_input_denormal, s);
103
- }
104
- return float32_one_point_five;
105
- }
106
- product = float32_mul(a, b, s);
107
- return float32_div(float32_sub(float32_three, product, s), float32_two, s);
108
-}
109
-
110
/* NEON helpers. */
111
112
/* Constants 256 and 512 are used in some helpers; we avoid relying on
113
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/translate-neon.c.inc
116
+++ b/target/arm/translate-neon.c.inc
117
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMLS, gen_helper_gvec_fmls_s, gen_helper_gvec_fmls_h)
118
DO_3S_FP_GVEC(VFMA, gen_helper_gvec_vfma_s, gen_helper_gvec_vfma_h)
119
DO_3S_FP_GVEC(VFMS, gen_helper_gvec_vfms_s, gen_helper_gvec_vfms_h)
120
DO_3S_FP_GVEC(VRECPS, gen_helper_gvec_recps_nf_s, gen_helper_gvec_recps_nf_h)
121
+DO_3S_FP_GVEC(VRSQRTS, gen_helper_gvec_rsqrts_nf_s, gen_helper_gvec_rsqrts_nf_h)
122
123
WRAP_FP_GVEC(gen_VMAXNM_fp32_3s, FPST_STD, gen_helper_gvec_fmaxnum_s)
124
WRAP_FP_GVEC(gen_VMAXNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fmaxnum_h)
125
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
126
return do_3same(s, a, gen_VMINNM_fp32_3s);
127
}
128
129
-WRAP_ENV_FN(gen_VRSQRTS_tramp, gen_helper_rsqrts_f32)
130
-
131
-static void gen_VRSQRTS_fp_3s(unsigned vece, uint32_t rd_ofs,
132
- uint32_t rn_ofs, uint32_t rm_ofs,
133
- uint32_t oprsz, uint32_t maxsz)
134
-{
135
- static const GVecGen3 ops = { .fni4 = gen_VRSQRTS_tramp };
136
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops);
137
-}
138
-
139
-static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a)
140
-{
141
- if (a->size != 0) {
142
- /* TODO fp16 support */
143
- return false;
144
- }
145
-
146
- return do_3same(s, a, gen_VRSQRTS_fp_3s);
147
-}
148
-
149
static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
150
{
151
/* FP operations handled pairwise 32 bits at a time */
152
--
37
--
153
2.20.1
38
2.34.1
154
155
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
Convert the Neon float-point VMAX and VMIN insns over to using
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
a gvec helper, and use this to implement the fp16 case.
2
ifdef from pickNaNMulAdd().
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-29-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-23-peter.maydell@linaro.org
7
---
7
---
8
target/arm/helper.h | 6 ++++++
8
target/mips/fpu_helper.h | 4 ++++
9
target/arm/vec_helper.c | 6 ++++++
9
target/mips/msa.c | 3 +++
10
target/arm/translate-neon.c.inc | 5 ++---
10
fpu/softfloat-specialize.c.inc | 8 +-------
11
3 files changed, 14 insertions(+), 3 deletions(-)
11
3 files changed, 8 insertions(+), 7 deletions(-)
12
12
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/arm/helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_facge_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
18
DEF_HELPER_FLAGS_5(gvec_facgt_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
18
{
19
DEF_HELPER_FLAGS_5(gvec_facgt_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
20
20
FloatInfZeroNaNRule izn_rule;
21
+DEF_HELPER_FLAGS_5(gvec_fmax_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
+ Float3NaNPropRule nan3_rule;
22
+DEF_HELPER_FLAGS_5(gvec_fmax_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
28
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
29
+ nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
30
+ set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
23
+
31
+
24
+DEF_HELPER_FLAGS_5(gvec_fmin_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
32
}
25
+DEF_HELPER_FLAGS_5(gvec_fmin_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
33
34
static inline void restore_fp_status(CPUMIPSState *env)
35
diff --git a/target/mips/msa.c b/target/mips/msa.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/mips/msa.c
38
+++ b/target/mips/msa.c
39
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
40
set_float_2nan_prop_rule(float_2nan_prop_s_ab,
41
&env->active_tc.msa_fp_status);
42
43
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab,
44
+ &env->active_tc.msa_fp_status);
26
+
45
+
27
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
46
/* clear float_status exception flags */
28
void, ptr, ptr, ptr, ptr, i32)
47
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
29
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
48
30
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
49
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/vec_helper.c
51
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/target/arm/vec_helper.c
52
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_facge_s, float32_acge, float32)
53
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
DO_3OP(gvec_facgt_h, float16_acgt, float16)
36
DO_3OP(gvec_facgt_s, float32_acgt, float32)
37
38
+DO_3OP(gvec_fmax_h, float16_max, float16)
39
+DO_3OP(gvec_fmax_s, float32_max, float32)
40
+
41
+DO_3OP(gvec_fmin_h, float16_min, float16)
42
+DO_3OP(gvec_fmin_s, float32_min, float32)
43
+
44
#ifdef TARGET_AARCH64
45
46
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
47
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate-neon.c.inc
50
+++ b/target/arm/translate-neon.c.inc
51
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VCGE, gen_helper_gvec_fcge_s, gen_helper_gvec_fcge_h)
52
DO_3S_FP_GVEC(VCGT, gen_helper_gvec_fcgt_s, gen_helper_gvec_fcgt_h)
53
DO_3S_FP_GVEC(VACGE, gen_helper_gvec_facge_s, gen_helper_gvec_facge_h)
54
DO_3S_FP_GVEC(VACGT, gen_helper_gvec_facgt_s, gen_helper_gvec_facgt_h)
55
+DO_3S_FP_GVEC(VMAX, gen_helper_gvec_fmax_s, gen_helper_gvec_fmax_h)
56
+DO_3S_FP_GVEC(VMIN, gen_helper_gvec_fmin_s, gen_helper_gvec_fmin_h)
57
58
/*
59
* For all the functions using this macro, size == 1 means fp16,
60
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VACGT, gen_helper_gvec_facgt_s, gen_helper_gvec_facgt_h)
61
return do_3same_fp(s, a, FUNC, READS_VD); \
62
}
54
}
63
55
64
-DO_3S_FP(VMAX, gen_helper_vfp_maxs, false)
56
if (rule == float_3nan_prop_none) {
65
-DO_3S_FP(VMIN, gen_helper_vfp_mins, false)
57
-#if defined(TARGET_MIPS)
66
-
58
- if (snan_bit_is_one(status)) {
67
static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
59
- rule = float_3nan_prop_s_abc;
68
TCGv_ptr fpstatus)
60
- } else {
69
{
61
- rule = float_3nan_prop_s_cab;
62
- }
63
-#elif defined(TARGET_XTENSA)
64
+#if defined(TARGET_XTENSA)
65
if (status->use_first_nan) {
66
rule = float_3nan_prop_abc;
67
} else {
70
--
68
--
71
2.20.1
69
2.34.1
72
73
diff view generated by jsdifflib
1
Implement the fp16 versions of the VFP VSEL instruction.
1
Set the Float3NaNPropRule explicitly for xtensa, and remove the
2
ifdef from pickNaNMulAdd().
2
3
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200828183354.27913-18-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-24-peter.maydell@linaro.org
6
---
7
---
7
target/arm/vfp-uncond.decode | 6 ++++--
8
target/xtensa/fpu_helper.c | 2 ++
8
target/arm/translate-vfp.c.inc | 16 ++++++++++++----
9
fpu/softfloat-specialize.c.inc | 8 --------
9
2 files changed, 16 insertions(+), 6 deletions(-)
10
2 files changed, 2 insertions(+), 8 deletions(-)
10
11
11
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
12
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/vfp-uncond.decode
14
--- a/target/xtensa/fpu_helper.c
14
+++ b/target/arm/vfp-uncond.decode
15
+++ b/target/xtensa/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
16
@vfp_dnm_s ................................ vm=%vm_sp vn=%vn_sp vd=%vd_sp
17
set_use_first_nan(use_first, &env->fp_status);
17
@vfp_dnm_d ................................ vm=%vm_dp vn=%vn_dp vd=%vd_dp
18
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
18
19
&env->fp_status);
19
+VSEL 1111 1110 0. cc:2 .... .... 1001 .0.0 .... \
20
+ set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
20
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp sz=1
21
+ &env->fp_status);
21
VSEL 1111 1110 0. cc:2 .... .... 1010 .0.0 .... \
22
}
22
- vm=%vm_sp vn=%vn_sp vd=%vd_sp dp=0
23
23
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp sz=2
24
void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
24
VSEL 1111 1110 0. cc:2 .... .... 1011 .0.0 .... \
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
- vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
26
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp sz=3
27
28
VMAXNM_hp 1111 1110 1.00 .... .... 1001 .0.0 .... @vfp_dnm_s
29
VMINNM_hp 1111 1110 1.00 .... .... 1001 .1.0 .... @vfp_dnm_s
30
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
31
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/translate-vfp.c.inc
27
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/target/arm/translate-vfp.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check(DisasContext *s)
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
36
{
37
uint32_t rd, rn, rm;
38
- bool dp = a->dp;
39
+ int sz = a->sz;
40
41
if (!dc_isar_feature(aa32_vsel, s)) {
42
return false;
43
}
30
}
44
31
45
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
32
if (rule == float_3nan_prop_none) {
46
+ if (sz == 3 && !dc_isar_feature(aa32_fpdp_v2, s)) {
33
-#if defined(TARGET_XTENSA)
47
+ return false;
34
- if (status->use_first_nan) {
48
+ }
35
- rule = float_3nan_prop_abc;
49
+
36
- } else {
50
+ if (sz == 1 && !dc_isar_feature(aa32_fp16_arith, s)) {
37
- rule = float_3nan_prop_cba;
51
return false;
38
- }
39
-#else
40
rule = float_3nan_prop_abc;
41
-#endif
52
}
42
}
53
43
54
/* UNDEF accesses to D16-D31 if they don't exist */
44
assert(rule != float_3nan_prop_none);
55
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
56
+ if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) &&
57
((a->vm | a->vn | a->vd) & 0x10)) {
58
return false;
59
}
60
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
61
return true;
62
}
63
64
- if (dp) {
65
+ if (sz == 3) {
66
TCGv_i64 frn, frm, dest;
67
TCGv_i64 tmp, zero, zf, nf, vf;
68
69
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
70
tcg_temp_free_i32(tmp);
71
break;
72
}
73
+ /* For fp16 the top half is always zeroes */
74
+ if (sz == 1) {
75
+ tcg_gen_andi_i32(dest, dest, 0xffff);
76
+ }
77
neon_store_reg32(dest, rd);
78
tcg_temp_free_i32(frn);
79
tcg_temp_free_i32(frm);
80
--
45
--
81
2.20.1
46
2.34.1
82
83
diff view generated by jsdifflib
1
Convert the neon floating-point vector compare-vs-0 insns VCEQ0,
1
Set the Float3NaNPropRule explicitly for i386. We had no
2
VCGT0, VCLE0, VCGE0 and VCLT0 to use a gvec helper, and use this to
2
i386-specific behaviour in the old ifdef ladder, so we were using the
3
implement the fp16 case.
3
default "prefer a then b then c" fallback; this is actually the
4
correct per-the-spec handling for i386.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200828183354.27913-33-peter.maydell@linaro.org
8
Message-id: 20241202131347.498124-25-peter.maydell@linaro.org
8
---
9
---
9
target/arm/helper.h | 15 +++++++++++++++
10
target/i386/tcg/fpu_helper.c | 1 +
10
target/arm/vec_helper.c | 25 +++++++++++++++++++++++++
11
1 file changed, 1 insertion(+)
11
target/arm/translate-neon.c.inc | 33 +++++----------------------------
12
3 files changed, 45 insertions(+), 28 deletions(-)
13
12
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.h
15
--- a/target/i386/tcg/fpu_helper.c
17
+++ b/target/arm/helper.h
16
+++ b/target/i386/tcg/fpu_helper.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_frsqrte_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
17
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
19
DEF_HELPER_FLAGS_4(gvec_frsqrte_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
18
* there are multiple input NaNs they are selected in the order a, b, c.
20
DEF_HELPER_FLAGS_4(gvec_frsqrte_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
19
*/
21
20
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
22
+DEF_HELPER_FLAGS_4(gvec_fcgt0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
21
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
23
+DEF_HELPER_FLAGS_4(gvec_fcgt0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+
25
+DEF_HELPER_FLAGS_4(gvec_fcge0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_4(gvec_fcge0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
+
28
+DEF_HELPER_FLAGS_4(gvec_fceq0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_4(gvec_fceq0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
30
+
31
+DEF_HELPER_FLAGS_4(gvec_fcle0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
32
+DEF_HELPER_FLAGS_4(gvec_fcle0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
+
34
+DEF_HELPER_FLAGS_4(gvec_fclt0_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_4(gvec_fclt0_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
36
+
37
DEF_HELPER_FLAGS_5(gvec_fadd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
38
DEF_HELPER_FLAGS_5(gvec_fadd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
39
DEF_HELPER_FLAGS_5(gvec_fadd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
40
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/vec_helper.c
43
+++ b/target/arm/vec_helper.c
44
@@ -XXX,XX +XXX,XX @@ DO_2OP(gvec_frsqrte_h, helper_rsqrte_f16, float16)
45
DO_2OP(gvec_frsqrte_s, helper_rsqrte_f32, float32)
46
DO_2OP(gvec_frsqrte_d, helper_rsqrte_f64, float64)
47
48
+#define WRAP_CMP0_FWD(FN, CMPOP, TYPE) \
49
+ static TYPE TYPE##_##FN##0(TYPE op, float_status *stat) \
50
+ { \
51
+ return TYPE##_##CMPOP(op, TYPE##_zero, stat); \
52
+ }
53
+
54
+#define WRAP_CMP0_REV(FN, CMPOP, TYPE) \
55
+ static TYPE TYPE##_##FN##0(TYPE op, float_status *stat) \
56
+ { \
57
+ return TYPE##_##CMPOP(TYPE##_zero, op, stat); \
58
+ }
59
+
60
+#define DO_2OP_CMP0(FN, CMPOP, DIRN) \
61
+ WRAP_CMP0_##DIRN(FN, CMPOP, float16) \
62
+ WRAP_CMP0_##DIRN(FN, CMPOP, float32) \
63
+ DO_2OP(gvec_f##FN##0_h, float16_##FN##0, float16) \
64
+ DO_2OP(gvec_f##FN##0_s, float32_##FN##0, float32)
65
+
66
+DO_2OP_CMP0(cgt, cgt, FWD)
67
+DO_2OP_CMP0(cge, cge, FWD)
68
+DO_2OP_CMP0(ceq, ceq, FWD)
69
+DO_2OP_CMP0(clt, cgt, REV)
70
+DO_2OP_CMP0(cle, cge, REV)
71
+
72
#undef DO_2OP
73
+#undef DO_2OP_CMP0
74
75
/* Floating-point trigonometric starting value.
76
* See the ARM ARM pseudocode function FPTrigSMul.
77
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
78
index XXXXXXX..XXXXXXX 100644
79
--- a/target/arm/translate-neon.c.inc
80
+++ b/target/arm/translate-neon.c.inc
81
@@ -XXX,XX +XXX,XX @@ DO_2MISC_FP(VCVT_UF, gen_helper_vfp_touizs)
82
83
DO_2MISC_FP_VEC(VRECPE_F, gen_helper_gvec_frecpe_h, gen_helper_gvec_frecpe_s)
84
DO_2MISC_FP_VEC(VRSQRTE_F, gen_helper_gvec_frsqrte_h, gen_helper_gvec_frsqrte_s)
85
+DO_2MISC_FP_VEC(VCGT0_F, gen_helper_gvec_fcgt0_h, gen_helper_gvec_fcgt0_s)
86
+DO_2MISC_FP_VEC(VCGE0_F, gen_helper_gvec_fcge0_h, gen_helper_gvec_fcge0_s)
87
+DO_2MISC_FP_VEC(VCEQ0_F, gen_helper_gvec_fceq0_h, gen_helper_gvec_fceq0_s)
88
+DO_2MISC_FP_VEC(VCLT0_F, gen_helper_gvec_fclt0_h, gen_helper_gvec_fclt0_s)
89
+DO_2MISC_FP_VEC(VCLE0_F, gen_helper_gvec_fcle0_h, gen_helper_gvec_fcle0_s)
90
91
static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
92
{
93
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
94
return do_2misc_fp(s, a, gen_helper_rints_exact);
95
}
22
}
96
23
97
-#define WRAP_FP_CMP0_FWD(WRAPNAME, FUNC) \
24
static inline uint8_t save_exception_flags(CPUX86State *env)
98
- static void WRAPNAME(TCGv_i32 d, TCGv_i32 m, TCGv_ptr fpst) \
99
- { \
100
- TCGv_i32 zero = tcg_const_i32(0); \
101
- FUNC(d, m, zero, fpst); \
102
- tcg_temp_free_i32(zero); \
103
- }
104
-#define WRAP_FP_CMP0_REV(WRAPNAME, FUNC) \
105
- static void WRAPNAME(TCGv_i32 d, TCGv_i32 m, TCGv_ptr fpst) \
106
- { \
107
- TCGv_i32 zero = tcg_const_i32(0); \
108
- FUNC(d, zero, m, fpst); \
109
- tcg_temp_free_i32(zero); \
110
- }
111
-
112
-#define DO_FP_CMP0(INSN, FUNC, REV) \
113
- WRAP_FP_CMP0_##REV(gen_##INSN, FUNC) \
114
- static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
115
- { \
116
- return do_2misc_fp(s, a, gen_##INSN); \
117
- }
118
-
119
-DO_FP_CMP0(VCGT0_F, gen_helper_neon_cgt_f32, FWD)
120
-DO_FP_CMP0(VCGE0_F, gen_helper_neon_cge_f32, FWD)
121
-DO_FP_CMP0(VCEQ0_F, gen_helper_neon_ceq_f32, FWD)
122
-DO_FP_CMP0(VCLE0_F, gen_helper_neon_cge_f32, REV)
123
-DO_FP_CMP0(VCLT0_F, gen_helper_neon_cgt_f32, REV)
124
-
125
static bool do_vrint(DisasContext *s, arg_2misc *a, int rmode)
126
{
127
/*
128
--
25
--
129
2.20.1
26
2.34.1
130
131
diff view generated by jsdifflib
1
Convert the neon floating-point vector absolute comparison ops
1
Set the Float3NaNPropRule explicitly for HPPA, and remove the
2
VACGE and VACGT over to using a gvec hepler and use this to
2
ifdef from pickNaNMulAdd().
3
implement the fp16 case.
3
4
HPPA is the only target that was using the default branch of the
5
ifdef ladder (other targets either do not use muladd or set
6
default_nan_mode), so we can remove the ifdef fallback entirely now
7
(allowing the "rule not set" case to fall into the default of the
8
switch statement and assert).
9
10
We add a TODO note that the HPPA rule is probably wrong; this is
11
not a behavioural change for this refactoring.
4
12
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200828183354.27913-28-peter.maydell@linaro.org
15
Message-id: 20241202131347.498124-26-peter.maydell@linaro.org
8
---
16
---
9
target/arm/helper.h | 6 ++++++
17
target/hppa/fpu_helper.c | 8 ++++++++
10
target/arm/vec_helper.c | 26 ++++++++++++++++++++++++++
18
fpu/softfloat-specialize.c.inc | 4 ----
11
target/arm/translate-neon.c.inc | 4 ++--
19
2 files changed, 8 insertions(+), 4 deletions(-)
12
3 files changed, 34 insertions(+), 2 deletions(-)
13
20
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
21
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.h
23
--- a/target/hppa/fpu_helper.c
17
+++ b/target/arm/helper.h
24
+++ b/target/hppa/fpu_helper.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fcge_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
19
DEF_HELPER_FLAGS_5(gvec_fcgt_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
* HPPA does note implement a CPU reset method at all...
20
DEF_HELPER_FLAGS_5(gvec_fcgt_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
*/
21
28
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
22
+DEF_HELPER_FLAGS_5(gvec_facge_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
29
+ /*
23
+DEF_HELPER_FLAGS_5(gvec_facge_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
30
+ * TODO: The HPPA architecture reference only documents its NaN
24
+
31
+ * propagation rule for 2-operand operations. Testing on real hardware
25
+DEF_HELPER_FLAGS_5(gvec_facgt_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
32
+ * might be necessary to confirm whether this order for muladd is correct.
26
+DEF_HELPER_FLAGS_5(gvec_facgt_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
33
+ * Not preferring the SNaN is almost certainly incorrect as it diverges
27
+
34
+ * from the documented rules for 2-operand operations.
28
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
35
+ */
29
void, ptr, ptr, ptr, ptr, i32)
36
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
30
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
37
/* For inf * 0 + NaN, return the input NaN */
31
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
38
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
39
}
40
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/vec_helper.c
42
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/target/arm/vec_helper.c
43
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static uint32_t float32_cgt(float32 op1, float32 op2, float_status *stat)
44
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
return -float32_lt(op2, op1, stat);
45
}
37
}
38
39
+static uint16_t float16_acge(float16 op1, float16 op2, float_status *stat)
40
+{
41
+ return -float16_le(float16_abs(op2), float16_abs(op1), stat);
42
+}
43
+
44
+static uint32_t float32_acge(float32 op1, float32 op2, float_status *stat)
45
+{
46
+ return -float32_le(float32_abs(op2), float32_abs(op1), stat);
47
+}
48
+
49
+static uint16_t float16_acgt(float16 op1, float16 op2, float_status *stat)
50
+{
51
+ return -float16_lt(float16_abs(op2), float16_abs(op1), stat);
52
+}
53
+
54
+static uint32_t float32_acgt(float32 op1, float32 op2, float_status *stat)
55
+{
56
+ return -float32_lt(float32_abs(op2), float32_abs(op1), stat);
57
+}
58
+
59
#define DO_2OP(NAME, FUNC, TYPE) \
60
void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
61
{ \
62
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_fcge_s, float32_cge, float32)
63
DO_3OP(gvec_fcgt_h, float16_cgt, float16)
64
DO_3OP(gvec_fcgt_s, float32_cgt, float32)
65
66
+DO_3OP(gvec_facge_h, float16_acge, float16)
67
+DO_3OP(gvec_facge_s, float32_acge, float32)
68
+
69
+DO_3OP(gvec_facgt_h, float16_acgt, float16)
70
+DO_3OP(gvec_facgt_s, float32_acgt, float32)
71
+
72
#ifdef TARGET_AARCH64
73
74
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
75
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/translate-neon.c.inc
78
+++ b/target/arm/translate-neon.c.inc
79
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s, gen_helper_gvec_fmul_h)
80
DO_3S_FP_GVEC(VCEQ, gen_helper_gvec_fceq_s, gen_helper_gvec_fceq_h)
81
DO_3S_FP_GVEC(VCGE, gen_helper_gvec_fcge_s, gen_helper_gvec_fcge_h)
82
DO_3S_FP_GVEC(VCGT, gen_helper_gvec_fcgt_s, gen_helper_gvec_fcgt_h)
83
+DO_3S_FP_GVEC(VACGE, gen_helper_gvec_facge_s, gen_helper_gvec_facge_h)
84
+DO_3S_FP_GVEC(VACGT, gen_helper_gvec_facgt_s, gen_helper_gvec_facgt_h)
85
86
/*
87
* For all the functions using this macro, size == 1 means fp16,
88
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VCGT, gen_helper_gvec_fcgt_s, gen_helper_gvec_fcgt_h)
89
return do_3same_fp(s, a, FUNC, READS_VD); \
90
}
46
}
91
47
92
-DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false)
48
- if (rule == float_3nan_prop_none) {
93
-DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false)
49
- rule = float_3nan_prop_abc;
94
DO_3S_FP(VMAX, gen_helper_vfp_maxs, false)
50
- }
95
DO_3S_FP(VMIN, gen_helper_vfp_mins, false)
51
-
96
52
assert(rule != float_3nan_prop_none);
53
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
54
/* We have at least one SNaN input and should prefer it */
97
--
55
--
98
2.20.1
56
2.34.1
99
100
diff view generated by jsdifflib
1
Convert the Neon VRECPS insn to using a gvec helper, and
1
The use_first_nan field in float_status was an xtensa-specific way to
2
use this to implement the fp16 case.
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
The phrasing of the new float32_recps_nf() is slightly different from
4
that we've just added, we can remove use_first_nan, because there is
5
the old recps_f32() so that it parallels the f16 version; for f16 we
5
no longer any code that reads it.
6
can't assume that flush-to-zero is always enabled.
7
6
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200828183354.27913-34-peter.maydell@linaro.org
9
Message-id: 20241202131347.498124-27-peter.maydell@linaro.org
11
---
10
---
12
target/arm/helper.h | 4 +++-
11
include/fpu/softfloat-helpers.h | 5 -----
13
target/arm/vec_helper.c | 31 +++++++++++++++++++++++++++++++
12
include/fpu/softfloat-types.h | 1 -
14
target/arm/vfp_helper.c | 13 -------------
13
target/xtensa/fpu_helper.c | 1 -
15
target/arm/translate-neon.c.inc | 21 +--------------------
14
3 files changed, 7 deletions(-)
16
4 files changed, 35 insertions(+), 34 deletions(-)
17
15
18
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.h
18
--- a/include/fpu/softfloat-helpers.h
21
+++ b/target/arm/helper.h
19
+++ b/include/fpu/softfloat-helpers.h
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
20
@@ -XXX,XX +XXX,XX @@ static inline void set_snan_bit_is_one(bool val, float_status *status)
23
DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
21
status->snan_bit_is_one = val;
24
DEF_HELPER_4(vfp_muladdh, f16, f16, f16, f16, ptr)
25
26
-DEF_HELPER_3(recps_f32, f32, env, f32, f32)
27
DEF_HELPER_3(rsqrts_f32, f32, env, f32, f32)
28
DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
29
DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
30
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmaxnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i3
31
DEF_HELPER_FLAGS_5(gvec_fminnum_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_5(gvec_fminnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
33
34
+DEF_HELPER_FLAGS_5(gvec_recps_nf_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_5(gvec_recps_nf_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
36
+
37
DEF_HELPER_FLAGS_5(gvec_fmla_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
38
DEF_HELPER_FLAGS_5(gvec_fmla_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
39
40
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/vec_helper.c
43
+++ b/target/arm/vec_helper.c
44
@@ -XXX,XX +XXX,XX @@ static float32 float32_abd(float32 op1, float32 op2, float_status *stat)
45
return float32_abs(float32_sub(op1, op2, stat));
46
}
22
}
47
23
48
+/*
24
-static inline void set_use_first_nan(bool val, float_status *status)
49
+ * Reciprocal step. These are the AArch32 version which uses a
50
+ * non-fused multiply-and-subtract.
51
+ */
52
+static float16 float16_recps_nf(float16 op1, float16 op2, float_status *stat)
53
+{
54
+ op1 = float16_squash_input_denormal(op1, stat);
55
+ op2 = float16_squash_input_denormal(op2, stat);
56
+
57
+ if ((float16_is_infinity(op1) && float16_is_zero(op2)) ||
58
+ (float16_is_infinity(op2) && float16_is_zero(op1))) {
59
+ return float16_two;
60
+ }
61
+ return float16_sub(float16_two, float16_mul(op1, op2, stat), stat);
62
+}
63
+
64
+static float32 float32_recps_nf(float32 op1, float32 op2, float_status *stat)
65
+{
66
+ op1 = float32_squash_input_denormal(op1, stat);
67
+ op2 = float32_squash_input_denormal(op2, stat);
68
+
69
+ if ((float32_is_infinity(op1) && float32_is_zero(op2)) ||
70
+ (float32_is_infinity(op2) && float32_is_zero(op1))) {
71
+ return float32_two;
72
+ }
73
+ return float32_sub(float32_two, float32_mul(op1, op2, stat), stat);
74
+}
75
+
76
#define DO_3OP(NAME, FUNC, TYPE) \
77
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
78
{ \
79
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_fmaxnum_s, float32_maxnum, float32)
80
DO_3OP(gvec_fminnum_h, float16_minnum, float16)
81
DO_3OP(gvec_fminnum_s, float32_minnum, float32)
82
83
+DO_3OP(gvec_recps_nf_h, float16_recps_nf, float16)
84
+DO_3OP(gvec_recps_nf_s, float32_recps_nf, float32)
85
+
86
#ifdef TARGET_AARCH64
87
88
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
89
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/vfp_helper.c
92
+++ b/target/arm/vfp_helper.c
93
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
94
return r;
95
}
96
97
-float32 HELPER(recps_f32)(CPUARMState *env, float32 a, float32 b)
98
-{
25
-{
99
- float_status *s = &env->vfp.standard_fp_status;
26
- status->use_first_nan = val;
100
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
101
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
102
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
103
- float_raise(float_flag_input_denormal, s);
104
- }
105
- return float32_two;
106
- }
107
- return float32_sub(float32_two, float32_mul(a, b, s), s);
108
-}
27
-}
109
-
28
-
110
float32 HELPER(rsqrts_f32)(CPUARMState *env, float32 a, float32 b)
29
static inline void set_no_signaling_nans(bool val, float_status *status)
111
{
30
{
112
float_status *s = &env->vfp.standard_fp_status;
31
status->no_signaling_nans = val;
113
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
32
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
114
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/translate-neon.c.inc
34
--- a/include/fpu/softfloat-types.h
116
+++ b/target/arm/translate-neon.c.inc
35
+++ b/include/fpu/softfloat-types.h
117
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMLA, gen_helper_gvec_fmla_s, gen_helper_gvec_fmla_h)
36
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
118
DO_3S_FP_GVEC(VMLS, gen_helper_gvec_fmls_s, gen_helper_gvec_fmls_h)
37
* softfloat-specialize.inc.c)
119
DO_3S_FP_GVEC(VFMA, gen_helper_gvec_vfma_s, gen_helper_gvec_vfma_h)
38
*/
120
DO_3S_FP_GVEC(VFMS, gen_helper_gvec_vfms_s, gen_helper_gvec_vfms_h)
39
bool snan_bit_is_one;
121
+DO_3S_FP_GVEC(VRECPS, gen_helper_gvec_recps_nf_s, gen_helper_gvec_recps_nf_h)
40
- bool use_first_nan;
122
41
bool no_signaling_nans;
123
WRAP_FP_GVEC(gen_VMAXNM_fp32_3s, FPST_STD, gen_helper_gvec_fmaxnum_s)
42
/* should overflowed results subtract re_bias to its exponent? */
124
WRAP_FP_GVEC(gen_VMAXNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fmaxnum_h)
43
bool rebias_overflow;
125
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
44
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
126
return do_3same(s, a, gen_VMINNM_fp32_3s);
45
index XXXXXXX..XXXXXXX 100644
127
}
46
--- a/target/xtensa/fpu_helper.c
128
47
+++ b/target/xtensa/fpu_helper.c
129
-WRAP_ENV_FN(gen_VRECPS_tramp, gen_helper_recps_f32)
48
@@ -XXX,XX +XXX,XX @@ static const struct {
130
-
49
131
-static void gen_VRECPS_fp_3s(unsigned vece, uint32_t rd_ofs,
50
void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
132
- uint32_t rn_ofs, uint32_t rm_ofs,
51
{
133
- uint32_t oprsz, uint32_t maxsz)
52
- set_use_first_nan(use_first, &env->fp_status);
134
-{
53
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
135
- static const GVecGen3 ops = { .fni4 = gen_VRECPS_tramp };
54
&env->fp_status);
136
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops);
55
set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
137
-}
138
-
139
-static bool trans_VRECPS_fp_3s(DisasContext *s, arg_3same *a)
140
-{
141
- if (a->size != 0) {
142
- /* TODO fp16 support */
143
- return false;
144
- }
145
-
146
- return do_3same(s, a, gen_VRECPS_fp_3s);
147
-}
148
-
149
WRAP_ENV_FN(gen_VRSQRTS_tramp, gen_helper_rsqrts_f32)
150
151
static void gen_VRSQRTS_fp_3s(unsigned vece, uint32_t rd_ofs,
152
--
56
--
153
2.20.1
57
2.34.1
154
155
diff view generated by jsdifflib
New patch
1
Currently m68k_cpu_reset_hold() calls floatx80_default_nan(NULL)
2
to get the NaN bit pattern to reset the FPU registers. This
3
works because it happens that our implementation of
4
floatx80_default_nan() doesn't actually look at the float_status
5
pointer except for TARGET_MIPS. However, this isn't guaranteed,
6
and to be able to remove the ifdef in floatx80_default_nan()
7
we're going to need a real float_status here.
1
8
9
Rearrange m68k_cpu_reset_hold() so that we initialize env->fp_status
10
earlier, and thus can pass it to floatx80_default_nan().
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20241202131347.498124-28-peter.maydell@linaro.org
15
---
16
target/m68k/cpu.c | 12 +++++++-----
17
1 file changed, 7 insertions(+), 5 deletions(-)
18
19
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/m68k/cpu.c
22
+++ b/target/m68k/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
24
CPUState *cs = CPU(obj);
25
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(obj);
26
CPUM68KState *env = cpu_env(cs);
27
- floatx80 nan = floatx80_default_nan(NULL);
28
+ floatx80 nan;
29
int i;
30
31
if (mcc->parent_phases.hold) {
32
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
33
#else
34
cpu_m68k_set_sr(env, SR_S | SR_I);
35
#endif
36
- for (i = 0; i < 8; i++) {
37
- env->fregs[i].d = nan;
38
- }
39
- cpu_m68k_set_fpcr(env, 0);
40
/*
41
* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
42
* 3.4 FLOATING-POINT INSTRUCTION DETAILS
43
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
44
* preceding paragraph for nonsignaling NaNs.
45
*/
46
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
47
+
48
+ nan = floatx80_default_nan(&env->fp_status);
49
+ for (i = 0; i < 8; i++) {
50
+ env->fregs[i].d = nan;
51
+ }
52
+ cpu_m68k_set_fpcr(env, 0);
53
env->fpsr = 0;
54
55
/* TODO: We should set PC from the interrupt vector. */
56
--
57
2.34.1
diff view generated by jsdifflib
1
In several places the target/arm code defines local float constants
1
We create our 128-bit default NaN by calling parts64_default_nan()
2
for 2, 3 and 1.5, which are also provided by include/fpu/softfloat.h.
2
and then adjusting the result. We can do the same trick for creating
3
Remove the unnecessary local duplicate versions.
3
the floatx80 default NaN, which lets us drop a target ifdef.
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.
4
36
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
38
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200828183354.27913-2-peter.maydell@linaro.org
39
Message-id: 20241202131347.498124-29-peter.maydell@linaro.org
8
---
40
---
9
target/arm/helper-a64.c | 11 -----------
41
fpu/softfloat-specialize.c.inc | 20 ++++++++++----------
10
target/arm/translate-sve.c | 4 ----
42
1 file changed, 10 insertions(+), 10 deletions(-)
11
target/arm/vfp_helper.c | 4 ----
12
3 files changed, 19 deletions(-)
13
43
14
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
44
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
15
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-a64.c
46
--- a/fpu/softfloat-specialize.c.inc
17
+++ b/target/arm/helper-a64.c
47
+++ b/fpu/softfloat-specialize.c.inc
18
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(neon_cgt_f64)(float64 a, float64 b, void *fpstp)
48
@@ -XXX,XX +XXX,XX @@ static void parts128_silence_nan(FloatParts128 *p, float_status *status)
19
* versions, these do a fully fused multiply-add or
49
floatx80 floatx80_default_nan(float_status *status)
20
* multiply-add-and-halve.
21
*/
22
-#define float16_two make_float16(0x4000)
23
-#define float16_three make_float16(0x4200)
24
-#define float16_one_point_five make_float16(0x3e00)
25
-
26
-#define float32_two make_float32(0x40000000)
27
-#define float32_three make_float32(0x40400000)
28
-#define float32_one_point_five make_float32(0x3fc00000)
29
-
30
-#define float64_two make_float64(0x4000000000000000ULL)
31
-#define float64_three make_float64(0x4008000000000000ULL)
32
-#define float64_one_point_five make_float64(0x3FF8000000000000ULL)
33
34
uint32_t HELPER(recpsf_f16)(uint32_t a, uint32_t b, void *fpstp)
35
{
50
{
36
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
51
floatx80 r;
37
index XXXXXXX..XXXXXXX 100644
52
+ /*
38
--- a/target/arm/translate-sve.c
53
+ * Extrapolate from the choices made by parts64_default_nan to fill
39
+++ b/target/arm/translate-sve.c
54
+ * in the floatx80 format. We assume that floatx80's explicit
40
@@ -XXX,XX +XXX,XX @@ static bool trans_##NAME##_zpzi(DisasContext *s, arg_rpri_esz *a) \
55
+ * integer bit is always set (this is true for i386 and m68k,
41
return true; \
56
+ * which are the only real users of this format).
42
}
57
+ */
43
58
+ FloatParts64 p64;
44
-#define float16_two make_float16(0x4000)
59
+ parts64_default_nan(&p64, status);
45
-#define float32_two make_float32(0x40000000)
60
46
-#define float64_two make_float64(0x4000000000000000ULL)
61
- /* None of the targets that have snan_bit_is_one use floatx80. */
47
-
62
- assert(!snan_bit_is_one(status));
48
DO_FP_IMM(FADD, fadds, half, one)
63
-#if defined(TARGET_M68K)
49
DO_FP_IMM(FSUB, fsubs, half, one)
64
- r.low = UINT64_C(0xFFFFFFFFFFFFFFFF);
50
DO_FP_IMM(FMUL, fmuls, half, two)
65
- r.high = 0x7FFF;
51
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
66
-#else
52
index XXXXXXX..XXXXXXX 100644
67
- /* X86 */
53
--- a/target/arm/vfp_helper.c
68
- r.low = UINT64_C(0xC000000000000000);
54
+++ b/target/arm/vfp_helper.c
69
- r.high = 0xFFFF;
55
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
70
-#endif
71
+ r.high = 0x7FFF | (p64.sign << 15);
72
+ r.low = (1ULL << DECOMPOSED_BINARY_POINT) | p64.frac;
56
return r;
73
return r;
57
}
74
}
58
75
59
-#define float32_two make_float32(0x40000000)
60
-#define float32_three make_float32(0x40400000)
61
-#define float32_one_point_five make_float32(0x3fc00000)
62
-
63
float32 HELPER(recps_f32)(CPUARMState *env, float32 a, float32 b)
64
{
65
float_status *s = &env->vfp.standard_fp_status;
66
--
76
--
67
2.20.1
77
2.34.1
68
69
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
Implement fp16 versions of the VFP VMLA, VMLS, VNMLS, VNMLA, VNMUL
1
In the helper functions flcmps and flcmpd we use a scratch float_status
2
instructions. (These are all the remaining ones which we implement
2
so that we don't change the CPU state if the comparison raises any
3
via do_vfp_3op_[hsd]p().)
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.
4
9
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200828183354.27913-5-peter.maydell@linaro.org
12
Message-id: 20241202131347.498124-33-peter.maydell@linaro.org
8
---
13
---
9
target/arm/helper.h | 1 +
14
target/sparc/helper.h | 4 ++--
10
target/arm/vfp.decode | 5 ++
15
target/sparc/fop_helper.c | 8 ++++----
11
target/arm/vfp_helper.c | 5 ++
16
target/sparc/translate.c | 4 ++--
12
target/arm/translate-vfp.c.inc | 84 ++++++++++++++++++++++++++++++++++
17
3 files changed, 8 insertions(+), 8 deletions(-)
13
4 files changed, 95 insertions(+)
14
18
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
19
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
21
--- a/target/sparc/helper.h
18
+++ b/target/arm/helper.h
22
+++ b/target/sparc/helper.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_maxnumd, f64, f64, f64, ptr)
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
20
DEF_HELPER_3(vfp_minnumh, f16, f16, f16, ptr)
24
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
21
DEF_HELPER_3(vfp_minnums, f32, f32, f32, ptr)
25
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128)
22
DEF_HELPER_3(vfp_minnumd, f64, f64, f64, ptr)
26
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128)
23
+DEF_HELPER_1(vfp_negh, f16, f16)
27
-DEF_HELPER_FLAGS_2(flcmps, TCG_CALL_NO_RWG_SE, i32, f32, f32)
24
DEF_HELPER_1(vfp_negs, f32, f32)
28
-DEF_HELPER_FLAGS_2(flcmpd, TCG_CALL_NO_RWG_SE, i32, f64, f64)
25
DEF_HELPER_1(vfp_negd, f64, f64)
29
+DEF_HELPER_FLAGS_3(flcmps, TCG_CALL_NO_RWG_SE, i32, env, f32, f32)
26
DEF_HELPER_1(vfp_abss, f32, f32)
30
+DEF_HELPER_FLAGS_3(flcmpd, TCG_CALL_NO_RWG_SE, i32, env, f64, f64)
27
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
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
28
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/vfp.decode
36
--- a/target/sparc/fop_helper.c
30
+++ b/target/arm/vfp.decode
37
+++ b/target/sparc/fop_helper.c
31
@@ -XXX,XX +XXX,XX @@ VLDM_VSTM_dp ---- 1101 0.1 l:1 rn:4 .... 1011 imm:8 \
38
@@ -XXX,XX +XXX,XX @@ uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
32
vd=%vd_dp p=1 u=0 w=1
39
return finish_fcmp(env, r, GETPC());
33
34
# 3-register VFP data-processing; bits [23,21:20,6] identify the operation.
35
+VMLA_hp ---- 1110 0.00 .... .... 1001 .0.0 .... @vfp_dnm_s
36
VMLA_sp ---- 1110 0.00 .... .... 1010 .0.0 .... @vfp_dnm_s
37
VMLA_dp ---- 1110 0.00 .... .... 1011 .0.0 .... @vfp_dnm_d
38
39
+VMLS_hp ---- 1110 0.00 .... .... 1001 .1.0 .... @vfp_dnm_s
40
VMLS_sp ---- 1110 0.00 .... .... 1010 .1.0 .... @vfp_dnm_s
41
VMLS_dp ---- 1110 0.00 .... .... 1011 .1.0 .... @vfp_dnm_d
42
43
+VNMLS_hp ---- 1110 0.01 .... .... 1001 .0.0 .... @vfp_dnm_s
44
VNMLS_sp ---- 1110 0.01 .... .... 1010 .0.0 .... @vfp_dnm_s
45
VNMLS_dp ---- 1110 0.01 .... .... 1011 .0.0 .... @vfp_dnm_d
46
47
+VNMLA_hp ---- 1110 0.01 .... .... 1001 .1.0 .... @vfp_dnm_s
48
VNMLA_sp ---- 1110 0.01 .... .... 1010 .1.0 .... @vfp_dnm_s
49
VNMLA_dp ---- 1110 0.01 .... .... 1011 .1.0 .... @vfp_dnm_d
50
51
@@ -XXX,XX +XXX,XX @@ VMUL_hp ---- 1110 0.10 .... .... 1001 .0.0 .... @vfp_dnm_s
52
VMUL_sp ---- 1110 0.10 .... .... 1010 .0.0 .... @vfp_dnm_s
53
VMUL_dp ---- 1110 0.10 .... .... 1011 .0.0 .... @vfp_dnm_d
54
55
+VNMUL_hp ---- 1110 0.10 .... .... 1001 .1.0 .... @vfp_dnm_s
56
VNMUL_sp ---- 1110 0.10 .... .... 1010 .1.0 .... @vfp_dnm_s
57
VNMUL_dp ---- 1110 0.10 .... .... 1011 .1.0 .... @vfp_dnm_d
58
59
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/vfp_helper.c
62
+++ b/target/arm/vfp_helper.c
63
@@ -XXX,XX +XXX,XX @@ VFP_BINOP(minnum)
64
VFP_BINOP(maxnum)
65
#undef VFP_BINOP
66
67
+dh_ctype_f16 VFP_HELPER(neg, h)(dh_ctype_f16 a)
68
+{
69
+ return float16_chs(a);
70
+}
71
+
72
float32 VFP_HELPER(neg, s)(float32 a)
73
{
74
return float32_chs(a);
75
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/translate-vfp.c.inc
78
+++ b/target/arm/translate-vfp.c.inc
79
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
80
return true;
81
}
40
}
82
41
83
+static void gen_VMLA_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
42
-uint32_t helper_flcmps(float32 src1, float32 src2)
84
+{
43
+uint32_t helper_flcmps(CPUSPARCState *env, float32 src1, float32 src2)
85
+ /* Note that order of inputs to the add matters for NaNs */
86
+ TCGv_i32 tmp = tcg_temp_new_i32();
87
+
88
+ gen_helper_vfp_mulh(tmp, vn, vm, fpst);
89
+ gen_helper_vfp_addh(vd, vd, tmp, fpst);
90
+ tcg_temp_free_i32(tmp);
91
+}
92
+
93
+static bool trans_VMLA_hp(DisasContext *s, arg_VMLA_sp *a)
94
+{
95
+ return do_vfp_3op_hp(s, gen_VMLA_hp, a->vd, a->vn, a->vm, true);
96
+}
97
+
98
static void gen_VMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
99
{
100
/* Note that order of inputs to the add matters for NaNs */
101
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLA_dp(DisasContext *s, arg_VMLA_dp *a)
102
return do_vfp_3op_dp(s, gen_VMLA_dp, a->vd, a->vn, a->vm, true);
103
}
104
105
+static void gen_VMLS_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
106
+{
107
+ /*
108
+ * VMLS: vd = vd + -(vn * vm)
109
+ * Note that order of inputs to the add matters for NaNs.
110
+ */
111
+ TCGv_i32 tmp = tcg_temp_new_i32();
112
+
113
+ gen_helper_vfp_mulh(tmp, vn, vm, fpst);
114
+ gen_helper_vfp_negh(tmp, tmp);
115
+ gen_helper_vfp_addh(vd, vd, tmp, fpst);
116
+ tcg_temp_free_i32(tmp);
117
+}
118
+
119
+static bool trans_VMLS_hp(DisasContext *s, arg_VMLS_sp *a)
120
+{
121
+ return do_vfp_3op_hp(s, gen_VMLS_hp, a->vd, a->vn, a->vm, true);
122
+}
123
+
124
static void gen_VMLS_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
125
{
44
{
126
/*
45
/*
127
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLS_dp(DisasContext *s, arg_VMLS_dp *a)
46
* FLCMP never raises an exception nor modifies any FSR fields.
128
return do_vfp_3op_dp(s, gen_VMLS_dp, a->vd, a->vn, a->vm, true);
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();
129
}
56
}
130
57
131
+static void gen_VNMLS_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
58
-uint32_t helper_flcmpd(float64 src1, float64 src2)
132
+{
59
+uint32_t helper_flcmpd(CPUSPARCState *env, float64 src1, float64 src2)
133
+ /*
134
+ * VNMLS: -fd + (fn * fm)
135
+ * Note that it isn't valid to replace (-A + B) with (B - A) or similar
136
+ * plausible looking simplifications because this will give wrong results
137
+ * for NaNs.
138
+ */
139
+ TCGv_i32 tmp = tcg_temp_new_i32();
140
+
141
+ gen_helper_vfp_mulh(tmp, vn, vm, fpst);
142
+ gen_helper_vfp_negh(vd, vd);
143
+ gen_helper_vfp_addh(vd, vd, tmp, fpst);
144
+ tcg_temp_free_i32(tmp);
145
+}
146
+
147
+static bool trans_VNMLS_hp(DisasContext *s, arg_VNMLS_sp *a)
148
+{
149
+ return do_vfp_3op_hp(s, gen_VNMLS_hp, a->vd, a->vn, a->vm, true);
150
+}
151
+
152
static void gen_VNMLS_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
153
{
60
{
154
/*
61
- float_status discard = { };
155
@@ -XXX,XX +XXX,XX @@ static bool trans_VNMLS_dp(DisasContext *s, arg_VNMLS_dp *a)
62
+ float_status discard = env->fp_status;
156
return do_vfp_3op_dp(s, gen_VNMLS_dp, a->vd, a->vn, a->vm, true);
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);
157
}
77
}
158
78
159
+static void gen_VNMLA_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
79
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
160
+{
80
161
+ /* VNMLA: -fd + -(fn * fm) */
81
src1 = gen_load_fpr_D(dc, a->rs1);
162
+ TCGv_i32 tmp = tcg_temp_new_i32();
82
src2 = gen_load_fpr_D(dc, a->rs2);
163
+
83
- gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
164
+ gen_helper_vfp_mulh(tmp, vn, vm, fpst);
84
+ gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
165
+ gen_helper_vfp_negh(tmp, tmp);
85
return advance_pc(dc);
166
+ gen_helper_vfp_negh(vd, vd);
167
+ gen_helper_vfp_addh(vd, vd, tmp, fpst);
168
+ tcg_temp_free_i32(tmp);
169
+}
170
+
171
+static bool trans_VNMLA_hp(DisasContext *s, arg_VNMLA_sp *a)
172
+{
173
+ return do_vfp_3op_hp(s, gen_VNMLA_hp, a->vd, a->vn, a->vm, true);
174
+}
175
+
176
static void gen_VNMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
177
{
178
/* VNMLA: -fd + -(fn * fm) */
179
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_dp(DisasContext *s, arg_VMUL_dp *a)
180
return do_vfp_3op_dp(s, gen_helper_vfp_muld, a->vd, a->vn, a->vm, false);
181
}
86
}
182
87
183
+static void gen_VNMUL_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
184
+{
185
+ /* VNMUL: -(fn * fm) */
186
+ gen_helper_vfp_mulh(vd, vn, vm, fpst);
187
+ gen_helper_vfp_negh(vd, vd);
188
+}
189
+
190
+static bool trans_VNMUL_hp(DisasContext *s, arg_VNMUL_sp *a)
191
+{
192
+ return do_vfp_3op_hp(s, gen_VNMUL_hp, a->vd, a->vn, a->vm, false);
193
+}
194
+
195
static void gen_VNMUL_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
196
{
197
/* VNMUL: -(fn * fm) */
198
--
88
--
199
2.20.1
89
2.34.1
200
201
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
Convert the Neon floating point VMAXNM and VMINNM insns to
1
From: Richard Henderson <richard.henderson@linaro.org>
2
using a gvec helper and use this to implement the fp16 case.
3
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>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20241203203949.483774-2-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-30-peter.maydell@linaro.org
7
---
14
---
8
target/arm/helper.h | 6 ++++++
15
target/arm/tcg/vec_helper.c | 20 +++++++-------------
9
target/arm/vec_helper.c | 6 ++++++
16
1 file changed, 7 insertions(+), 13 deletions(-)
10
target/arm/translate-neon.c.inc | 23 +++++++++++++++--------
11
3 files changed, 27 insertions(+), 8 deletions(-)
12
17
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
20
--- a/target/arm/tcg/vec_helper.c
16
+++ b/target/arm/helper.h
21
+++ b/target/arm/tcg/vec_helper.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmax_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
22
@@ -XXX,XX +XXX,XX @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp)
18
DEF_HELPER_FLAGS_5(gvec_fmin_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
23
* no effect on AArch32 instructions.
19
DEF_HELPER_FLAGS_5(gvec_fmin_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
*/
20
25
bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF;
21
+DEF_HELPER_FLAGS_5(gvec_fmaxnum_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
- *statusp = (float_status){
22
+DEF_HELPER_FLAGS_5(gvec_fmaxnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
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
- };
23
+
33
+
24
+DEF_HELPER_FLAGS_5(gvec_fminnum_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
34
+ *statusp = env->vfp.fp_status;
25
+DEF_HELPER_FLAGS_5(gvec_fminnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
35
+ set_default_nan_mode(true, statusp);
26
+
36
27
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
37
if (ebf) {
28
void, ptr, ptr, ptr, ptr, i32)
38
- float_status *fpst = &env->vfp.fp_status;
29
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
39
- set_flush_to_zero(get_flush_to_zero(fpst), statusp);
30
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
40
- set_flush_inputs_to_zero(get_flush_inputs_to_zero(fpst), statusp);
31
index XXXXXXX..XXXXXXX 100644
41
- set_float_rounding_mode(get_float_rounding_mode(fpst), statusp);
32
--- a/target/arm/vec_helper.c
42
-
33
+++ b/target/arm/vec_helper.c
43
/* EBF=1 needs to do a step with round-to-odd semantics */
34
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_fmax_s, float32_max, float32)
44
*oddstatusp = *statusp;
35
DO_3OP(gvec_fmin_h, float16_min, float16)
45
set_float_rounding_mode(float_round_to_odd, oddstatusp);
36
DO_3OP(gvec_fmin_s, float32_min, float32)
46
+ } else {
37
47
+ set_flush_to_zero(true, statusp);
38
+DO_3OP(gvec_fmaxnum_h, float16_maxnum, float16)
48
+ set_flush_inputs_to_zero(true, statusp);
39
+DO_3OP(gvec_fmaxnum_s, float32_maxnum, float32)
49
+ set_float_rounding_mode(float_round_to_odd_inf, statusp);
40
+
41
+DO_3OP(gvec_fminnum_h, float16_minnum, float16)
42
+DO_3OP(gvec_fminnum_s, float32_minnum, float32)
43
+
44
#ifdef TARGET_AARCH64
45
46
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
47
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate-neon.c.inc
50
+++ b/target/arm/translate-neon.c.inc
51
@@ -XXX,XX +XXX,XX @@ static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
52
DO_3S_FP(VMLA, gen_VMLA_fp_3s, true)
53
DO_3S_FP(VMLS, gen_VMLS_fp_3s, true)
54
55
+WRAP_FP_GVEC(gen_VMAXNM_fp32_3s, FPST_STD, gen_helper_gvec_fmaxnum_s)
56
+WRAP_FP_GVEC(gen_VMAXNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fmaxnum_h)
57
+WRAP_FP_GVEC(gen_VMINNM_fp32_3s, FPST_STD, gen_helper_gvec_fminnum_s)
58
+WRAP_FP_GVEC(gen_VMINNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fminnum_h)
59
+
60
static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
61
{
62
if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
63
@@ -XXX,XX +XXX,XX @@ static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
64
}
65
66
if (a->size != 0) {
67
- /* TODO fp16 support */
68
- return false;
69
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
70
+ return false;
71
+ }
72
+ return do_3same(s, a, gen_VMAXNM_fp16_3s);
73
}
50
}
74
-
51
-
75
- return do_3same_fp(s, a, gen_helper_vfp_maxnums, false);
52
return ebf;
76
+ return do_3same(s, a, gen_VMAXNM_fp32_3s);
77
}
53
}
78
54
79
static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
80
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
81
}
82
83
if (a->size != 0) {
84
- /* TODO fp16 support */
85
- return false;
86
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
87
+ return false;
88
+ }
89
+ return do_3same(s, a, gen_VMINNM_fp16_3s);
90
}
91
-
92
- return do_3same_fp(s, a, gen_helper_vfp_minnums, false);
93
+ return do_3same(s, a, gen_VMINNM_fp32_3s);
94
}
95
96
WRAP_ENV_FN(gen_VRECPS_tramp, gen_helper_recps_f32)
97
--
55
--
98
2.20.1
56
2.34.1
99
57
100
58
diff view generated by jsdifflib
1
Implement the fp16 version of the VFP VRINT* insns.
1
Currently we hardcode the default NaN value in parts64_default_nan()
2
using a compile-time ifdef ladder. This is awkward for two cases:
3
* for single-QEMU-binary we can't hard-code target-specifics like this
4
* for Arm FEAT_AFP the default NaN value depends on FPCR.AH
5
(specifically the sign bit is different)
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.
2
14
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200828183354.27913-19-peter.maydell@linaro.org
17
Message-id: 20241202131347.498124-35-peter.maydell@linaro.org
6
---
18
---
7
target/arm/helper.h | 2 +
19
include/fpu/softfloat-helpers.h | 11 +++++++
8
target/arm/vfp-uncond.decode | 6 ++-
20
include/fpu/softfloat-types.h | 10 ++++++
9
target/arm/vfp.decode | 3 ++
21
fpu/softfloat-specialize.c.inc | 55 ++++++++++++++++++++-------------
10
target/arm/vfp_helper.c | 21 ++++++++
22
3 files changed, 54 insertions(+), 22 deletions(-)
11
target/arm/translate-vfp.c.inc | 98 +++++++++++++++++++++++++++++++---
12
5 files changed, 122 insertions(+), 8 deletions(-)
13
23
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
24
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
15
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.h
26
--- a/include/fpu/softfloat-helpers.h
17
+++ b/target/arm/helper.h
27
+++ b/include/fpu/softfloat-helpers.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(shr_cc, i32, env, i32, i32)
28
@@ -XXX,XX +XXX,XX @@ static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
19
DEF_HELPER_3(sar_cc, i32, env, i32, i32)
29
status->float_infzeronan_rule = rule;
20
DEF_HELPER_3(ror_cc, i32, env, i32, i32)
21
22
+DEF_HELPER_FLAGS_2(rinth_exact, TCG_CALL_NO_RWG, f16, f16, ptr)
23
DEF_HELPER_FLAGS_2(rints_exact, TCG_CALL_NO_RWG, f32, f32, ptr)
24
DEF_HELPER_FLAGS_2(rintd_exact, TCG_CALL_NO_RWG, f64, f64, ptr)
25
+DEF_HELPER_FLAGS_2(rinth, TCG_CALL_NO_RWG, f16, f16, ptr)
26
DEF_HELPER_FLAGS_2(rints, TCG_CALL_NO_RWG, f32, f32, ptr)
27
DEF_HELPER_FLAGS_2(rintd, TCG_CALL_NO_RWG, f64, f64, ptr)
28
29
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/vfp-uncond.decode
32
+++ b/target/arm/vfp-uncond.decode
33
@@ -XXX,XX +XXX,XX @@ VMINNM_sp 1111 1110 1.00 .... .... 1010 .1.0 .... @vfp_dnm_s
34
VMAXNM_dp 1111 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
35
VMINNM_dp 1111 1110 1.00 .... .... 1011 .1.0 .... @vfp_dnm_d
36
37
+VRINT 1111 1110 1.11 10 rm:2 .... 1001 01.0 .... \
38
+ vm=%vm_sp vd=%vd_sp sz=1
39
VRINT 1111 1110 1.11 10 rm:2 .... 1010 01.0 .... \
40
- vm=%vm_sp vd=%vd_sp dp=0
41
+ vm=%vm_sp vd=%vd_sp sz=2
42
VRINT 1111 1110 1.11 10 rm:2 .... 1011 01.0 .... \
43
- vm=%vm_dp vd=%vd_dp dp=1
44
+ vm=%vm_dp vd=%vd_dp sz=3
45
46
# VCVT float to int with specified rounding mode; Vd is always single-precision
47
VCVT 1111 1110 1.11 11 rm:2 .... 1001 op:1 1.0 .... \
48
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/vfp.decode
51
+++ b/target/arm/vfp.decode
52
@@ -XXX,XX +XXX,XX @@ VCVT_f16_f32 ---- 1110 1.11 0011 .... 1010 t:1 1.0 .... \
53
VCVT_f16_f64 ---- 1110 1.11 0011 .... 1011 t:1 1.0 .... \
54
vd=%vd_sp vm=%vm_dp
55
56
+VRINTR_hp ---- 1110 1.11 0110 .... 1001 01.0 .... @vfp_dm_ss
57
VRINTR_sp ---- 1110 1.11 0110 .... 1010 01.0 .... @vfp_dm_ss
58
VRINTR_dp ---- 1110 1.11 0110 .... 1011 01.0 .... @vfp_dm_dd
59
60
+VRINTZ_hp ---- 1110 1.11 0110 .... 1001 11.0 .... @vfp_dm_ss
61
VRINTZ_sp ---- 1110 1.11 0110 .... 1010 11.0 .... @vfp_dm_ss
62
VRINTZ_dp ---- 1110 1.11 0110 .... 1011 11.0 .... @vfp_dm_dd
63
64
+VRINTX_hp ---- 1110 1.11 0111 .... 1001 01.0 .... @vfp_dm_ss
65
VRINTX_sp ---- 1110 1.11 0111 .... 1010 01.0 .... @vfp_dm_ss
66
VRINTX_dp ---- 1110 1.11 0111 .... 1011 01.0 .... @vfp_dm_dd
67
68
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/target/arm/vfp_helper.c
71
+++ b/target/arm/vfp_helper.c
72
@@ -XXX,XX +XXX,XX @@ float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
73
}
30
}
74
31
75
/* ARMv8 round to integral */
32
+static inline void set_float_default_nan_pattern(uint8_t dnan_pattern,
76
+dh_ctype_f16 HELPER(rinth_exact)(dh_ctype_f16 x, void *fp_status)
33
+ float_status *status)
77
+{
34
+{
78
+ return float16_round_to_int(x, fp_status);
35
+ status->default_nan_pattern = dnan_pattern;
79
+}
36
+}
80
+
37
+
81
float32 HELPER(rints_exact)(float32 x, void *fp_status)
38
static inline void set_flush_to_zero(bool val, float_status *status)
82
{
39
{
83
return float32_round_to_int(x, fp_status);
40
status->flush_to_zero = val;
84
@@ -XXX,XX +XXX,XX @@ float64 HELPER(rintd_exact)(float64 x, void *fp_status)
41
@@ -XXX,XX +XXX,XX @@ static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status
85
return float64_round_to_int(x, fp_status);
42
return status->float_infzeronan_rule;
86
}
43
}
87
44
88
+dh_ctype_f16 HELPER(rinth)(dh_ctype_f16 x, void *fp_status)
45
+static inline uint8_t get_float_default_nan_pattern(float_status *status)
89
+{
46
+{
90
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
47
+ return status->default_nan_pattern;
91
+ float16 ret;
92
+
93
+ ret = float16_round_to_int(x, fp_status);
94
+
95
+ /* Suppress any inexact exceptions the conversion produced */
96
+ if (!(old_flags & float_flag_inexact)) {
97
+ new_flags = get_float_exception_flags(fp_status);
98
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
99
+ }
100
+
101
+ return ret;
102
+}
48
+}
103
+
49
+
104
float32 HELPER(rints)(float32 x, void *fp_status)
50
static inline bool get_flush_to_zero(float_status *status)
105
{
51
{
106
int old_flags = get_float_exception_flags(fp_status), new_flags;
52
return status->flush_to_zero;
107
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
53
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
108
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
109
--- a/target/arm/translate-vfp.c.inc
55
--- a/include/fpu/softfloat-types.h
110
+++ b/target/arm/translate-vfp.c.inc
56
+++ b/include/fpu/softfloat-types.h
111
@@ -XXX,XX +XXX,XX @@ static const uint8_t fp_decode_rm[] = {
57
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
112
static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
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)
113
{
79
{
114
uint32_t rd, rm;
80
bool sign = 0;
115
- bool dp = a->dp;
81
uint64_t frac;
116
+ int sz = a->sz;
82
+ uint8_t dnan_pattern = status->default_nan_pattern;
117
TCGv_ptr fpst;
83
118
TCGv_i32 tcg_rmode;
84
+ if (dnan_pattern == 0) {
119
int rounding = fp_decode_rm[a->rm];
85
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
120
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
86
- /* !snan_bit_is_one, set all bits */
121
return false;
87
- frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
122
}
88
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
123
89
+ /* Sign bit clear, all frac bits set */
124
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
90
+ dnan_pattern = 0b01111111;
125
+ if (sz == 3 && !dc_isar_feature(aa32_fpdp_v2, s)) {
91
+#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
126
+ return false;
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
127
+ }
134
+ }
135
+ assert(dnan_pattern != 0);
128
+
136
+
129
+ if (sz == 1 && !dc_isar_feature(aa32_fp16_arith, s)) {
137
+ sign = dnan_pattern >> 7;
130
return false;
138
+ /*
131
}
139
+ * Place default_nan_pattern [6:0] into bits [62:56],
132
140
+ * and replecate bit [0] down into [55:0]
133
/* UNDEF accesses to D16-D31 if they don't exist */
141
+ */
134
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
142
+ frac = deposit64(0, DECOMPOSED_BINARY_POINT - 7, 7, dnan_pattern);
135
+ if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) &&
143
+ frac = deposit64(frac, 0, DECOMPOSED_BINARY_POINT - 7, -(dnan_pattern & 1));
136
((a->vm | a->vd) & 0x10)) {
144
137
return false;
145
*p = (FloatParts64) {
138
}
146
.cls = float_class_qnan,
139
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
140
return true;
141
}
142
143
- fpst = fpstatus_ptr(FPST_FPCR);
144
+ if (sz == 1) {
145
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
146
+ } else {
147
+ fpst = fpstatus_ptr(FPST_FPCR);
148
+ }
149
150
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
151
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
152
153
- if (dp) {
154
+ if (sz == 3) {
155
TCGv_i64 tcg_op;
156
TCGv_i64 tcg_res;
157
tcg_op = tcg_temp_new_i64();
158
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
159
tcg_op = tcg_temp_new_i32();
160
tcg_res = tcg_temp_new_i32();
161
neon_load_reg32(tcg_op, rm);
162
- gen_helper_rints(tcg_res, tcg_op, fpst);
163
+ if (sz == 1) {
164
+ gen_helper_rinth(tcg_res, tcg_op, fpst);
165
+ } else {
166
+ gen_helper_rints(tcg_res, tcg_op, fpst);
167
+ }
168
neon_store_reg32(tcg_res, rd);
169
tcg_temp_free_i32(tcg_op);
170
tcg_temp_free_i32(tcg_res);
171
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
172
return true;
173
}
174
175
+static bool trans_VRINTR_hp(DisasContext *s, arg_VRINTR_sp *a)
176
+{
177
+ TCGv_ptr fpst;
178
+ TCGv_i32 tmp;
179
+
180
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
181
+ return false;
182
+ }
183
+
184
+ if (!vfp_access_check(s)) {
185
+ return true;
186
+ }
187
+
188
+ tmp = tcg_temp_new_i32();
189
+ neon_load_reg32(tmp, a->vm);
190
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
191
+ gen_helper_rinth(tmp, tmp, fpst);
192
+ neon_store_reg32(tmp, a->vd);
193
+ tcg_temp_free_ptr(fpst);
194
+ tcg_temp_free_i32(tmp);
195
+ return true;
196
+}
197
+
198
static bool trans_VRINTR_sp(DisasContext *s, arg_VRINTR_sp *a)
199
{
200
TCGv_ptr fpst;
201
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
202
return true;
203
}
204
205
+static bool trans_VRINTZ_hp(DisasContext *s, arg_VRINTZ_sp *a)
206
+{
207
+ TCGv_ptr fpst;
208
+ TCGv_i32 tmp;
209
+ TCGv_i32 tcg_rmode;
210
+
211
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
212
+ return false;
213
+ }
214
+
215
+ if (!vfp_access_check(s)) {
216
+ return true;
217
+ }
218
+
219
+ tmp = tcg_temp_new_i32();
220
+ neon_load_reg32(tmp, a->vm);
221
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
222
+ tcg_rmode = tcg_const_i32(float_round_to_zero);
223
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
224
+ gen_helper_rinth(tmp, tmp, fpst);
225
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
226
+ neon_store_reg32(tmp, a->vd);
227
+ tcg_temp_free_ptr(fpst);
228
+ tcg_temp_free_i32(tcg_rmode);
229
+ tcg_temp_free_i32(tmp);
230
+ return true;
231
+}
232
+
233
static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a)
234
{
235
TCGv_ptr fpst;
236
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
237
return true;
238
}
239
240
+static bool trans_VRINTX_hp(DisasContext *s, arg_VRINTX_sp *a)
241
+{
242
+ TCGv_ptr fpst;
243
+ TCGv_i32 tmp;
244
+
245
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
246
+ return false;
247
+ }
248
+
249
+ if (!vfp_access_check(s)) {
250
+ return true;
251
+ }
252
+
253
+ tmp = tcg_temp_new_i32();
254
+ neon_load_reg32(tmp, a->vm);
255
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
256
+ gen_helper_rinth_exact(tmp, tmp, fpst);
257
+ neon_store_reg32(tmp, a->vd);
258
+ tcg_temp_free_ptr(fpst);
259
+ tcg_temp_free_i32(tmp);
260
+ return true;
261
+}
262
+
263
static bool trans_VRINTX_sp(DisasContext *s, arg_VRINTX_sp *a)
264
{
265
TCGv_ptr fpst;
266
--
147
--
267
2.20.1
148
2.34.1
268
269
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
Currently the VFP_CONV_FIX macros take a single fsz argument for the
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
size of the float type, which is used both to select the name of
2
parts64_default_nan().
3
the functions to call (eg float32_is_any_nan()) and also for the
4
type to use for the float inputs and outputs (eg float32).
5
6
Separate these into fsz and ftype arguments, so that we can use them
7
for fp16, which uses 'float16' in the function names but is still
8
passing inputs and outputs in a 32-bit sized type.
9
3
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200828183354.27913-14-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-38-peter.maydell@linaro.org
13
---
7
---
14
target/arm/vfp_helper.c | 46 ++++++++++++++++++++---------------------
8
target/i386/tcg/fpu_helper.c | 4 ++++
15
1 file changed, 23 insertions(+), 23 deletions(-)
9
fpu/softfloat-specialize.c.inc | 3 ---
10
2 files changed, 4 insertions(+), 3 deletions(-)
16
11
17
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
12
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/vfp_helper.c
14
--- a/target/i386/tcg/fpu_helper.c
20
+++ b/target/arm/vfp_helper.c
15
+++ b/target/i386/tcg/fpu_helper.c
21
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
16
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
17
*/
18
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
19
set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
20
+ /* Default NaN: sign bit set, most significant frac bit set */
21
+ set_float_default_nan_pattern(0b11000000, &env->fp_status);
22
+ set_float_default_nan_pattern(0b11000000, &env->mmx_status);
23
+ set_float_default_nan_pattern(0b11000000, &env->sse_status);
22
}
24
}
23
25
24
/* VFP3 fixed point conversion. */
26
static inline uint8_t save_exception_flags(CPUX86State *env)
25
-#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
-float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
28
index XXXXXXX..XXXXXXX 100644
27
+#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
29
--- a/fpu/softfloat-specialize.c.inc
28
+ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
30
+++ b/fpu/softfloat-specialize.c.inc
29
void *fpstp) \
31
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
30
{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
32
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
31
33
/* Sign bit clear, all frac bits set */
32
-#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
34
dnan_pattern = 0b01111111;
33
-uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
35
-#elif defined(TARGET_I386) || defined(TARGET_X86_64)
34
+#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
36
- /* Sign bit set, most significant frac bit set */
35
+uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
37
- dnan_pattern = 0b11000000;
36
void *fpst) \
38
#elif defined(TARGET_HPPA)
37
{ \
39
/* Sign bit clear, msb-1 frac bit set */
38
if (unlikely(float##fsz##_is_any_nan(x))) { \
40
dnan_pattern = 0b00100000;
39
@@ -XXX,XX +XXX,XX @@ uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
40
return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
41
}
42
43
-#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
44
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
45
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
46
+#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \
47
+VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
48
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
49
float_round_to_zero, _round_to_zero) \
50
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
51
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
52
get_float_rounding_mode(fpst), )
53
54
-#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
55
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
56
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
57
+#define VFP_CONV_FIX_A64(name, p, fsz, ftype, isz, itype) \
58
+VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
59
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
60
get_float_rounding_mode(fpst), )
61
62
-VFP_CONV_FIX(sh, d, 64, 64, int16)
63
-VFP_CONV_FIX(sl, d, 64, 64, int32)
64
-VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
65
-VFP_CONV_FIX(uh, d, 64, 64, uint16)
66
-VFP_CONV_FIX(ul, d, 64, 64, uint32)
67
-VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
68
-VFP_CONV_FIX(sh, s, 32, 32, int16)
69
-VFP_CONV_FIX(sl, s, 32, 32, int32)
70
-VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
71
-VFP_CONV_FIX(uh, s, 32, 32, uint16)
72
-VFP_CONV_FIX(ul, s, 32, 32, uint32)
73
-VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
74
+VFP_CONV_FIX(sh, d, 64, float64, 64, int16)
75
+VFP_CONV_FIX(sl, d, 64, float64, 64, int32)
76
+VFP_CONV_FIX_A64(sq, d, 64, float64, 64, int64)
77
+VFP_CONV_FIX(uh, d, 64, float64, 64, uint16)
78
+VFP_CONV_FIX(ul, d, 64, float64, 64, uint32)
79
+VFP_CONV_FIX_A64(uq, d, 64, float64, 64, uint64)
80
+VFP_CONV_FIX(sh, s, 32, float32, 32, int16)
81
+VFP_CONV_FIX(sl, s, 32, float32, 32, int32)
82
+VFP_CONV_FIX_A64(sq, s, 32, float32, 64, int64)
83
+VFP_CONV_FIX(uh, s, 32, float32, 32, uint16)
84
+VFP_CONV_FIX(ul, s, 32, float32, 32, uint32)
85
+VFP_CONV_FIX_A64(uq, s, 32, float32, 64, uint64)
86
87
#undef VFP_CONV_FIX
88
#undef VFP_CONV_FIX_FLOAT
89
--
41
--
90
2.20.1
42
2.34.1
91
92
diff view generated by jsdifflib
1
Macroify the uses of do_vfp_2op_sp() and do_vfp_2op_dp(); this will
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
make it easier to add the halfprec support.
2
parts64_default_nan().
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-8-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-39-peter.maydell@linaro.org
7
---
7
---
8
target/arm/translate-vfp.c.inc | 49 ++++++++++------------------------
8
target/hppa/fpu_helper.c | 2 ++
9
1 file changed, 14 insertions(+), 35 deletions(-)
9
fpu/softfloat-specialize.c.inc | 3 ---
10
2 files changed, 2 insertions(+), 3 deletions(-)
10
11
11
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
12
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.c.inc
14
--- a/target/hppa/fpu_helper.c
14
+++ b/target/arm/translate-vfp.c.inc
15
+++ b/target/hppa/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
16
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
16
return true;
17
set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
18
/* For inf * 0 + NaN, return the input NaN */
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ /* Default NaN: sign bit clear, msb-1 frac bit set */
21
+ set_float_default_nan_pattern(0b00100000, &env->fp_status);
17
}
22
}
18
23
19
-static bool trans_VMOV_reg_sp(DisasContext *s, arg_VMOV_reg_sp *a)
24
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
20
-{
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
21
- return do_vfp_2op_sp(s, tcg_gen_mov_i32, a->vd, a->vm);
26
index XXXXXXX..XXXXXXX 100644
22
-}
27
--- a/fpu/softfloat-specialize.c.inc
23
+#define DO_VFP_2OP(INSN, PREC, FN) \
28
+++ b/fpu/softfloat-specialize.c.inc
24
+ static bool trans_##INSN##_##PREC(DisasContext *s, \
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
25
+ arg_##INSN##_##PREC *a) \
30
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
26
+ { \
31
/* Sign bit clear, all frac bits set */
27
+ return do_vfp_2op_##PREC(s, FN, a->vd, a->vm); \
32
dnan_pattern = 0b01111111;
28
+ }
33
-#elif defined(TARGET_HPPA)
29
34
- /* Sign bit clear, msb-1 frac bit set */
30
-static bool trans_VMOV_reg_dp(DisasContext *s, arg_VMOV_reg_dp *a)
35
- dnan_pattern = 0b00100000;
31
-{
36
#elif defined(TARGET_HEXAGON)
32
- return do_vfp_2op_dp(s, tcg_gen_mov_i64, a->vd, a->vm);
37
/* Sign bit set, all frac bits set. */
33
-}
38
dnan_pattern = 0b11111111;
34
+DO_VFP_2OP(VMOV_reg, sp, tcg_gen_mov_i32)
35
+DO_VFP_2OP(VMOV_reg, dp, tcg_gen_mov_i64)
36
37
-static bool trans_VABS_sp(DisasContext *s, arg_VABS_sp *a)
38
-{
39
- return do_vfp_2op_sp(s, gen_helper_vfp_abss, a->vd, a->vm);
40
-}
41
+DO_VFP_2OP(VABS, sp, gen_helper_vfp_abss)
42
+DO_VFP_2OP(VABS, dp, gen_helper_vfp_absd)
43
44
-static bool trans_VABS_dp(DisasContext *s, arg_VABS_dp *a)
45
-{
46
- return do_vfp_2op_dp(s, gen_helper_vfp_absd, a->vd, a->vm);
47
-}
48
-
49
-static bool trans_VNEG_sp(DisasContext *s, arg_VNEG_sp *a)
50
-{
51
- return do_vfp_2op_sp(s, gen_helper_vfp_negs, a->vd, a->vm);
52
-}
53
-
54
-static bool trans_VNEG_dp(DisasContext *s, arg_VNEG_dp *a)
55
-{
56
- return do_vfp_2op_dp(s, gen_helper_vfp_negd, a->vd, a->vm);
57
-}
58
+DO_VFP_2OP(VNEG, sp, gen_helper_vfp_negs)
59
+DO_VFP_2OP(VNEG, dp, gen_helper_vfp_negd)
60
61
static void gen_VSQRT_sp(TCGv_i32 vd, TCGv_i32 vm)
62
{
63
gen_helper_vfp_sqrts(vd, vm, cpu_env);
64
}
65
66
-static bool trans_VSQRT_sp(DisasContext *s, arg_VSQRT_sp *a)
67
-{
68
- return do_vfp_2op_sp(s, gen_VSQRT_sp, a->vd, a->vm);
69
-}
70
-
71
static void gen_VSQRT_dp(TCGv_i64 vd, TCGv_i64 vm)
72
{
73
gen_helper_vfp_sqrtd(vd, vm, cpu_env);
74
}
75
76
-static bool trans_VSQRT_dp(DisasContext *s, arg_VSQRT_dp *a)
77
-{
78
- return do_vfp_2op_dp(s, gen_VSQRT_dp, a->vd, a->vm);
79
-}
80
+DO_VFP_2OP(VSQRT, sp, gen_VSQRT_sp)
81
+DO_VFP_2OP(VSQRT, dp, gen_VSQRT_dp)
82
83
static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a)
84
{
85
--
39
--
86
2.20.1
40
2.34.1
87
88
diff view generated by jsdifflib
1
Convert the Neon floating-point vector comparison ops VCEQ,
1
Set the default NaN pattern explicitly for the alpha target.
2
VCGE and VCGT over to using a gvec helper and use this to
3
implement the fp16 case.
4
5
(We put the float16_ceq() etc functions above the DO_2OP()
6
macro definition because later when we convert the
7
compare-against-zero instructions we'll want their
8
definitions to be visible at that point in the source file.)
9
2
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200828183354.27913-27-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-40-peter.maydell@linaro.org
13
---
6
---
14
target/arm/helper.h | 9 +++++++
7
target/alpha/cpu.c | 2 ++
15
target/arm/vec_helper.c | 44 +++++++++++++++++++++++++++++++++
8
1 file changed, 2 insertions(+)
16
target/arm/translate-neon.c.inc | 6 ++---
17
3 files changed, 56 insertions(+), 3 deletions(-)
18
9
19
diff --git a/target/arm/helper.h b/target/arm/helper.h
10
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
20
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.h
12
--- a/target/alpha/cpu.c
22
+++ b/target/arm/helper.h
13
+++ b/target/alpha/cpu.c
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmul_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
14
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_initfn(Object *obj)
24
DEF_HELPER_FLAGS_5(gvec_fabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
15
* operand in Fa. That is float_2nan_prop_ba.
25
DEF_HELPER_FLAGS_5(gvec_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
16
*/
26
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
27
+DEF_HELPER_FLAGS_5(gvec_fceq_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
18
+ /* Default NaN: sign bit clear, msb frac bit set */
28
+DEF_HELPER_FLAGS_5(gvec_fceq_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
29
+
20
#if defined(CONFIG_USER_ONLY)
30
+DEF_HELPER_FLAGS_5(gvec_fcge_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
env->flags = ENV_FLAG_PS_USER | ENV_FLAG_FEN;
31
+DEF_HELPER_FLAGS_5(gvec_fcge_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
22
cpu_alpha_store_fpcr(env, (uint64_t)(FPCR_INVD | FPCR_DZED | FPCR_OVFD
32
+
33
+DEF_HELPER_FLAGS_5(gvec_fcgt_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_5(gvec_fcgt_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
35
+
36
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
37
void, ptr, ptr, ptr, ptr, i32)
38
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
39
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/vec_helper.c
42
+++ b/target/arm/vec_helper.c
43
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
44
clear_tail(d, opr_sz, simd_maxsz(desc));
45
}
46
47
+/*
48
+ * Floating point comparisons producing an integer result (all 1s or all 0s).
49
+ * Note that EQ doesn't signal InvalidOp for QNaNs but GE and GT do.
50
+ * Softfloat routines return 0/1, which we convert to the 0/-1 Neon requires.
51
+ */
52
+static uint16_t float16_ceq(float16 op1, float16 op2, float_status *stat)
53
+{
54
+ return -float16_eq_quiet(op1, op2, stat);
55
+}
56
+
57
+static uint32_t float32_ceq(float32 op1, float32 op2, float_status *stat)
58
+{
59
+ return -float32_eq_quiet(op1, op2, stat);
60
+}
61
+
62
+static uint16_t float16_cge(float16 op1, float16 op2, float_status *stat)
63
+{
64
+ return -float16_le(op2, op1, stat);
65
+}
66
+
67
+static uint32_t float32_cge(float32 op1, float32 op2, float_status *stat)
68
+{
69
+ return -float32_le(op2, op1, stat);
70
+}
71
+
72
+static uint16_t float16_cgt(float16 op1, float16 op2, float_status *stat)
73
+{
74
+ return -float16_lt(op2, op1, stat);
75
+}
76
+
77
+static uint32_t float32_cgt(float32 op1, float32 op2, float_status *stat)
78
+{
79
+ return -float32_lt(op2, op1, stat);
80
+}
81
+
82
#define DO_2OP(NAME, FUNC, TYPE) \
83
void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
84
{ \
85
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_ftsmul_d, float64_ftsmul, float64)
86
DO_3OP(gvec_fabd_h, float16_abd, float16)
87
DO_3OP(gvec_fabd_s, float32_abd, float32)
88
89
+DO_3OP(gvec_fceq_h, float16_ceq, float16)
90
+DO_3OP(gvec_fceq_s, float32_ceq, float32)
91
+
92
+DO_3OP(gvec_fcge_h, float16_cge, float16)
93
+DO_3OP(gvec_fcge_s, float32_cge, float32)
94
+
95
+DO_3OP(gvec_fcgt_h, float16_cgt, float16)
96
+DO_3OP(gvec_fcgt_s, float32_cgt, float32)
97
+
98
#ifdef TARGET_AARCH64
99
100
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
101
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
102
index XXXXXXX..XXXXXXX 100644
103
--- a/target/arm/translate-neon.c.inc
104
+++ b/target/arm/translate-neon.c.inc
105
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s, gen_helper_gvec_fadd_h)
106
DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s, gen_helper_gvec_fsub_h)
107
DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s, gen_helper_gvec_fabd_h)
108
DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s, gen_helper_gvec_fmul_h)
109
+DO_3S_FP_GVEC(VCEQ, gen_helper_gvec_fceq_s, gen_helper_gvec_fceq_h)
110
+DO_3S_FP_GVEC(VCGE, gen_helper_gvec_fcge_s, gen_helper_gvec_fcge_h)
111
+DO_3S_FP_GVEC(VCGT, gen_helper_gvec_fcgt_s, gen_helper_gvec_fcgt_h)
112
113
/*
114
* For all the functions using this macro, size == 1 means fp16,
115
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s, gen_helper_gvec_fmul_h)
116
return do_3same_fp(s, a, FUNC, READS_VD); \
117
}
118
119
-DO_3S_FP(VCEQ, gen_helper_neon_ceq_f32, false)
120
-DO_3S_FP(VCGE, gen_helper_neon_cge_f32, false)
121
-DO_3S_FP(VCGT, gen_helper_neon_cgt_f32, false)
122
DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false)
123
DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false)
124
DO_3S_FP(VMAX, gen_helper_vfp_maxs, false)
125
--
23
--
126
2.20.1
24
2.34.1
127
128
diff view generated by jsdifflib
1
Macroify creation of the trans functions for single and double
1
Set the default NaN pattern explicitly for the arm target.
2
precision VFMA, VFMS, VFNMA, VFNMS. The repetition was OK for
2
This includes setting it for the old linux-user nwfpe emulation.
3
two sizes, but we're about to add halfprec and it will get a bit
3
For nwfpe, our default doesn't match the real kernel, but we
4
more than seems reasonable.
4
avoid making a behaviour change in this commit.
5
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200828183354.27913-6-peter.maydell@linaro.org
8
Message-id: 20241202131347.498124-41-peter.maydell@linaro.org
9
---
9
---
10
target/arm/translate-vfp.c.inc | 50 +++++++++-------------------------
10
linux-user/arm/nwfpe/fpa11.c | 5 +++++
11
1 file changed, 13 insertions(+), 37 deletions(-)
11
target/arm/cpu.c | 2 ++
12
2 files changed, 7 insertions(+)
12
13
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.c.inc
16
--- a/linux-user/arm/nwfpe/fpa11.c
16
+++ b/target/arm/translate-vfp.c.inc
17
+++ b/linux-user/arm/nwfpe/fpa11.c
17
@@ -XXX,XX +XXX,XX @@ static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
18
@@ -XXX,XX +XXX,XX @@ void resetFPA11(void)
18
return true;
19
* this late date.
20
*/
21
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &fpa11->fp_status);
22
+ /*
23
+ * Use the same default NaN value as Arm VFP. This doesn't match
24
+ * the Linux kernel's nwfpe emulation, which uses an all-1s value.
25
+ */
26
+ set_float_default_nan_pattern(0b01000000, &fpa11->fp_status);
19
}
27
}
20
28
21
-static bool trans_VFMA_sp(DisasContext *s, arg_VFMA_sp *a)
29
void SetRoundingMode(const unsigned int opcode)
22
-{
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
23
- return do_vfm_sp(s, a, false, false);
31
index XXXXXXX..XXXXXXX 100644
24
-}
32
--- a/target/arm/cpu.c
25
-
33
+++ b/target/arm/cpu.c
26
-static bool trans_VFMS_sp(DisasContext *s, arg_VFMS_sp *a)
34
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
27
-{
35
* the pseudocode function the arguments are in the order c, a, b.
28
- return do_vfm_sp(s, a, true, false);
36
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
29
-}
37
* and the input NaN if it is signalling
30
-
38
+ * * Default NaN has sign bit clear, msb frac bit set
31
-static bool trans_VFNMA_sp(DisasContext *s, arg_VFNMA_sp *a)
39
*/
32
-{
40
static void arm_set_default_fp_behaviours(float_status *s)
33
- return do_vfm_sp(s, a, false, true);
34
-}
35
-
36
-static bool trans_VFNMS_sp(DisasContext *s, arg_VFNMS_sp *a)
37
-{
38
- return do_vfm_sp(s, a, true, true);
39
-}
40
-
41
static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
42
{
41
{
43
/*
42
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
44
@@ -XXX,XX +XXX,XX @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
45
return true;
44
set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
46
+ set_float_default_nan_pattern(0b01000000, s);
46
}
47
}
47
48
48
-static bool trans_VFMA_dp(DisasContext *s, arg_VFMA_dp *a)
49
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
49
-{
50
- return do_vfm_dp(s, a, false, false);
51
-}
52
+#define MAKE_ONE_VFM_TRANS_FN(INSN, PREC, NEGN, NEGD) \
53
+ static bool trans_##INSN##_##PREC(DisasContext *s, \
54
+ arg_##INSN##_##PREC *a) \
55
+ { \
56
+ return do_vfm_##PREC(s, a, NEGN, NEGD); \
57
+ }
58
59
-static bool trans_VFMS_dp(DisasContext *s, arg_VFMS_dp *a)
60
-{
61
- return do_vfm_dp(s, a, true, false);
62
-}
63
+#define MAKE_VFM_TRANS_FNS(PREC) \
64
+ MAKE_ONE_VFM_TRANS_FN(VFMA, PREC, false, false) \
65
+ MAKE_ONE_VFM_TRANS_FN(VFMS, PREC, true, false) \
66
+ MAKE_ONE_VFM_TRANS_FN(VFNMA, PREC, false, true) \
67
+ MAKE_ONE_VFM_TRANS_FN(VFNMS, PREC, true, true)
68
69
-static bool trans_VFNMA_dp(DisasContext *s, arg_VFNMA_dp *a)
70
-{
71
- return do_vfm_dp(s, a, false, true);
72
-}
73
-
74
-static bool trans_VFNMS_dp(DisasContext *s, arg_VFNMS_dp *a)
75
-{
76
- return do_vfm_dp(s, a, true, true);
77
-}
78
+MAKE_VFM_TRANS_FNS(sp)
79
+MAKE_VFM_TRANS_FNS(dp)
80
81
static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
82
{
83
--
50
--
84
2.20.1
51
2.34.1
85
86
diff view generated by jsdifflib
1
Implement FP16 support for the Neon insns which use the DO_3S_FP_GVEC
1
Set the default NaN pattern explicitly for loongarch.
2
macro: VADD, VSUB, VABD, VMUL.
3
4
For VABD this requires us to implement a new gvec_fabd_h helper
5
using the machinery we have already for the other helpers.
6
2
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200828183354.27913-24-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-42-peter.maydell@linaro.org
10
---
6
---
11
target/arm/helper.h | 1 +
7
target/loongarch/tcg/fpu_helper.c | 2 ++
12
target/arm/vec_helper.c | 6 ++++++
8
1 file changed, 2 insertions(+)
13
target/arm/translate-neon.c.inc | 36 +++++++++++++++++----------------
14
3 files changed, 26 insertions(+), 17 deletions(-)
15
9
16
diff --git a/target/arm/helper.h b/target/arm/helper.h
10
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
17
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.h
12
--- a/target/loongarch/tcg/fpu_helper.c
19
+++ b/target/arm/helper.h
13
+++ b/target/loongarch/tcg/fpu_helper.c
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmul_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
14
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
21
DEF_HELPER_FLAGS_5(gvec_fmul_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
15
*/
22
DEF_HELPER_FLAGS_5(gvec_fmul_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
23
17
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
24
+DEF_HELPER_FLAGS_5(gvec_fabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
18
+ /* Default NaN: sign bit clear, msb frac bit set */
25
DEF_HELPER_FLAGS_5(gvec_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
26
27
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
28
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/vec_helper.c
31
+++ b/target/arm/vec_helper.c
32
@@ -XXX,XX +XXX,XX @@ static float64 float64_ftsmul(float64 op1, uint64_t op2, float_status *stat)
33
return result;
34
}
20
}
35
21
36
+static float16 float16_abd(float16 op1, float16 op2, float_status *stat)
22
int ieee_ex_to_loongarch(int xcpt)
37
+{
38
+ return float16_abs(float16_sub(op1, op2, stat));
39
+}
40
+
41
static float32 float32_abd(float32 op1, float32 op2, float_status *stat)
42
{
43
return float32_abs(float32_sub(op1, op2, stat));
44
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_ftsmul_h, float16_ftsmul, float16)
45
DO_3OP(gvec_ftsmul_s, float32_ftsmul, float32)
46
DO_3OP(gvec_ftsmul_d, float64_ftsmul, float64)
47
48
+DO_3OP(gvec_fabd_h, float16_abd, float16)
49
DO_3OP(gvec_fabd_s, float32_abd, float32)
50
51
#ifdef TARGET_AARCH64
52
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/translate-neon.c.inc
55
+++ b/target/arm/translate-neon.c.inc
56
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn,
57
return true;
58
}
59
60
-/*
61
- * For all the functions using this macro, size == 1 means fp16,
62
- * which is an architecture extension we don't implement yet.
63
- */
64
-#define DO_3S_FP_GVEC(INSN,FUNC) \
65
- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
66
- uint32_t rn_ofs, uint32_t rm_ofs, \
67
- uint32_t oprsz, uint32_t maxsz) \
68
+#define WRAP_FP_GVEC(WRAPNAME, FPST, FUNC) \
69
+ static void WRAPNAME(unsigned vece, uint32_t rd_ofs, \
70
+ uint32_t rn_ofs, uint32_t rm_ofs, \
71
+ uint32_t oprsz, uint32_t maxsz) \
72
{ \
73
- TCGv_ptr fpst = fpstatus_ptr(FPST_STD); \
74
+ TCGv_ptr fpst = fpstatus_ptr(FPST); \
75
tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpst, \
76
oprsz, maxsz, 0, FUNC); \
77
tcg_temp_free_ptr(fpst); \
78
- } \
79
+ }
80
+
81
+#define DO_3S_FP_GVEC(INSN,SFUNC,HFUNC) \
82
+ WRAP_FP_GVEC(gen_##INSN##_fp32_3s, FPST_STD, SFUNC) \
83
+ WRAP_FP_GVEC(gen_##INSN##_fp16_3s, FPST_STD_F16, HFUNC) \
84
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
85
{ \
86
if (a->size != 0) { \
87
- /* TODO fp16 support */ \
88
- return false; \
89
+ if (!dc_isar_feature(aa32_fp16_arith, s)) { \
90
+ return false; \
91
+ } \
92
+ return do_3same(s, a, gen_##INSN##_fp16_3s); \
93
} \
94
- return do_3same(s, a, gen_##INSN##_3s); \
95
+ return do_3same(s, a, gen_##INSN##_fp32_3s); \
96
}
97
98
99
-DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s)
100
-DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s)
101
-DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s)
102
-DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s)
103
+DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s, gen_helper_gvec_fadd_h)
104
+DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s, gen_helper_gvec_fsub_h)
105
+DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s, gen_helper_gvec_fabd_h)
106
+DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s, gen_helper_gvec_fmul_h)
107
108
/*
109
* For all the functions using this macro, size == 1 means fp16,
110
--
23
--
111
2.20.1
24
2.34.1
112
113
diff view generated by jsdifflib
1
Convert the Neon floating-point VMLA and VMLS insns over to using a
1
Set the default NaN pattern explicitly for m68k.
2
gvec helper, and use this to implement the fp16 case.
3
2
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-31-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-43-peter.maydell@linaro.org
7
---
6
---
8
target/arm/helper.h | 6 +++++
7
target/m68k/cpu.c | 2 ++
9
target/arm/vec_helper.c | 42 +++++++++++++++++++++++++++++++++
8
fpu/softfloat-specialize.c.inc | 2 +-
10
target/arm/translate-neon.c.inc | 33 ++------------------------
9
2 files changed, 3 insertions(+), 1 deletion(-)
11
3 files changed, 50 insertions(+), 31 deletions(-)
12
10
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
11
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
13
--- a/target/m68k/cpu.c
16
+++ b/target/arm/helper.h
14
+++ b/target/m68k/cpu.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmaxnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i3
15
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
18
DEF_HELPER_FLAGS_5(gvec_fminnum_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
16
* preceding paragraph for nonsignaling NaNs.
19
DEF_HELPER_FLAGS_5(gvec_fminnum_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
17
*/
20
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
21
+DEF_HELPER_FLAGS_5(gvec_fmla_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
+ /* Default NaN: sign bit clear, all frac bits set */
22
+DEF_HELPER_FLAGS_5(gvec_fmla_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
23
+
21
24
+DEF_HELPER_FLAGS_5(gvec_fmls_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
22
nan = floatx80_default_nan(&env->fp_status);
25
+DEF_HELPER_FLAGS_5(gvec_fmls_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
23
for (i = 0; i < 8; i++) {
26
+
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
27
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
28
void, ptr, ptr, ptr, ptr, i32)
29
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
30
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
31
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/vec_helper.c
26
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/target/arm/vec_helper.c
27
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_rsqrts_d, helper_rsqrtsf_f64, float64)
28
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
35
#endif
29
uint8_t dnan_pattern = status->default_nan_pattern;
36
#undef DO_3OP
30
37
31
if (dnan_pattern == 0) {
38
+/* Non-fused multiply-add (unlike float16_muladd etc, which are fused) */
32
-#if defined(TARGET_SPARC) || defined(TARGET_M68K)
39
+static float16 float16_muladd_nf(float16 dest, float16 op1, float16 op2,
33
+#if defined(TARGET_SPARC)
40
+ float_status *stat)
34
/* Sign bit clear, all frac bits set */
41
+{
35
dnan_pattern = 0b01111111;
42
+ return float16_add(dest, float16_mul(op1, op2, stat), stat);
36
#elif defined(TARGET_HEXAGON)
43
+}
44
+
45
+static float32 float32_muladd_nf(float32 dest, float32 op1, float32 op2,
46
+ float_status *stat)
47
+{
48
+ return float32_add(dest, float32_mul(op1, op2, stat), stat);
49
+}
50
+
51
+static float16 float16_mulsub_nf(float16 dest, float16 op1, float16 op2,
52
+ float_status *stat)
53
+{
54
+ return float16_sub(dest, float16_mul(op1, op2, stat), stat);
55
+}
56
+
57
+static float32 float32_mulsub_nf(float32 dest, float32 op1, float32 op2,
58
+ float_status *stat)
59
+{
60
+ return float32_sub(dest, float32_mul(op1, op2, stat), stat);
61
+}
62
+
63
+#define DO_MULADD(NAME, FUNC, TYPE) \
64
+void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
65
+{ \
66
+ intptr_t i, oprsz = simd_oprsz(desc); \
67
+ TYPE *d = vd, *n = vn, *m = vm; \
68
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
69
+ d[i] = FUNC(d[i], n[i], m[i], stat); \
70
+ } \
71
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
72
+}
73
+
74
+DO_MULADD(gvec_fmla_h, float16_muladd_nf, float16)
75
+DO_MULADD(gvec_fmla_s, float32_muladd_nf, float32)
76
+
77
+DO_MULADD(gvec_fmls_h, float16_mulsub_nf, float16)
78
+DO_MULADD(gvec_fmls_s, float32_mulsub_nf, float32)
79
+
80
/* For the indexed ops, SVE applies the index per 128-bit vector segment.
81
* For AdvSIMD, there is of course only one such vector segment.
82
*/
83
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/translate-neon.c.inc
86
+++ b/target/arm/translate-neon.c.inc
87
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VACGE, gen_helper_gvec_facge_s, gen_helper_gvec_facge_h)
88
DO_3S_FP_GVEC(VACGT, gen_helper_gvec_facgt_s, gen_helper_gvec_facgt_h)
89
DO_3S_FP_GVEC(VMAX, gen_helper_gvec_fmax_s, gen_helper_gvec_fmax_h)
90
DO_3S_FP_GVEC(VMIN, gen_helper_gvec_fmin_s, gen_helper_gvec_fmin_h)
91
-
92
-/*
93
- * For all the functions using this macro, size == 1 means fp16,
94
- * which is an architecture extension we don't implement yet.
95
- */
96
-#define DO_3S_FP(INSN,FUNC,READS_VD) \
97
- static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
98
- { \
99
- if (a->size != 0) { \
100
- /* TODO fp16 support */ \
101
- return false; \
102
- } \
103
- return do_3same_fp(s, a, FUNC, READS_VD); \
104
- }
105
-
106
-static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
107
- TCGv_ptr fpstatus)
108
-{
109
- gen_helper_vfp_muls(vn, vn, vm, fpstatus);
110
- gen_helper_vfp_adds(vd, vd, vn, fpstatus);
111
-}
112
-
113
-static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
114
- TCGv_ptr fpstatus)
115
-{
116
- gen_helper_vfp_muls(vn, vn, vm, fpstatus);
117
- gen_helper_vfp_subs(vd, vd, vn, fpstatus);
118
-}
119
-
120
-DO_3S_FP(VMLA, gen_VMLA_fp_3s, true)
121
-DO_3S_FP(VMLS, gen_VMLS_fp_3s, true)
122
+DO_3S_FP_GVEC(VMLA, gen_helper_gvec_fmla_s, gen_helper_gvec_fmla_h)
123
+DO_3S_FP_GVEC(VMLS, gen_helper_gvec_fmls_s, gen_helper_gvec_fmls_h)
124
125
WRAP_FP_GVEC(gen_VMAXNM_fp32_3s, FPST_STD, gen_helper_gvec_fmaxnum_s)
126
WRAP_FP_GVEC(gen_VMAXNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fmaxnum_h)
127
--
37
--
128
2.20.1
38
2.34.1
129
130
diff view generated by jsdifflib
1
The aa32_fp16_arith feature check function currently looks at the
1
Set the default NaN pattern explicitly for MIPS. Note that this
2
AArch64 ID_AA64PFR0 register. This is (as the comment notes) not
2
is our only target which currently changes the default NaN
3
correct. The bogus check was put in mostly to allow testing of the
3
at runtime (which it was previously doing indirectly when it
4
fp16 variants of the VCMLA instructions and it was something of
4
changed the snan_bit_is_one setting).
5
a mistake that we allowed them to exist in master.
6
7
Switch the feature check function to testing VMFR1.FPHP, which is
8
what it ought to be.
9
10
This will remove emulation of the VCMLA and VCADD insns from
11
AArch32 code running on an AArch64 '-cpu max' using system emulation.
12
(They were never enabled for aarch32 linux-user and system-emulation.)
13
Since we weren't advertising their existence via the AArch32 ID
14
register, well-behaved guests wouldn't have been using them anyway.
15
16
Once we have implemented all the AArch32 support for the FP16 extension
17
we will advertise it in the MVFR1 ID register field, which will reenable
18
these insns along with all the others.
19
5
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Message-id: 20200828183354.27913-3-peter.maydell@linaro.org
8
Message-id: 20241202131347.498124-44-peter.maydell@linaro.org
23
---
9
---
24
target/arm/cpu.h | 7 +------
10
target/mips/fpu_helper.h | 7 +++++++
25
1 file changed, 1 insertion(+), 6 deletions(-)
11
target/mips/msa.c | 3 +++
12
2 files changed, 10 insertions(+)
26
13
27
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
28
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/cpu.h
16
--- a/target/mips/fpu_helper.h
30
+++ b/target/arm/cpu.h
17
+++ b/target/mips/fpu_helper.h
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
18
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
32
19
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
33
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
20
nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
34
{
21
set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
35
- /*
22
+ /*
36
- * This is a placeholder for use by VCMA until the rest of
23
+ * With nan2008, the default NaN value has the sign bit clear and the
37
- * the ARMv8.2-FP16 extension is implemented for aa32 mode.
24
+ * frac msb set; with the older mode, the sign bit is clear, and all
38
- * At which point we can properly set and check MVFR1.FPHP.
25
+ * frac bits except the msb are set.
39
- */
26
+ */
40
- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
27
+ set_float_default_nan_pattern(nan2008 ? 0b01000000 : 0b00111111,
41
+ return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3;
28
+ &env->active_fpu.fp_status);
29
42
}
30
}
43
31
44
static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id)
32
diff --git a/target/mips/msa.c b/target/mips/msa.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/mips/msa.c
35
+++ b/target/mips/msa.c
36
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
37
/* Inf * 0 + NaN returns the input NaN */
38
set_float_infzeronan_rule(float_infzeronan_dnan_never,
39
&env->active_tc.msa_fp_status);
40
+ /* Default NaN: sign bit clear, frac msb set */
41
+ set_float_default_nan_pattern(0b01000000,
42
+ &env->active_tc.msa_fp_status);
43
}
45
--
44
--
46
2.20.1
45
2.34.1
47
48
diff view generated by jsdifflib
1
In the gvec helper functions for indexed operations, for AArch32
1
Set the default NaN pattern explicitly for openrisc.
2
Neon the oprsz (total size of the vector) can be less than 16 bytes
3
if the operation is on a D reg. Since the inner loop in these
4
helpers always goes from 0 to segment, we must clamp it based
5
on oprsz to avoid processing a full 16 byte segment when asked to
6
handle an 8 byte wide vector.
7
2
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200828183354.27913-43-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-45-peter.maydell@linaro.org
11
---
6
---
12
target/arm/vec_helper.c | 12 ++++++++----
7
target/openrisc/cpu.c | 2 ++
13
1 file changed, 8 insertions(+), 4 deletions(-)
8
1 file changed, 2 insertions(+)
14
9
15
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
10
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
16
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/vec_helper.c
12
--- a/target/openrisc/cpu.c
18
+++ b/target/arm/vec_helper.c
13
+++ b/target/openrisc/cpu.c
19
@@ -XXX,XX +XXX,XX @@ DO_MULADD(gvec_vfms_s, float32_mulsub_f, float32)
14
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_reset_hold(Object *obj, ResetType type)
20
#define DO_MUL_IDX(NAME, TYPE, H) \
15
*/
21
void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
16
set_float_2nan_prop_rule(float_2nan_prop_x87, &cpu->env.fp_status);
22
{ \
17
23
- intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \
18
+ /* Default NaN: sign bit clear, frac msb set */
24
+ intptr_t i, j, oprsz = simd_oprsz(desc); \
19
+ set_float_default_nan_pattern(0b01000000, &cpu->env.fp_status);
25
+ intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \
20
26
intptr_t idx = simd_data(desc); \
21
#ifndef CONFIG_USER_ONLY
27
TYPE *d = vd, *n = vn, *m = vm; \
22
cpu->env.picmr = 0x00000000;
28
for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \
29
@@ -XXX,XX +XXX,XX @@ DO_MUL_IDX(gvec_mul_idx_d, uint64_t, )
30
#define DO_MLA_IDX(NAME, TYPE, OP, H) \
31
void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \
32
{ \
33
- intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \
34
+ intptr_t i, j, oprsz = simd_oprsz(desc); \
35
+ intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \
36
intptr_t idx = simd_data(desc); \
37
TYPE *d = vd, *n = vn, *m = vm, *a = va; \
38
for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \
39
@@ -XXX,XX +XXX,XX @@ DO_MLA_IDX(gvec_mls_idx_d, uint64_t, -, )
40
#define DO_FMUL_IDX(NAME, TYPE, H) \
41
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
42
{ \
43
- intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \
44
+ intptr_t i, j, oprsz = simd_oprsz(desc); \
45
+ intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \
46
intptr_t idx = simd_data(desc); \
47
TYPE *d = vd, *n = vn, *m = vm; \
48
for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \
49
@@ -XXX,XX +XXX,XX @@ DO_FMUL_IDX(gvec_fmul_idx_d, float64, )
50
void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, \
51
void *stat, uint32_t desc) \
52
{ \
53
- intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \
54
+ intptr_t i, j, oprsz = simd_oprsz(desc); \
55
+ intptr_t segment = MIN(16, oprsz) / sizeof(TYPE); \
56
TYPE op1_neg = extract32(desc, SIMD_DATA_SHIFT, 1); \
57
intptr_t idx = desc >> (SIMD_DATA_SHIFT + 1); \
58
TYPE *d = vd, *n = vn, *m = vm, *a = va; \
59
--
23
--
60
2.20.1
24
2.34.1
61
62
diff view generated by jsdifflib
1
Implement VFP fp16 for VABS, VNEG and VSQRT. This is all
1
Set the default NaN pattern explicitly for ppc.
2
the fp16 insns that use the DO_VFP_2OP macro, because there
3
is no fp16 version of VMOV_reg.
4
5
Notes:
6
* the gen_helper_vfp_negh already exists as we needed to create
7
it for the fp16 multiply-add insns
8
* as usual we need to use the f16 version of the fp_status;
9
this is only relevant for VSQRT
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: 20200828183354.27913-9-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-46-peter.maydell@linaro.org
14
---
6
---
15
target/arm/helper.h | 2 ++
7
target/ppc/cpu_init.c | 4 ++++
16
target/arm/vfp.decode | 3 +++
8
1 file changed, 4 insertions(+)
17
target/arm/vfp_helper.c | 10 +++++++++
18
target/arm/translate-vfp.c.inc | 40 ++++++++++++++++++++++++++++++++++
19
4 files changed, 55 insertions(+)
20
9
21
diff --git a/target/arm/helper.h b/target/arm/helper.h
10
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
22
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.h
12
--- a/target/ppc/cpu_init.c
24
+++ b/target/arm/helper.h
13
+++ b/target/ppc/cpu_init.c
25
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_minnumd, f64, f64, f64, ptr)
14
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
26
DEF_HELPER_1(vfp_negh, f16, f16)
15
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
27
DEF_HELPER_1(vfp_negs, f32, f32)
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
28
DEF_HELPER_1(vfp_negd, f64, f64)
17
29
+DEF_HELPER_1(vfp_absh, f16, f16)
18
+ /* Default NaN: sign bit clear, set frac msb */
30
DEF_HELPER_1(vfp_abss, f32, f32)
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
31
DEF_HELPER_1(vfp_absd, f64, f64)
20
+ set_float_default_nan_pattern(0b01000000, &env->vec_status);
32
+DEF_HELPER_2(vfp_sqrth, f16, f16, env)
33
DEF_HELPER_2(vfp_sqrts, f32, f32, env)
34
DEF_HELPER_2(vfp_sqrtd, f64, f64, env)
35
DEF_HELPER_3(vfp_cmps, void, f32, f32, env)
36
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/vfp.decode
39
+++ b/target/arm/vfp.decode
40
@@ -XXX,XX +XXX,XX @@ VMOV_imm_dp ---- 1110 1.11 .... .... 1011 0000 .... \
41
VMOV_reg_sp ---- 1110 1.11 0000 .... 1010 01.0 .... @vfp_dm_ss
42
VMOV_reg_dp ---- 1110 1.11 0000 .... 1011 01.0 .... @vfp_dm_dd
43
44
+VABS_hp ---- 1110 1.11 0000 .... 1001 11.0 .... @vfp_dm_ss
45
VABS_sp ---- 1110 1.11 0000 .... 1010 11.0 .... @vfp_dm_ss
46
VABS_dp ---- 1110 1.11 0000 .... 1011 11.0 .... @vfp_dm_dd
47
48
+VNEG_hp ---- 1110 1.11 0001 .... 1001 01.0 .... @vfp_dm_ss
49
VNEG_sp ---- 1110 1.11 0001 .... 1010 01.0 .... @vfp_dm_ss
50
VNEG_dp ---- 1110 1.11 0001 .... 1011 01.0 .... @vfp_dm_dd
51
52
+VSQRT_hp ---- 1110 1.11 0001 .... 1001 11.0 .... @vfp_dm_ss
53
VSQRT_sp ---- 1110 1.11 0001 .... 1010 11.0 .... @vfp_dm_ss
54
VSQRT_dp ---- 1110 1.11 0001 .... 1011 11.0 .... @vfp_dm_dd
55
56
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/vfp_helper.c
59
+++ b/target/arm/vfp_helper.c
60
@@ -XXX,XX +XXX,XX @@ float64 VFP_HELPER(neg, d)(float64 a)
61
return float64_chs(a);
62
}
63
64
+dh_ctype_f16 VFP_HELPER(abs, h)(dh_ctype_f16 a)
65
+{
66
+ return float16_abs(a);
67
+}
68
+
21
+
69
float32 VFP_HELPER(abs, s)(float32 a)
22
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
70
{
23
ppc_spr_t *spr = &env->spr_cb[i];
71
return float32_abs(a);
72
@@ -XXX,XX +XXX,XX @@ float64 VFP_HELPER(abs, d)(float64 a)
73
return float64_abs(a);
74
}
75
76
+dh_ctype_f16 VFP_HELPER(sqrt, h)(dh_ctype_f16 a, CPUARMState *env)
77
+{
78
+ return float16_sqrt(a, &env->vfp.fp_status_f16);
79
+}
80
+
81
float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
82
{
83
return float32_sqrt(a, &env->vfp.fp_status);
84
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/translate-vfp.c.inc
87
+++ b/target/arm/translate-vfp.c.inc
88
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
89
return true;
90
}
91
92
+static bool do_vfp_2op_hp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
93
+{
94
+ /*
95
+ * Do a half-precision operation. Functionally this is
96
+ * the same as do_vfp_2op_sp(), except:
97
+ * - it doesn't need the VFP vector handling (fp16 is a
98
+ * v8 feature, and in v8 VFP vectors don't exist)
99
+ * - it does the aa32_fp16_arith feature test
100
+ */
101
+ TCGv_i32 f0;
102
+
103
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
104
+ return false;
105
+ }
106
+
107
+ if (s->vec_len != 0 || s->vec_stride != 0) {
108
+ return false;
109
+ }
110
+
111
+ if (!vfp_access_check(s)) {
112
+ return true;
113
+ }
114
+
115
+ f0 = tcg_temp_new_i32();
116
+ neon_load_reg32(f0, vm);
117
+ fn(f0, f0);
118
+ neon_store_reg32(f0, vd);
119
+ tcg_temp_free_i32(f0);
120
+
121
+ return true;
122
+}
123
+
124
static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
125
{
126
uint32_t delta_m = 0;
127
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
128
DO_VFP_2OP(VMOV_reg, sp, tcg_gen_mov_i32)
129
DO_VFP_2OP(VMOV_reg, dp, tcg_gen_mov_i64)
130
131
+DO_VFP_2OP(VABS, hp, gen_helper_vfp_absh)
132
DO_VFP_2OP(VABS, sp, gen_helper_vfp_abss)
133
DO_VFP_2OP(VABS, dp, gen_helper_vfp_absd)
134
135
+DO_VFP_2OP(VNEG, hp, gen_helper_vfp_negh)
136
DO_VFP_2OP(VNEG, sp, gen_helper_vfp_negs)
137
DO_VFP_2OP(VNEG, dp, gen_helper_vfp_negd)
138
139
+static void gen_VSQRT_hp(TCGv_i32 vd, TCGv_i32 vm)
140
+{
141
+ gen_helper_vfp_sqrth(vd, vm, cpu_env);
142
+}
143
+
144
static void gen_VSQRT_sp(TCGv_i32 vd, TCGv_i32 vm)
145
{
146
gen_helper_vfp_sqrts(vd, vm, cpu_env);
147
@@ -XXX,XX +XXX,XX @@ static void gen_VSQRT_dp(TCGv_i64 vd, TCGv_i64 vm)
148
gen_helper_vfp_sqrtd(vd, vm, cpu_env);
149
}
150
151
+DO_VFP_2OP(VSQRT, hp, gen_VSQRT_hp)
152
DO_VFP_2OP(VSQRT, sp, gen_VSQRT_sp)
153
DO_VFP_2OP(VSQRT, dp, gen_VSQRT_dp)
154
24
155
--
25
--
156
2.20.1
26
2.34.1
157
158
diff view generated by jsdifflib
1
Implement the VFP fp16 variant of VMOV that transfers a 16-bit
1
Set the default NaN pattern explicitly for sh4. Note that sh4
2
value between a general purpose register and a VFP register.
2
is one of the only three targets (the others being HPPA and
3
3
sometimes MIPS) that has snan_bit_is_one set.
4
Note that Rt == 15 is UNPREDICTABLE; since this insn is v8 and later
5
only we have no need to replicate the old "updates CPSR.NZCV"
6
behaviour that the singleprec version of this insn does.
7
4
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200828183354.27913-22-peter.maydell@linaro.org
7
Message-id: 20241202131347.498124-47-peter.maydell@linaro.org
11
---
8
---
12
target/arm/vfp.decode | 1 +
9
target/sh4/cpu.c | 2 ++
13
target/arm/translate-vfp.c.inc | 34 ++++++++++++++++++++++++++++++++++
10
1 file changed, 2 insertions(+)
14
2 files changed, 35 insertions(+)
15
11
16
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
12
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/vfp.decode
14
--- a/target/sh4/cpu.c
19
+++ b/target/arm/vfp.decode
15
+++ b/target/sh4/cpu.c
20
@@ -XXX,XX +XXX,XX @@ VDUP ---- 1110 1 b:1 q:1 0 .... rt:4 1011 . 0 e:1 1 0000 \
16
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
21
vn=%vn_dp
17
set_flush_to_zero(1, &env->fp_status);
22
18
#endif
23
VMSR_VMRS ---- 1110 111 l:1 reg:4 rt:4 1010 0001 0000
19
set_default_nan_mode(1, &env->fp_status);
24
+VMOV_half ---- 1110 000 l:1 .... rt:4 1001 . 001 0000 vn=%vn_sp
20
+ /* sign bit clear, set all frac bits other than msb */
25
VMOV_single ---- 1110 000 l:1 .... rt:4 1010 . 001 0000 vn=%vn_sp
21
+ set_float_default_nan_pattern(0b00111111, &env->fp_status);
26
27
VMOV_64_sp ---- 1100 010 op:1 rt2:4 rt:4 1010 00.1 .... vm=%vm_sp
28
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-vfp.c.inc
31
+++ b/target/arm/translate-vfp.c.inc
32
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
33
return true;
34
}
22
}
35
23
36
+static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
24
static void superh_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
37
+{
38
+ TCGv_i32 tmp;
39
+
40
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
41
+ return false;
42
+ }
43
+
44
+ if (a->rt == 15) {
45
+ /* UNPREDICTABLE; we choose to UNDEF */
46
+ return false;
47
+ }
48
+
49
+ if (!vfp_access_check(s)) {
50
+ return true;
51
+ }
52
+
53
+ if (a->l) {
54
+ /* VFP to general purpose register */
55
+ tmp = tcg_temp_new_i32();
56
+ neon_load_reg32(tmp, a->vn);
57
+ tcg_gen_andi_i32(tmp, tmp, 0xffff);
58
+ store_reg(s, a->rt, tmp);
59
+ } else {
60
+ /* general purpose register to VFP */
61
+ tmp = load_reg(s, a->rt);
62
+ tcg_gen_andi_i32(tmp, tmp, 0xffff);
63
+ neon_store_reg32(tmp, a->vn);
64
+ tcg_temp_free_i32(tmp);
65
+ }
66
+
67
+ return true;
68
+}
69
+
70
static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a)
71
{
72
TCGv_i32 tmp;
73
--
25
--
74
2.20.1
26
2.34.1
75
76
diff view generated by jsdifflib
1
Implement the fp16 versions of the VFP VCVT instruction forms which
1
Set the default NaN pattern explicitly for rx.
2
convert between floating point and integer.
3
2
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-13-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-48-peter.maydell@linaro.org
7
---
6
---
8
target/arm/vfp.decode | 4 +++
7
target/rx/cpu.c | 2 ++
9
target/arm/translate-vfp.c.inc | 65 ++++++++++++++++++++++++++++++++++
8
1 file changed, 2 insertions(+)
10
2 files changed, 69 insertions(+)
11
9
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
10
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
13
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/vfp.decode
12
--- a/target/rx/cpu.c
15
+++ b/target/arm/vfp.decode
13
+++ b/target/rx/cpu.c
16
@@ -XXX,XX +XXX,XX @@ VCVT_sp ---- 1110 1.11 0111 .... 1010 11.0 .... @vfp_dm_ds
14
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_reset_hold(Object *obj, ResetType type)
17
VCVT_dp ---- 1110 1.11 0111 .... 1011 11.0 .... @vfp_dm_sd
15
* then prefer dest over source", which is float_2nan_prop_s_ab.
18
16
*/
19
# VCVT from integer to floating point: Vm always single; Vd depends on size
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
20
+VCVT_int_hp ---- 1110 1.11 1000 .... 1001 s:1 1.0 .... \
18
+ /* Default NaN value: sign bit clear, set frac msb */
21
+ vd=%vd_sp vm=%vm_sp
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
22
VCVT_int_sp ---- 1110 1.11 1000 .... 1010 s:1 1.0 .... \
23
vd=%vd_sp vm=%vm_sp
24
VCVT_int_dp ---- 1110 1.11 1000 .... 1011 s:1 1.0 .... \
25
@@ -XXX,XX +XXX,XX @@ VCVT_fix_dp ---- 1110 1.11 1.1. .... 1011 .1.0 .... \
26
vd=%vd_dp imm=%vm_sp opc=%vcvt_fix_op
27
28
# VCVT float to integer (VCVT and VCVTR): Vd always single; Vd depends on size
29
+VCVT_hp_int ---- 1110 1.11 110 s:1 .... 1001 rz:1 1.0 .... \
30
+ vd=%vd_sp vm=%vm_sp
31
VCVT_sp_int ---- 1110 1.11 110 s:1 .... 1010 rz:1 1.0 .... \
32
vd=%vd_sp vm=%vm_sp
33
VCVT_dp_int ---- 1110 1.11 110 s:1 .... 1011 rz:1 1.0 .... \
34
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/translate-vfp.c.inc
37
+++ b/target/arm/translate-vfp.c.inc
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
39
return true;
40
}
20
}
41
21
42
+static bool trans_VCVT_int_hp(DisasContext *s, arg_VCVT_int_sp *a)
22
static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
43
+{
44
+ TCGv_i32 vm;
45
+ TCGv_ptr fpst;
46
+
47
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
48
+ return false;
49
+ }
50
+
51
+ if (!vfp_access_check(s)) {
52
+ return true;
53
+ }
54
+
55
+ vm = tcg_temp_new_i32();
56
+ neon_load_reg32(vm, a->vm);
57
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
58
+ if (a->s) {
59
+ /* i32 -> f16 */
60
+ gen_helper_vfp_sitoh(vm, vm, fpst);
61
+ } else {
62
+ /* u32 -> f16 */
63
+ gen_helper_vfp_uitoh(vm, vm, fpst);
64
+ }
65
+ neon_store_reg32(vm, a->vd);
66
+ tcg_temp_free_i32(vm);
67
+ tcg_temp_free_ptr(fpst);
68
+ return true;
69
+}
70
+
71
static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a)
72
{
73
TCGv_i32 vm;
74
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
75
return true;
76
}
77
78
+static bool trans_VCVT_hp_int(DisasContext *s, arg_VCVT_sp_int *a)
79
+{
80
+ TCGv_i32 vm;
81
+ TCGv_ptr fpst;
82
+
83
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
84
+ return false;
85
+ }
86
+
87
+ if (!vfp_access_check(s)) {
88
+ return true;
89
+ }
90
+
91
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
92
+ vm = tcg_temp_new_i32();
93
+ neon_load_reg32(vm, a->vm);
94
+
95
+ if (a->s) {
96
+ if (a->rz) {
97
+ gen_helper_vfp_tosizh(vm, vm, fpst);
98
+ } else {
99
+ gen_helper_vfp_tosih(vm, vm, fpst);
100
+ }
101
+ } else {
102
+ if (a->rz) {
103
+ gen_helper_vfp_touizh(vm, vm, fpst);
104
+ } else {
105
+ gen_helper_vfp_touih(vm, vm, fpst);
106
+ }
107
+ }
108
+ neon_store_reg32(vm, a->vd);
109
+ tcg_temp_free_i32(vm);
110
+ tcg_temp_free_ptr(fpst);
111
+ return true;
112
+}
113
+
114
static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a)
115
{
116
TCGv_i32 vm;
117
--
23
--
118
2.20.1
24
2.34.1
119
120
diff view generated by jsdifflib
1
The fp16 extension includes a new instruction VMOVX, which copies the
1
Set the default NaN pattern explicitly for s390x.
2
upper 16 bits of a 32-bit source VFP register into the lower 16
3
bits of the destination and zeroes the high half of the destination.
4
Implement it.
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
Message-id: 20200828183354.27913-21-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-49-peter.maydell@linaro.org
9
---
6
---
10
target/arm/vfp-uncond.decode | 3 +++
7
target/s390x/cpu.c | 2 ++
11
target/arm/translate-vfp.c.inc | 25 +++++++++++++++++++++++++
8
1 file changed, 2 insertions(+)
12
2 files changed, 28 insertions(+)
13
9
14
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
10
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
15
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/vfp-uncond.decode
12
--- a/target/s390x/cpu.c
17
+++ b/target/arm/vfp-uncond.decode
13
+++ b/target/s390x/cpu.c
18
@@ -XXX,XX +XXX,XX @@ VCVT 1111 1110 1.11 11 rm:2 .... 1010 op:1 1.0 .... \
14
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
19
VCVT 1111 1110 1.11 11 rm:2 .... 1011 op:1 1.0 .... \
15
set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
20
vm=%vm_dp vd=%vd_sp sz=3
16
set_float_infzeronan_rule(float_infzeronan_dnan_always,
21
17
&env->fpu_status);
22
+VMOVX 1111 1110 1.11 0000 .... 1010 01 . 0 .... \
18
+ /* Default NaN value: sign bit clear, frac msb set */
23
+ vd=%vd_sp vm=%vm_sp
19
+ set_float_default_nan_pattern(0b01000000, &env->fpu_status);
24
+
20
/* fall through */
25
VINS 1111 1110 1.11 0000 .... 1010 11 . 0 .... \
21
case RESET_TYPE_S390_CPU_NORMAL:
26
vd=%vd_sp vm=%vm_sp
22
env->psw.mask &= ~PSW_MASK_RI;
27
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-vfp.c.inc
30
+++ b/target/arm/translate-vfp.c.inc
31
@@ -XXX,XX +XXX,XX @@ static bool trans_VINS(DisasContext *s, arg_VINS *a)
32
tcg_temp_free_i32(rd);
33
return true;
34
}
35
+
36
+static bool trans_VMOVX(DisasContext *s, arg_VINS *a)
37
+{
38
+ TCGv_i32 rm;
39
+
40
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
41
+ return false;
42
+ }
43
+
44
+ if (s->vec_len != 0 || s->vec_stride != 0) {
45
+ return false;
46
+ }
47
+
48
+ if (!vfp_access_check(s)) {
49
+ return true;
50
+ }
51
+
52
+ /* Set Vd to high half of Vm */
53
+ rm = tcg_temp_new_i32();
54
+ neon_load_reg32(rm, a->vm);
55
+ tcg_gen_shri_i32(rm, rm, 16);
56
+ neon_store_reg32(rm, a->vd);
57
+ tcg_temp_free_i32(rm);
58
+ return true;
59
+}
60
--
23
--
61
2.20.1
24
2.34.1
62
63
diff view generated by jsdifflib
1
The fp16 extension includes a new instruction VINS, which copies the
1
Set the default NaN pattern explicitly for SPARC, and remove
2
lower 16 bits of a 32-bit source VFP register into the upper 16 bits
2
the ifdef from parts64_default_nan.
3
of the destination. Implement it.
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: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200828183354.27913-20-peter.maydell@linaro.org
6
Message-id: 20241202131347.498124-50-peter.maydell@linaro.org
8
---
7
---
9
target/arm/vfp-uncond.decode | 3 +++
8
target/sparc/cpu.c | 2 ++
10
target/arm/translate-vfp.c.inc | 28 ++++++++++++++++++++++++++++
9
fpu/softfloat-specialize.c.inc | 5 +----
11
2 files changed, 31 insertions(+)
10
2 files changed, 3 insertions(+), 4 deletions(-)
12
11
13
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/vfp-uncond.decode
14
--- a/target/sparc/cpu.c
16
+++ b/target/arm/vfp-uncond.decode
15
+++ b/target/sparc/cpu.c
17
@@ -XXX,XX +XXX,XX @@ VCVT 1111 1110 1.11 11 rm:2 .... 1010 op:1 1.0 .... \
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
18
vm=%vm_sp vd=%vd_sp sz=2
17
set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
19
VCVT 1111 1110 1.11 11 rm:2 .... 1011 op:1 1.0 .... \
18
/* For inf * 0 + NaN, return the input NaN */
20
vm=%vm_dp vd=%vd_sp sz=3
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
21
+
20
+ /* Default NaN value: sign bit clear, all frac bits set */
22
+VINS 1111 1110 1.11 0000 .... 1010 11 . 0 .... \
21
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
23
+ vd=%vd_sp vm=%vm_sp
22
24
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
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
25
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/translate-vfp.c.inc
27
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/target/arm/translate-vfp.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
29
30
uint8_t dnan_pattern = status->default_nan_pattern;
30
return false;
31
31
}
32
if (dnan_pattern == 0) {
32
+
33
-#if defined(TARGET_SPARC)
33
+static bool trans_VINS(DisasContext *s, arg_VINS *a)
34
- /* Sign bit clear, all frac bits set */
34
+{
35
- dnan_pattern = 0b01111111;
35
+ TCGv_i32 rd, rm;
36
-#elif defined(TARGET_HEXAGON)
36
+
37
+#if defined(TARGET_HEXAGON)
37
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
38
/* Sign bit set, all frac bits set. */
38
+ return false;
39
dnan_pattern = 0b11111111;
39
+ }
40
#else
40
+
41
+ if (s->vec_len != 0 || s->vec_stride != 0) {
42
+ return false;
43
+ }
44
+
45
+ if (!vfp_access_check(s)) {
46
+ return true;
47
+ }
48
+
49
+ /* Insert low half of Vm into high half of Vd */
50
+ rm = tcg_temp_new_i32();
51
+ rd = tcg_temp_new_i32();
52
+ neon_load_reg32(rm, a->vm);
53
+ neon_load_reg32(rd, a->vd);
54
+ tcg_gen_deposit_i32(rd, rd, rm, 16, 16);
55
+ neon_store_reg32(rd, a->vd);
56
+ tcg_temp_free_i32(rm);
57
+ tcg_temp_free_i32(rd);
58
+ return true;
59
+}
60
--
41
--
61
2.20.1
42
2.34.1
62
63
diff view generated by jsdifflib
1
Implement the fp16 versions of the VFP VLDR/VSTR (immediate).
1
Set the default NaN pattern explicitly for xtensa.
2
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200828183354.27913-12-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-51-peter.maydell@linaro.org
6
---
6
---
7
target/arm/vfp.decode | 3 +--
7
target/xtensa/cpu.c | 2 ++
8
target/arm/translate-vfp.c.inc | 35 ++++++++++++++++++++++++++++++++++
8
1 file changed, 2 insertions(+)
9
2 files changed, 36 insertions(+), 2 deletions(-)
10
9
11
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
10
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
12
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/vfp.decode
12
--- a/target/xtensa/cpu.c
14
+++ b/target/arm/vfp.decode
13
+++ b/target/xtensa/cpu.c
15
@@ -XXX,XX +XXX,XX @@ VMOV_single ---- 1110 000 l:1 .... rt:4 1010 . 001 0000 vn=%vn_sp
14
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
16
VMOV_64_sp ---- 1100 010 op:1 rt2:4 rt:4 1010 00.1 .... vm=%vm_sp
15
/* For inf * 0 + NaN, return the input NaN */
17
VMOV_64_dp ---- 1100 010 op:1 rt2:4 rt:4 1011 00.1 .... vm=%vm_dp
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
18
17
set_no_signaling_nans(!dfpu, &env->fp_status);
19
-# Note that the half-precision variants of VLDR and VSTR are
18
+ /* Default NaN value: sign bit clear, set frac msb */
20
-# not part of this decodetree at all because they have bits [9:8] == 0b01
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
21
+VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
20
xtensa_use_first_nan(env, !dfpu);
22
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
23
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
24
25
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/translate-vfp.c.inc
28
+++ b/target/arm/translate-vfp.c.inc
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_dp *a)
30
return true;
31
}
21
}
32
22
33
+static bool trans_VLDR_VSTR_hp(DisasContext *s, arg_VLDR_VSTR_sp *a)
34
+{
35
+ uint32_t offset;
36
+ TCGv_i32 addr, tmp;
37
+
38
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
39
+ return false;
40
+ }
41
+
42
+ if (!vfp_access_check(s)) {
43
+ return true;
44
+ }
45
+
46
+ /* imm8 field is offset/2 for fp16, unlike fp32 and fp64 */
47
+ offset = a->imm << 1;
48
+ if (!a->u) {
49
+ offset = -offset;
50
+ }
51
+
52
+ /* For thumb, use of PC is UNPREDICTABLE. */
53
+ addr = add_reg_for_lit(s, a->rn, offset);
54
+ tmp = tcg_temp_new_i32();
55
+ if (a->l) {
56
+ gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
57
+ neon_store_reg32(tmp, a->vd);
58
+ } else {
59
+ neon_load_reg32(tmp, a->vd);
60
+ gen_aa32_st16(s, tmp, addr, get_mem_index(s));
61
+ }
62
+ tcg_temp_free_i32(tmp);
63
+ tcg_temp_free_i32(addr);
64
+
65
+ return true;
66
+}
67
+
68
static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a)
69
{
70
uint32_t offset;
71
--
23
--
72
2.20.1
24
2.34.1
73
74
diff view generated by jsdifflib
1
Implement VFP fp16 support for fused multiply-add insns
1
Set the default NaN pattern explicitly for hexagon.
2
VFNMA, VFNMS, VFMA, VFMS.
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
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-7-peter.maydell@linaro.org
7
Message-id: 20241202131347.498124-52-peter.maydell@linaro.org
7
---
8
---
8
target/arm/helper.h | 1 +
9
target/hexagon/cpu.c | 2 ++
9
target/arm/vfp.decode | 5 +++
10
fpu/softfloat-specialize.c.inc | 5 -----
10
target/arm/vfp_helper.c | 7 ++++
11
2 files changed, 2 insertions(+), 5 deletions(-)
11
target/arm/translate-vfp.c.inc | 64 ++++++++++++++++++++++++++++++++++
12
4 files changed, 77 insertions(+)
13
12
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.h
15
--- a/target/hexagon/cpu.c
17
+++ b/target/arm/helper.h
16
+++ b/target/hexagon/cpu.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(vfp_fcvt_f64_to_f16, TCG_CALL_NO_RWG, f16, f64, ptr, i32)
17
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
19
18
20
DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
19
set_default_nan_mode(1, &env->fp_status);
21
DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
20
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
22
+DEF_HELPER_4(vfp_muladdh, f16, f16, f16, f16, ptr)
21
+ /* Default NaN value: sign bit set, all frac bits set */
23
22
+ set_float_default_nan_pattern(0b11111111, &env->fp_status);
24
DEF_HELPER_3(recps_f32, f32, env, f32, f32)
23
}
25
DEF_HELPER_3(rsqrts_f32, f32, env, f32, f32)
24
26
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
25
static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
26
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
27
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/vfp.decode
28
--- a/fpu/softfloat-specialize.c.inc
29
+++ b/target/arm/vfp.decode
29
+++ b/fpu/softfloat-specialize.c.inc
30
@@ -XXX,XX +XXX,XX @@ VDIV_hp ---- 1110 1.00 .... .... 1001 .0.0 .... @vfp_dnm_s
30
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
31
VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
31
uint8_t dnan_pattern = status->default_nan_pattern;
32
VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
32
33
33
if (dnan_pattern == 0) {
34
+VFMA_hp ---- 1110 1.10 .... .... 1001 .0. 0 .... @vfp_dnm_s
34
-#if defined(TARGET_HEXAGON)
35
+VFMS_hp ---- 1110 1.10 .... .... 1001 .1. 0 .... @vfp_dnm_s
35
- /* Sign bit set, all frac bits set. */
36
+VFNMA_hp ---- 1110 1.01 .... .... 1001 .0. 0 .... @vfp_dnm_s
36
- dnan_pattern = 0b11111111;
37
+VFNMS_hp ---- 1110 1.01 .... .... 1001 .1. 0 .... @vfp_dnm_s
37
-#else
38
+
38
/*
39
VFMA_sp ---- 1110 1.10 .... .... 1010 .0. 0 .... @vfp_dnm_s
39
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
40
VFMS_sp ---- 1110 1.10 .... .... 1010 .1. 0 .... @vfp_dnm_s
40
* S390, SH4, TriCore, and Xtensa. Our other supported targets
41
VFNMA_sp ---- 1110 1.01 .... .... 1010 .0. 0 .... @vfp_dnm_s
41
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
42
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
42
/* sign bit clear, set frac msb */
43
index XXXXXXX..XXXXXXX 100644
43
dnan_pattern = 0b01000000;
44
--- a/target/arm/vfp_helper.c
44
}
45
+++ b/target/arm/vfp_helper.c
45
-#endif
46
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(rsqrte_u32)(uint32_t a)
46
}
47
}
47
assert(dnan_pattern != 0);
48
49
/* VFPv4 fused multiply-accumulate */
50
+dh_ctype_f16 VFP_HELPER(muladd, h)(dh_ctype_f16 a, dh_ctype_f16 b,
51
+ dh_ctype_f16 c, void *fpstp)
52
+{
53
+ float_status *fpst = fpstp;
54
+ return float16_muladd(a, b, c, 0, fpst);
55
+}
56
+
57
float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
58
{
59
float_status *fpst = fpstp;
60
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/translate-vfp.c.inc
63
+++ b/target/arm/translate-vfp.c.inc
64
@@ -XXX,XX +XXX,XX @@ static bool trans_VMAXNM_dp(DisasContext *s, arg_VMAXNM_dp *a)
65
a->vd, a->vn, a->vm, false);
66
}
67
68
+static bool do_vfm_hp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
69
+{
70
+ /*
71
+ * VFNMA : fd = muladd(-fd, fn, fm)
72
+ * VFNMS : fd = muladd(-fd, -fn, fm)
73
+ * VFMA : fd = muladd( fd, fn, fm)
74
+ * VFMS : fd = muladd( fd, -fn, fm)
75
+ *
76
+ * These are fused multiply-add, and must be done as one floating
77
+ * point operation with no rounding between the multiplication and
78
+ * addition steps. NB that doing the negations here as separate
79
+ * steps is correct : an input NaN should come out with its sign
80
+ * bit flipped if it is a negated-input.
81
+ */
82
+ TCGv_ptr fpst;
83
+ TCGv_i32 vn, vm, vd;
84
+
85
+ /*
86
+ * Present in VFPv4 only, and only with the FP16 extension.
87
+ * Note that we can't rely on the SIMDFMAC check alone, because
88
+ * in a Neon-no-VFP core that ID register field will be non-zero.
89
+ */
90
+ if (!dc_isar_feature(aa32_fp16_arith, s) ||
91
+ !dc_isar_feature(aa32_simdfmac, s) ||
92
+ !dc_isar_feature(aa32_fpsp_v2, s)) {
93
+ return false;
94
+ }
95
+
96
+ if (s->vec_len != 0 || s->vec_stride != 0) {
97
+ return false;
98
+ }
99
+
100
+ if (!vfp_access_check(s)) {
101
+ return true;
102
+ }
103
+
104
+ vn = tcg_temp_new_i32();
105
+ vm = tcg_temp_new_i32();
106
+ vd = tcg_temp_new_i32();
107
+
108
+ neon_load_reg32(vn, a->vn);
109
+ neon_load_reg32(vm, a->vm);
110
+ if (neg_n) {
111
+ /* VFNMS, VFMS */
112
+ gen_helper_vfp_negh(vn, vn);
113
+ }
114
+ neon_load_reg32(vd, a->vd);
115
+ if (neg_d) {
116
+ /* VFNMA, VFNMS */
117
+ gen_helper_vfp_negh(vd, vd);
118
+ }
119
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
120
+ gen_helper_vfp_muladdh(vd, vn, vm, vd, fpst);
121
+ neon_store_reg32(vd, a->vd);
122
+
123
+ tcg_temp_free_ptr(fpst);
124
+ tcg_temp_free_i32(vn);
125
+ tcg_temp_free_i32(vm);
126
+ tcg_temp_free_i32(vd);
127
+
128
+ return true;
129
+}
130
+
131
static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
132
{
133
/*
134
@@ -XXX,XX +XXX,XX @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
135
MAKE_ONE_VFM_TRANS_FN(VFNMA, PREC, false, true) \
136
MAKE_ONE_VFM_TRANS_FN(VFNMS, PREC, true, true)
137
138
+MAKE_VFM_TRANS_FNS(hp)
139
MAKE_VFM_TRANS_FNS(sp)
140
MAKE_VFM_TRANS_FNS(dp)
141
48
142
--
49
--
143
2.20.1
50
2.34.1
144
145
diff view generated by jsdifflib
1
Now the VFP_CONV_FIX macros can handle fp16's distinction between the
1
Set the default NaN pattern explicitly for riscv.
2
width of the operation and the width of the type used to pass operands,
3
use the macros rather than the open-coded functions.
4
5
This creates an extra six helper functions, all of which we are going
6
to need for the AArch32 VFP fp16 instructions.
7
2
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200828183354.27913-15-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-53-peter.maydell@linaro.org
11
---
6
---
12
target/arm/helper.h | 6 +++
7
target/riscv/cpu.c | 2 ++
13
target/arm/vfp_helper.c | 86 +++--------------------------------------
8
1 file changed, 2 insertions(+)
14
2 files changed, 12 insertions(+), 80 deletions(-)
15
9
16
diff --git a/target/arm/helper.h b/target/arm/helper.h
10
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
17
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.h
12
--- a/target/riscv/cpu.c
19
+++ b/target/arm/helper.h
13
+++ b/target/riscv/cpu.c
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(vfp_tosizh, s32, f16, ptr)
14
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
21
DEF_HELPER_2(vfp_tosizs, s32, f32, ptr)
15
cs->exception_index = RISCV_EXCP_NONE;
22
DEF_HELPER_2(vfp_tosizd, s32, f64, ptr)
16
env->load_res = -1;
23
17
set_default_nan_mode(1, &env->fp_status);
24
+DEF_HELPER_3(vfp_toshh_round_to_zero, i32, f16, i32, ptr)
18
+ /* Default NaN value: sign bit clear, frac msb set */
25
+DEF_HELPER_3(vfp_toslh_round_to_zero, i32, f16, i32, ptr)
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
26
+DEF_HELPER_3(vfp_touhh_round_to_zero, i32, f16, i32, ptr)
20
env->vill = true;
27
+DEF_HELPER_3(vfp_toulh_round_to_zero, i32, f16, i32, ptr)
21
28
DEF_HELPER_3(vfp_toshs_round_to_zero, i32, f32, i32, ptr)
22
#ifndef CONFIG_USER_ONLY
29
DEF_HELPER_3(vfp_tosls_round_to_zero, i32, f32, i32, ptr)
30
DEF_HELPER_3(vfp_touhs_round_to_zero, i32, f32, i32, ptr)
31
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_sqtod, f64, i64, i32, ptr)
32
DEF_HELPER_3(vfp_uhtod, f64, i64, i32, ptr)
33
DEF_HELPER_3(vfp_ultod, f64, i64, i32, ptr)
34
DEF_HELPER_3(vfp_uqtod, f64, i64, i32, ptr)
35
+DEF_HELPER_3(vfp_shtoh, f16, i32, i32, ptr)
36
+DEF_HELPER_3(vfp_uhtoh, f16, i32, i32, ptr)
37
DEF_HELPER_3(vfp_sltoh, f16, i32, i32, ptr)
38
DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
39
DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
40
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/vfp_helper.c
43
+++ b/target/arm/vfp_helper.c
44
@@ -XXX,XX +XXX,XX @@ VFP_CONV_FIX_A64(sq, s, 32, float32, 64, int64)
45
VFP_CONV_FIX(uh, s, 32, float32, 32, uint16)
46
VFP_CONV_FIX(ul, s, 32, float32, 32, uint32)
47
VFP_CONV_FIX_A64(uq, s, 32, float32, 64, uint64)
48
+VFP_CONV_FIX(sh, h, 16, dh_ctype_f16, 32, int16)
49
+VFP_CONV_FIX(sl, h, 16, dh_ctype_f16, 32, int32)
50
+VFP_CONV_FIX_A64(sq, h, 16, dh_ctype_f16, 64, int64)
51
+VFP_CONV_FIX(uh, h, 16, dh_ctype_f16, 32, uint16)
52
+VFP_CONV_FIX(ul, h, 16, dh_ctype_f16, 32, uint32)
53
+VFP_CONV_FIX_A64(uq, h, 16, dh_ctype_f16, 64, uint64)
54
55
#undef VFP_CONV_FIX
56
#undef VFP_CONV_FIX_FLOAT
57
#undef VFP_CONV_FLOAT_FIX_ROUND
58
#undef VFP_CONV_FIX_A64
59
60
-uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
61
-{
62
- return int32_to_float16_scalbn(x, -shift, fpst);
63
-}
64
-
65
-uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
66
-{
67
- return uint32_to_float16_scalbn(x, -shift, fpst);
68
-}
69
-
70
-uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
71
-{
72
- return int64_to_float16_scalbn(x, -shift, fpst);
73
-}
74
-
75
-uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
76
-{
77
- return uint64_to_float16_scalbn(x, -shift, fpst);
78
-}
79
-
80
-uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
81
-{
82
- if (unlikely(float16_is_any_nan(x))) {
83
- float_raise(float_flag_invalid, fpst);
84
- return 0;
85
- }
86
- return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
87
- shift, fpst);
88
-}
89
-
90
-uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
91
-{
92
- if (unlikely(float16_is_any_nan(x))) {
93
- float_raise(float_flag_invalid, fpst);
94
- return 0;
95
- }
96
- return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
97
- shift, fpst);
98
-}
99
-
100
-uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
101
-{
102
- if (unlikely(float16_is_any_nan(x))) {
103
- float_raise(float_flag_invalid, fpst);
104
- return 0;
105
- }
106
- return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
107
- shift, fpst);
108
-}
109
-
110
-uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
111
-{
112
- if (unlikely(float16_is_any_nan(x))) {
113
- float_raise(float_flag_invalid, fpst);
114
- return 0;
115
- }
116
- return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
117
- shift, fpst);
118
-}
119
-
120
-uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
121
-{
122
- if (unlikely(float16_is_any_nan(x))) {
123
- float_raise(float_flag_invalid, fpst);
124
- return 0;
125
- }
126
- return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
127
- shift, fpst);
128
-}
129
-
130
-uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
131
-{
132
- if (unlikely(float16_is_any_nan(x))) {
133
- float_raise(float_flag_invalid, fpst);
134
- return 0;
135
- }
136
- return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
137
- shift, fpst);
138
-}
139
-
140
/* Set the current fp rounding mode and return the old one.
141
* The argument is a softfloat float_round_ value.
142
*/
143
--
23
--
144
2.20.1
24
2.34.1
145
146
diff view generated by jsdifflib
1
Implement fp16 version of VCMP.
1
Set the default NaN pattern explicitly for tricore.
2
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200828183354.27913-11-peter.maydell@linaro.org
5
Message-id: 20241202131347.498124-54-peter.maydell@linaro.org
6
---
6
---
7
target/arm/helper.h | 2 ++
7
target/tricore/helper.c | 2 ++
8
target/arm/vfp.decode | 2 ++
8
1 file changed, 2 insertions(+)
9
target/arm/vfp_helper.c | 15 +++++++------
10
target/arm/translate-vfp.c.inc | 39 ++++++++++++++++++++++++++++++++++
11
4 files changed, 51 insertions(+), 7 deletions(-)
12
9
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
10
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
12
--- a/target/tricore/helper.c
16
+++ b/target/arm/helper.h
13
+++ b/target/tricore/helper.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(vfp_absd, f64, f64)
14
@@ -XXX,XX +XXX,XX @@ void fpu_set_state(CPUTriCoreState *env)
18
DEF_HELPER_2(vfp_sqrth, f16, f16, env)
15
set_flush_to_zero(1, &env->fp_status);
19
DEF_HELPER_2(vfp_sqrts, f32, f32, env)
16
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
20
DEF_HELPER_2(vfp_sqrtd, f64, f64, env)
17
set_default_nan_mode(1, &env->fp_status);
21
+DEF_HELPER_3(vfp_cmph, void, f16, f16, env)
18
+ /* Default NaN pattern: sign bit clear, frac msb set */
22
DEF_HELPER_3(vfp_cmps, void, f32, f32, env)
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
23
DEF_HELPER_3(vfp_cmpd, void, f64, f64, env)
24
+DEF_HELPER_3(vfp_cmpeh, void, f16, f16, env)
25
DEF_HELPER_3(vfp_cmpes, void, f32, f32, env)
26
DEF_HELPER_3(vfp_cmped, void, f64, f64, env)
27
28
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/vfp.decode
31
+++ b/target/arm/vfp.decode
32
@@ -XXX,XX +XXX,XX @@ VSQRT_hp ---- 1110 1.11 0001 .... 1001 11.0 .... @vfp_dm_ss
33
VSQRT_sp ---- 1110 1.11 0001 .... 1010 11.0 .... @vfp_dm_ss
34
VSQRT_dp ---- 1110 1.11 0001 .... 1011 11.0 .... @vfp_dm_dd
35
36
+VCMP_hp ---- 1110 1.11 010 z:1 .... 1001 e:1 1.0 .... \
37
+ vd=%vd_sp vm=%vm_sp
38
VCMP_sp ---- 1110 1.11 010 z:1 .... 1010 e:1 1.0 .... \
39
vd=%vd_sp vm=%vm_sp
40
VCMP_dp ---- 1110 1.11 010 z:1 .... 1011 e:1 1.0 .... \
41
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/vfp_helper.c
44
+++ b/target/arm/vfp_helper.c
45
@@ -XXX,XX +XXX,XX @@ static void softfloat_to_vfp_compare(CPUARMState *env, FloatRelation cmp)
46
}
20
}
47
21
48
/* XXX: check quiet/signaling case */
22
uint32_t psw_read(CPUTriCoreState *env)
49
-#define DO_VFP_cmp(p, type) \
50
-void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
51
+#define DO_VFP_cmp(P, FLOATTYPE, ARGTYPE, FPST) \
52
+void VFP_HELPER(cmp, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \
53
{ \
54
softfloat_to_vfp_compare(env, \
55
- type ## _compare_quiet(a, b, &env->vfp.fp_status)); \
56
+ FLOATTYPE ## _compare_quiet(a, b, &env->vfp.FPST)); \
57
} \
58
-void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
59
+void VFP_HELPER(cmpe, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \
60
{ \
61
softfloat_to_vfp_compare(env, \
62
- type ## _compare(a, b, &env->vfp.fp_status)); \
63
+ FLOATTYPE ## _compare(a, b, &env->vfp.FPST)); \
64
}
65
-DO_VFP_cmp(s, float32)
66
-DO_VFP_cmp(d, float64)
67
+DO_VFP_cmp(h, float16, dh_ctype_f16, fp_status_f16)
68
+DO_VFP_cmp(s, float32, float32, fp_status)
69
+DO_VFP_cmp(d, float64, float64, fp_status)
70
#undef DO_VFP_cmp
71
72
/* Integer to float and float to integer conversions */
73
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
74
index XXXXXXX..XXXXXXX 100644
75
--- a/target/arm/translate-vfp.c.inc
76
+++ b/target/arm/translate-vfp.c.inc
77
@@ -XXX,XX +XXX,XX @@ DO_VFP_2OP(VSQRT, hp, gen_VSQRT_hp)
78
DO_VFP_2OP(VSQRT, sp, gen_VSQRT_sp)
79
DO_VFP_2OP(VSQRT, dp, gen_VSQRT_dp)
80
81
+static bool trans_VCMP_hp(DisasContext *s, arg_VCMP_sp *a)
82
+{
83
+ TCGv_i32 vd, vm;
84
+
85
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
86
+ return false;
87
+ }
88
+
89
+ /* Vm/M bits must be zero for the Z variant */
90
+ if (a->z && a->vm != 0) {
91
+ return false;
92
+ }
93
+
94
+ if (!vfp_access_check(s)) {
95
+ return true;
96
+ }
97
+
98
+ vd = tcg_temp_new_i32();
99
+ vm = tcg_temp_new_i32();
100
+
101
+ neon_load_reg32(vd, a->vd);
102
+ if (a->z) {
103
+ tcg_gen_movi_i32(vm, 0);
104
+ } else {
105
+ neon_load_reg32(vm, a->vm);
106
+ }
107
+
108
+ if (a->e) {
109
+ gen_helper_vfp_cmpeh(vd, vm, cpu_env);
110
+ } else {
111
+ gen_helper_vfp_cmph(vd, vm, cpu_env);
112
+ }
113
+
114
+ tcg_temp_free_i32(vd);
115
+ tcg_temp_free_i32(vm);
116
+
117
+ return true;
118
+}
119
+
120
static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a)
121
{
122
TCGv_i32 vd, vm;
123
--
23
--
124
2.20.1
24
2.34.1
125
126
diff view generated by jsdifflib
1
Implement VFP fp16 support for the VMOV immediate insn.
1
Now that all our targets have bene converted to explicitly specify
2
their pattern for the default NaN value we can remove the remaining
3
fallback code in parts64_default_nan().
2
4
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200828183354.27913-10-peter.maydell@linaro.org
7
Message-id: 20241202131347.498124-55-peter.maydell@linaro.org
6
---
8
---
7
target/arm/vfp.decode | 2 ++
9
fpu/softfloat-specialize.c.inc | 14 --------------
8
target/arm/translate-vfp.c.inc | 22 ++++++++++++++++++++++
10
1 file changed, 14 deletions(-)
9
2 files changed, 24 insertions(+)
10
11
11
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
12
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
12
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/vfp.decode
14
--- a/fpu/softfloat-specialize.c.inc
14
+++ b/target/arm/vfp.decode
15
+++ b/fpu/softfloat-specialize.c.inc
15
@@ -XXX,XX +XXX,XX @@ VFMS_dp ---- 1110 1.10 .... .... 1011 .1.0 .... @vfp_dnm_d
16
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
16
VFNMA_dp ---- 1110 1.01 .... .... 1011 .0.0 .... @vfp_dnm_d
17
uint64_t frac;
17
VFNMS_dp ---- 1110 1.01 .... .... 1011 .1.0 .... @vfp_dnm_d
18
uint8_t dnan_pattern = status->default_nan_pattern;
18
19
19
+VMOV_imm_hp ---- 1110 1.11 .... .... 1001 0000 .... \
20
- if (dnan_pattern == 0) {
20
+ vd=%vd_sp imm=%vmov_imm
21
- /*
21
VMOV_imm_sp ---- 1110 1.11 .... .... 1010 0000 .... \
22
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
22
vd=%vd_sp imm=%vmov_imm
23
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
23
VMOV_imm_dp ---- 1110 1.11 .... .... 1011 0000 .... \
24
- * do not have floating-point.
24
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
25
- */
25
index XXXXXXX..XXXXXXX 100644
26
- if (snan_bit_is_one(status)) {
26
--- a/target/arm/translate-vfp.c.inc
27
- /* sign bit clear, set all frac bits other than msb */
27
+++ b/target/arm/translate-vfp.c.inc
28
- dnan_pattern = 0b00111111;
28
@@ -XXX,XX +XXX,XX @@ MAKE_VFM_TRANS_FNS(hp)
29
- } else {
29
MAKE_VFM_TRANS_FNS(sp)
30
- /* sign bit clear, set frac msb */
30
MAKE_VFM_TRANS_FNS(dp)
31
- dnan_pattern = 0b01000000;
31
32
- }
32
+static bool trans_VMOV_imm_hp(DisasContext *s, arg_VMOV_imm_sp *a)
33
- }
33
+{
34
assert(dnan_pattern != 0);
34
+ TCGv_i32 fd;
35
35
+
36
sign = dnan_pattern >> 7;
36
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
37
+ return false;
38
+ }
39
+
40
+ if (s->vec_len != 0 || s->vec_stride != 0) {
41
+ return false;
42
+ }
43
+
44
+ if (!vfp_access_check(s)) {
45
+ return true;
46
+ }
47
+
48
+ fd = tcg_const_i32(vfp_expand_imm(MO_16, a->imm));
49
+ neon_store_reg32(fd, a->vd);
50
+ tcg_temp_free_i32(fd);
51
+ return true;
52
+}
53
+
54
static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
55
{
56
uint32_t delta_d = 0;
57
--
37
--
58
2.20.1
38
2.34.1
59
60
diff view generated by jsdifflib
1
Convert the Neon VRINTX insn to use gvec, and use this to implement
1
From: Richard Henderson <richard.henderson@linaro.org>
2
fp16 support for it.
3
2
3
Inline pickNaNMulAdd into its only caller. This makes
4
one assert redundant with the immediately preceding IF.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-3-richard.henderson@linaro.org
9
[PMM: keep comment from old code in new location]
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-42-peter.maydell@linaro.org
7
---
11
---
8
target/arm/helper.h | 3 +++
12
fpu/softfloat-parts.c.inc | 41 +++++++++++++++++++++++++-
9
target/arm/vec_helper.c | 3 +++
13
fpu/softfloat-specialize.c.inc | 54 ----------------------------------
10
target/arm/translate-neon.c.inc | 45 +++------------------------------
14
2 files changed, 40 insertions(+), 55 deletions(-)
11
3 files changed, 9 insertions(+), 42 deletions(-)
12
15
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
18
--- a/fpu/softfloat-parts.c.inc
16
+++ b/target/arm/helper.h
19
+++ b/fpu/softfloat-parts.c.inc
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_vcvt_rm_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
18
DEF_HELPER_FLAGS_4(gvec_vrint_rm_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
21
}
19
DEF_HELPER_FLAGS_4(gvec_vrint_rm_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
20
23
if (s->default_nan_mode) {
21
+DEF_HELPER_FLAGS_4(gvec_vrintx_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+ /*
22
+DEF_HELPER_FLAGS_4(gvec_vrintx_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+ * We guarantee not to require the target to tell us how to
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;
23
+
53
+
24
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
54
+ assert(rule != float_3nan_prop_none);
25
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
55
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
26
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
56
+ /* We have at least one SNaN input and should prefer it */
27
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
57
+ do {
58
+ which = rule & R_3NAN_1ST_MASK;
59
+ rule >>= R_3NAN_1ST_LENGTH;
60
+ } while (!is_snan(cls[which]));
61
+ } else {
62
+ do {
63
+ which = rule & R_3NAN_1ST_MASK;
64
+ rule >>= R_3NAN_1ST_LENGTH;
65
+ } while (!is_nan(cls[which]));
66
+ }
67
}
68
69
if (which == 3) {
70
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/vec_helper.c
72
--- a/fpu/softfloat-specialize.c.inc
30
+++ b/target/arm/vec_helper.c
73
+++ b/fpu/softfloat-specialize.c.inc
31
@@ -XXX,XX +XXX,XX @@ DO_2OP(gvec_frsqrte_h, helper_rsqrte_f16, float16)
74
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
32
DO_2OP(gvec_frsqrte_s, helper_rsqrte_f32, float32)
75
}
33
DO_2OP(gvec_frsqrte_d, helper_rsqrte_f64, float64)
34
35
+DO_2OP(gvec_vrintx_h, float16_round_to_int, float16)
36
+DO_2OP(gvec_vrintx_s, float32_round_to_int, float32)
37
+
38
DO_2OP(gvec_sitos, helper_vfp_sitos, int32_t)
39
DO_2OP(gvec_uitos, helper_vfp_uitos, uint32_t)
40
DO_2OP(gvec_tosizs, helper_vfp_tosizs, float32)
41
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
42
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/translate-neon.c.inc
44
+++ b/target/arm/translate-neon.c.inc
45
@@ -XXX,XX +XXX,XX @@ static bool trans_VQNEG(DisasContext *s, arg_2misc *a)
46
return do_2misc(s, a, fn[a->size]);
47
}
76
}
48
77
49
-static bool do_2misc_fp(DisasContext *s, arg_2misc *a,
78
-/*----------------------------------------------------------------------------
50
- NeonGenOneSingleOpFn *fn)
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)
51
-{
86
-{
52
- int pass;
87
- FloatClass cls[3] = { a_cls, b_cls, c_cls };
53
- TCGv_ptr fpst;
88
- Float3NaNPropRule rule = status->float_3nan_prop_rule;
89
- int which;
54
-
90
-
55
- /* Handle a 2-reg-misc operation by iterating 32 bits at a time */
91
- /*
56
- if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
92
- * We guarantee not to require the target to tell us how to
57
- return false;
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
- }
58
- }
114
- }
59
-
115
-
60
- /* UNDEF accesses to D16-D31 if they don't exist. */
116
- assert(rule != float_3nan_prop_none);
61
- if (!dc_isar_feature(aa32_simd_r32, s) &&
117
- if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
62
- ((a->vd | a->vm) & 0x10)) {
118
- /* We have at least one SNaN input and should prefer it */
63
- return false;
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]));
64
- }
128
- }
65
-
129
- return which;
66
- if (a->size != 2) {
67
- /* TODO: FP16 will be the size == 1 case */
68
- return false;
69
- }
70
-
71
- if ((a->vd | a->vm) & a->q) {
72
- return false;
73
- }
74
-
75
- if (!vfp_access_check(s)) {
76
- return true;
77
- }
78
-
79
- fpst = fpstatus_ptr(FPST_STD);
80
- for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
81
- TCGv_i32 tmp = neon_load_reg(a->vm, pass);
82
- fn(tmp, tmp, fpst);
83
- neon_store_reg(a->vd, pass, tmp);
84
- }
85
- tcg_temp_free_ptr(fpst);
86
-
87
- return true;
88
-}
130
-}
89
-
131
-
90
#define DO_2MISC_FP_VEC(INSN, HFUNC, SFUNC) \
132
/*----------------------------------------------------------------------------
91
static void gen_##INSN(unsigned vece, uint32_t rd_ofs, \
133
| Returns 1 if the double-precision floating-point value `a' is a quiet
92
uint32_t rm_ofs, \
134
| NaN; otherwise returns 0.
93
@@ -XXX,XX +XXX,XX @@ DO_2MISC_FP_VEC(VCVT_FU, gen_helper_gvec_ustoh, gen_helper_gvec_uitos)
94
DO_2MISC_FP_VEC(VCVT_SF, gen_helper_gvec_tosszh, gen_helper_gvec_tosizs)
95
DO_2MISC_FP_VEC(VCVT_UF, gen_helper_gvec_touszh, gen_helper_gvec_touizs)
96
97
+DO_2MISC_FP_VEC(VRINTX_impl, gen_helper_gvec_vrintx_h, gen_helper_gvec_vrintx_s)
98
+
99
static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
100
{
101
if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
102
return false;
103
}
104
- return do_2misc_fp(s, a, gen_helper_rints_exact);
105
+ return trans_VRINTX_impl(s, a);
106
}
107
108
#define DO_VEC_RMODE(INSN, RMODE, OP) \
109
--
135
--
110
2.20.1
136
2.34.1
111
137
112
138
diff view generated by jsdifflib
1
Convert the Neon VCVT with-specified-rounding-mode instructions
1
From: Richard Henderson <richard.henderson@linaro.org>
2
to gvec, and use this to implement fp16 support for them.
3
2
3
Remove "3" as a special case for which and simply
4
branch to return the desired value.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-4-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-40-peter.maydell@linaro.org
7
---
10
---
8
target/arm/helper.h | 5 ++
11
fpu/softfloat-parts.c.inc | 20 ++++++++++----------
9
target/arm/vec_helper.c | 23 +++++++
12
1 file changed, 10 insertions(+), 10 deletions(-)
10
target/arm/translate-neon.c.inc | 105 ++++++++++++--------------------
11
3 files changed, 66 insertions(+), 67 deletions(-)
12
13
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
16
--- a/fpu/softfloat-parts.c.inc
16
+++ b/target/arm/helper.h
17
+++ b/fpu/softfloat-parts.c.inc
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_vcvt_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
18
DEF_HELPER_FLAGS_4(gvec_vcvt_hs, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
19
* But if we're not in default-NaN mode then the target must
19
DEF_HELPER_FLAGS_4(gvec_vcvt_hu, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
20
* specify.
20
21
*/
21
+DEF_HELPER_FLAGS_4(gvec_vcvt_rm_ss, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
- which = 3;
22
+DEF_HELPER_FLAGS_4(gvec_vcvt_rm_us, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
+ goto default_nan;
23
+DEF_HELPER_FLAGS_4(gvec_vcvt_rm_sh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
} else if (infzero) {
24
+DEF_HELPER_FLAGS_4(gvec_vcvt_rm_uh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
/*
25
+
26
* Inf * 0 + NaN -- some implementations return the
26
DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
27
DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
*/
28
DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
switch (s->float_infzeronan_rule) {
29
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
30
case float_infzeronan_dnan_never:
30
index XXXXXXX..XXXXXXX 100644
31
- which = 2;
31
--- a/target/arm/vec_helper.c
32
break;
32
+++ b/target/arm/vec_helper.c
33
case float_infzeronan_dnan_always:
33
@@ -XXX,XX +XXX,XX @@ DO_VCVT_FIXED(gvec_vcvt_hs, helper_vfp_toshh_round_to_zero, uint16_t)
34
- which = 3;
34
DO_VCVT_FIXED(gvec_vcvt_hu, helper_vfp_touhh_round_to_zero, uint16_t)
35
- break;
35
36
+ goto default_nan;
36
#undef DO_VCVT_FIXED
37
case float_infzeronan_dnan_if_qnan:
37
+
38
- which = is_qnan(c->cls) ? 3 : 2;
38
+#define DO_VCVT_RMODE(NAME, FUNC, TYPE) \
39
+ if (is_qnan(c->cls)) {
39
+ void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
40
+ goto default_nan;
40
+ { \
41
+ }
41
+ float_status *fpst = stat; \
42
break;
42
+ intptr_t i, oprsz = simd_oprsz(desc); \
43
default:
43
+ uint32_t rmode = simd_data(desc); \
44
g_assert_not_reached();
44
+ uint32_t prev_rmode = get_float_rounding_mode(fpst); \
45
}
45
+ TYPE *d = vd, *n = vn; \
46
+ which = 2;
46
+ set_float_rounding_mode(rmode, fpst); \
47
} else {
47
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
48
FloatClass cls[3] = { a->cls, b->cls, c->cls };
48
+ d[i] = FUNC(n[i], 0, fpst); \
49
Float3NaNPropRule rule = s->float_3nan_prop_rule;
49
+ } \
50
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
50
+ set_float_rounding_mode(prev_rmode, fpst); \
51
}
51
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
52
+ }
53
+
54
+DO_VCVT_RMODE(gvec_vcvt_rm_ss, helper_vfp_tosls, uint32_t)
55
+DO_VCVT_RMODE(gvec_vcvt_rm_us, helper_vfp_touls, uint32_t)
56
+DO_VCVT_RMODE(gvec_vcvt_rm_sh, helper_vfp_toshh, uint16_t)
57
+DO_VCVT_RMODE(gvec_vcvt_rm_uh, helper_vfp_touhh, uint16_t)
58
+
59
+#undef DO_VCVT_RMODE
60
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/translate-neon.c.inc
63
+++ b/target/arm/translate-neon.c.inc
64
@@ -XXX,XX +XXX,XX @@ DO_VRINT(VRINTZ, FPROUNDING_ZERO)
65
DO_VRINT(VRINTM, FPROUNDING_NEGINF)
66
DO_VRINT(VRINTP, FPROUNDING_POSINF)
67
68
-static bool do_vcvt(DisasContext *s, arg_2misc *a, int rmode, bool is_signed)
69
-{
70
- /*
71
- * Handle a VCVT* operation by iterating 32 bits at a time,
72
- * with a specified rounding mode in operation.
73
- */
74
- int pass;
75
- TCGv_ptr fpst;
76
- TCGv_i32 tcg_rmode, tcg_shift;
77
-
78
- if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
79
- !arm_dc_feature(s, ARM_FEATURE_V8)) {
80
- return false;
81
+#define DO_VEC_RMODE(INSN, RMODE, OP) \
82
+ static void gen_##INSN(unsigned vece, uint32_t rd_ofs, \
83
+ uint32_t rm_ofs, \
84
+ uint32_t oprsz, uint32_t maxsz) \
85
+ { \
86
+ static gen_helper_gvec_2_ptr * const fns[4] = { \
87
+ NULL, \
88
+ gen_helper_gvec_##OP##h, \
89
+ gen_helper_gvec_##OP##s, \
90
+ NULL, \
91
+ }; \
92
+ TCGv_ptr fpst; \
93
+ fpst = fpstatus_ptr(vece == 1 ? FPST_STD_F16 : FPST_STD); \
94
+ tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, oprsz, maxsz, \
95
+ arm_rmode_to_sf(RMODE), fns[vece]); \
96
+ tcg_temp_free_ptr(fpst); \
97
+ } \
98
+ static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
99
+ { \
100
+ if (!arm_dc_feature(s, ARM_FEATURE_V8)) { \
101
+ return false; \
102
+ } \
103
+ if (a->size == MO_16) { \
104
+ if (!dc_isar_feature(aa32_fp16_arith, s)) { \
105
+ return false; \
106
+ } \
107
+ } else if (a->size != MO_32) { \
108
+ return false; \
109
+ } \
110
+ return do_2misc_vec(s, a, gen_##INSN); \
111
}
52
}
112
53
113
- /* UNDEF accesses to D16-D31 if they don't exist. */
54
- if (which == 3) {
114
- if (!dc_isar_feature(aa32_simd_r32, s) &&
55
- parts_default_nan(a, s);
115
- ((a->vd | a->vm) & 0x10)) {
56
- return a;
116
- return false;
117
- }
57
- }
118
-
58
-
119
- if (a->size != 2) {
59
switch (which) {
120
- /* TODO: FP16 will be the size == 1 case */
60
case 0:
121
- return false;
61
break;
122
- }
62
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
123
-
63
parts_silence_nan(a, s);
124
- if ((a->vd | a->vm) & a->q) {
64
}
125
- return false;
65
return a;
126
- }
66
+
127
-
67
+ default_nan:
128
- if (!vfp_access_check(s)) {
68
+ parts_default_nan(a, s);
129
- return true;
69
+ return a;
130
- }
70
}
131
-
71
132
- fpst = fpstatus_ptr(FPST_STD);
72
/*
133
- tcg_shift = tcg_const_i32(0);
134
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
135
- gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
136
- for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
137
- TCGv_i32 tmp = neon_load_reg(a->vm, pass);
138
- if (is_signed) {
139
- gen_helper_vfp_tosls(tmp, tmp, tcg_shift, fpst);
140
- } else {
141
- gen_helper_vfp_touls(tmp, tmp, tcg_shift, fpst);
142
- }
143
- neon_store_reg(a->vd, pass, tmp);
144
- }
145
- gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
146
- tcg_temp_free_i32(tcg_rmode);
147
- tcg_temp_free_i32(tcg_shift);
148
- tcg_temp_free_ptr(fpst);
149
-
150
- return true;
151
-}
152
-
153
-#define DO_VCVT(INSN, RMODE, SIGNED) \
154
- static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
155
- { \
156
- return do_vcvt(s, a, RMODE, SIGNED); \
157
- }
158
-
159
-DO_VCVT(VCVTAU, FPROUNDING_TIEAWAY, false)
160
-DO_VCVT(VCVTAS, FPROUNDING_TIEAWAY, true)
161
-DO_VCVT(VCVTNU, FPROUNDING_TIEEVEN, false)
162
-DO_VCVT(VCVTNS, FPROUNDING_TIEEVEN, true)
163
-DO_VCVT(VCVTPU, FPROUNDING_POSINF, false)
164
-DO_VCVT(VCVTPS, FPROUNDING_POSINF, true)
165
-DO_VCVT(VCVTMU, FPROUNDING_NEGINF, false)
166
-DO_VCVT(VCVTMS, FPROUNDING_NEGINF, true)
167
+DO_VEC_RMODE(VCVTAU, FPROUNDING_TIEAWAY, vcvt_rm_u)
168
+DO_VEC_RMODE(VCVTAS, FPROUNDING_TIEAWAY, vcvt_rm_s)
169
+DO_VEC_RMODE(VCVTNU, FPROUNDING_TIEEVEN, vcvt_rm_u)
170
+DO_VEC_RMODE(VCVTNS, FPROUNDING_TIEEVEN, vcvt_rm_s)
171
+DO_VEC_RMODE(VCVTPU, FPROUNDING_POSINF, vcvt_rm_u)
172
+DO_VEC_RMODE(VCVTPS, FPROUNDING_POSINF, vcvt_rm_s)
173
+DO_VEC_RMODE(VCVTMU, FPROUNDING_NEGINF, vcvt_rm_u)
174
+DO_VEC_RMODE(VCVTMS, FPROUNDING_NEGINF, vcvt_rm_s)
175
176
static bool trans_VSWP(DisasContext *s, arg_2misc *a)
177
{
178
--
73
--
179
2.20.1
74
2.34.1
180
75
181
76
diff view generated by jsdifflib
1
We already have gvec helpers for floating point VRECPE and
1
From: Richard Henderson <richard.henderson@linaro.org>
2
VRQSRTE, so convert the Neon decoder to use them and
3
add the fp16 support.
4
2
3
Assign the pointer return value to 'a' directly,
4
rather than going through an intermediary index.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-5-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200828183354.27913-25-peter.maydell@linaro.org
8
---
10
---
9
target/arm/translate-neon.c.inc | 31 +++++++++++++++++++++++++++++--
11
fpu/softfloat-parts.c.inc | 32 ++++++++++----------------------
10
1 file changed, 29 insertions(+), 2 deletions(-)
12
1 file changed, 10 insertions(+), 22 deletions(-)
11
13
12
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-neon.c.inc
16
--- a/fpu/softfloat-parts.c.inc
15
+++ b/target/arm/translate-neon.c.inc
17
+++ b/fpu/softfloat-parts.c.inc
16
@@ -XXX,XX +XXX,XX @@ static bool do_2misc_fp(DisasContext *s, arg_2misc *a,
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
17
return do_2misc_fp(s, a, FUNC); \
19
FloatPartsN *c, float_status *s,
20
int ab_mask, int abc_mask)
21
{
22
- int which;
23
bool infzero = (ab_mask == float_cmask_infzero);
24
bool have_snan = (abc_mask & float_cmask_snan);
25
+ FloatPartsN *ret;
26
27
if (unlikely(have_snan)) {
28
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
30
default:
31
g_assert_not_reached();
32
}
33
- which = 2;
34
+ ret = c;
35
} else {
36
- FloatClass cls[3] = { a->cls, b->cls, c->cls };
37
+ FloatPartsN *val[3] = { a, b, c };
38
Float3NaNPropRule rule = s->float_3nan_prop_rule;
39
40
assert(rule != float_3nan_prop_none);
41
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
42
/* We have at least one SNaN input and should prefer it */
43
do {
44
- which = rule & R_3NAN_1ST_MASK;
45
+ ret = val[rule & R_3NAN_1ST_MASK];
46
rule >>= R_3NAN_1ST_LENGTH;
47
- } while (!is_snan(cls[which]));
48
+ } while (!is_snan(ret->cls));
49
} else {
50
do {
51
- which = rule & R_3NAN_1ST_MASK;
52
+ ret = val[rule & R_3NAN_1ST_MASK];
53
rule >>= R_3NAN_1ST_LENGTH;
54
- } while (!is_nan(cls[which]));
55
+ } while (!is_nan(ret->cls));
56
}
18
}
57
}
19
58
20
-DO_2MISC_FP(VRECPE_F, gen_helper_recpe_f32)
59
- switch (which) {
21
-DO_2MISC_FP(VRSQRTE_F, gen_helper_rsqrte_f32)
60
- case 0:
22
DO_2MISC_FP(VCVT_FS, gen_helper_vfp_sitos)
61
- break;
23
DO_2MISC_FP(VCVT_FU, gen_helper_vfp_uitos)
62
- case 1:
24
DO_2MISC_FP(VCVT_SF, gen_helper_vfp_tosizs)
63
- a = b;
25
DO_2MISC_FP(VCVT_UF, gen_helper_vfp_touizs)
64
- break;
26
65
- case 2:
27
+#define DO_2MISC_FP_VEC(INSN, HFUNC, SFUNC) \
66
- a = c;
28
+ static void gen_##INSN(unsigned vece, uint32_t rd_ofs, \
67
- break;
29
+ uint32_t rm_ofs, \
68
- default:
30
+ uint32_t oprsz, uint32_t maxsz) \
69
- g_assert_not_reached();
31
+ { \
70
+ if (is_snan(ret->cls)) {
32
+ static gen_helper_gvec_2_ptr * const fns[4] = { \
71
+ parts_silence_nan(ret, s);
33
+ NULL, HFUNC, SFUNC, NULL, \
72
}
34
+ }; \
73
- if (is_snan(a->cls)) {
35
+ TCGv_ptr fpst; \
74
- parts_silence_nan(a, s);
36
+ fpst = fpstatus_ptr(vece == MO_16 ? FPST_STD_F16 : FPST_STD); \
75
- }
37
+ tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, oprsz, maxsz, 0, \
76
- return a;
38
+ fns[vece]); \
77
+ return ret;
39
+ tcg_temp_free_ptr(fpst); \
78
40
+ } \
79
default_nan:
41
+ static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
80
parts_default_nan(a, s);
42
+ { \
43
+ if (a->size == MO_16) { \
44
+ if (!dc_isar_feature(aa32_fp16_arith, s)) { \
45
+ return false; \
46
+ } \
47
+ } else if (a->size != MO_32) { \
48
+ return false; \
49
+ } \
50
+ return do_2misc_vec(s, a, gen_##INSN); \
51
+ }
52
+
53
+DO_2MISC_FP_VEC(VRECPE_F, gen_helper_gvec_frecpe_h, gen_helper_gvec_frecpe_s)
54
+DO_2MISC_FP_VEC(VRSQRTE_F, gen_helper_gvec_frsqrte_h, gen_helper_gvec_frsqrte_s)
55
+
56
static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
57
{
58
if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
59
--
81
--
60
2.20.1
82
2.34.1
61
83
62
84
diff view generated by jsdifflib
1
From: Graeme Gregory <graeme@nuviainc.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add the previously created sbsa-ec device to the sbsa-ref machine in
3
While all indices into val[] should be in [0-2], the mask
4
secure memory so the PSCI implementation in ARM-TF can access it, but
4
applied is two bits. To help static analysis see there is
5
not expose it to non secure firmware or OS except by via ARM-TF.
5
no possibility of read beyond the end of the array, pad the
6
array to 4 entries, with the final being (implicitly) NULL.
6
7
7
Signed-off-by: Graeme Gregory <graeme@nuviainc.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Tested-by: Leif Lindholm <leif@nuviainc.com>
10
Message-id: 20241203203949.483774-6-richard.henderson@linaro.org
10
Message-id: 20200826141952.136164-3-graeme@nuviainc.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
12
---
14
hw/arm/sbsa-ref.c | 14 ++++++++++++++
13
fpu/softfloat-parts.c.inc | 2 +-
15
1 file changed, 14 insertions(+)
14
1 file changed, 1 insertion(+), 1 deletion(-)
16
15
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/sbsa-ref.c
18
--- a/fpu/softfloat-parts.c.inc
20
+++ b/hw/arm/sbsa-ref.c
19
+++ b/fpu/softfloat-parts.c.inc
21
@@ -XXX,XX +XXX,XX @@ enum {
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
22
SBSA_CPUPERIPHS,
21
}
23
SBSA_GIC_DIST,
22
ret = c;
24
SBSA_GIC_REDIST,
23
} else {
25
+ SBSA_SECURE_EC,
24
- FloatPartsN *val[3] = { a, b, c };
26
SBSA_SMMU,
25
+ FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
27
SBSA_UART,
26
Float3NaNPropRule rule = s->float_3nan_prop_rule;
28
SBSA_RTC,
27
29
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry sbsa_ref_memmap[] = {
28
assert(rule != float_3nan_prop_none);
30
[SBSA_CPUPERIPHS] = { 0x40000000, 0x00040000 },
31
[SBSA_GIC_DIST] = { 0x40060000, 0x00010000 },
32
[SBSA_GIC_REDIST] = { 0x40080000, 0x04000000 },
33
+ [SBSA_SECURE_EC] = { 0x50000000, 0x00001000 },
34
[SBSA_UART] = { 0x60000000, 0x00001000 },
35
[SBSA_RTC] = { 0x60010000, 0x00001000 },
36
[SBSA_GPIO] = { 0x60020000, 0x00001000 },
37
@@ -XXX,XX +XXX,XX @@ static void *sbsa_ref_dtb(const struct arm_boot_info *binfo, int *fdt_size)
38
return board->fdt;
39
}
40
41
+static void create_secure_ec(MemoryRegion *mem)
42
+{
43
+ hwaddr base = sbsa_ref_memmap[SBSA_SECURE_EC].base;
44
+ DeviceState *dev = qdev_new("sbsa-ec");
45
+ SysBusDevice *s = SYS_BUS_DEVICE(dev);
46
+
47
+ memory_region_add_subregion(mem, base,
48
+ sysbus_mmio_get_region(s, 0));
49
+}
50
+
51
static void sbsa_ref_init(MachineState *machine)
52
{
53
unsigned int smp_cpus = machine->smp.cpus;
54
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
55
56
create_pcie(sms);
57
58
+ create_secure_ec(secure_sysmem);
59
+
60
sms->bootinfo.ram_size = machine->ram_size;
61
sms->bootinfo.nb_cpus = smp_cpus;
62
sms->bootinfo.board_id = -1;
63
--
29
--
64
2.20.1
30
2.34.1
65
31
66
32
diff view generated by jsdifflib
1
Implmeent VFP fp16 support for simple binary-operator VFP insns VADD,
1
From: Richard Henderson <richard.henderson@linaro.org>
2
VSUB, VMUL, VDIV, VMINNM and VMAXNM:
3
2
4
* make the VFP_BINOP() macro generate float16 helpers as well as
3
This function is part of the public interface and
5
float32 and float64
4
is not "specialized" to any target in any way.
6
* implement a do_vfp_3op_hp() function similar to the existing
7
do_vfp_3op_sp()
8
* add decode for the half-precision insn patterns
9
5
10
Note that the VFP_BINOP macro use creates a couple of unused helper
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
functions vfp_maxh and vfp_minh, but they're small so it's not worth
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
splitting the BINOP operations into "needs halfprec" and "no
8
Message-id: 20241203203949.483774-7-richard.henderson@linaro.org
13
halfprec" groups.
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++++++++
12
fpu/softfloat-specialize.c.inc | 52 ----------------------------------
13
2 files changed, 52 insertions(+), 52 deletions(-)
14
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20200828183354.27913-4-peter.maydell@linaro.org
18
---
19
target/arm/helper.h | 8 ++++
20
target/arm/vfp-uncond.decode | 3 ++
21
target/arm/vfp.decode | 4 ++
22
target/arm/vfp_helper.c | 5 ++
23
target/arm/translate-vfp.c.inc | 86 ++++++++++++++++++++++++++++++++++
24
5 files changed, 106 insertions(+)
25
26
diff --git a/target/arm/helper.h b/target/arm/helper.h
27
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/helper.h
17
--- a/fpu/softfloat.c
29
+++ b/target/arm/helper.h
18
+++ b/fpu/softfloat.c
30
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(probe_access, TCG_CALL_NO_WG, void, env, tl, i32, i32, i32)
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
31
DEF_HELPER_1(vfp_get_fpscr, i32, env)
20
*zExpPtr = 1 - shiftCount;
32
DEF_HELPER_2(vfp_set_fpscr, void, env, i32)
21
}
33
22
34
+DEF_HELPER_3(vfp_addh, f16, f16, f16, ptr)
23
+/*----------------------------------------------------------------------------
35
DEF_HELPER_3(vfp_adds, f32, f32, f32, ptr)
24
+| Takes two extended double-precision floating-point values `a' and `b', one
36
DEF_HELPER_3(vfp_addd, f64, f64, f64, ptr)
25
+| of which is a NaN, and returns the appropriate NaN result. If either `a' or
37
+DEF_HELPER_3(vfp_subh, f16, f16, f16, ptr)
26
+| `b' is a signaling NaN, the invalid exception is raised.
38
DEF_HELPER_3(vfp_subs, f32, f32, f32, ptr)
27
+*----------------------------------------------------------------------------*/
39
DEF_HELPER_3(vfp_subd, f64, f64, f64, ptr)
40
+DEF_HELPER_3(vfp_mulh, f16, f16, f16, ptr)
41
DEF_HELPER_3(vfp_muls, f32, f32, f32, ptr)
42
DEF_HELPER_3(vfp_muld, f64, f64, f64, ptr)
43
+DEF_HELPER_3(vfp_divh, f16, f16, f16, ptr)
44
DEF_HELPER_3(vfp_divs, f32, f32, f32, ptr)
45
DEF_HELPER_3(vfp_divd, f64, f64, f64, ptr)
46
+DEF_HELPER_3(vfp_maxh, f16, f16, f16, ptr)
47
DEF_HELPER_3(vfp_maxs, f32, f32, f32, ptr)
48
DEF_HELPER_3(vfp_maxd, f64, f64, f64, ptr)
49
+DEF_HELPER_3(vfp_minh, f16, f16, f16, ptr)
50
DEF_HELPER_3(vfp_mins, f32, f32, f32, ptr)
51
DEF_HELPER_3(vfp_mind, f64, f64, f64, ptr)
52
+DEF_HELPER_3(vfp_maxnumh, f16, f16, f16, ptr)
53
DEF_HELPER_3(vfp_maxnums, f32, f32, f32, ptr)
54
DEF_HELPER_3(vfp_maxnumd, f64, f64, f64, ptr)
55
+DEF_HELPER_3(vfp_minnumh, f16, f16, f16, ptr)
56
DEF_HELPER_3(vfp_minnums, f32, f32, f32, ptr)
57
DEF_HELPER_3(vfp_minnumd, f64, f64, f64, ptr)
58
DEF_HELPER_1(vfp_negs, f32, f32)
59
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/vfp-uncond.decode
62
+++ b/target/arm/vfp-uncond.decode
63
@@ -XXX,XX +XXX,XX @@ VSEL 1111 1110 0. cc:2 .... .... 1010 .0.0 .... \
64
VSEL 1111 1110 0. cc:2 .... .... 1011 .0.0 .... \
65
vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
66
67
+VMAXNM_hp 1111 1110 1.00 .... .... 1001 .0.0 .... @vfp_dnm_s
68
+VMINNM_hp 1111 1110 1.00 .... .... 1001 .1.0 .... @vfp_dnm_s
69
+
28
+
70
VMAXNM_sp 1111 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
29
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
71
VMINNM_sp 1111 1110 1.00 .... .... 1010 .1.0 .... @vfp_dnm_s
72
73
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
74
index XXXXXXX..XXXXXXX 100644
75
--- a/target/arm/vfp.decode
76
+++ b/target/arm/vfp.decode
77
@@ -XXX,XX +XXX,XX @@ VNMLS_dp ---- 1110 0.01 .... .... 1011 .0.0 .... @vfp_dnm_d
78
VNMLA_sp ---- 1110 0.01 .... .... 1010 .1.0 .... @vfp_dnm_s
79
VNMLA_dp ---- 1110 0.01 .... .... 1011 .1.0 .... @vfp_dnm_d
80
81
+VMUL_hp ---- 1110 0.10 .... .... 1001 .0.0 .... @vfp_dnm_s
82
VMUL_sp ---- 1110 0.10 .... .... 1010 .0.0 .... @vfp_dnm_s
83
VMUL_dp ---- 1110 0.10 .... .... 1011 .0.0 .... @vfp_dnm_d
84
85
VNMUL_sp ---- 1110 0.10 .... .... 1010 .1.0 .... @vfp_dnm_s
86
VNMUL_dp ---- 1110 0.10 .... .... 1011 .1.0 .... @vfp_dnm_d
87
88
+VADD_hp ---- 1110 0.11 .... .... 1001 .0.0 .... @vfp_dnm_s
89
VADD_sp ---- 1110 0.11 .... .... 1010 .0.0 .... @vfp_dnm_s
90
VADD_dp ---- 1110 0.11 .... .... 1011 .0.0 .... @vfp_dnm_d
91
92
+VSUB_hp ---- 1110 0.11 .... .... 1001 .1.0 .... @vfp_dnm_s
93
VSUB_sp ---- 1110 0.11 .... .... 1010 .1.0 .... @vfp_dnm_s
94
VSUB_dp ---- 1110 0.11 .... .... 1011 .1.0 .... @vfp_dnm_d
95
96
+VDIV_hp ---- 1110 1.00 .... .... 1001 .0.0 .... @vfp_dnm_s
97
VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
98
VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
99
100
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/target/arm/vfp_helper.c
103
+++ b/target/arm/vfp_helper.c
104
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val)
105
#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
106
107
#define VFP_BINOP(name) \
108
+dh_ctype_f16 VFP_HELPER(name, h)(dh_ctype_f16 a, dh_ctype_f16 b, void *fpstp) \
109
+{ \
110
+ float_status *fpst = fpstp; \
111
+ return float16_ ## name(a, b, fpst); \
112
+} \
113
float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
114
{ \
115
float_status *fpst = fpstp; \
116
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
117
index XXXXXXX..XXXXXXX 100644
118
--- a/target/arm/translate-vfp.c.inc
119
+++ b/target/arm/translate-vfp.c.inc
120
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn,
121
return true;
122
}
123
124
+static bool do_vfp_3op_hp(DisasContext *s, VFPGen3OpSPFn *fn,
125
+ int vd, int vn, int vm, bool reads_vd)
126
+{
30
+{
127
+ /*
31
+ bool aIsLargerSignificand;
128
+ * Do a half-precision operation. Functionally this is
32
+ FloatClass a_cls, b_cls;
129
+ * the same as do_vfp_3op_sp(), except:
130
+ * - it uses the FPST_FPCR_F16
131
+ * - it doesn't need the VFP vector handling (fp16 is a
132
+ * v8 feature, and in v8 VFP vectors don't exist)
133
+ * - it does the aa32_fp16_arith feature test
134
+ */
135
+ TCGv_i32 f0, f1, fd;
136
+ TCGv_ptr fpst;
137
+
33
+
138
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
34
+ /* This is not complete, but is good enough for pickNaN. */
139
+ return false;
35
+ a_cls = (!floatx80_is_any_nan(a)
36
+ ? float_class_normal
37
+ : floatx80_is_signaling_nan(a, status)
38
+ ? float_class_snan
39
+ : float_class_qnan);
40
+ b_cls = (!floatx80_is_any_nan(b)
41
+ ? float_class_normal
42
+ : floatx80_is_signaling_nan(b, status)
43
+ ? float_class_snan
44
+ : float_class_qnan);
45
+
46
+ if (is_snan(a_cls) || is_snan(b_cls)) {
47
+ float_raise(float_flag_invalid, status);
140
+ }
48
+ }
141
+
49
+
142
+ if (s->vec_len != 0 || s->vec_stride != 0) {
50
+ if (status->default_nan_mode) {
143
+ return false;
51
+ return floatx80_default_nan(status);
144
+ }
52
+ }
145
+
53
+
146
+ if (!vfp_access_check(s)) {
54
+ if (a.low < b.low) {
147
+ return true;
55
+ aIsLargerSignificand = 0;
56
+ } else if (b.low < a.low) {
57
+ aIsLargerSignificand = 1;
58
+ } else {
59
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
148
+ }
60
+ }
149
+
61
+
150
+ f0 = tcg_temp_new_i32();
62
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
151
+ f1 = tcg_temp_new_i32();
63
+ if (is_snan(b_cls)) {
152
+ fd = tcg_temp_new_i32();
64
+ return floatx80_silence_nan(b, status);
153
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
65
+ }
154
+
66
+ return b;
155
+ neon_load_reg32(f0, vn);
67
+ } else {
156
+ neon_load_reg32(f1, vm);
68
+ if (is_snan(a_cls)) {
157
+
69
+ return floatx80_silence_nan(a, status);
158
+ if (reads_vd) {
70
+ }
159
+ neon_load_reg32(fd, vd);
71
+ return a;
160
+ }
72
+ }
161
+ fn(fd, f0, f1, fpst);
162
+ neon_store_reg32(fd, vd);
163
+
164
+ tcg_temp_free_i32(f0);
165
+ tcg_temp_free_i32(f1);
166
+ tcg_temp_free_i32(fd);
167
+ tcg_temp_free_ptr(fpst);
168
+
169
+ return true;
170
+}
73
+}
171
+
74
+
172
static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
75
/*----------------------------------------------------------------------------
173
int vd, int vn, int vm, bool reads_vd)
76
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
174
{
77
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
175
@@ -XXX,XX +XXX,XX @@ static bool trans_VNMLA_dp(DisasContext *s, arg_VNMLA_dp *a)
78
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
176
return do_vfp_3op_dp(s, gen_VNMLA_dp, a->vd, a->vn, a->vm, true);
79
index XXXXXXX..XXXXXXX 100644
80
--- a/fpu/softfloat-specialize.c.inc
81
+++ b/fpu/softfloat-specialize.c.inc
82
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
83
return a;
177
}
84
}
178
85
179
+static bool trans_VMUL_hp(DisasContext *s, arg_VMUL_sp *a)
86
-/*----------------------------------------------------------------------------
180
+{
87
-| Takes two extended double-precision floating-point values `a' and `b', one
181
+ return do_vfp_3op_hp(s, gen_helper_vfp_mulh, a->vd, a->vn, a->vm, false);
88
-| of which is a NaN, and returns the appropriate NaN result. If either `a' or
182
+}
89
-| `b' is a signaling NaN, the invalid exception is raised.
183
+
90
-*----------------------------------------------------------------------------*/
184
static bool trans_VMUL_sp(DisasContext *s, arg_VMUL_sp *a)
91
-
185
{
92
-floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
186
return do_vfp_3op_sp(s, gen_helper_vfp_muls, a->vd, a->vn, a->vm, false);
93
-{
187
@@ -XXX,XX +XXX,XX @@ static bool trans_VNMUL_dp(DisasContext *s, arg_VNMUL_dp *a)
94
- bool aIsLargerSignificand;
188
return do_vfp_3op_dp(s, gen_VNMUL_dp, a->vd, a->vn, a->vm, false);
95
- FloatClass a_cls, b_cls;
189
}
96
-
190
97
- /* This is not complete, but is good enough for pickNaN. */
191
+static bool trans_VADD_hp(DisasContext *s, arg_VADD_sp *a)
98
- a_cls = (!floatx80_is_any_nan(a)
192
+{
99
- ? float_class_normal
193
+ return do_vfp_3op_hp(s, gen_helper_vfp_addh, a->vd, a->vn, a->vm, false);
100
- : floatx80_is_signaling_nan(a, status)
194
+}
101
- ? float_class_snan
195
+
102
- : float_class_qnan);
196
static bool trans_VADD_sp(DisasContext *s, arg_VADD_sp *a)
103
- b_cls = (!floatx80_is_any_nan(b)
197
{
104
- ? float_class_normal
198
return do_vfp_3op_sp(s, gen_helper_vfp_adds, a->vd, a->vn, a->vm, false);
105
- : floatx80_is_signaling_nan(b, status)
199
@@ -XXX,XX +XXX,XX @@ static bool trans_VADD_dp(DisasContext *s, arg_VADD_dp *a)
106
- ? float_class_snan
200
return do_vfp_3op_dp(s, gen_helper_vfp_addd, a->vd, a->vn, a->vm, false);
107
- : float_class_qnan);
201
}
108
-
202
109
- if (is_snan(a_cls) || is_snan(b_cls)) {
203
+static bool trans_VSUB_hp(DisasContext *s, arg_VSUB_sp *a)
110
- float_raise(float_flag_invalid, status);
204
+{
111
- }
205
+ return do_vfp_3op_hp(s, gen_helper_vfp_subh, a->vd, a->vn, a->vm, false);
112
-
206
+}
113
- if (status->default_nan_mode) {
207
+
114
- return floatx80_default_nan(status);
208
static bool trans_VSUB_sp(DisasContext *s, arg_VSUB_sp *a)
115
- }
209
{
116
-
210
return do_vfp_3op_sp(s, gen_helper_vfp_subs, a->vd, a->vn, a->vm, false);
117
- if (a.low < b.low) {
211
@@ -XXX,XX +XXX,XX @@ static bool trans_VSUB_dp(DisasContext *s, arg_VSUB_dp *a)
118
- aIsLargerSignificand = 0;
212
return do_vfp_3op_dp(s, gen_helper_vfp_subd, a->vd, a->vn, a->vm, false);
119
- } else if (b.low < a.low) {
213
}
120
- aIsLargerSignificand = 1;
214
121
- } else {
215
+static bool trans_VDIV_hp(DisasContext *s, arg_VDIV_sp *a)
122
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
216
+{
123
- }
217
+ return do_vfp_3op_hp(s, gen_helper_vfp_divh, a->vd, a->vn, a->vm, false);
124
-
218
+}
125
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
219
+
126
- if (is_snan(b_cls)) {
220
static bool trans_VDIV_sp(DisasContext *s, arg_VDIV_sp *a)
127
- return floatx80_silence_nan(b, status);
221
{
128
- }
222
return do_vfp_3op_sp(s, gen_helper_vfp_divs, a->vd, a->vn, a->vm, false);
129
- return b;
223
@@ -XXX,XX +XXX,XX @@ static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_dp *a)
130
- } else {
224
return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false);
131
- if (is_snan(a_cls)) {
225
}
132
- return floatx80_silence_nan(a, status);
226
133
- }
227
+static bool trans_VMINNM_hp(DisasContext *s, arg_VMINNM_sp *a)
134
- return a;
228
+{
135
- }
229
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
136
-}
230
+ return false;
137
-
231
+ }
138
/*----------------------------------------------------------------------------
232
+ return do_vfp_3op_hp(s, gen_helper_vfp_minnumh,
139
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
233
+ a->vd, a->vn, a->vm, false);
140
| NaN; otherwise returns 0.
234
+}
235
+
236
+static bool trans_VMAXNM_hp(DisasContext *s, arg_VMAXNM_sp *a)
237
+{
238
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
239
+ return false;
240
+ }
241
+ return do_vfp_3op_hp(s, gen_helper_vfp_maxnumh,
242
+ a->vd, a->vn, a->vm, false);
243
+}
244
+
245
static bool trans_VMINNM_sp(DisasContext *s, arg_VMINNM_sp *a)
246
{
247
if (!dc_isar_feature(aa32_vminmaxnm, s)) {
248
--
141
--
249
2.20.1
142
2.34.1
250
251
diff view generated by jsdifflib
1
Convert the neon floating-point vector operations VFMA and VFMS
1
From: Richard Henderson <richard.henderson@linaro.org>
2
to use a gvec helper, and use this to implement the fp16 case.
3
2
4
This is the last use of do_3same_fp() so we can now delete
3
Unpacking and repacking the parts may be slightly more work
5
that function.
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
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241203203949.483774-8-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20200828183354.27913-32-peter.maydell@linaro.org
10
---
11
---
11
target/arm/helper.h | 6 +++
12
fpu/softfloat.c | 43 +++++--------------------------------------
12
target/arm/vec_helper.c | 33 +++++++++++-
13
1 file changed, 5 insertions(+), 38 deletions(-)
13
target/arm/translate-neon.c.inc | 92 +--------------------------------
14
3 files changed, 40 insertions(+), 91 deletions(-)
15
14
16
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.h
17
--- a/fpu/softfloat.c
19
+++ b/target/arm/helper.h
18
+++ b/fpu/softfloat.c
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmla_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
21
DEF_HELPER_FLAGS_5(gvec_fmls_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
22
DEF_HELPER_FLAGS_5(gvec_fmls_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
23
22
{
24
+DEF_HELPER_FLAGS_5(gvec_vfma_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
23
- bool aIsLargerSignificand;
25
+DEF_HELPER_FLAGS_5(gvec_vfma_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
- FloatClass a_cls, b_cls;
26
+
25
+ FloatParts128 pa, pb, *pr;
27
+DEF_HELPER_FLAGS_5(gvec_vfms_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
26
28
+DEF_HELPER_FLAGS_5(gvec_vfms_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
- /* This is not complete, but is good enough for pickNaN. */
29
+
28
- a_cls = (!floatx80_is_any_nan(a)
30
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
29
- ? float_class_normal
31
void, ptr, ptr, ptr, ptr, i32)
30
- : floatx80_is_signaling_nan(a, status)
32
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
31
- ? float_class_snan
33
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
32
- : float_class_qnan);
34
index XXXXXXX..XXXXXXX 100644
33
- b_cls = (!floatx80_is_any_nan(b)
35
--- a/target/arm/vec_helper.c
34
- ? float_class_normal
36
+++ b/target/arm/vec_helper.c
35
- : floatx80_is_signaling_nan(b, status)
37
@@ -XXX,XX +XXX,XX @@ static float32 float32_mulsub_nf(float32 dest, float32 op1, float32 op2,
36
- ? float_class_snan
38
return float32_sub(dest, float32_mul(op1, op2, stat), stat);
37
- : float_class_qnan);
39
}
40
41
-#define DO_MULADD(NAME, FUNC, TYPE) \
42
+/* Fused versions; these have the semantics Neon VFMA/VFMS want */
43
+static float16 float16_muladd_f(float16 dest, float16 op1, float16 op2,
44
+ float_status *stat)
45
+{
46
+ return float16_muladd(op1, op2, dest, 0, stat);
47
+}
48
+
49
+static float32 float32_muladd_f(float32 dest, float32 op1, float32 op2,
50
+ float_status *stat)
51
+{
52
+ return float32_muladd(op1, op2, dest, 0, stat);
53
+}
54
+
55
+static float16 float16_mulsub_f(float16 dest, float16 op1, float16 op2,
56
+ float_status *stat)
57
+{
58
+ return float16_muladd(float16_chs(op1), op2, dest, 0, stat);
59
+}
60
+
61
+static float32 float32_mulsub_f(float32 dest, float32 op1, float32 op2,
62
+ float_status *stat)
63
+{
64
+ return float32_muladd(float32_chs(op1), op2, dest, 0, stat);
65
+}
66
+
67
+#define DO_MULADD(NAME, FUNC, TYPE) \
68
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
69
{ \
70
intptr_t i, oprsz = simd_oprsz(desc); \
71
@@ -XXX,XX +XXX,XX @@ DO_MULADD(gvec_fmla_s, float32_muladd_nf, float32)
72
DO_MULADD(gvec_fmls_h, float16_mulsub_nf, float16)
73
DO_MULADD(gvec_fmls_s, float32_mulsub_nf, float32)
74
75
+DO_MULADD(gvec_vfma_h, float16_muladd_f, float16)
76
+DO_MULADD(gvec_vfma_s, float32_muladd_f, float32)
77
+
78
+DO_MULADD(gvec_vfms_h, float16_mulsub_f, float16)
79
+DO_MULADD(gvec_vfms_s, float32_mulsub_f, float32)
80
+
81
/* For the indexed ops, SVE applies the index per 128-bit vector segment.
82
* For AdvSIMD, there is of course only one such vector segment.
83
*/
84
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/translate-neon.c.inc
87
+++ b/target/arm/translate-neon.c.inc
88
@@ -XXX,XX +XXX,XX @@ DO_3SAME_PAIR(VPADD, padd_u)
89
DO_3SAME_VQDMULH(VQDMULH, qdmulh)
90
DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
91
92
-static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn,
93
- bool reads_vd)
94
-{
95
- /*
96
- * FP operations handled elementwise 32 bits at a time.
97
- * If reads_vd is true then the old value of Vd will be
98
- * loaded before calling the callback function. This is
99
- * used for multiply-accumulate type operations.
100
- */
101
- TCGv_i32 tmp, tmp2;
102
- int pass;
103
-
38
-
104
- if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
39
- if (is_snan(a_cls) || is_snan(b_cls)) {
105
- return false;
40
- float_raise(float_flag_invalid, status);
106
- }
41
- }
107
-
42
-
108
- /* UNDEF accesses to D16-D31 if they don't exist. */
43
- if (status->default_nan_mode) {
109
- if (!dc_isar_feature(aa32_simd_r32, s) &&
44
+ if (!floatx80_unpack_canonical(&pa, a, status) ||
110
- ((a->vd | a->vn | a->vm) & 0x10)) {
45
+ !floatx80_unpack_canonical(&pb, b, status)) {
111
- return false;
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;
112
- }
55
- }
113
-
56
-
114
- if ((a->vn | a->vm | a->vd) & a->q) {
57
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
115
- return false;
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;
116
- }
67
- }
117
-
68
+ pr = parts_pick_nan(&pa, &pb, status);
118
- if (!vfp_access_check(s)) {
69
+ return floatx80_round_pack_canonical(pr, status);
119
- return true;
120
- }
121
-
122
- TCGv_ptr fpstatus = fpstatus_ptr(FPST_STD);
123
- for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
124
- tmp = neon_load_reg(a->vn, pass);
125
- tmp2 = neon_load_reg(a->vm, pass);
126
- if (reads_vd) {
127
- TCGv_i32 tmp_rd = neon_load_reg(a->vd, pass);
128
- fn(tmp_rd, tmp, tmp2, fpstatus);
129
- neon_store_reg(a->vd, pass, tmp_rd);
130
- tcg_temp_free_i32(tmp);
131
- } else {
132
- fn(tmp, tmp, tmp2, fpstatus);
133
- neon_store_reg(a->vd, pass, tmp);
134
- }
135
- tcg_temp_free_i32(tmp2);
136
- }
137
- tcg_temp_free_ptr(fpstatus);
138
- return true;
139
-}
140
-
141
#define WRAP_FP_GVEC(WRAPNAME, FPST, FUNC) \
142
static void WRAPNAME(unsigned vece, uint32_t rd_ofs, \
143
uint32_t rn_ofs, uint32_t rm_ofs, \
144
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMAX, gen_helper_gvec_fmax_s, gen_helper_gvec_fmax_h)
145
DO_3S_FP_GVEC(VMIN, gen_helper_gvec_fmin_s, gen_helper_gvec_fmin_h)
146
DO_3S_FP_GVEC(VMLA, gen_helper_gvec_fmla_s, gen_helper_gvec_fmla_h)
147
DO_3S_FP_GVEC(VMLS, gen_helper_gvec_fmls_s, gen_helper_gvec_fmls_h)
148
+DO_3S_FP_GVEC(VFMA, gen_helper_gvec_vfma_s, gen_helper_gvec_vfma_h)
149
+DO_3S_FP_GVEC(VFMS, gen_helper_gvec_vfms_s, gen_helper_gvec_vfms_h)
150
151
WRAP_FP_GVEC(gen_VMAXNM_fp32_3s, FPST_STD, gen_helper_gvec_fmaxnum_s)
152
WRAP_FP_GVEC(gen_VMAXNM_fp16_3s, FPST_STD_F16, gen_helper_gvec_fmaxnum_h)
153
@@ -XXX,XX +XXX,XX @@ static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a)
154
return do_3same(s, a, gen_VRSQRTS_fp_3s);
155
}
70
}
156
71
157
-static void gen_VFMA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
72
/*----------------------------------------------------------------------------
158
- TCGv_ptr fpstatus)
159
-{
160
- gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus);
161
-}
162
-
163
-static bool trans_VFMA_fp_3s(DisasContext *s, arg_3same *a)
164
-{
165
- if (!dc_isar_feature(aa32_simdfmac, s)) {
166
- return false;
167
- }
168
-
169
- if (a->size != 0) {
170
- /* TODO fp16 support */
171
- return false;
172
- }
173
-
174
- return do_3same_fp(s, a, gen_VFMA_fp_3s, true);
175
-}
176
-
177
-static void gen_VFMS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
178
- TCGv_ptr fpstatus)
179
-{
180
- gen_helper_vfp_negs(vn, vn);
181
- gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus);
182
-}
183
-
184
-static bool trans_VFMS_fp_3s(DisasContext *s, arg_3same *a)
185
-{
186
- if (!dc_isar_feature(aa32_simdfmac, s)) {
187
- return false;
188
- }
189
-
190
- if (a->size != 0) {
191
- /* TODO fp16 support */
192
- return false;
193
- }
194
-
195
- return do_3same_fp(s, a, gen_VFMS_fp_3s, true);
196
-}
197
-
198
static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
199
{
200
/* FP operations handled pairwise 32 bits at a time */
201
--
73
--
202
2.20.1
74
2.34.1
203
204
diff view generated by jsdifflib
1
Implement the fp16 versions of the VFP VCVT instruction forms which
1
From: Richard Henderson <richard.henderson@linaro.org>
2
convert between floating point and fixed-point.
2
3
3
Inline pickNaN into its only caller. This makes one assert
4
redundant with the immediately preceding IF.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20241203203949.483774-9-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200828183354.27913-16-peter.maydell@linaro.org
7
---
10
---
8
target/arm/vfp.decode | 2 ++
11
fpu/softfloat-parts.c.inc | 82 +++++++++++++++++++++++++----
9
target/arm/translate-vfp.c.inc | 59 ++++++++++++++++++++++++++++++++++
12
fpu/softfloat-specialize.c.inc | 96 ----------------------------------
10
2 files changed, 61 insertions(+)
13
2 files changed, 73 insertions(+), 105 deletions(-)
11
14
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
15
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/vfp.decode
17
--- a/fpu/softfloat-parts.c.inc
15
+++ b/target/arm/vfp.decode
18
+++ b/fpu/softfloat-parts.c.inc
16
@@ -XXX,XX +XXX,XX @@ VJCVT ---- 1110 1.11 1001 .... 1011 11.0 .... @vfp_dm_sd
19
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
17
# We assemble bits 18 (op), 16 (u) and 7 (sx) into a single opc field
20
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
18
# for the convenience of the trans_VCVT_fix functions.
21
float_status *s)
19
%vcvt_fix_op 18:1 16:1 7:1
22
{
20
+VCVT_fix_hp ---- 1110 1.11 1.1. .... 1001 .1.0 .... \
23
+ int cmp, which;
21
+ vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op
22
VCVT_fix_sp ---- 1110 1.11 1.1. .... 1010 .1.0 .... \
23
vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op
24
VCVT_fix_dp ---- 1110 1.11 1.1. .... 1011 .1.0 .... \
25
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/translate-vfp.c.inc
28
+++ b/target/arm/translate-vfp.c.inc
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
30
return true;
31
}
32
33
+static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
34
+{
35
+ TCGv_i32 vd, shift;
36
+ TCGv_ptr fpst;
37
+ int frac_bits;
38
+
24
+
39
+ if (!dc_isar_feature(aa32_fp16_arith, s)) {
25
if (is_snan(a->cls) || is_snan(b->cls)) {
40
+ return false;
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
27
}
28
29
if (s->default_nan_mode) {
30
parts_default_nan(a, s);
31
- } else {
32
- int cmp = frac_cmp(a, b);
33
- if (cmp == 0) {
34
- cmp = a->sign < b->sign;
35
- }
36
+ return a;
37
+ }
38
39
- if (pickNaN(a->cls, b->cls, cmp > 0, s)) {
40
- a = b;
41
- }
42
+ cmp = frac_cmp(a, b);
43
+ if (cmp == 0) {
44
+ cmp = a->sign < b->sign;
41
+ }
45
+ }
42
+
46
+
43
+ if (!vfp_access_check(s)) {
47
+ switch (s->float_2nan_prop_rule) {
44
+ return true;
48
+ case float_2nan_prop_s_ab:
45
+ }
49
if (is_snan(a->cls)) {
46
+
50
- parts_silence_nan(a, s);
47
+ frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm);
51
+ which = 0;
48
+
52
+ } else if (is_snan(b->cls)) {
49
+ vd = tcg_temp_new_i32();
53
+ which = 1;
50
+ neon_load_reg32(vd, a->vd);
54
+ } else if (is_qnan(a->cls)) {
51
+
55
+ which = 0;
52
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
56
+ } else {
53
+ shift = tcg_const_i32(frac_bits);
57
+ which = 1;
54
+
58
}
55
+ /* Switch on op:U:sx bits */
59
+ break;
56
+ switch (a->opc) {
60
+ case float_2nan_prop_s_ba:
57
+ case 0:
61
+ if (is_snan(b->cls)) {
58
+ gen_helper_vfp_shtoh(vd, vd, shift, fpst);
62
+ which = 1;
59
+ break;
63
+ } else if (is_snan(a->cls)) {
60
+ case 1:
64
+ which = 0;
61
+ gen_helper_vfp_sltoh(vd, vd, shift, fpst);
65
+ } else if (is_qnan(b->cls)) {
62
+ break;
66
+ which = 1;
63
+ case 2:
67
+ } else {
64
+ gen_helper_vfp_uhtoh(vd, vd, shift, fpst);
68
+ which = 0;
65
+ break;
69
+ }
66
+ case 3:
70
+ break;
67
+ gen_helper_vfp_ultoh(vd, vd, shift, fpst);
71
+ case float_2nan_prop_ab:
68
+ break;
72
+ which = is_nan(a->cls) ? 0 : 1;
69
+ case 4:
73
+ break;
70
+ gen_helper_vfp_toshh_round_to_zero(vd, vd, shift, fpst);
74
+ case float_2nan_prop_ba:
71
+ break;
75
+ which = is_nan(b->cls) ? 1 : 0;
72
+ case 5:
76
+ break;
73
+ gen_helper_vfp_toslh_round_to_zero(vd, vd, shift, fpst);
77
+ case float_2nan_prop_x87:
74
+ break;
78
+ /*
75
+ case 6:
79
+ * This implements x87 NaN propagation rules:
76
+ gen_helper_vfp_touhh_round_to_zero(vd, vd, shift, fpst);
80
+ * SNaN + QNaN => return the QNaN
77
+ break;
81
+ * two SNaNs => return the one with the larger significand, silenced
78
+ case 7:
82
+ * two QNaNs => return the one with the larger significand
79
+ gen_helper_vfp_toulh_round_to_zero(vd, vd, shift, fpst);
83
+ * SNaN and a non-NaN => return the SNaN, silenced
84
+ * QNaN and a non-NaN => return the QNaN
85
+ *
86
+ * If we get down to comparing significands and they are the same,
87
+ * return the NaN with the positive sign bit (if any).
88
+ */
89
+ if (is_snan(a->cls)) {
90
+ if (is_snan(b->cls)) {
91
+ which = cmp > 0 ? 0 : 1;
92
+ } else {
93
+ which = is_qnan(b->cls) ? 1 : 0;
94
+ }
95
+ } else if (is_qnan(a->cls)) {
96
+ if (is_snan(b->cls) || !is_qnan(b->cls)) {
97
+ which = 0;
98
+ } else {
99
+ which = cmp > 0 ? 0 : 1;
100
+ }
101
+ } else {
102
+ which = 1;
103
+ }
80
+ break;
104
+ break;
81
+ default:
105
+ default:
82
+ g_assert_not_reached();
106
+ g_assert_not_reached();
83
+ }
107
+ }
84
+
108
+
85
+ neon_store_reg32(vd, a->vd);
109
+ if (which) {
86
+ tcg_temp_free_i32(vd);
110
+ a = b;
87
+ tcg_temp_free_i32(shift);
111
+ }
88
+ tcg_temp_free_ptr(fpst);
112
+ if (is_snan(a->cls)) {
89
+ return true;
113
+ parts_silence_nan(a, s);
90
+}
114
}
91
+
115
return a;
92
static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
116
}
93
{
117
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
94
TCGv_i32 vd, shift;
118
index XXXXXXX..XXXXXXX 100644
119
--- a/fpu/softfloat-specialize.c.inc
120
+++ b/fpu/softfloat-specialize.c.inc
121
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
122
}
123
}
124
125
-/*----------------------------------------------------------------------------
126
-| Select which NaN to propagate for a two-input operation.
127
-| IEEE754 doesn't specify all the details of this, so the
128
-| algorithm is target-specific.
129
-| The routine is passed various bits of information about the
130
-| two NaNs and should return 0 to select NaN a and 1 for NaN b.
131
-| Note that signalling NaNs are always squashed to quiet NaNs
132
-| by the caller, by calling floatXX_silence_nan() before
133
-| returning them.
134
-|
135
-| aIsLargerSignificand is only valid if both a and b are NaNs
136
-| of some kind, and is true if a has the larger significand,
137
-| or if both a and b have the same significand but a is
138
-| positive but b is negative. It is only needed for the x87
139
-| tie-break rule.
140
-*----------------------------------------------------------------------------*/
141
-
142
-static int pickNaN(FloatClass a_cls, FloatClass b_cls,
143
- bool aIsLargerSignificand, float_status *status)
144
-{
145
- /*
146
- * We guarantee not to require the target to tell us how to
147
- * pick a NaN if we're always returning the default NaN.
148
- * But if we're not in default-NaN mode then the target must
149
- * specify via set_float_2nan_prop_rule().
150
- */
151
- assert(!status->default_nan_mode);
152
-
153
- switch (status->float_2nan_prop_rule) {
154
- case float_2nan_prop_s_ab:
155
- if (is_snan(a_cls)) {
156
- return 0;
157
- } else if (is_snan(b_cls)) {
158
- return 1;
159
- } else if (is_qnan(a_cls)) {
160
- return 0;
161
- } else {
162
- return 1;
163
- }
164
- break;
165
- case float_2nan_prop_s_ba:
166
- if (is_snan(b_cls)) {
167
- return 1;
168
- } else if (is_snan(a_cls)) {
169
- return 0;
170
- } else if (is_qnan(b_cls)) {
171
- return 1;
172
- } else {
173
- return 0;
174
- }
175
- break;
176
- case float_2nan_prop_ab:
177
- if (is_nan(a_cls)) {
178
- return 0;
179
- } else {
180
- return 1;
181
- }
182
- break;
183
- case float_2nan_prop_ba:
184
- if (is_nan(b_cls)) {
185
- return 1;
186
- } else {
187
- return 0;
188
- }
189
- break;
190
- case float_2nan_prop_x87:
191
- /*
192
- * This implements x87 NaN propagation rules:
193
- * SNaN + QNaN => return the QNaN
194
- * two SNaNs => return the one with the larger significand, silenced
195
- * two QNaNs => return the one with the larger significand
196
- * SNaN and a non-NaN => return the SNaN, silenced
197
- * QNaN and a non-NaN => return the QNaN
198
- *
199
- * If we get down to comparing significands and they are the same,
200
- * return the NaN with the positive sign bit (if any).
201
- */
202
- if (is_snan(a_cls)) {
203
- if (is_snan(b_cls)) {
204
- return aIsLargerSignificand ? 0 : 1;
205
- }
206
- return is_qnan(b_cls) ? 1 : 0;
207
- } else if (is_qnan(a_cls)) {
208
- if (is_snan(b_cls) || !is_qnan(b_cls)) {
209
- return 0;
210
- } else {
211
- return aIsLargerSignificand ? 0 : 1;
212
- }
213
- } else {
214
- return 1;
215
- }
216
- default:
217
- g_assert_not_reached();
218
- }
219
-}
220
-
221
/*----------------------------------------------------------------------------
222
| Returns 1 if the double-precision floating-point value `a' is a quiet
223
| NaN; otherwise returns 0.
95
--
224
--
96
2.20.1
225
2.34.1
97
226
98
227
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Remember if there was an SNaN, and use that to simplify
4
float_2nan_prop_s_{ab,ba} to only the snan component.
5
Then, fall through to the corresponding
6
float_2nan_prop_{ab,ba} case to handle any remaining
7
nans, which must be quiet.
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20241203203949.483774-10-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
fpu/softfloat-parts.c.inc | 32 ++++++++++++--------------------
15
1 file changed, 12 insertions(+), 20 deletions(-)
16
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
18
index XXXXXXX..XXXXXXX 100644
19
--- a/fpu/softfloat-parts.c.inc
20
+++ b/fpu/softfloat-parts.c.inc
21
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
22
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
23
float_status *s)
24
{
25
+ bool have_snan = false;
26
int cmp, which;
27
28
if (is_snan(a->cls) || is_snan(b->cls)) {
29
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
30
+ have_snan = true;
31
}
32
33
if (s->default_nan_mode) {
34
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
35
36
switch (s->float_2nan_prop_rule) {
37
case float_2nan_prop_s_ab:
38
- if (is_snan(a->cls)) {
39
- which = 0;
40
- } else if (is_snan(b->cls)) {
41
- which = 1;
42
- } else if (is_qnan(a->cls)) {
43
- which = 0;
44
- } else {
45
- which = 1;
46
+ if (have_snan) {
47
+ which = is_snan(a->cls) ? 0 : 1;
48
+ break;
49
}
50
- break;
51
- case float_2nan_prop_s_ba:
52
- if (is_snan(b->cls)) {
53
- which = 1;
54
- } else if (is_snan(a->cls)) {
55
- which = 0;
56
- } else if (is_qnan(b->cls)) {
57
- which = 1;
58
- } else {
59
- which = 0;
60
- }
61
- break;
62
+ /* fall through */
63
case float_2nan_prop_ab:
64
which = is_nan(a->cls) ? 0 : 1;
65
break;
66
+ case float_2nan_prop_s_ba:
67
+ if (have_snan) {
68
+ which = is_snan(b->cls) ? 1 : 0;
69
+ break;
70
+ }
71
+ /* fall through */
72
case float_2nan_prop_ba:
73
which = is_nan(b->cls) ? 1 : 0;
74
break;
75
--
76
2.34.1
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
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>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20241203203949.483774-11-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
fpu/softfloat-parts.c.inc | 19 +++++++++----------
15
1 file changed, 9 insertions(+), 10 deletions(-)
16
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
18
index XXXXXXX..XXXXXXX 100644
19
--- a/fpu/softfloat-parts.c.inc
20
+++ b/fpu/softfloat-parts.c.inc
21
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
22
return a;
23
}
24
25
- cmp = frac_cmp(a, b);
26
- if (cmp == 0) {
27
- cmp = a->sign < b->sign;
28
- }
29
-
30
switch (s->float_2nan_prop_rule) {
31
case float_2nan_prop_s_ab:
32
if (have_snan) {
33
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
34
* return the NaN with the positive sign bit (if any).
35
*/
36
if (is_snan(a->cls)) {
37
- if (is_snan(b->cls)) {
38
- which = cmp > 0 ? 0 : 1;
39
- } else {
40
+ if (!is_snan(b->cls)) {
41
which = is_qnan(b->cls) ? 1 : 0;
42
+ break;
43
}
44
} else if (is_qnan(a->cls)) {
45
if (is_snan(b->cls) || !is_qnan(b->cls)) {
46
which = 0;
47
- } else {
48
- which = cmp > 0 ? 0 : 1;
49
+ break;
50
}
51
} else {
52
which = 1;
53
+ break;
54
}
55
+ cmp = frac_cmp(a, b);
56
+ if (cmp == 0) {
57
+ cmp = a->sign < b->sign;
58
+ }
59
+ which = cmp > 0 ? 0 : 1;
60
break;
61
default:
62
g_assert_not_reached();
63
--
64
2.34.1
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The sbsa-ref platform uses a minimal device tree to pass amount of memory
3
Replace the "index" selecting between A and B with a result variable
4
as well as number of cpus to the firmware. However, when dumping that
4
of the proper type. This improves clarity within the function.
5
minimal dtb (with -M sbsa-virt,dumpdtb=<file>), the resulting blob
6
generates a warning when decompiled by dtc due to lack of reg property.
7
5
8
Add a simple reg property per cpu, representing a 64-bit MPIDR_EL1.
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
This also ends up being cleaner than having the firmware calculating its
8
Message-id: 20241203203949.483774-12-richard.henderson@linaro.org
11
own IDs for generating APCI.
12
13
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20200827124335.30586-1-leif@nuviainc.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
10
---
18
hw/arm/sbsa-ref.c | 29 +++++++++++++++++++++++------
11
fpu/softfloat-parts.c.inc | 28 +++++++++++++---------------
19
1 file changed, 23 insertions(+), 6 deletions(-)
12
1 file changed, 13 insertions(+), 15 deletions(-)
20
13
21
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/sbsa-ref.c
16
--- a/fpu/softfloat-parts.c.inc
24
+++ b/hw/arm/sbsa-ref.c
17
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
26
[SBSA_EHCI] = 11,
19
float_status *s)
27
};
20
{
28
21
bool have_snan = false;
29
+static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
22
- int cmp, which;
30
+{
23
+ FloatPartsN *ret;
31
+ uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
24
+ int cmp;
32
+ return arm_cpu_mp_affinity(idx, clustersz);
25
33
+}
26
if (is_snan(a->cls) || is_snan(b->cls)) {
34
+
27
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
35
/*
28
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
36
* Firmware on this machine only uses ACPI table to load OS, these limited
29
switch (s->float_2nan_prop_rule) {
37
* device tree nodes are just to let firmware know the info which varies from
30
case float_2nan_prop_s_ab:
38
@@ -XXX,XX +XXX,XX @@ static void create_fdt(SBSAMachineState *sms)
31
if (have_snan) {
39
g_free(matrix);
32
- which = is_snan(a->cls) ? 0 : 1;
33
+ ret = is_snan(a->cls) ? a : b;
34
break;
35
}
36
/* fall through */
37
case float_2nan_prop_ab:
38
- which = is_nan(a->cls) ? 0 : 1;
39
+ ret = is_nan(a->cls) ? a : b;
40
break;
41
case float_2nan_prop_s_ba:
42
if (have_snan) {
43
- which = is_snan(b->cls) ? 1 : 0;
44
+ ret = is_snan(b->cls) ? b : a;
45
break;
46
}
47
/* fall through */
48
case float_2nan_prop_ba:
49
- which = is_nan(b->cls) ? 1 : 0;
50
+ ret = is_nan(b->cls) ? b : a;
51
break;
52
case float_2nan_prop_x87:
53
/*
54
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
55
*/
56
if (is_snan(a->cls)) {
57
if (!is_snan(b->cls)) {
58
- which = is_qnan(b->cls) ? 1 : 0;
59
+ ret = is_qnan(b->cls) ? b : a;
60
break;
61
}
62
} else if (is_qnan(a->cls)) {
63
if (is_snan(b->cls) || !is_qnan(b->cls)) {
64
- which = 0;
65
+ ret = a;
66
break;
67
}
68
} else {
69
- which = 1;
70
+ ret = b;
71
break;
72
}
73
cmp = frac_cmp(a, b);
74
if (cmp == 0) {
75
cmp = a->sign < b->sign;
76
}
77
- which = cmp > 0 ? 0 : 1;
78
+ ret = cmp > 0 ? a : b;
79
break;
80
default:
81
g_assert_not_reached();
40
}
82
}
41
83
42
+ /*
84
- if (which) {
43
+ * From Documentation/devicetree/bindings/arm/cpus.yaml
85
- a = b;
44
+ * On ARM v8 64-bit systems this property is required
86
+ if (is_snan(ret->cls)) {
45
+ * and matches the MPIDR_EL1 register affinity bits.
87
+ parts_silence_nan(ret, s);
46
+ *
88
}
47
+ * * If cpus node's #address-cells property is set to 2
89
- if (is_snan(a->cls)) {
48
+ *
90
- parts_silence_nan(a, s);
49
+ * The first reg cell bits [7:0] must be set to
91
- }
50
+ * bits [39:32] of MPIDR_EL1.
92
- return a;
51
+ *
93
+ return ret;
52
+ * The second reg cell bits [23:0] must be set to
53
+ * bits [23:0] of MPIDR_EL1.
54
+ */
55
qemu_fdt_add_subnode(sms->fdt, "/cpus");
56
+ qemu_fdt_setprop_cell(sms->fdt, "/cpus", "#address-cells", 2);
57
+ qemu_fdt_setprop_cell(sms->fdt, "/cpus", "#size-cells", 0x0);
58
59
for (cpu = sms->smp_cpus - 1; cpu >= 0; cpu--) {
60
char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
61
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
62
CPUState *cs = CPU(armcpu);
63
+ uint64_t mpidr = sbsa_ref_cpu_mp_affinity(sms, cpu);
64
65
qemu_fdt_add_subnode(sms->fdt, nodename);
66
+ qemu_fdt_setprop_u64(sms->fdt, nodename, "reg", mpidr);
67
68
if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) {
69
qemu_fdt_setprop_cell(sms->fdt, nodename, "numa-node-id",
70
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
71
arm_load_kernel(ARM_CPU(first_cpu), machine, &sms->bootinfo);
72
}
94
}
73
95
74
-static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
96
static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
75
-{
76
- uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
77
- return arm_cpu_mp_affinity(idx, clustersz);
78
-}
79
-
80
static const CPUArchIdList *sbsa_ref_possible_cpu_arch_ids(MachineState *ms)
81
{
82
unsigned int max_cpus = ms->smp.max_cpus;
83
--
97
--
84
2.20.1
98
2.34.1
85
99
86
100
diff view generated by jsdifflib
1
Add gvec helpers for doing Neon-style indexed non-fused fp
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
multiply-and-accumulate operations.
3
2
3
I'm migrating to Qualcomm's new open source email infrastructure, so
4
update my email address, and update the mailmap to match.
5
6
Signed-off-by: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
8
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
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
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20200828183354.27913-44-peter.maydell@linaro.org
6
---
13
---
7
target/arm/helper.h | 10 ++++++++++
14
MAINTAINERS | 2 +-
8
target/arm/vec_helper.c | 27 ++++++++++++++++++++++-----
15
.mailmap | 5 +++--
9
2 files changed, 32 insertions(+), 5 deletions(-)
16
2 files changed, 4 insertions(+), 3 deletions(-)
10
17
11
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
diff --git a/MAINTAINERS b/MAINTAINERS
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/helper.h
20
--- a/MAINTAINERS
14
+++ b/target/arm/helper.h
21
+++ b/MAINTAINERS
15
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmul_idx_s, TCG_CALL_NO_RWG,
22
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
16
DEF_HELPER_FLAGS_5(gvec_fmul_idx_d, TCG_CALL_NO_RWG,
23
SBSA-REF
17
void, ptr, ptr, ptr, ptr, i32)
24
M: Radoslaw Biernacki <rad@semihalf.com>
18
25
M: Peter Maydell <peter.maydell@linaro.org>
19
+DEF_HELPER_FLAGS_5(gvec_fmla_nf_idx_h, TCG_CALL_NO_RWG,
26
-R: Leif Lindholm <quic_llindhol@quicinc.com>
20
+ void, ptr, ptr, ptr, ptr, i32)
27
+R: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
21
+DEF_HELPER_FLAGS_5(gvec_fmla_nf_idx_s, TCG_CALL_NO_RWG,
28
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
22
+ void, ptr, ptr, ptr, ptr, i32)
29
L: qemu-arm@nongnu.org
23
+
30
S: Maintained
24
+DEF_HELPER_FLAGS_5(gvec_fmls_nf_idx_h, TCG_CALL_NO_RWG,
31
diff --git a/.mailmap b/.mailmap
25
+ void, ptr, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_5(gvec_fmls_nf_idx_s, TCG_CALL_NO_RWG,
27
+ void, ptr, ptr, ptr, ptr, i32)
28
+
29
DEF_HELPER_FLAGS_6(gvec_fmla_idx_h, TCG_CALL_NO_RWG,
30
void, ptr, ptr, ptr, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_6(gvec_fmla_idx_s, TCG_CALL_NO_RWG,
32
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
33
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/vec_helper.c
33
--- a/.mailmap
35
+++ b/target/arm/vec_helper.c
34
+++ b/.mailmap
36
@@ -XXX,XX +XXX,XX @@ DO_MLA_IDX(gvec_mls_idx_d, uint64_t, -, )
35
@@ -XXX,XX +XXX,XX @@ Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
37
36
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
38
#undef DO_MLA_IDX
37
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
39
38
Juan Quintela <quintela@trasno.org> <quintela@redhat.com>
40
-#define DO_FMUL_IDX(NAME, TYPE, H) \
39
-Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
41
+#define DO_FMUL_IDX(NAME, ADD, TYPE, H) \
40
-Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
42
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
41
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <quic_llindhol@quicinc.com>
43
{ \
42
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif.lindholm@linaro.org>
44
intptr_t i, j, oprsz = simd_oprsz(desc); \
43
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif@nuviainc.com>
45
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
44
Luc Michel <luc@lmichel.fr> <luc.michel@git.antfield.fr>
46
for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \
45
Luc Michel <luc@lmichel.fr> <luc.michel@greensocs.com>
47
TYPE mm = m[H(i + idx)]; \
46
Luc Michel <luc@lmichel.fr> <lmichel@kalray.eu>
48
for (j = 0; j < segment; j++) { \
49
- d[i + j] = TYPE##_mul(n[i + j], mm, stat); \
50
+ d[i + j] = TYPE##_##ADD(d[i + j], \
51
+ TYPE##_mul(n[i + j], mm, stat), stat); \
52
} \
53
} \
54
clear_tail(d, oprsz, simd_maxsz(desc)); \
55
}
56
57
-DO_FMUL_IDX(gvec_fmul_idx_h, float16, H2)
58
-DO_FMUL_IDX(gvec_fmul_idx_s, float32, H4)
59
-DO_FMUL_IDX(gvec_fmul_idx_d, float64, )
60
+#define float16_nop(N, M, S) (M)
61
+#define float32_nop(N, M, S) (M)
62
+#define float64_nop(N, M, S) (M)
63
64
+DO_FMUL_IDX(gvec_fmul_idx_h, nop, float16, H2)
65
+DO_FMUL_IDX(gvec_fmul_idx_s, nop, float32, H4)
66
+DO_FMUL_IDX(gvec_fmul_idx_d, nop, float64, )
67
+
68
+/*
69
+ * Non-fused multiply-accumulate operations, for Neon. NB that unlike
70
+ * the fused ops below they assume accumulate both from and into Vd.
71
+ */
72
+DO_FMUL_IDX(gvec_fmla_nf_idx_h, add, float16, H2)
73
+DO_FMUL_IDX(gvec_fmla_nf_idx_s, add, float32, H4)
74
+DO_FMUL_IDX(gvec_fmls_nf_idx_h, sub, float16, H2)
75
+DO_FMUL_IDX(gvec_fmls_nf_idx_s, sub, float32, H4)
76
+
77
+#undef float16_nop
78
+#undef float32_nop
79
+#undef float64_nop
80
#undef DO_FMUL_IDX
81
82
#define DO_FMLA_IDX(NAME, TYPE, H) \
83
--
47
--
84
2.20.1
48
2.34.1
85
49
86
50
diff view generated by jsdifflib
New patch
1
From: Vikram Garhwal <vikram.garhwal@bytedance.com>
1
2
3
Previously, maintainer role was paused due to inactive email id. Commit id:
4
c009d715721861984c4987bcc78b7ee183e86d75.
5
6
Signed-off-by: Vikram Garhwal <vikram.garhwal@bytedance.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20241204184205.12952-1-vikram.garhwal@bytedance.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
MAINTAINERS | 2 ++
12
1 file changed, 2 insertions(+)
13
14
diff --git a/MAINTAINERS b/MAINTAINERS
15
index XXXXXXX..XXXXXXX 100644
16
--- a/MAINTAINERS
17
+++ b/MAINTAINERS
18
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-sb16-test.c
19
20
Xilinx CAN
21
M: Francisco Iglesias <francisco.iglesias@amd.com>
22
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
23
S: Maintained
24
F: hw/net/can/xlnx-*
25
F: include/hw/net/xlnx-*
26
@@ -XXX,XX +XXX,XX @@ F: include/hw/rx/
27
CAN bus subsystem and hardware
28
M: Pavel Pisa <pisa@cmp.felk.cvut.cz>
29
M: Francisco Iglesias <francisco.iglesias@amd.com>
30
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
31
S: Maintained
32
W: https://canbus.pages.fel.cvut.cz/
33
F: net/can/*
34
--
35
2.34.1
diff view generated by jsdifflib