1
Arm queue -- I have more stuff pending but I prefer to push
1
First arm pullreq of the cycle; this is mostly my softfloat NaN
2
this first lot out and keep the pull below 50 patches.
2
handling series. (Lots more in my to-review queue, but I don't
3
Most of this is Alex's FP16 support work.
3
like pullreqs growing too close to a hundred patches at a time :-))
4
4
5
thanks
5
-- PMM
6
-- PMM
6
7
8
The following changes since commit 97f2796a3736ed37a1b85dc1c76a6c45b829dd17:
7
9
8
The following changes since commit 6697439794f72b3501ee16bb95d16854f9981421:
10
Open 10.0 development tree (2024-12-10 17:41:17 +0000)
9
10
Merge remote-tracking branch 'remotes/kraxel/tags/usb-20180227-pull-request' into staging (2018-02-27 17:50:46 +0000)
11
11
12
are available in the Git repository at:
12
are available in the Git repository at:
13
13
14
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180301
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20241211
15
15
16
for you to fetch changes up to c22e580c2ad1cccef582e1490e732f254d4ac064:
16
for you to fetch changes up to 1abe28d519239eea5cf9620bb13149423e5665f8:
17
17
18
MAINTAINERS: Update my email address (2018-03-01 11:13:59 +0000)
18
MAINTAINERS: Add correct email address for Vikram Garhwal (2024-12-11 15:31:09 +0000)
19
19
20
----------------------------------------------------------------
20
----------------------------------------------------------------
21
target-arm queue:
21
target-arm queue:
22
* update MAINTAINERS for Alistair's new email address
22
* hw/net/lan9118: Extract PHY model, reuse with imx_fec, fix bugs
23
* add Arm v8.2 FP16 arithmetic extension for linux-user
23
* fpu: Make muladd NaN handling runtime-selected, not compile-time
24
* implement display connector emulation for vexpress board
24
* fpu: Make default NaN pattern runtime-selected, not compile-time
25
* xilinx_spips: Enable only two slaves when reading/writing with stripe
25
* fpu: Minor NaN-related cleanups
26
* xilinx_spips: Use 8 dummy cycles with the QIOR/QIOR4 commands
26
* MAINTAINERS: email address updates
27
* hw: register: Run post_write hook on reset
28
27
29
----------------------------------------------------------------
28
----------------------------------------------------------------
30
Alex Bennée (31):
29
Bernhard Beschow (5):
31
include/exec/helper-head.h: support f16 in helper calls
30
hw/net/lan9118: Extract lan9118_phy
32
target/arm/cpu64: introduce ARM_V8_FP16 feature bit
31
hw/net/lan9118_phy: Reuse in imx_fec and consolidate implementations
33
target/arm/cpu.h: update comment for half-precision values
32
hw/net/lan9118_phy: Fix off-by-one error in MII_ANLPAR register
34
target/arm/cpu.h: add additional float_status flags
33
hw/net/lan9118_phy: Reuse MII constants
35
target/arm/helper: pass explicit fpst to set_rmode
34
hw/net/lan9118_phy: Add missing 100 mbps full duplex advertisement
36
arm/translate-a64: implement half-precision F(MIN|MAX)(V|NMV)
37
arm/translate-a64: handle_3same_64 comment fix
38
arm/translate-a64: initial decode for simd_three_reg_same_fp16
39
arm/translate-a64: add FP16 FADD/FABD/FSUB/FMUL/FDIV to simd_three_reg_same_fp16
40
arm/translate-a64: add FP16 F[A]C[EQ/GE/GT] to simd_three_reg_same_fp16
41
arm/translate-a64: add FP16 FMULA/X/S to simd_three_reg_same_fp16
42
arm/translate-a64: add FP16 FR[ECP/SQRT]S to simd_three_reg_same_fp16
43
arm/translate-a64: add FP16 pairwise ops simd_three_reg_same_fp16
44
arm/translate-a64: add FP16 FMULX/MLS/FMLA to simd_indexed
45
arm/translate-a64: add FP16 x2 ops for simd_indexed
46
arm/translate-a64: initial decode for simd_two_reg_misc_fp16
47
arm/translate-a64: add FP16 FPRINTx to simd_two_reg_misc_fp16
48
arm/translate-a64: add FCVTxx to simd_two_reg_misc_fp16
49
arm/translate-a64: add FP16 FCMxx (zero) to simd_two_reg_misc_fp16
50
arm/translate-a64: add FP16 SCVTF/UCVFT to simd_two_reg_misc_fp16
51
arm/translate-a64: add FP16 FNEG/FABS to simd_two_reg_misc_fp16
52
arm/helper.c: re-factor recpe and add recepe_f16
53
arm/translate-a64: add FP16 FRECPE
54
arm/translate-a64: add FP16 FRCPX to simd_two_reg_misc_fp16
55
arm/translate-a64: add FP16 FSQRT to simd_two_reg_misc_fp16
56
arm/helper.c: re-factor rsqrte and add rsqrte_f16
57
arm/translate-a64: add FP16 FRSQRTE to simd_two_reg_misc_fp16
58
arm/translate-a64: add FP16 FMOV to simd_mod_imm
59
arm/translate-a64: add all FP16 ops in simd_scalar_pairwise
60
arm/translate-a64: implement simd_scalar_three_reg_same_fp16
61
arm/translate-a64: add all single op FP16 to handle_fp_1src_half
62
35
63
Alistair Francis (2):
36
Leif Lindholm (1):
64
hw: register: Run post_write hook on reset
37
MAINTAINERS: update email address for Leif Lindholm
65
MAINTAINERS: Update my email address
66
38
67
Corey Minyard (2):
39
Peter Maydell (54):
68
i2c: Fix some brace style issues
40
fpu: handle raising Invalid for infzero in pick_nan_muladd
69
i2c: Move the bus class to i2c.h
41
fpu: Check for default_nan_mode before calling pickNaNMulAdd
42
softfloat: Allow runtime choice of inf * 0 + NaN result
43
tests/fp: Explicitly set inf-zero-nan rule
44
target/arm: Set FloatInfZeroNaNRule explicitly
45
target/s390: Set FloatInfZeroNaNRule explicitly
46
target/ppc: Set FloatInfZeroNaNRule explicitly
47
target/mips: Set FloatInfZeroNaNRule explicitly
48
target/sparc: Set FloatInfZeroNaNRule explicitly
49
target/xtensa: Set FloatInfZeroNaNRule explicitly
50
target/x86: Set FloatInfZeroNaNRule explicitly
51
target/loongarch: Set FloatInfZeroNaNRule explicitly
52
target/hppa: Set FloatInfZeroNaNRule explicitly
53
softfloat: Pass have_snan to pickNaNMulAdd
54
softfloat: Allow runtime choice of NaN propagation for muladd
55
tests/fp: Explicitly set 3-NaN propagation rule
56
target/arm: Set Float3NaNPropRule explicitly
57
target/loongarch: Set Float3NaNPropRule explicitly
58
target/ppc: Set Float3NaNPropRule explicitly
59
target/s390x: Set Float3NaNPropRule explicitly
60
target/sparc: Set Float3NaNPropRule explicitly
61
target/mips: Set Float3NaNPropRule explicitly
62
target/xtensa: Set Float3NaNPropRule explicitly
63
target/i386: Set Float3NaNPropRule explicitly
64
target/hppa: Set Float3NaNPropRule explicitly
65
fpu: Remove use_first_nan field from float_status
66
target/m68k: Don't pass NULL float_status to floatx80_default_nan()
67
softfloat: Create floatx80 default NaN from parts64_default_nan
68
target/loongarch: Use normal float_status in fclass_s and fclass_d helpers
69
target/m68k: In frem helper, initialize local float_status from env->fp_status
70
target/m68k: Init local float_status from env fp_status in gdb get/set reg
71
target/sparc: Initialize local scratch float_status from env->fp_status
72
target/ppc: Use env->fp_status in helper_compute_fprf functions
73
fpu: Allow runtime choice of default NaN value
74
tests/fp: Set default NaN pattern explicitly
75
target/microblaze: Set default NaN pattern explicitly
76
target/i386: Set default NaN pattern explicitly
77
target/hppa: Set default NaN pattern explicitly
78
target/alpha: Set default NaN pattern explicitly
79
target/arm: Set default NaN pattern explicitly
80
target/loongarch: Set default NaN pattern explicitly
81
target/m68k: Set default NaN pattern explicitly
82
target/mips: Set default NaN pattern explicitly
83
target/openrisc: Set default NaN pattern explicitly
84
target/ppc: Set default NaN pattern explicitly
85
target/sh4: Set default NaN pattern explicitly
86
target/rx: Set default NaN pattern explicitly
87
target/s390x: Set default NaN pattern explicitly
88
target/sparc: Set default NaN pattern explicitly
89
target/xtensa: Set default NaN pattern explicitly
90
target/hexagon: Set default NaN pattern explicitly
91
target/riscv: Set default NaN pattern explicitly
92
target/tricore: Set default NaN pattern explicitly
93
fpu: Remove default handling for dnan_pattern
70
94
71
Francisco Iglesias (2):
95
Richard Henderson (11):
72
xilinx_spips: Enable only two slaves when reading/writing with stripe
96
target/arm: Copy entire float_status in is_ebf
73
xilinx_spips: Use 8 dummy cycles with the QIOR/QIOR4 commands
97
softfloat: Inline pickNaNMulAdd
98
softfloat: Use goto for default nan case in pick_nan_muladd
99
softfloat: Remove which from parts_pick_nan_muladd
100
softfloat: Pad array size in pick_nan_muladd
101
softfloat: Move propagateFloatx80NaN to softfloat.c
102
softfloat: Use parts_pick_nan in propagateFloatx80NaN
103
softfloat: Inline pickNaN
104
softfloat: Share code between parts_pick_nan cases
105
softfloat: Sink frac_cmp in parts_pick_nan until needed
106
softfloat: Replace WHICH with RET in parts_pick_nan
74
107
75
Linus Walleij (3):
108
Vikram Garhwal (1):
76
hw/i2c-ddc: Do not fail writes
109
MAINTAINERS: Add correct email address for Vikram Garhwal
77
hw/sii9022: Add support for Silicon Image SII9022
78
arm/vexpress: Add proper display connector emulation
79
110
80
Peter Maydell (2):
111
MAINTAINERS | 4 +-
81
target/arm: Enable ARM_V8_FP16 feature bit for the AArch64 "any" CPU
112
include/fpu/softfloat-helpers.h | 38 +++-
82
linux-user: Report AArch64 FP16 support via hwcap bits
113
include/fpu/softfloat-types.h | 89 +++++++-
83
114
include/hw/net/imx_fec.h | 9 +-
84
hw/display/Makefile.objs | 1 +
115
include/hw/net/lan9118_phy.h | 37 ++++
85
include/exec/helper-head.h | 3 +
116
include/hw/net/mii.h | 6 +
86
include/fpu/softfloat.h | 18 +-
117
target/mips/fpu_helper.h | 20 ++
87
include/hw/i2c/i2c.h | 23 +-
118
target/sparc/helper.h | 4 +-
88
include/hw/register.h | 6 +-
119
fpu/softfloat.c | 19 ++
89
target/arm/cpu.h | 34 +-
120
hw/net/imx_fec.c | 146 ++------------
90
target/arm/helper-a64.h | 33 +
121
hw/net/lan9118.c | 137 ++-----------
91
target/arm/helper.h | 14 +-
122
hw/net/lan9118_phy.c | 222 ++++++++++++++++++++
92
hw/arm/vexpress.c | 6 +-
123
linux-user/arm/nwfpe/fpa11.c | 5 +
93
hw/core/register.c | 8 +
124
target/alpha/cpu.c | 2 +
94
hw/display/sii9022.c | 191 ++++++
125
target/arm/cpu.c | 10 +
95
hw/i2c/core.c | 18 -
126
target/arm/tcg/vec_helper.c | 20 +-
96
hw/i2c/i2c-ddc.c | 4 +-
127
target/hexagon/cpu.c | 2 +
97
hw/ssi/xilinx_spips.c | 43 +-
128
target/hppa/fpu_helper.c | 12 ++
98
linux-user/elfload.c | 2 +
129
target/i386/tcg/fpu_helper.c | 12 ++
99
target/arm/cpu64.c | 1 +
130
target/loongarch/tcg/fpu_helper.c | 14 +-
100
target/arm/helper-a64.c | 269 +++++++++
131
target/m68k/cpu.c | 14 +-
101
target/arm/helper.c | 481 ++++++++-------
132
target/m68k/fpu_helper.c | 6 +-
102
target/arm/translate-a64.c | 1266 +++++++++++++++++++++++++++++++++------
133
target/m68k/helper.c | 6 +-
103
target/arm/translate.c | 12 +-
134
target/microblaze/cpu.c | 2 +
104
MAINTAINERS | 12 +-
135
target/mips/msa.c | 10 +
105
default-configs/arm-softmmu.mak | 2 +
136
target/openrisc/cpu.c | 2 +
106
hw/display/trace-events | 5 +
137
target/ppc/cpu_init.c | 19 ++
107
23 files changed, 1981 insertions(+), 471 deletions(-)
138
target/ppc/fpu_helper.c | 3 +-
108
create mode 100644 hw/display/sii9022.c
139
target/riscv/cpu.c | 2 +
109
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: Linus Walleij <linus.walleij@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
This adds support for emulating the Silicon Image SII9022 DVI/HDMI
3
A very similar implementation of the same device exists in imx_fec. Prepare for
4
bridge. It's not very clever right now, it just acknowledges
4
a common implementation by extracting a device model into its own files.
5
the switch into DDC I2C mode and back. Combining this with the
6
existing DDC I2C emulation gives the right behavior on the Versatile
7
Express emulation passing through the QEMU EDID to the emulated
8
platform.
9
5
10
Cc: Peter Maydell <peter.maydell@linaro.org>
6
Some migration state has been moved into the new device model which breaks
11
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
7
migration compatibility for the following machines:
12
Message-id: 20180227104903.21353-5-linus.walleij@linaro.org
8
* smdkc210
9
* realview-*
10
* vexpress-*
11
* kzm
12
* mps2-*
13
14
While breaking migration ABI, fix the size of the MII registers to be 16 bit,
15
as defined by IEEE 802.3u.
16
17
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
18
Tested-by: Guenter Roeck <linux@roeck-us.net>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
[PMM: explictly reset ddc_req/ddc_skip_finish/ddc]
20
Message-id: 20241102125724.532843-2-shentey@gmail.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
22
---
17
hw/display/Makefile.objs | 1 +
23
include/hw/net/lan9118_phy.h | 37 ++++++++
18
hw/display/sii9022.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++
24
hw/net/lan9118.c | 137 +++++-----------------------
19
hw/display/trace-events | 5 ++
25
hw/net/lan9118_phy.c | 169 +++++++++++++++++++++++++++++++++++
20
3 files changed, 197 insertions(+)
26
hw/net/Kconfig | 4 +
21
create mode 100644 hw/display/sii9022.c
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/display/Makefile.objs b/hw/display/Makefile.objs
32
diff --git a/include/hw/net/lan9118_phy.h b/include/hw/net/lan9118_phy.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/display/Makefile.objs
26
+++ b/hw/display/Makefile.objs
27
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o
28
common-obj-$(CONFIG_G364FB) += g364fb.o
29
common-obj-$(CONFIG_JAZZ_LED) += jazz_led.o
30
common-obj-$(CONFIG_PL110) += pl110.o
31
+common-obj-$(CONFIG_SII9022) += sii9022.o
32
common-obj-$(CONFIG_SSD0303) += ssd0303.o
33
common-obj-$(CONFIG_SSD0323) += ssd0323.o
34
common-obj-$(CONFIG_XEN) += xenfb.o
35
diff --git a/hw/display/sii9022.c b/hw/display/sii9022.c
36
new file mode 100644
33
new file mode 100644
37
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
38
--- /dev/null
35
--- /dev/null
39
+++ b/hw/display/sii9022.c
36
+++ b/include/hw/net/lan9118_phy.h
40
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
41
+/*
38
+/*
42
+ * Silicon Image SiI9022
39
+ * SMSC LAN9118 PHY emulation
43
+ *
40
+ *
44
+ * This is a pretty hollow emulation: all we do is acknowledge that we
41
+ * Copyright (c) 2009 CodeSourcery, LLC.
45
+ * exist (chip ID) and confirm that we get switched over into DDC mode
42
+ * Written by Paul Brook
46
+ * so the emulated host can proceed to read out EDID data. All subsequent
47
+ * set-up of connectors etc will be acknowledged and ignored.
48
+ *
49
+ * Copyright (C) 2018 Linus Walleij
50
+ *
43
+ *
51
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
52
+ * See the COPYING file in the top-level directory.
45
+ * See the COPYING file in the top-level directory.
53
+ * SPDX-License-Identifier: GPL-2.0-or-later
54
+ */
46
+ */
55
+
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
319
+ *
320
+ * Copyright (c) 2009 CodeSourcery, LLC.
321
+ * Written by Paul Brook
322
+ *
323
+ * This code is licensed under the GNU GPL v2
324
+ *
325
+ * Contributions after 2012-01-13 are licensed under the terms of the
326
+ * GNU GPL, version 2 or (at your option) any later version.
327
+ */
328
+
56
+#include "qemu/osdep.h"
329
+#include "qemu/osdep.h"
57
+#include "qemu-common.h"
330
+#include "hw/net/lan9118_phy.h"
58
+#include "hw/i2c/i2c.h"
331
+#include "hw/irq.h"
59
+#include "hw/i2c/i2c-ddc.h"
332
+#include "hw/resettable.h"
60
+#include "trace.h"
333
+#include "migration/vmstate.h"
61
+
334
+#include "qemu/log.h"
62
+#define SII9022_SYS_CTRL_DATA 0x1a
335
+
63
+#define SII9022_SYS_CTRL_PWR_DWN 0x10
336
+#define PHY_INT_ENERGYON (1 << 7)
64
+#define SII9022_SYS_CTRL_AV_MUTE 0x08
337
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
65
+#define SII9022_SYS_CTRL_DDC_BUS_REQ 0x04
338
+#define PHY_INT_FAULT (1 << 5)
66
+#define SII9022_SYS_CTRL_DDC_BUS_GRTD 0x02
339
+#define PHY_INT_DOWN (1 << 4)
67
+#define SII9022_SYS_CTRL_OUTPUT_MODE 0x01
340
+#define PHY_INT_AUTONEG_LP (1 << 3)
68
+#define SII9022_SYS_CTRL_OUTPUT_HDMI 1
341
+#define PHY_INT_PARFAULT (1 << 2)
69
+#define SII9022_SYS_CTRL_OUTPUT_DVI 0
342
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
70
+#define SII9022_REG_CHIPID 0x1b
343
+
71
+#define SII9022_INT_ENABLE 0x3c
344
+static void lan9118_phy_update_irq(Lan9118PhyState *s)
72
+#define SII9022_INT_STATUS 0x3d
345
+{
73
+#define SII9022_INT_STATUS_HOTPLUG 0x01;
346
+ qemu_set_irq(s->irq, !!(s->ints & s->int_mask));
74
+#define SII9022_INT_STATUS_PLUGGED 0x04;
347
+}
75
+
348
+
76
+#define TYPE_SII9022 "sii9022"
349
+uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
77
+#define SII9022(obj) OBJECT_CHECK(sii9022_state, (obj), TYPE_SII9022)
350
+{
78
+
351
+ uint16_t val;
79
+typedef struct sii9022_state {
352
+
80
+ I2CSlave parent_obj;
353
+ switch (reg) {
81
+ uint8_t ptr;
354
+ case 0: /* Basic Control */
82
+ bool addr_byte;
355
+ return s->control;
83
+ bool ddc_req;
356
+ case 1: /* Basic Status */
84
+ bool ddc_skip_finish;
357
+ return s->status;
85
+ bool ddc;
358
+ case 2: /* ID1 */
86
+} sii9022_state;
359
+ return 0x0007;
87
+
360
+ case 3: /* ID2 */
88
+static const VMStateDescription vmstate_sii9022 = {
361
+ return 0xc0d1;
89
+ .name = "sii9022",
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",
90
+ .version_id = 1,
453
+ .version_id = 1,
91
+ .minimum_version_id = 1,
454
+ .minimum_version_id = 1,
92
+ .fields = (VMStateField[]) {
455
+ .fields = (const VMStateField[]) {
93
+ VMSTATE_I2C_SLAVE(parent_obj, sii9022_state),
456
+ VMSTATE_UINT16(control, Lan9118PhyState),
94
+ VMSTATE_UINT8(ptr, sii9022_state),
457
+ VMSTATE_UINT16(status, Lan9118PhyState),
95
+ VMSTATE_BOOL(addr_byte, sii9022_state),
458
+ VMSTATE_UINT16(advertise, Lan9118PhyState),
96
+ VMSTATE_BOOL(ddc_req, sii9022_state),
459
+ VMSTATE_UINT16(ints, Lan9118PhyState),
97
+ VMSTATE_BOOL(ddc_skip_finish, sii9022_state),
460
+ VMSTATE_UINT16(int_mask, Lan9118PhyState),
98
+ VMSTATE_BOOL(ddc, sii9022_state),
461
+ VMSTATE_BOOL(link_down, Lan9118PhyState),
99
+ VMSTATE_END_OF_LIST()
462
+ VMSTATE_END_OF_LIST()
100
+ }
463
+ }
101
+};
464
+};
102
+
465
+
103
+static int sii9022_event(I2CSlave *i2c, enum i2c_event event)
466
+static void lan9118_phy_class_init(ObjectClass *klass, void *data)
104
+{
467
+{
105
+ sii9022_state *s = SII9022(i2c);
468
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
106
+
469
+ DeviceClass *dc = DEVICE_CLASS(klass);
107
+ switch (event) {
470
+
108
+ case I2C_START_SEND:
471
+ rc->phases.hold = lan9118_phy_reset_hold;
109
+ s->addr_byte = true;
472
+ dc->vmsd = &vmstate_lan9118_phy;
110
+ break;
473
+}
111
+ case I2C_START_RECV:
474
+
112
+ break;
475
+static const TypeInfo types[] = {
113
+ case I2C_FINISH:
476
+ {
114
+ break;
477
+ .name = TYPE_LAN9118_PHY,
115
+ case I2C_NACK:
478
+ .parent = TYPE_SYS_BUS_DEVICE,
116
+ break;
479
+ .instance_size = sizeof(Lan9118PhyState),
480
+ .instance_init = lan9118_phy_init,
481
+ .class_init = lan9118_phy_class_init,
117
+ }
482
+ }
118
+
119
+ return 0;
120
+}
121
+
122
+static int sii9022_rx(I2CSlave *i2c)
123
+{
124
+ sii9022_state *s = SII9022(i2c);
125
+ uint8_t res = 0x00;
126
+
127
+ switch (s->ptr) {
128
+ case SII9022_SYS_CTRL_DATA:
129
+ if (s->ddc_req) {
130
+ /* Acknowledge DDC bus request */
131
+ res = SII9022_SYS_CTRL_DDC_BUS_GRTD | SII9022_SYS_CTRL_DDC_BUS_REQ;
132
+ }
133
+ break;
134
+ case SII9022_REG_CHIPID:
135
+ res = 0xb0;
136
+ break;
137
+ case SII9022_INT_STATUS:
138
+ /* Something is cold-plugged in, no interrupts */
139
+ res = SII9022_INT_STATUS_PLUGGED;
140
+ break;
141
+ default:
142
+ break;
143
+ }
144
+
145
+ trace_sii9022_read_reg(s->ptr, res);
146
+ s->ptr++;
147
+
148
+ return res;
149
+}
150
+
151
+static int sii9022_tx(I2CSlave *i2c, uint8_t data)
152
+{
153
+ sii9022_state *s = SII9022(i2c);
154
+
155
+ if (s->addr_byte) {
156
+ s->ptr = data;
157
+ s->addr_byte = false;
158
+ return 0;
159
+ }
160
+
161
+ switch (s->ptr) {
162
+ case SII9022_SYS_CTRL_DATA:
163
+ if (data & SII9022_SYS_CTRL_DDC_BUS_REQ) {
164
+ s->ddc_req = true;
165
+ if (data & SII9022_SYS_CTRL_DDC_BUS_GRTD) {
166
+ s->ddc = true;
167
+ /* Skip this finish since we just switched to DDC */
168
+ s->ddc_skip_finish = true;
169
+ trace_sii9022_switch_mode("DDC");
170
+ }
171
+ } else {
172
+ s->ddc_req = false;
173
+ s->ddc = false;
174
+ trace_sii9022_switch_mode("normal");
175
+ }
176
+ break;
177
+ default:
178
+ break;
179
+ }
180
+
181
+ trace_sii9022_write_reg(s->ptr, data);
182
+ s->ptr++;
183
+
184
+ return 0;
185
+}
186
+
187
+static void sii9022_reset(DeviceState *dev)
188
+{
189
+ sii9022_state *s = SII9022(dev);
190
+
191
+ s->ptr = 0;
192
+ s->addr_byte = false;
193
+ s->ddc_req = false;
194
+ s->ddc_skip_finish = false;
195
+ s->ddc = false;
196
+}
197
+
198
+static void sii9022_realize(DeviceState *dev, Error **errp)
199
+{
200
+ I2CBus *bus;
201
+
202
+ bus = I2C_BUS(qdev_get_parent_bus(dev));
203
+ i2c_create_slave(bus, TYPE_I2CDDC, 0x50);
204
+}
205
+
206
+static void sii9022_class_init(ObjectClass *klass, void *data)
207
+{
208
+ DeviceClass *dc = DEVICE_CLASS(klass);
209
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
210
+
211
+ k->event = sii9022_event;
212
+ k->recv = sii9022_rx;
213
+ k->send = sii9022_tx;
214
+ dc->reset = sii9022_reset;
215
+ dc->realize = sii9022_realize;
216
+ dc->vmsd = &vmstate_sii9022;
217
+}
218
+
219
+static const TypeInfo sii9022_info = {
220
+ .name = TYPE_SII9022,
221
+ .parent = TYPE_I2C_SLAVE,
222
+ .instance_size = sizeof(sii9022_state),
223
+ .class_init = sii9022_class_init,
224
+};
483
+};
225
+
484
+
226
+static void sii9022_register_types(void)
485
+DEFINE_TYPES(types)
227
+{
486
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
228
+ type_register_static(&sii9022_info);
229
+}
230
+
231
+type_init(sii9022_register_types)
232
diff --git a/hw/display/trace-events b/hw/display/trace-events
233
index XXXXXXX..XXXXXXX 100644
487
index XXXXXXX..XXXXXXX 100644
234
--- a/hw/display/trace-events
488
--- a/hw/net/Kconfig
235
+++ b/hw/display/trace-events
489
+++ b/hw/net/Kconfig
236
@@ -XXX,XX +XXX,XX @@ vga_cirrus_read_io(uint32_t addr, uint32_t val) "addr 0x%x, val 0x%x"
490
@@ -XXX,XX +XXX,XX @@ config VMXNET3_PCI
237
vga_cirrus_write_io(uint32_t addr, uint32_t val) "addr 0x%x, val 0x%x"
491
config SMC91C111
238
vga_cirrus_read_blt(uint32_t offset, uint32_t val) "offset 0x%x, val 0x%x"
492
bool
239
vga_cirrus_write_blt(uint32_t offset, uint32_t val) "offset 0x%x, val 0x%x"
493
240
+
494
+config LAN9118_PHY
241
+# hw/display/sii9022.c
495
+ bool
242
+sii9022_read_reg(uint8_t addr, uint8_t val) "addr 0x%02x, val 0x%02x"
496
+
243
+sii9022_write_reg(uint8_t addr, uint8_t val) "addr 0x%02x, val 0x%02x"
497
config LAN9118
244
+sii9022_switch_mode(const char *mode) "mode: %s"
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'))
245
--
515
--
246
2.16.2
516
2.34.1
247
248
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
3
imx_fec models the same PHY as lan9118_phy. The code is almost the same with
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
imx_fec having more logging and tracing. Merge these improvements into
5
Message-id: 20180227143852.11175-3-alex.bennee@linaro.org
5
lan9118_phy and reuse in imx_fec to fix the code duplication.
6
[PMM: postpone actually enabling feature until end of the
6
7
patch series]
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
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
19
---
10
target/arm/cpu.h | 1 +
20
include/hw/net/imx_fec.h | 9 ++-
11
1 file changed, 1 insertion(+)
21
hw/net/imx_fec.c | 146 ++++-----------------------------------
22
hw/net/lan9118_phy.c | 82 ++++++++++++++++------
23
hw/net/Kconfig | 1 +
24
hw/net/trace-events | 10 +--
25
5 files changed, 85 insertions(+), 163 deletions(-)
12
26
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
14
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
29
--- a/include/hw/net/imx_fec.h
16
+++ b/target/arm/cpu.h
30
+++ b/include/hw/net/imx_fec.h
17
@@ -XXX,XX +XXX,XX @@ enum arm_features {
31
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXFECState, IMX_FEC)
18
ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
32
#define TYPE_IMX_ENET "imx.enet"
19
ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
33
20
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
34
#include "hw/sysbus.h"
21
+ ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
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
},
22
};
80
};
23
81
24
static inline int arm_feature(CPUARMState *env, int feature)
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"
25
--
471
--
26
2.16.2
472
2.34.1
27
28
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
3
Turns 0x70 into 0xe0 (== 0x70 << 1) which adds the missing MII_ANLPAR_TX and
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
fixes the MSB of selector field to be zero, as specified in the datasheet.
5
Message-id: 20180227143852.11175-26-alex.bennee@linaro.org
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
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
12
---
8
target/arm/helper-a64.h | 1 +
13
hw/net/lan9118_phy.c | 2 +-
9
target/arm/helper-a64.c | 13 +++++++++++++
14
1 file changed, 1 insertion(+), 1 deletion(-)
10
target/arm/translate-a64.c | 5 +++++
11
3 files changed, 19 insertions(+)
12
15
13
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-a64.h
18
--- a/hw/net/lan9118_phy.c
16
+++ b/target/arm/helper-a64.h
19
+++ b/hw/net/lan9118_phy.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(advsimd_rinth_exact, f16, f16, ptr)
20
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
18
DEF_HELPER_2(advsimd_rinth, f16, f16, ptr)
21
val = s->advertise;
19
DEF_HELPER_2(advsimd_f16tosinth, i32, f16, ptr)
20
DEF_HELPER_2(advsimd_f16touinth, i32, f16, ptr)
21
+DEF_HELPER_2(sqrt_f16, f16, f16, ptr)
22
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/helper-a64.c
25
+++ b/target/arm/helper-a64.c
26
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(advsimd_f16touinth)(float16 a, void *fpstp)
27
}
28
return float16_to_uint16(a, fpst);
29
}
30
+
31
+/*
32
+ * Square Root and Reciprocal square root
33
+ */
34
+
35
+float16 HELPER(sqrt_f16)(float16 a, void *fpstp)
36
+{
37
+ float_status *s = fpstp;
38
+
39
+ return float16_sqrt(a, s);
40
+}
41
+
42
+
43
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/translate-a64.c
46
+++ b/target/arm/translate-a64.c
47
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
48
case 0x6f: /* FNEG */
49
need_fpst = false;
50
break;
22
break;
51
+ case 0x7f: /* FSQRT (vector) */
23
case 5: /* Auto-neg Link Partner Ability */
52
+ break;
24
- val = 0x0f71;
53
default:
25
+ val = 0x0fe1;
54
fprintf(stderr, "%s: insn %#04x fpop %#2x\n", __func__, insn, fpop);
26
break;
55
g_assert_not_reached();
27
case 6: /* Auto-neg Expansion */
56
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
28
val = 1;
57
case 0x6f: /* FNEG */
58
tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
59
break;
60
+ case 0x7f: /* FSQRT */
61
+ gen_helper_sqrt_f16(tcg_res, tcg_op, tcg_fpstatus);
62
+ break;
63
default:
64
g_assert_not_reached();
65
}
66
--
29
--
67
2.16.2
30
2.34.1
68
69
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
Only one half-precision instruction has been added to this group.
3
Prefer named constants over magic values for better readability.
4
4
5
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
7
Message-id: 20180227143852.11175-29-alex.bennee@linaro.org
7
Tested-by: Guenter Roeck <linux@roeck-us.net>
8
Message-id: 20241102125724.532843-5-shentey@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/translate-a64.c | 35 +++++++++++++++++++++++++----------
11
include/hw/net/mii.h | 6 +++++
11
1 file changed, 25 insertions(+), 10 deletions(-)
12
hw/net/lan9118_phy.c | 63 ++++++++++++++++++++++++++++----------------
13
2 files changed, 46 insertions(+), 23 deletions(-)
12
14
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
diff --git a/include/hw/net/mii.h b/include/hw/net/mii.h
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
17
--- a/include/hw/net/mii.h
16
+++ b/target/arm/translate-a64.c
18
+++ b/include/hw/net/mii.h
17
@@ -XXX,XX +XXX,XX @@ static void disas_simd_copy(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@
18
* MVNI - move inverted (shifted) imm into register
20
#define MII_BMSR_JABBER (1 << 1) /* Jabber detected */
19
* ORR - bitwise OR of (shifted) imm with register
21
#define MII_BMSR_EXTCAP (1 << 0) /* Ext-reg capability */
20
* BIC - bitwise clear of (shifted) imm with register
22
21
+ * With ARMv8.2 we also have:
23
+#define MII_ANAR_RFAULT (1 << 13) /* Say we can detect faults */
22
+ * FMOV half-precision
24
#define MII_ANAR_PAUSE_ASYM (1 << 11) /* Try for asymmetric pause */
23
*/
25
#define MII_ANAR_PAUSE (1 << 10) /* Try for pause */
24
static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
26
#define MII_ANAR_TXFD (1 << 8)
25
{
27
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
28
#define MII_ANAR_10FD (1 << 6)
27
uint64_t imm = 0;
29
#define MII_ANAR_10 (1 << 5)
28
30
#define MII_ANAR_CSMACD (1 << 0)
29
if (o2 != 0 || ((cmode == 0xf) && is_neg && !is_q)) {
31
+#define MII_ANAR_SELECT (0x001f) /* Selector bits */
30
- unallocated_encoding(s);
32
31
- return;
33
#define MII_ANLPAR_ACK (1 << 14)
32
+ /* Check for FMOV (vector, immediate) - half-precision */
34
#define MII_ANLPAR_PAUSEASY (1 << 11) /* can pause asymmetrically */
33
+ if (!(arm_dc_feature(s, ARM_FEATURE_V8_FP16) && o2 && cmode == 0xf)) {
35
@@ -XXX,XX +XXX,XX @@
34
+ unallocated_encoding(s);
36
#define RTL8201CP_PHYID1 0x0000
35
+ return;
37
#define RTL8201CP_PHYID2 0x8201
36
+ }
38
37
}
39
+/* SMSC LAN9118 */
38
40
+#define SMSCLAN9118_PHYID1 0x0007
39
if (!fp_access_check(s)) {
41
+#define SMSCLAN9118_PHYID2 0xc0d1
40
@@ -XXX,XX +XXX,XX @@ static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
42
+
41
imm |= 0x4000000000000000ULL;
43
/* RealTek 8211E */
42
}
44
#define RTL8211E_PHYID1 0x001c
43
} else {
45
#define RTL8211E_PHYID2 0xc915
44
- imm = (abcdefgh & 0x3f) << 19;
46
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
45
- if (abcdefgh & 0x80) {
47
index XXXXXXX..XXXXXXX 100644
46
- imm |= 0x80000000;
48
--- a/hw/net/lan9118_phy.c
47
- }
49
+++ b/hw/net/lan9118_phy.c
48
- if (abcdefgh & 0x40) {
50
@@ -XXX,XX +XXX,XX @@
49
- imm |= 0x3e000000;
51
50
+ if (o2) {
52
#include "qemu/osdep.h"
51
+ /* FMOV (vector, immediate) - half-precision */
53
#include "hw/net/lan9118_phy.h"
52
+ imm = vfp_expand_imm(MO_16, abcdefgh);
54
+#include "hw/net/mii.h"
53
+ /* now duplicate across the lanes */
55
#include "hw/irq.h"
54
+ imm = bitfield_replicate(imm, 16);
56
#include "hw/resettable.h"
55
} else {
57
#include "migration/vmstate.h"
56
- imm |= 0x40000000;
58
@@ -XXX,XX +XXX,XX @@ uint16_t lan9118_phy_read(Lan9118PhyState *s, int reg)
57
+ imm = (abcdefgh & 0x3f) << 19;
59
uint16_t val;
58
+ if (abcdefgh & 0x80) {
60
59
+ imm |= 0x80000000;
61
switch (reg) {
60
+ }
62
- case 0: /* Basic Control */
61
+ if (abcdefgh & 0x40) {
63
+ case MII_BMCR:
62
+ imm |= 0x3e000000;
64
val = s->control;
63
+ } else {
65
break;
64
+ imm |= 0x40000000;
66
- case 1: /* Basic Status */
65
+ }
67
+ case MII_BMSR:
66
+ imm |= (imm << 32);
68
val = s->status;
67
}
69
break;
68
- imm |= (imm << 32);
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;
69
}
117
}
70
}
118
}
71
break;
119
break;
72
+ default:
120
- case 4: /* Auto-neg advertisement */
73
+ fprintf(stderr, "%s: cmode_3_1: %x\n", __func__, cmode_3_1);
121
- s->advertise = (val & 0x2d7f) | 0x80;
74
+ g_assert_not_reached();
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;
75
}
143
}
76
144
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_reset(Lan9118PhyState *s)
77
if (cmode_3_1 != 7 && is_neg) {
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);
78
--
166
--
79
2.16.2
167
2.34.1
80
81
diff view generated by jsdifflib
1
From: Linus Walleij <linus.walleij@linaro.org>
1
From: Bernhard Beschow <shentey@gmail.com>
2
2
3
The tx function of the DDC I2C slave emulation was returning 1
3
The real device advertises this mode and the device model already advertises
4
on all writes resulting in NACK in the I2C bus. Changing it to
4
100 mbps half duplex and 10 mbps full+half duplex. So advertise this mode to
5
0 makes the DDC I2C work fine with bit-banged I2C such as the
5
make the model more realistic.
6
versatile I2C.
7
8
I guess it was not affecting whatever I2C controller this was
9
used with until now, but with the Versatile I2C it surely
10
does not work.
11
6
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
8
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
14
Message-id: 20180227104903.21353-4-linus.walleij@linaro.org
9
Tested-by: Guenter Roeck <linux@roeck-us.net>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20241102125724.532843-6-shentey@gmail.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
12
---
18
hw/i2c/i2c-ddc.c | 4 ++--
13
hw/net/lan9118_phy.c | 4 ++--
19
1 file changed, 2 insertions(+), 2 deletions(-)
14
1 file changed, 2 insertions(+), 2 deletions(-)
20
15
21
diff --git a/hw/i2c/i2c-ddc.c b/hw/i2c/i2c-ddc.c
16
diff --git a/hw/net/lan9118_phy.c b/hw/net/lan9118_phy.c
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/i2c/i2c-ddc.c
18
--- a/hw/net/lan9118_phy.c
24
+++ b/hw/i2c/i2c-ddc.c
19
+++ b/hw/net/lan9118_phy.c
25
@@ -XXX,XX +XXX,XX @@ static int i2c_ddc_tx(I2CSlave *i2c, uint8_t data)
20
@@ -XXX,XX +XXX,XX @@ void lan9118_phy_write(Lan9118PhyState *s, int reg, uint16_t val)
26
s->reg = data;
21
break;
27
s->firstbyte = false;
22
case MII_ANAR:
28
DPRINTF("[EDID] Written new pointer: %u\n", data);
23
s->advertise = (val & (MII_ANAR_RFAULT | MII_ANAR_PAUSE_ASYM |
29
- return 1;
24
- MII_ANAR_PAUSE | MII_ANAR_10FD | MII_ANAR_10 |
30
+ return 0;
25
- MII_ANAR_SELECT))
31
}
26
+ MII_ANAR_PAUSE | MII_ANAR_TXFD | MII_ANAR_10FD |
32
27
+ MII_ANAR_10 | MII_ANAR_SELECT))
33
/* Ignore all writes */
28
| MII_ANAR_TX;
34
s->reg++;
29
break;
35
- return 1;
30
case 30: /* Interrupt mask */
36
+ return 0;
37
}
38
39
static void i2c_ddc_init(Object *obj)
40
--
31
--
41
2.16.2
32
2.34.1
42
43
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
For IEEE fused multiply-add, the (0 * inf) + NaN case should raise
2
Invalid for the multiplication of 0 by infinity. Currently we handle
3
this in the per-architecture ifdef ladder in pickNaNMulAdd().
4
However, since this isn't really architecture specific we can hoist
5
it up to the generic code.
2
6
3
Much like recpe the ARM ARM has simplified the pseudo code for the
7
For the cases where the infzero test in pickNaNMulAdd was
4
calculation which is done on a fixed point 9 bit integer maths. So
8
returning 2, we can delete the check entirely and allow the
5
while adding f16 we can also clean this up to be a little less heavy
9
code to fall into the normal pick-a-NaN handling, because this
6
on the floating point and just return the fractional part and leave
10
will return 2 anyway (input 'c' being the only NaN in this case).
7
the calle's to do the final packing of the result.
11
For the cases where infzero was returning 3 to indicate "return
12
the default NaN", we must retain that "return 3".
8
13
9
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
14
For Arm, this looks like it might be a behaviour change because we
15
used to set float_flag_invalid | float_flag_invalid_imz only if C is
16
a quiet NaN. However, it is not, because Arm target code never looks
17
at float_flag_invalid_imz, and for the (0 * inf) + SNaN case we
18
already raised float_flag_invalid via the "abc_mask &
19
float_cmask_snan" check in pick_nan_muladd.
20
21
For any target architecture using the "default implementation" at the
22
bottom of the ifdef, this is a behaviour change but will be fixing a
23
bug (where we failed to raise the Invalid exception for (0 * inf +
24
QNaN). The architectures using the default case are:
25
* hppa
26
* i386
27
* sh4
28
* tricore
29
30
The x86, Tricore and SH4 CPU architecture manuals are clear that this
31
should have raised Invalid; HPPA is a bit vaguer but still seems
32
clear enough.
33
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180227143852.11175-27-alex.bennee@linaro.org
36
Message-id: 20241202131347.498124-2-peter.maydell@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
37
---
14
target/arm/helper.h | 1 +
38
fpu/softfloat-parts.c.inc | 13 +++++++------
15
target/arm/helper.c | 221 ++++++++++++++++++++++++----------------------------
39
fpu/softfloat-specialize.c.inc | 29 +----------------------------
16
2 files changed, 104 insertions(+), 118 deletions(-)
40
2 files changed, 8 insertions(+), 34 deletions(-)
17
41
18
diff --git a/target/arm/helper.h b/target/arm/helper.h
42
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
19
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.h
44
--- a/fpu/softfloat-parts.c.inc
21
+++ b/target/arm/helper.h
45
+++ b/fpu/softfloat-parts.c.inc
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
46
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
23
DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
47
int ab_mask, int abc_mask)
24
DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
25
DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
26
+DEF_HELPER_FLAGS_2(rsqrte_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
27
DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
28
DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
29
DEF_HELPER_2(recpe_u32, i32, i32, ptr)
30
diff --git a/target/arm/helper.c b/target/arm/helper.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/helper.c
33
+++ b/target/arm/helper.c
34
@@ -XXX,XX +XXX,XX @@ float64 HELPER(recpe_f64)(float64 input, void *fpstp)
35
/* The algorithm that must be used to calculate the estimate
36
* is specified by the ARM ARM.
37
*/
38
-static float64 recip_sqrt_estimate(float64 a, float_status *real_fp_status)
39
+
40
+static int do_recip_sqrt_estimate(int a)
41
{
48
{
42
- /* These calculations mustn't set any fp exception flags,
49
int which;
43
- * so we use a local copy of the fp_status.
50
+ bool infzero = (ab_mask == float_cmask_infzero);
44
- */
51
45
- float_status dummy_status = *real_fp_status;
52
if (unlikely(abc_mask & float_cmask_snan)) {
46
- float_status *s = &dummy_status;
53
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
47
- float64 q;
48
- int64_t q_int;
49
+ int b, estimate;
50
51
- if (float64_lt(a, float64_half, s)) {
52
- /* range 0.25 <= a < 0.5 */
53
-
54
- /* a in units of 1/512 rounded down */
55
- /* q0 = (int)(a * 512.0); */
56
- q = float64_mul(float64_512, a, s);
57
- q_int = float64_to_int64_round_to_zero(q, s);
58
-
59
- /* reciprocal root r */
60
- /* r = 1.0 / sqrt(((double)q0 + 0.5) / 512.0); */
61
- q = int64_to_float64(q_int, s);
62
- q = float64_add(q, float64_half, s);
63
- q = float64_div(q, float64_512, s);
64
- q = float64_sqrt(q, s);
65
- q = float64_div(float64_one, q, s);
66
+ assert(128 <= a && a < 512);
67
+ if (a < 256) {
68
+ a = a * 2 + 1;
69
} else {
70
- /* range 0.5 <= a < 1.0 */
71
-
72
- /* a in units of 1/256 rounded down */
73
- /* q1 = (int)(a * 256.0); */
74
- q = float64_mul(float64_256, a, s);
75
- int64_t q_int = float64_to_int64_round_to_zero(q, s);
76
-
77
- /* reciprocal root r */
78
- /* r = 1.0 /sqrt(((double)q1 + 0.5) / 256); */
79
- q = int64_to_float64(q_int, s);
80
- q = float64_add(q, float64_half, s);
81
- q = float64_div(q, float64_256, s);
82
- q = float64_sqrt(q, s);
83
- q = float64_div(float64_one, q, s);
84
+ a = (a >> 1) << 1;
85
+ a = (a + 1) * 2;
86
}
54
}
87
- /* r in units of 1/256 rounded to nearest */
55
88
- /* s = (int)(256.0 * r + 0.5); */
56
- which = pickNaNMulAdd(a->cls, b->cls, c->cls,
89
+ b = 512;
57
- ab_mask == float_cmask_infzero, s);
90
+ while (a * (b + 1) * (b + 1) < (1 << 28)) {
58
+ if (infzero) {
91
+ b += 1;
59
+ /* This is (0 * inf) + NaN or (inf * 0) + NaN */
92
+ }
60
+ float_raise(float_flag_invalid | float_flag_invalid_imz, s);
93
+ estimate = (b + 1) / 2;
94
+ assert(256 <= estimate && estimate < 512);
95
96
- q = float64_mul(q, float64_256,s );
97
- q = float64_add(q, float64_half, s);
98
- q_int = float64_to_int64_round_to_zero(q, s);
99
+ return estimate;
100
+}
101
102
- /* return (double)s / 256.0;*/
103
- return float64_div(int64_to_float64(q_int, s), float64_256, s);
104
+
105
+static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac)
106
+{
107
+ int estimate;
108
+ uint32_t scaled;
109
+
110
+ if (*exp == 0) {
111
+ while (extract64(frac, 51, 1) == 0) {
112
+ frac = frac << 1;
113
+ *exp -= 1;
114
+ }
115
+ frac = extract64(frac, 0, 51) << 1;
116
+ }
61
+ }
117
+
62
+
118
+ if (*exp & 1) {
63
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
119
+ /* scaled = UInt('01':fraction<51:45>) */
64
120
+ scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
65
if (s->default_nan_mode || which == 3) {
121
+ } else {
66
- /*
122
+ /* scaled = UInt('1':fraction<51:44>) */
67
- * Note that this check is after pickNaNMulAdd so that function
123
+ scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
68
- * has an opportunity to set the Invalid flag for infzero.
124
+ }
69
- */
125
+ estimate = do_recip_sqrt_estimate(scaled);
70
parts_default_nan(a, s);
71
return a;
72
}
73
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
74
index XXXXXXX..XXXXXXX 100644
75
--- a/fpu/softfloat-specialize.c.inc
76
+++ b/fpu/softfloat-specialize.c.inc
77
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
78
* the default NaN
79
*/
80
if (infzero && is_qnan(c_cls)) {
81
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
82
return 3;
83
}
84
85
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
86
* case sets InvalidOp and returns the default NaN
87
*/
88
if (infzero) {
89
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
90
return 3;
91
}
92
/* Prefer sNaN over qNaN, in the a, b, c order. */
93
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
94
* For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
95
* case sets InvalidOp and returns the input value 'c'
96
*/
97
- if (infzero) {
98
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
99
- return 2;
100
- }
101
/* Prefer sNaN over qNaN, in the c, a, b order. */
102
if (is_snan(c_cls)) {
103
return 2;
104
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
105
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
106
* case sets InvalidOp and returns the input value 'c'
107
*/
108
- if (infzero) {
109
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
110
- return 2;
111
- }
126
+
112
+
127
+ *exp = (exp_off - *exp) / 2;
113
/* Prefer sNaN over qNaN, in the c, a, b order. */
128
+ return extract64(estimate, 0, 8) << 44;
114
if (is_snan(c_cls)) {
129
+}
115
return 2;
130
+
116
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
131
+float16 HELPER(rsqrte_f16)(float16 input, void *fpstp)
117
* to return an input NaN if we have one (ie c) rather than generating
132
+{
118
* a default NaN
133
+ float_status *s = fpstp;
119
*/
134
+ float16 f16 = float16_squash_input_denormal(input, s);
120
- if (infzero) {
135
+ uint16_t val = float16_val(f16);
121
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
136
+ bool f16_sign = float16_is_neg(f16);
122
- return 2;
137
+ int f16_exp = extract32(val, 10, 5);
138
+ uint16_t f16_frac = extract32(val, 0, 10);
139
+ uint64_t f64_frac;
140
+
141
+ if (float16_is_any_nan(f16)) {
142
+ float16 nan = f16;
143
+ if (float16_is_signaling_nan(f16, s)) {
144
+ float_raise(float_flag_invalid, s);
145
+ nan = float16_maybe_silence_nan(f16, s);
146
+ }
147
+ if (s->default_nan_mode) {
148
+ nan = float16_default_nan(s);
149
+ }
150
+ return nan;
151
+ } else if (float16_is_zero(f16)) {
152
+ float_raise(float_flag_divbyzero, s);
153
+ return float16_set_sign(float16_infinity, f16_sign);
154
+ } else if (f16_sign) {
155
+ float_raise(float_flag_invalid, s);
156
+ return float16_default_nan(s);
157
+ } else if (float16_is_infinity(f16)) {
158
+ return float16_zero;
159
+ }
160
+
161
+ /* Scale and normalize to a double-precision value between 0.25 and 1.0,
162
+ * preserving the parity of the exponent. */
163
+
164
+ f64_frac = ((uint64_t) f16_frac) << (52 - 10);
165
+
166
+ f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac);
167
+
168
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
169
+ val = deposit32(0, 15, 1, f16_sign);
170
+ val = deposit32(val, 10, 5, f16_exp);
171
+ val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
172
+ return make_float16(val);
173
}
174
175
float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
176
@@ -XXX,XX +XXX,XX @@ float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
177
float_status *s = fpstp;
178
float32 f32 = float32_squash_input_denormal(input, s);
179
uint32_t val = float32_val(f32);
180
- uint32_t f32_sbit = 0x80000000 & val;
181
- int32_t f32_exp = extract32(val, 23, 8);
182
+ uint32_t f32_sign = float32_is_neg(f32);
183
+ int f32_exp = extract32(val, 23, 8);
184
uint32_t f32_frac = extract32(val, 0, 23);
185
uint64_t f64_frac;
186
- uint64_t val64;
187
- int result_exp;
188
- float64 f64;
189
190
if (float32_is_any_nan(f32)) {
191
float32 nan = f32;
192
@@ -XXX,XX +XXX,XX @@ float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
193
* preserving the parity of the exponent. */
194
195
f64_frac = ((uint64_t) f32_frac) << 29;
196
- if (f32_exp == 0) {
197
- while (extract64(f64_frac, 51, 1) == 0) {
198
- f64_frac = f64_frac << 1;
199
- f32_exp = f32_exp-1;
200
- }
201
- f64_frac = extract64(f64_frac, 0, 51) << 1;
202
- }
123
- }
203
124
204
- if (extract64(f32_exp, 0, 1) == 0) {
125
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
205
- f64 = make_float64(((uint64_t) f32_sbit) << 32
126
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
206
- | (0x3feULL << 52)
127
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
207
- | f64_frac);
128
return 1;
208
- } else {
129
}
209
- f64 = make_float64(((uint64_t) f32_sbit) << 32
130
#elif defined(TARGET_RISCV)
210
- | (0x3fdULL << 52)
131
- /* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
211
- | f64_frac);
132
- if (infzero) {
133
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
212
- }
134
- }
213
+ f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac);
135
return 3; /* default NaN */
214
136
#elif defined(TARGET_S390X)
215
- result_exp = (380 - f32_exp) / 2;
137
if (infzero) {
216
-
138
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
217
- f64 = recip_sqrt_estimate(f64, s);
139
return 3;
218
-
219
- val64 = float64_val(f64);
220
-
221
- val = ((result_exp & 0xff) << 23)
222
- | ((val64 >> 29) & 0x7fffff);
223
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(15) */
224
+ val = deposit32(0, 31, 1, f32_sign);
225
+ val = deposit32(val, 23, 8, f32_exp);
226
+ val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
227
return make_float32(val);
228
}
229
230
@@ -XXX,XX +XXX,XX @@ float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
231
float_status *s = fpstp;
232
float64 f64 = float64_squash_input_denormal(input, s);
233
uint64_t val = float64_val(f64);
234
- uint64_t f64_sbit = 0x8000000000000000ULL & val;
235
- int64_t f64_exp = extract64(val, 52, 11);
236
+ bool f64_sign = float64_is_neg(f64);
237
+ int f64_exp = extract64(val, 52, 11);
238
uint64_t f64_frac = extract64(val, 0, 52);
239
- int64_t result_exp;
240
- uint64_t result_frac;
241
242
if (float64_is_any_nan(f64)) {
243
float64 nan = f64;
244
@@ -XXX,XX +XXX,XX @@ float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
245
return float64_zero;
246
}
140
}
247
141
248
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
142
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
249
- * preserving the parity of the exponent. */
143
return 2;
250
+ f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac);
144
}
251
145
#elif defined(TARGET_SPARC)
252
- if (f64_exp == 0) {
146
- /* For (inf,0,nan) return c. */
253
- while (extract64(f64_frac, 51, 1) == 0) {
147
- if (infzero) {
254
- f64_frac = f64_frac << 1;
148
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
255
- f64_exp = f64_exp - 1;
149
- return 2;
256
- }
257
- f64_frac = extract64(f64_frac, 0, 51) << 1;
258
- }
150
- }
259
-
151
/* Prefer SNaN over QNaN, order C, B, A. */
260
- if (extract64(f64_exp, 0, 1) == 0) {
152
if (is_snan(c_cls)) {
261
- f64 = make_float64(f64_sbit
153
return 2;
262
- | (0x3feULL << 52)
154
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
263
- | f64_frac);
155
* For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
264
- } else {
156
* an input NaN if we have one (ie c).
265
- f64 = make_float64(f64_sbit
157
*/
266
- | (0x3fdULL << 52)
158
- if (infzero) {
267
- | f64_frac);
159
- float_raise(float_flag_invalid | float_flag_invalid_imz, status);
160
- return 2;
268
- }
161
- }
269
-
162
if (status->use_first_nan) {
270
- result_exp = (3068 - f64_exp) / 2;
163
if (is_nan(a_cls)) {
271
-
164
return 0;
272
- f64 = recip_sqrt_estimate(f64, s);
273
-
274
- result_frac = extract64(float64_val(f64), 0, 52);
275
-
276
- return make_float64(f64_sbit |
277
- ((result_exp & 0x7ff) << 52) |
278
- result_frac);
279
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
280
+ val = deposit64(0, 61, 1, f64_sign);
281
+ val = deposit64(val, 52, 11, f64_exp);
282
+ val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
283
+ return make_float64(val);
284
}
285
286
uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
287
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
288
289
uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
290
{
291
- float_status *fpst = fpstp;
292
- float64 f64;
293
+ int estimate;
294
295
if ((a & 0xc0000000) == 0) {
296
return 0xffffffff;
297
}
298
299
- if (a & 0x80000000) {
300
- f64 = make_float64((0x3feULL << 52)
301
- | ((uint64_t)(a & 0x7fffffff) << 21));
302
- } else { /* bits 31-30 == '01' */
303
- f64 = make_float64((0x3fdULL << 52)
304
- | ((uint64_t)(a & 0x3fffffff) << 22));
305
- }
306
+ estimate = do_recip_sqrt_estimate(extract32(a, 23, 9));
307
308
- f64 = recip_sqrt_estimate(f64, fpst);
309
-
310
- return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
311
+ return deposit32(0, 23, 9, estimate);
312
}
313
314
/* VFPv4 fused multiply-accumulate */
315
--
165
--
316
2.16.2
166
2.34.1
317
318
diff view generated by jsdifflib
New patch
1
If the target sets default_nan_mode then we're always going to return
2
the default NaN, and pickNaNMulAdd() no longer has any side effects.
3
For consistency with pickNaN(), check for default_nan_mode before
4
calling pickNaNMulAdd().
1
5
6
When we convert pickNaNMulAdd() to allow runtime selection of the NaN
7
propagation rule, this means we won't have to make the targets which
8
use default_nan_mode also set a propagation rule.
9
10
Since RiscV always uses default_nan_mode, this allows us to remove
11
its ifdef case from pickNaNMulAdd().
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20241202131347.498124-3-peter.maydell@linaro.org
16
---
17
fpu/softfloat-parts.c.inc | 8 ++++++--
18
fpu/softfloat-specialize.c.inc | 9 +++++++--
19
2 files changed, 13 insertions(+), 4 deletions(-)
20
21
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
22
index XXXXXXX..XXXXXXX 100644
23
--- a/fpu/softfloat-parts.c.inc
24
+++ b/fpu/softfloat-parts.c.inc
25
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
26
float_raise(float_flag_invalid | float_flag_invalid_imz, s);
27
}
28
29
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
30
+ if (s->default_nan_mode) {
31
+ which = 3;
32
+ } else {
33
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
34
+ }
35
36
- if (s->default_nan_mode || which == 3) {
37
+ if (which == 3) {
38
parts_default_nan(a, s);
39
return a;
40
}
41
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
42
index XXXXXXX..XXXXXXX 100644
43
--- a/fpu/softfloat-specialize.c.inc
44
+++ b/fpu/softfloat-specialize.c.inc
45
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
46
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
47
bool infzero, float_status *status)
48
{
49
+ /*
50
+ * We guarantee not to require the target to tell us how to
51
+ * pick a NaN if we're always returning the default NaN.
52
+ * But if we're not in default-NaN mode then the target must
53
+ * specify.
54
+ */
55
+ assert(!status->default_nan_mode);
56
#if defined(TARGET_ARM)
57
/* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
58
* the default NaN
59
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
60
} else {
61
return 1;
62
}
63
-#elif defined(TARGET_RISCV)
64
- return 3; /* default NaN */
65
#elif defined(TARGET_S390X)
66
if (infzero) {
67
return 3;
68
--
69
2.34.1
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
IEEE 758 does not define a fixed rule for what NaN to return in
2
2
the case of a fused multiply-add of inf * 0 + NaN. Different
3
This is the initial decode skeleton for the Advanced SIMD three same
3
architectures thus do different things:
4
instruction group.
4
* some return the default NaN
5
5
* some return the input NaN
6
The fprintf is purely to aid debugging as the additional instructions
6
* Arm returns the default NaN if the input NaN is quiet,
7
are added. It will be removed once the group is complete.
7
and the input NaN if it is signalling
8
8
9
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
9
We want to make this logic be runtime selected rather than
10
hardcoded into the binary, because:
11
* this will let us have multiple targets in one QEMU binary
12
* the Arm FEAT_AFP architectural feature includes letting
13
the guest select a NaN propagation rule at runtime
14
15
In this commit we add an enum for the propagation rule, the field in
16
float_status, and the corresponding getters and setters. We change
17
pickNaNMulAdd to honour this, but because all targets still leave
18
this field at its default 0 value, the fallback logic will pick the
19
rule type with the old ifdef ladder.
20
21
Note that four architectures both use the muladd softfloat functions
22
and did not have a branch of the ifdef ladder to specify their
23
behaviour (and so were ending up with the "default" case, probably
24
wrongly): i386, HPPA, SH4 and Tricore. SH4 and Tricore both set
25
default_nan_mode, and so will never get into pickNaNMulAdd(). For
26
HPPA and i386 we retain the same behaviour as the old default-case,
27
which is to not ever return the default NaN. This might not be
28
correct but it is not a behaviour change.
29
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180227143852.11175-9-alex.bennee@linaro.org
32
Message-id: 20241202131347.498124-4-peter.maydell@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
33
---
14
target/arm/translate-a64.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++
34
include/fpu/softfloat-helpers.h | 11 ++++
15
1 file changed, 73 insertions(+)
35
include/fpu/softfloat-types.h | 23 +++++++++
16
36
fpu/softfloat-specialize.c.inc | 91 ++++++++++++++++++++++-----------
17
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
37
3 files changed, 95 insertions(+), 30 deletions(-)
38
39
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
18
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/translate-a64.c
41
--- a/include/fpu/softfloat-helpers.h
20
+++ b/target/arm/translate-a64.c
42
+++ b/include/fpu/softfloat-helpers.h
21
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn)
43
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
22
}
44
status->float_2nan_prop_rule = rule;
23
}
45
}
24
46
47
+static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
+ float_status *status)
49
+{
50
+ status->float_infzeronan_rule = rule;
51
+}
52
+
53
static inline void set_flush_to_zero(bool val, float_status *status)
54
{
55
status->flush_to_zero = val;
56
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
57
return status->float_2nan_prop_rule;
58
}
59
60
+static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
61
+{
62
+ return status->float_infzeronan_rule;
63
+}
64
+
65
static inline bool get_flush_to_zero(float_status *status)
66
{
67
return status->flush_to_zero;
68
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
69
index XXXXXXX..XXXXXXX 100644
70
--- a/include/fpu/softfloat-types.h
71
+++ b/include/fpu/softfloat-types.h
72
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
73
float_2nan_prop_x87,
74
} Float2NaNPropRule;
75
25
+/*
76
+/*
26
+ * Advanced SIMD three same (ARMv8.2 FP16 variants)
77
+ * Rule for result of fused multiply-add 0 * Inf + NaN.
78
+ * This must be a NaN, but implementations differ on whether this
79
+ * is the input NaN or the default NaN.
27
+ *
80
+ *
28
+ * 31 30 29 28 24 23 22 21 20 16 15 14 13 11 10 9 5 4 0
81
+ * You don't need to set this if default_nan_mode is enabled.
29
+ * +---+---+---+-----------+---------+------+-----+--------+---+------+------+
82
+ * When not in default-NaN mode, it is an error for the target
30
+ * | 0 | Q | U | 0 1 1 1 0 | a | 1 0 | Rm | 0 0 | opcode | 1 | Rn | Rd |
83
+ * not to set the rule in float_status if it uses muladd, and we
31
+ * +---+---+---+-----------+---------+------+-----+--------+---+------+------+
84
+ * will assert if we need to handle an input NaN and no rule was
32
+ *
85
+ * selected.
33
+ * This includes FMULX, FCMEQ (register), FRECPS, FRSQRTS, FCMGE
34
+ * (register), FACGE, FABD, FCMGT (register) and FACGT.
35
+ *
36
+ */
86
+ */
37
+static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
87
+typedef enum __attribute__((__packed__)) {
38
+{
88
+ /* No propagation rule specified */
39
+ int opcode, fpopcode;
89
+ float_infzeronan_none = 0,
40
+ int is_q, u, a, rm, rn, rd;
90
+ /* Result is never the default NaN (so always the input NaN) */
41
+ int datasize, elements;
91
+ float_infzeronan_dnan_never,
42
+ int pass;
92
+ /* Result is always the default NaN */
43
+ TCGv_ptr fpst;
93
+ float_infzeronan_dnan_always,
44
+
94
+ /* Result is the default NaN if the input NaN is quiet */
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
95
+ float_infzeronan_dnan_if_qnan,
46
+ unallocated_encoding(s);
96
+} FloatInfZeroNaNRule;
47
+ return;
97
+
48
+ }
98
/*
49
+
99
* Floating Point Status. Individual architectures may maintain
50
+ if (!fp_access_check(s)) {
100
* several versions of float_status for different functions. The
51
+ return;
101
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
52
+ }
102
FloatRoundMode float_rounding_mode;
53
+
103
FloatX80RoundPrec floatx80_rounding_precision;
54
+ /* For these floating point ops, the U, a and opcode bits
104
Float2NaNPropRule float_2nan_prop_rule;
55
+ * together indicate the operation.
105
+ FloatInfZeroNaNRule float_infzeronan_rule;
56
+ */
106
bool tininess_before_rounding;
57
+ opcode = extract32(insn, 11, 3);
107
/* should denormalised results go to zero and set the inexact flag? */
58
+ u = extract32(insn, 29, 1);
108
bool flush_to_zero;
59
+ a = extract32(insn, 23, 1);
109
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
60
+ is_q = extract32(insn, 30, 1);
110
index XXXXXXX..XXXXXXX 100644
61
+ rm = extract32(insn, 16, 5);
111
--- a/fpu/softfloat-specialize.c.inc
62
+ rn = extract32(insn, 5, 5);
112
+++ b/fpu/softfloat-specialize.c.inc
63
+ rd = extract32(insn, 0, 5);
113
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
64
+
114
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
65
+ fpopcode = opcode | (a << 3) | (u << 4);
115
bool infzero, float_status *status)
66
+ datasize = is_q ? 128 : 64;
116
{
67
+ elements = datasize / 16;
117
+ FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
68
+
118
+
69
+ fpst = get_fpstatus_ptr(true);
119
/*
70
+
120
* We guarantee not to require the target to tell us how to
71
+ for (pass = 0; pass < elements; pass++) {
121
* pick a NaN if we're always returning the default NaN.
72
+ TCGv_i32 tcg_op1 = tcg_temp_new_i32();
122
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
73
+ TCGv_i32 tcg_op2 = tcg_temp_new_i32();
123
* specify.
74
+ TCGv_i32 tcg_res = tcg_temp_new_i32();
124
*/
75
+
125
assert(!status->default_nan_mode);
76
+ read_vec_element_i32(s, tcg_op1, rn, pass, MO_16);
126
+
77
+ read_vec_element_i32(s, tcg_op2, rm, pass, MO_16);
127
+ if (rule == float_infzeronan_none) {
78
+
128
+ /*
79
+ switch (fpopcode) {
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;
80
+ default:
186
+ default:
81
+ fprintf(stderr, "%s: insn %#04x, fpop %#2x @ %#" PRIx64 "\n",
82
+ __func__, insn, fpopcode, s->pc);
83
+ g_assert_not_reached();
187
+ g_assert_not_reached();
84
+ }
188
+ }
85
+
86
+ write_vec_element_i32(s, tcg_res, rd, pass, MO_16);
87
+ tcg_temp_free_i32(tcg_res);
88
+ tcg_temp_free_i32(tcg_op1);
89
+ tcg_temp_free_i32(tcg_op2);
90
+ }
189
+ }
91
+
190
+
92
+ tcg_temp_free_ptr(fpst);
191
+#if defined(TARGET_ARM)
93
+
192
+
94
+ clear_vec_high(s, is_q, rd);
193
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
95
+}
194
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
96
+
195
*/
97
static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
196
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
98
int size, int rn, int rd)
197
}
99
{
198
#elif defined(TARGET_MIPS)
100
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
199
if (snan_bit_is_one(status)) {
101
{ 0xce000000, 0xff808000, disas_crypto_four_reg },
200
- /*
102
{ 0xce800000, 0xffe00000, disas_crypto_xar },
201
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
103
{ 0xce408000, 0xffe0c000, disas_crypto_three_reg_imm2 },
202
- * case sets InvalidOp and returns the default NaN
104
+ { 0x0e400400, 0x9f60c400, disas_simd_three_reg_same_fp16 },
203
- */
105
{ 0x00000000, 0x00000000, NULL }
204
- if (infzero) {
106
};
205
- return 3;
107
206
- }
207
/* Prefer sNaN over qNaN, in the a, b, c order. */
208
if (is_snan(a_cls)) {
209
return 0;
210
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
211
return 2;
212
}
213
} else {
214
- /*
215
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
216
- * case sets InvalidOp and returns the input value 'c'
217
- */
218
/* Prefer sNaN over qNaN, in the c, a, b order. */
219
if (is_snan(c_cls)) {
220
return 2;
221
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
222
}
223
}
224
#elif defined(TARGET_LOONGARCH64)
225
- /*
226
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
227
- * case sets InvalidOp and returns the input value 'c'
228
- */
229
-
230
/* Prefer sNaN over qNaN, in the c, a, b order. */
231
if (is_snan(c_cls)) {
232
return 2;
233
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
234
return 1;
235
}
236
#elif defined(TARGET_PPC)
237
- /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
238
- * to return an input NaN if we have one (ie c) rather than generating
239
- * a default NaN
240
- */
241
-
242
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
243
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
244
*/
245
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
246
return 1;
247
}
248
#elif defined(TARGET_S390X)
249
- if (infzero) {
250
- return 3;
251
- }
252
-
253
if (is_snan(a_cls)) {
254
return 0;
255
} else if (is_snan(b_cls)) {
108
--
256
--
109
2.16.2
257
2.34.1
110
111
diff view generated by jsdifflib
New patch
1
Explicitly set a rule in the softfloat tests for the inf-zero-nan
2
muladd special case. In meson.build we put -DTARGET_ARM in fpcflags,
3
and so we should select here the Arm rule of
4
float_infzeronan_dnan_if_qnan.
1
5
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20241202131347.498124-5-peter.maydell@linaro.org
9
---
10
tests/fp/fp-bench.c | 5 +++++
11
tests/fp/fp-test.c | 5 +++++
12
2 files changed, 10 insertions(+)
13
14
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/fp/fp-bench.c
17
+++ b/tests/fp/fp-bench.c
18
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
19
{
20
bench_func_t f;
21
22
+ /*
23
+ * These implementation-defined choices for various things IEEE
24
+ * doesn't specify match those used by the Arm architecture.
25
+ */
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
28
29
f = bench_funcs[operation][precision];
30
g_assert(f);
31
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/tests/fp/fp-test.c
34
+++ b/tests/fp/fp-test.c
35
@@ -XXX,XX +XXX,XX @@ void run_test(void)
36
{
37
unsigned int i;
38
39
+ /*
40
+ * These implementation-defined choices for various things IEEE
41
+ * doesn't specify match those used by the Arm architecture.
42
+ */
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
44
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
45
46
genCases_setLevel(test_level);
47
verCases_maxErrorCount = n_max_errors;
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the Arm target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-6-peter.maydell@linaro.org
7
---
8
target/arm/cpu.c | 3 +++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 4 insertions(+), 7 deletions(-)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
17
* * tininess-before-rounding
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
21
+ * and the input NaN if it is signalling
22
*/
23
static void arm_set_default_fp_behaviours(float_status *s)
24
{
25
set_float_detect_tininess(float_tininess_before_rounding, s);
26
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
27
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
28
}
29
30
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
/*
37
* Temporarily fall back to ifdef ladder
38
*/
39
-#if defined(TARGET_ARM)
40
- /*
41
- * For ARM, the (inf,zero,qnan) case returns the default NaN,
42
- * but (inf,zero,snan) returns the input NaN.
43
- */
44
- rule = float_infzeronan_dnan_if_qnan;
45
-#elif defined(TARGET_MIPS)
46
+#if defined(TARGET_MIPS)
47
if (snan_bit_is_one(status)) {
48
/*
49
* For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
50
--
51
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for s390, so we
2
can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-7-peter.maydell@linaro.org
7
---
8
target/s390x/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/s390x/cpu.c
15
+++ b/target/s390x/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
17
set_float_detect_tininess(float_tininess_before_rounding,
18
&env->fpu_status);
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
20
+ set_float_infzeronan_rule(float_infzeronan_dnan_always,
21
+ &env->fpu_status);
22
/* fall through */
23
case RESET_TYPE_S390_CPU_NORMAL:
24
env->psw.mask &= ~PSW_MASK_RI;
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
* a default NaN
31
*/
32
rule = float_infzeronan_dnan_never;
33
-#elif defined(TARGET_S390X)
34
- rule = float_infzeronan_dnan_always;
35
#endif
36
}
37
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the PPC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-8-peter.maydell@linaro.org
7
---
8
target/ppc/cpu_init.c | 7 +++++++
9
fpu/softfloat-specialize.c.inc | 7 +------
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
15
+++ b/target/ppc/cpu_init.c
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
21
+ * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
22
+ * to return an input NaN if we have one (ie c) rather than generating
23
+ * a default NaN
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
27
28
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
29
ppc_spr_t *spr = &env->spr_cb[i];
30
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
31
index XXXXXXX..XXXXXXX 100644
32
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
*/
36
rule = float_infzeronan_dnan_never;
37
}
38
-#elif defined(TARGET_PPC) || defined(TARGET_SPARC) || \
39
+#elif defined(TARGET_SPARC) || \
40
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
41
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
42
/*
43
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
44
* case sets InvalidOp and returns the input value 'c'
45
*/
46
- /*
47
- * For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
48
- * to return an input NaN if we have one (ie c) rather than generating
49
- * a default NaN
50
- */
51
rule = float_infzeronan_dnan_never;
52
#endif
53
}
54
--
55
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the MIPS target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-9-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 9 +++++++++
9
target/mips/msa.c | 4 ++++
10
fpu/softfloat-specialize.c.inc | 16 +---------------
11
3 files changed, 14 insertions(+), 15 deletions(-)
12
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_flush_mode(CPUMIPSState *env)
18
static inline void restore_snan_bit_mode(CPUMIPSState *env)
19
{
20
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
21
+ FloatInfZeroNaNRule izn_rule;
22
23
/*
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
*/
27
set_snan_bit_is_one(!nan2008, &env->active_fpu.fp_status);
28
set_default_nan_mode(!nan2008, &env->active_fpu.fp_status);
29
+ /*
30
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
31
+ * case sets InvalidOp and returns the default NaN.
32
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
33
+ * case sets InvalidOp and returns the input value 'c'.
34
+ */
35
+ izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
36
+ set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
37
}
38
39
static inline void restore_fp_status(CPUMIPSState *env)
40
diff --git a/target/mips/msa.c b/target/mips/msa.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/mips/msa.c
43
+++ b/target/mips/msa.c
44
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
45
46
/* set proper signanling bit meaning ("1" means "quiet") */
47
set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
48
+
49
+ /* Inf * 0 + NaN returns the input NaN */
50
+ set_float_infzeronan_rule(float_infzeronan_dnan_never,
51
+ &env->active_tc.msa_fp_status);
52
}
53
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
54
index XXXXXXX..XXXXXXX 100644
55
--- a/fpu/softfloat-specialize.c.inc
56
+++ b/fpu/softfloat-specialize.c.inc
57
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
58
/*
59
* Temporarily fall back to ifdef ladder
60
*/
61
-#if defined(TARGET_MIPS)
62
- if (snan_bit_is_one(status)) {
63
- /*
64
- * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
65
- * case sets InvalidOp and returns the default NaN
66
- */
67
- rule = float_infzeronan_dnan_always;
68
- } else {
69
- /*
70
- * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
71
- * case sets InvalidOp and returns the input value 'c'
72
- */
73
- rule = float_infzeronan_dnan_never;
74
- }
75
-#elif defined(TARGET_SPARC) || \
76
+#if defined(TARGET_SPARC) || \
77
defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
78
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
79
/*
80
--
81
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the SPARC target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-10-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 +--
10
2 files changed, 3 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
23
cpu_exec_realizefn(cs, &local_err);
24
if (local_err != NULL) {
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_SPARC) || \
34
- defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
35
+#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
36
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
37
/*
38
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the xtensa target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-11-peter.maydell@linaro.org
7
---
8
target/xtensa/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 +-
10
2 files changed, 3 insertions(+), 1 deletion(-)
11
12
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/xtensa/cpu.c
15
+++ b/target/xtensa/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
17
reset_mmu(env);
18
cs->halted = env->runstall;
19
#endif
20
+ /* For inf * 0 + NaN, return the input NaN */
21
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
22
set_no_signaling_nans(!dfpu, &env->fp_status);
23
xtensa_use_first_nan(env, !dfpu);
24
}
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
/*
31
* Temporarily fall back to ifdef ladder
32
*/
33
-#if defined(TARGET_XTENSA) || defined(TARGET_HPPA) || \
34
+#if defined(TARGET_HPPA) || \
35
defined(TARGET_I386) || defined(TARGET_LOONGARCH)
36
/*
37
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
38
--
39
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the x86 target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-12-peter.maydell@linaro.org
6
---
7
target/i386/tcg/fpu_helper.c | 7 +++++++
8
fpu/softfloat-specialize.c.inc | 2 +-
9
2 files changed, 8 insertions(+), 1 deletion(-)
10
11
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/i386/tcg/fpu_helper.c
14
+++ b/target/i386/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->mmx_status);
18
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->sse_status);
19
+ /*
20
+ * Only SSE has multiply-add instructions. In the SDM Section 14.5.2
21
+ * "Fused-Multiply-ADD (FMA) Numeric Behavior" the NaN handling is
22
+ * specified -- for 0 * inf + NaN the input NaN is selected, and if
23
+ * there are multiple input NaNs they are selected in the order a, b, c.
24
+ */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
26
}
27
28
static inline uint8_t save_exception_flags(CPUX86State *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
34
* Temporarily fall back to ifdef ladder
35
*/
36
#if defined(TARGET_HPPA) || \
37
- defined(TARGET_I386) || defined(TARGET_LOONGARCH)
38
+ defined(TARGET_LOONGARCH)
39
/*
40
* For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
41
* case sets InvalidOp and returns the input value 'c'
42
--
43
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the loongarch target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-13-peter.maydell@linaro.org
6
---
7
target/loongarch/tcg/fpu_helper.c | 5 +++++
8
fpu/softfloat-specialize.c.inc | 7 +------
9
2 files changed, 6 insertions(+), 6 deletions(-)
10
11
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/loongarch/tcg/fpu_helper.c
14
+++ b/target/loongarch/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
16
&env->fp_status);
17
set_flush_to_zero(0, &env->fp_status);
18
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
19
+ /*
20
+ * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
21
+ * case sets InvalidOp and returns the input value 'c'
22
+ */
23
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
}
25
26
int ieee_ex_to_loongarch(int xcpt)
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
index XXXXXXX..XXXXXXX 100644
29
--- a/fpu/softfloat-specialize.c.inc
30
+++ b/fpu/softfloat-specialize.c.inc
31
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
32
/*
33
* Temporarily fall back to ifdef ladder
34
*/
35
-#if defined(TARGET_HPPA) || \
36
- defined(TARGET_LOONGARCH)
37
- /*
38
- * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
39
- * case sets InvalidOp and returns the input value 'c'
40
- */
41
+#if defined(TARGET_HPPA)
42
rule = float_infzeronan_dnan_never;
43
#endif
44
}
45
--
46
2.34.1
diff view generated by jsdifflib
New patch
1
Set the FloatInfZeroNaNRule explicitly for the HPPA target,
2
so we can remove the ifdef from pickNaNMulAdd().
1
3
4
As this is the last target to be converted to explicitly setting
5
the rule, we can remove the fallback code in pickNaNMulAdd()
6
entirely.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20241202131347.498124-14-peter.maydell@linaro.org
11
---
12
target/hppa/fpu_helper.c | 2 ++
13
fpu/softfloat-specialize.c.inc | 13 +------------
14
2 files changed, 3 insertions(+), 12 deletions(-)
15
16
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/hppa/fpu_helper.c
19
+++ b/target/hppa/fpu_helper.c
20
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
21
* HPPA does note implement a CPU reset method at all...
22
*/
23
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
24
+ /* For inf * 0 + NaN, return the input NaN */
25
+ set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
26
}
27
28
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
29
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
30
index XXXXXXX..XXXXXXX 100644
31
--- a/fpu/softfloat-specialize.c.inc
32
+++ b/fpu/softfloat-specialize.c.inc
33
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
34
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
35
bool infzero, float_status *status)
36
{
37
- FloatInfZeroNaNRule rule = status->float_infzeronan_rule;
38
-
39
/*
40
* We guarantee not to require the target to tell us how to
41
* pick a NaN if we're always returning the default NaN.
42
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
43
*/
44
assert(!status->default_nan_mode);
45
46
- if (rule == float_infzeronan_none) {
47
- /*
48
- * Temporarily fall back to ifdef ladder
49
- */
50
-#if defined(TARGET_HPPA)
51
- rule = float_infzeronan_dnan_never;
52
-#endif
53
- }
54
-
55
if (infzero) {
56
/*
57
* Inf * 0 + NaN -- some implementations return the default NaN here,
58
* and some return the input NaN.
59
*/
60
- switch (rule) {
61
+ switch (status->float_infzeronan_rule) {
62
case float_infzeronan_dnan_never:
63
return 2;
64
case float_infzeronan_dnan_always:
65
--
66
2.34.1
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
The new implementation of pickNaNMulAdd() will find it convenient
2
to know whether at least one of the three arguments to the muladd
3
was a signaling NaN. We already calculate that in the caller,
4
so pass it in as a new bool have_snan.
2
5
3
The helpers use the new re-factored muladd support in SoftFloat for
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the float16 work.
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241202131347.498124-15-peter.maydell@linaro.org
9
---
10
fpu/softfloat-parts.c.inc | 5 +++--
11
fpu/softfloat-specialize.c.inc | 2 +-
12
2 files changed, 4 insertions(+), 3 deletions(-)
5
13
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
7
Message-id: 20180227143852.11175-15-alex.bennee@linaro.org
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/translate-a64.c | 82 +++++++++++++++++++++++++++++++++++++---------
12
1 file changed, 66 insertions(+), 16 deletions(-)
13
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
16
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/translate-a64.c
17
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
19
int rd = extract32(insn, 0, 5);
19
{
20
bool is_long = false;
20
int which;
21
bool is_fp = false;
21
bool infzero = (ab_mask == float_cmask_infzero);
22
+ bool is_fp16 = false;
22
+ bool have_snan = (abc_mask & float_cmask_snan);
23
int index;
23
24
TCGv_ptr fpst;
24
- if (unlikely(abc_mask & float_cmask_snan)) {
25
25
+ if (unlikely(have_snan)) {
26
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
27
}
28
/* fall through */
29
case 0x9: /* FMUL, FMULX */
30
- if (!extract32(size, 1, 1)) {
31
+ if (size == 1) {
32
unallocated_encoding(s);
33
return;
34
}
35
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
36
}
27
}
37
28
38
if (is_fp) {
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
39
- /* low bit of size indicates single/double */
30
if (s->default_nan_mode) {
40
- size = extract32(size, 0, 1) ? 3 : 2;
31
which = 3;
41
- if (size == 2) {
42
+ /* convert insn encoded size to TCGMemOp size */
43
+ switch (size) {
44
+ case 2: /* single precision */
45
+ size = MO_32;
46
index = h << 1 | l;
47
- } else {
48
+ rm |= (m << 4);
49
+ break;
50
+ case 3: /* double precision */
51
+ size = MO_64;
52
if (l || !is_q) {
53
unallocated_encoding(s);
54
return;
55
}
56
index = h;
57
+ rm |= (m << 4);
58
+ break;
59
+ case 0: /* half precision */
60
+ size = MO_16;
61
+ index = h << 2 | l << 1 | m;
62
+ is_fp16 = true;
63
+ if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
64
+ break;
65
+ }
66
+ /* fallthru */
67
+ default: /* unallocated */
68
+ unallocated_encoding(s);
69
+ return;
70
}
71
- rm |= (m << 4);
72
} else {
32
} else {
73
switch (size) {
33
- which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, s);
74
case 1:
34
+ which = pickNaNMulAdd(a->cls, b->cls, c->cls, infzero, have_snan, s);
75
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
76
}
35
}
77
36
78
if (is_fp) {
37
if (which == 3) {
79
- fpst = get_fpstatus_ptr(false);
38
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
80
+ fpst = get_fpstatus_ptr(is_fp16);
39
index XXXXXXX..XXXXXXX 100644
81
} else {
40
--- a/fpu/softfloat-specialize.c.inc
82
fpst = NULL;
41
+++ b/fpu/softfloat-specialize.c.inc
83
}
42
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
84
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
43
| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
85
break;
44
*----------------------------------------------------------------------------*/
86
}
45
static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
87
case 0x5: /* FMLS */
46
- bool infzero, float_status *status)
88
- /* As usual for ARM, separate negation for fused multiply-add */
47
+ bool infzero, bool have_snan, float_status *status)
89
- gen_helper_vfp_negs(tcg_op, tcg_op);
48
{
90
- /* fall through */
49
/*
91
case 0x1: /* FMLA */
50
* We guarantee not to require the target to tell us how to
92
- read_vec_element_i32(s, tcg_res, rd, pass, MO_32);
93
- gen_helper_vfp_muladds(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
94
+ read_vec_element_i32(s, tcg_res, rd, pass,
95
+ is_scalar ? size : MO_32);
96
+ switch (size) {
97
+ case 1:
98
+ if (opcode == 0x5) {
99
+ /* As usual for ARM, separate negation for fused
100
+ * multiply-add */
101
+ tcg_gen_xori_i32(tcg_op, tcg_op, 0x80008000);
102
+ }
103
+ gen_helper_advsimd_muladdh(tcg_res, tcg_op, tcg_idx,
104
+ tcg_res, fpst);
105
+ break;
106
+ case 2:
107
+ if (opcode == 0x5) {
108
+ /* As usual for ARM, separate negation for
109
+ * fused multiply-add */
110
+ tcg_gen_xori_i32(tcg_op, tcg_op, 0x80000000);
111
+ }
112
+ gen_helper_vfp_muladds(tcg_res, tcg_op, tcg_idx,
113
+ tcg_res, fpst);
114
+ break;
115
+ default:
116
+ g_assert_not_reached();
117
+ }
118
break;
119
case 0x9: /* FMUL, FMULX */
120
- if (u) {
121
- gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
122
- } else {
123
- gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
124
+ switch (size) {
125
+ case 1:
126
+ if (u) {
127
+ gen_helper_advsimd_mulxh(tcg_res, tcg_op, tcg_idx,
128
+ fpst);
129
+ } else {
130
+ g_assert_not_reached();
131
+ }
132
+ break;
133
+ case 2:
134
+ if (u) {
135
+ gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
136
+ } else {
137
+ gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
138
+ }
139
+ break;
140
+ default:
141
+ g_assert_not_reached();
142
}
143
break;
144
case 0xc: /* SQDMULH */
145
--
51
--
146
2.16.2
52
2.34.1
147
148
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
IEEE 758 does not define a fixed rule for which NaN to pick as the
2
2
result if both operands of a 3-operand fused multiply-add operation
3
It looks like the ARM ARM has simplified the pseudo code for the
3
are NaNs. As a result different architectures have ended up with
4
calculation which is done on a fixed point 9 bit integer maths. So
4
different rules for propagating NaNs.
5
while adding f16 we can also clean this up to be a little less heavy
5
6
on the floating point and just return the fractional part and leave
6
QEMU currently hardcodes the NaN propagation logic into the binary
7
the calle's to do the final packing of the result.
7
because pickNaNMulAdd() has an ifdef ladder for different targets.
8
8
We want to make the propagation rule instead be selectable at
9
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
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.
23
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180227143852.11175-23-alex.bennee@linaro.org
26
Message-id: 20241202131347.498124-16-peter.maydell@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
27
---
14
target/arm/helper.h | 1 +
28
include/fpu/softfloat-helpers.h | 11 +++
15
target/arm/helper.c | 226 +++++++++++++++++++++++++++++-----------------------
29
include/fpu/softfloat-types.h | 55 +++++++++++
16
2 files changed, 129 insertions(+), 98 deletions(-)
30
fpu/softfloat-specialize.c.inc | 167 ++++++++------------------------
17
31
3 files changed, 107 insertions(+), 126 deletions(-)
18
diff --git a/target/arm/helper.h b/target/arm/helper.h
32
33
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
19
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.h
35
--- a/include/fpu/softfloat-helpers.h
21
+++ b/target/arm/helper.h
36
+++ b/include/fpu/softfloat-helpers.h
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
37
@@ -XXX,XX +XXX,XX @@ static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
23
38
status->float_2nan_prop_rule = rule;
24
DEF_HELPER_3(recps_f32, f32, f32, f32, env)
39
}
25
DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
40
26
+DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
41
+static inline void set_float_3nan_prop_rule(Float3NaNPropRule rule,
27
DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
42
+ float_status *status)
28
DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
43
+{
29
DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
44
+ status->float_3nan_prop_rule = rule;
30
diff --git a/target/arm/helper.c b/target/arm/helper.c
45
+}
46
+
47
static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
48
float_status *status)
49
{
50
@@ -XXX,XX +XXX,XX @@ static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
51
return status->float_2nan_prop_rule;
52
}
53
54
+static inline Float3NaNPropRule get_float_3nan_prop_rule(float_status *status)
55
+{
56
+ return status->float_3nan_prop_rule;
57
+}
58
+
59
static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status)
60
{
61
return status->float_infzeronan_rule;
62
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
31
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/helper.c
64
--- a/include/fpu/softfloat-types.h
33
+++ b/target/arm/helper.c
65
+++ b/include/fpu/softfloat-types.h
34
@@ -XXX,XX +XXX,XX @@ float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
66
@@ -XXX,XX +XXX,XX @@ this code that are retained.
35
* int->float conversions at run-time. */
67
#ifndef SOFTFLOAT_TYPES_H
36
#define float64_256 make_float64(0x4070000000000000LL)
68
#define SOFTFLOAT_TYPES_H
37
#define float64_512 make_float64(0x4080000000000000LL)
69
38
+#define float16_maxnorm make_float16(0x7bff)
70
+#include "hw/registerfields.h"
39
#define float32_maxnorm make_float32(0x7f7fffff)
71
+
40
#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
72
/*
41
73
* Software IEC/IEEE floating-point types.
42
/* Reciprocal functions
43
*
44
* The algorithm that must be used to calculate the estimate
45
- * is specified by the ARM ARM, see FPRecipEstimate()
46
+ * is specified by the ARM ARM, see FPRecipEstimate()/RecipEstimate
47
*/
74
*/
48
75
@@ -XXX,XX +XXX,XX @@ typedef enum __attribute__((__packed__)) {
49
-static float64 recip_estimate(float64 a, float_status *real_fp_status)
76
float_2nan_prop_x87,
50
+/* See RecipEstimate()
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.
51
+ *
84
+ *
52
+ * input is a 9 bit fixed point number
85
+ * If default_nan_mode is enabled then it is valid not to set a NaN
53
+ * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
86
+ * propagation rule, because the softfloat code guarantees not to try
54
+ * result range 256 .. 511 for a number from 1.0 to 511/256.
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.
55
+ */
99
+ */
56
+
100
+
57
+static int recip_estimate(int input)
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)
58
{
149
{
59
- /* These calculations mustn't set any fp exception flags,
150
+ FloatClass cls[3] = { a_cls, b_cls, c_cls };
60
- * so we use a local copy of the fp_status.
151
+ Float3NaNPropRule rule = status->float_3nan_prop_rule;
61
- */
152
+ int which;
62
- float_status dummy_status = *real_fp_status;
153
+
63
- float_status *s = &dummy_status;
154
/*
64
- /* q = (int)(a * 512.0) */
155
* We guarantee not to require the target to tell us how to
65
- float64 q = float64_mul(float64_512, a, s);
156
* pick a NaN if we're always returning the default NaN.
66
- int64_t q_int = float64_to_int64_round_to_zero(q, s);
157
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
67
-
68
- /* r = 1.0 / (((double)q + 0.5) / 512.0) */
69
- q = int64_to_float64(q_int, s);
70
- q = float64_add(q, float64_half, s);
71
- q = float64_div(q, float64_512, s);
72
- q = float64_div(float64_one, q, s);
73
-
74
- /* s = (int)(256.0 * r + 0.5) */
75
- q = float64_mul(q, float64_256, s);
76
- q = float64_add(q, float64_half, s);
77
- q_int = float64_to_int64_round_to_zero(q, s);
78
-
79
- /* return (double)s / 256.0 */
80
- return float64_div(int64_to_float64(q_int, s), float64_256, s);
81
+ int a, b, r;
82
+ assert(256 <= input && input < 512);
83
+ a = (input * 2) + 1;
84
+ b = (1 << 19) / a;
85
+ r = (b + 1) >> 1;
86
+ assert(256 <= r && r < 512);
87
+ return r;
88
}
89
90
-/* Common wrapper to call recip_estimate */
91
-static float64 call_recip_estimate(float64 num, int off, float_status *fpst)
92
-{
93
- uint64_t val64 = float64_val(num);
94
- uint64_t frac = extract64(val64, 0, 52);
95
- int64_t exp = extract64(val64, 52, 11);
96
- uint64_t sbit;
97
- float64 scaled, estimate;
98
+/*
99
+ * Common wrapper to call recip_estimate
100
+ *
101
+ * The parameters are exponent and 64 bit fraction (without implicit
102
+ * bit) where the binary point is nominally at bit 52. Returns a
103
+ * float64 which can then be rounded to the appropriate size by the
104
+ * callee.
105
+ */
106
107
- /* Generate the scaled number for the estimate function */
108
- if (exp == 0) {
109
+static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac)
110
+{
111
+ uint32_t scaled, estimate;
112
+ uint64_t result_frac;
113
+ int result_exp;
114
+
115
+ /* Handle sub-normals */
116
+ if (*exp == 0) {
117
if (extract64(frac, 51, 1) == 0) {
118
- exp = -1;
119
- frac = extract64(frac, 0, 50) << 2;
120
+ *exp = -1;
121
+ frac <<= 2;
122
} else {
123
- frac = extract64(frac, 0, 51) << 1;
124
+ frac <<= 1;
125
}
158
}
126
}
159
}
127
160
128
- /* scaled = '0' : '01111111110' : fraction<51:44> : Zeros(44); */
161
+ if (rule == float_3nan_prop_none) {
129
- scaled = make_float64((0x3feULL << 52)
162
#if defined(TARGET_ARM)
130
- | extract64(frac, 44, 8) << 44);
131
+ /* scaled = UInt('1':fraction<51:44>) */
132
+ scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
133
+ estimate = recip_estimate(scaled);
134
135
- estimate = recip_estimate(scaled, fpst);
136
-
163
-
137
- /* Build new result */
164
- /* This looks different from the ARM ARM pseudocode, because the ARM ARM
138
- val64 = float64_val(estimate);
165
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
139
- sbit = 0x8000000000000000ULL & val64;
166
- */
140
- exp = off - exp;
167
- if (is_snan(c_cls)) {
141
- frac = extract64(val64, 0, 52);
168
- return 2;
142
-
169
- } else if (is_snan(a_cls)) {
143
- if (exp == 0) {
170
- return 0;
144
- frac = 1ULL << 51 | extract64(frac, 1, 51);
171
- } else if (is_snan(b_cls)) {
145
- } else if (exp == -1) {
172
- return 1;
146
- frac = 1ULL << 50 | extract64(frac, 2, 50);
173
- } else if (is_qnan(c_cls)) {
147
- exp = 0;
174
- return 2;
148
+ result_exp = exp_off - *exp;
175
- } else if (is_qnan(a_cls)) {
149
+ result_frac = deposit64(0, 44, 8, estimate);
176
- return 0;
150
+ if (result_exp == 0) {
177
- } else {
151
+ result_frac = deposit64(result_frac >> 1, 51, 1, 1);
178
- return 1;
152
+ } else if (result_exp == -1) {
179
- }
153
+ result_frac = deposit64(result_frac >> 2, 50, 2, 1);
180
+ /*
154
+ result_exp = 0;
181
+ * This looks different from the ARM ARM pseudocode, because the ARM ARM
155
}
182
+ * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
156
183
+ */
157
- return make_float64(sbit | (exp << 52) | frac);
184
+ rule = float_3nan_prop_s_cab;
158
+ *exp = result_exp;
185
#elif defined(TARGET_MIPS)
159
+
186
- if (snan_bit_is_one(status)) {
160
+ return result_frac;
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;
161
}
337
}
162
338
163
static bool round_to_inf(float_status *fpst, bool sign_bit)
339
/*----------------------------------------------------------------------------
164
@@ -XXX,XX +XXX,XX @@ static bool round_to_inf(float_status *fpst, bool sign_bit)
165
g_assert_not_reached();
166
}
167
168
+float16 HELPER(recpe_f16)(float16 input, void *fpstp)
169
+{
170
+ float_status *fpst = fpstp;
171
+ float16 f16 = float16_squash_input_denormal(input, fpst);
172
+ uint32_t f16_val = float16_val(f16);
173
+ uint32_t f16_sign = float16_is_neg(f16);
174
+ int f16_exp = extract32(f16_val, 10, 5);
175
+ uint32_t f16_frac = extract32(f16_val, 0, 10);
176
+ uint64_t f64_frac;
177
+
178
+ if (float16_is_any_nan(f16)) {
179
+ float16 nan = f16;
180
+ if (float16_is_signaling_nan(f16, fpst)) {
181
+ float_raise(float_flag_invalid, fpst);
182
+ nan = float16_maybe_silence_nan(f16, fpst);
183
+ }
184
+ if (fpst->default_nan_mode) {
185
+ nan = float16_default_nan(fpst);
186
+ }
187
+ return nan;
188
+ } else if (float16_is_infinity(f16)) {
189
+ return float16_set_sign(float16_zero, float16_is_neg(f16));
190
+ } else if (float16_is_zero(f16)) {
191
+ float_raise(float_flag_divbyzero, fpst);
192
+ return float16_set_sign(float16_infinity, float16_is_neg(f16));
193
+ } else if (float16_abs(f16) < (1 << 8)) {
194
+ /* Abs(value) < 2.0^-16 */
195
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
196
+ if (round_to_inf(fpst, f16_sign)) {
197
+ return float16_set_sign(float16_infinity, f16_sign);
198
+ } else {
199
+ return float16_set_sign(float16_maxnorm, f16_sign);
200
+ }
201
+ } else if (f16_exp >= 29 && fpst->flush_to_zero) {
202
+ float_raise(float_flag_underflow, fpst);
203
+ return float16_set_sign(float16_zero, float16_is_neg(f16));
204
+ }
205
+
206
+ f64_frac = call_recip_estimate(&f16_exp, 29,
207
+ ((uint64_t) f16_frac) << (52 - 10));
208
+
209
+ /* result = sign : result_exp<4:0> : fraction<51:42> */
210
+ f16_val = deposit32(0, 15, 1, f16_sign);
211
+ f16_val = deposit32(f16_val, 10, 5, f16_exp);
212
+ f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
213
+ return make_float16(f16_val);
214
+}
215
+
216
float32 HELPER(recpe_f32)(float32 input, void *fpstp)
217
{
218
float_status *fpst = fpstp;
219
float32 f32 = float32_squash_input_denormal(input, fpst);
220
uint32_t f32_val = float32_val(f32);
221
- uint32_t f32_sbit = 0x80000000ULL & f32_val;
222
- int32_t f32_exp = extract32(f32_val, 23, 8);
223
+ bool f32_sign = float32_is_neg(f32);
224
+ int f32_exp = extract32(f32_val, 23, 8);
225
uint32_t f32_frac = extract32(f32_val, 0, 23);
226
- float64 f64, r64;
227
- uint64_t r64_val;
228
- int64_t r64_exp;
229
- uint64_t r64_frac;
230
+ uint64_t f64_frac;
231
232
if (float32_is_any_nan(f32)) {
233
float32 nan = f32;
234
@@ -XXX,XX +XXX,XX @@ float32 HELPER(recpe_f32)(float32 input, void *fpstp)
235
} else if (float32_is_zero(f32)) {
236
float_raise(float_flag_divbyzero, fpst);
237
return float32_set_sign(float32_infinity, float32_is_neg(f32));
238
- } else if ((f32_val & ~(1ULL << 31)) < (1ULL << 21)) {
239
+ } else if (float32_abs(f32) < (1ULL << 21)) {
240
/* Abs(value) < 2.0^-128 */
241
float_raise(float_flag_overflow | float_flag_inexact, fpst);
242
- if (round_to_inf(fpst, f32_sbit)) {
243
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
244
+ if (round_to_inf(fpst, f32_sign)) {
245
+ return float32_set_sign(float32_infinity, f32_sign);
246
} else {
247
- return float32_set_sign(float32_maxnorm, float32_is_neg(f32));
248
+ return float32_set_sign(float32_maxnorm, f32_sign);
249
}
250
} else if (f32_exp >= 253 && fpst->flush_to_zero) {
251
float_raise(float_flag_underflow, fpst);
252
return float32_set_sign(float32_zero, float32_is_neg(f32));
253
}
254
255
+ f64_frac = call_recip_estimate(&f32_exp, 253,
256
+ ((uint64_t) f32_frac) << (52 - 23));
257
258
- f64 = make_float64(((int64_t)(f32_exp) << 52) | (int64_t)(f32_frac) << 29);
259
- r64 = call_recip_estimate(f64, 253, fpst);
260
- r64_val = float64_val(r64);
261
- r64_exp = extract64(r64_val, 52, 11);
262
- r64_frac = extract64(r64_val, 0, 52);
263
-
264
- /* result = sign : result_exp<7:0> : fraction<51:29>; */
265
- return make_float32(f32_sbit |
266
- (r64_exp & 0xff) << 23 |
267
- extract64(r64_frac, 29, 24));
268
+ /* result = sign : result_exp<7:0> : fraction<51:29> */
269
+ f32_val = deposit32(0, 31, 1, f32_sign);
270
+ f32_val = deposit32(f32_val, 23, 8, f32_exp);
271
+ f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
272
+ return make_float32(f32_val);
273
}
274
275
float64 HELPER(recpe_f64)(float64 input, void *fpstp)
276
@@ -XXX,XX +XXX,XX @@ float64 HELPER(recpe_f64)(float64 input, void *fpstp)
277
float_status *fpst = fpstp;
278
float64 f64 = float64_squash_input_denormal(input, fpst);
279
uint64_t f64_val = float64_val(f64);
280
- uint64_t f64_sbit = 0x8000000000000000ULL & f64_val;
281
- int64_t f64_exp = extract64(f64_val, 52, 11);
282
- float64 r64;
283
- uint64_t r64_val;
284
- int64_t r64_exp;
285
- uint64_t r64_frac;
286
+ bool f64_sign = float64_is_neg(f64);
287
+ int f64_exp = extract64(f64_val, 52, 11);
288
+ uint64_t f64_frac = extract64(f64_val, 0, 52);
289
290
/* Deal with any special cases */
291
if (float64_is_any_nan(f64)) {
292
@@ -XXX,XX +XXX,XX @@ float64 HELPER(recpe_f64)(float64 input, void *fpstp)
293
} else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
294
/* Abs(value) < 2.0^-1024 */
295
float_raise(float_flag_overflow | float_flag_inexact, fpst);
296
- if (round_to_inf(fpst, f64_sbit)) {
297
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
298
+ if (round_to_inf(fpst, f64_sign)) {
299
+ return float64_set_sign(float64_infinity, f64_sign);
300
} else {
301
- return float64_set_sign(float64_maxnorm, float64_is_neg(f64));
302
+ return float64_set_sign(float64_maxnorm, f64_sign);
303
}
304
} else if (f64_exp >= 2045 && fpst->flush_to_zero) {
305
float_raise(float_flag_underflow, fpst);
306
return float64_set_sign(float64_zero, float64_is_neg(f64));
307
}
308
309
- r64 = call_recip_estimate(f64, 2045, fpst);
310
- r64_val = float64_val(r64);
311
- r64_exp = extract64(r64_val, 52, 11);
312
- r64_frac = extract64(r64_val, 0, 52);
313
+ f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac);
314
315
- /* result = sign : result_exp<10:0> : fraction<51:0> */
316
- return make_float64(f64_sbit |
317
- ((r64_exp & 0x7ff) << 52) |
318
- r64_frac);
319
+ /* result = sign : result_exp<10:0> : fraction<51:0>; */
320
+ f64_val = deposit64(0, 63, 1, f64_sign);
321
+ f64_val = deposit64(f64_val, 52, 11, f64_exp);
322
+ f64_val = deposit64(f64_val, 0, 52, f64_frac);
323
+ return make_float64(f64_val);
324
}
325
326
/* The algorithm that must be used to calculate the estimate
327
@@ -XXX,XX +XXX,XX @@ float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
328
329
uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
330
{
331
- float_status *s = fpstp;
332
- float64 f64;
333
+ /* float_status *s = fpstp; */
334
+ int input, estimate;
335
336
if ((a & 0x80000000) == 0) {
337
return 0xffffffff;
338
}
339
340
- f64 = make_float64((0x3feULL << 52)
341
- | ((int64_t)(a & 0x7fffffff) << 21));
342
+ input = extract32(a, 23, 9);
343
+ estimate = recip_estimate(input);
344
345
- f64 = recip_estimate(f64, s);
346
-
347
- return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
348
+ return deposit32(0, (32 - 9), 9, estimate);
349
}
350
351
uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
352
--
340
--
353
2.16.2
341
2.34.1
354
355
diff view generated by jsdifflib
New patch
1
Explicitly set a rule in the softfloat tests for propagating NaNs in
2
the muladd case. In meson.build we put -DTARGET_ARM in fpcflags, and
3
so we should select here the Arm rule of float_3nan_prop_s_cab.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241202131347.498124-17-peter.maydell@linaro.org
8
---
9
tests/fp/fp-bench.c | 1 +
10
tests/fp/fp-test.c | 1 +
11
2 files changed, 2 insertions(+)
12
13
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/fp/fp-bench.c
16
+++ b/tests/fp/fp-bench.c
17
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
18
* doesn't specify match those used by the Arm architecture.
19
*/
20
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
21
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &soft_status);
22
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
23
24
f = bench_funcs[operation][precision];
25
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/tests/fp/fp-test.c
28
+++ b/tests/fp/fp-test.c
29
@@ -XXX,XX +XXX,XX @@ void run_test(void)
30
* doesn't specify match those used by the Arm architecture.
31
*/
32
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
33
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &qsf);
34
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
35
36
genCases_setLevel(test_level);
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-18-peter.maydell@linaro.org
7
---
8
target/arm/cpu.c | 5 +++++
9
fpu/softfloat-specialize.c.inc | 8 +-------
10
2 files changed, 6 insertions(+), 7 deletions(-)
11
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
17
* * tininess-before-rounding
18
* * 2-input NaN propagation prefers SNaN over QNaN, and then
19
* operand A over operand B (see FPProcessNaNs() pseudocode)
20
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
21
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
22
+ * but note that for QEMU muladd is a * b + c, whereas for
23
+ * the pseudocode function the arguments are in the order c, a, b.
24
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
25
* and the input NaN if it is signalling
26
*/
27
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
28
{
29
set_float_detect_tininess(float_tininess_before_rounding, s);
30
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
31
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
32
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
33
}
34
35
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
36
index XXXXXXX..XXXXXXX 100644
37
--- a/fpu/softfloat-specialize.c.inc
38
+++ b/fpu/softfloat-specialize.c.inc
39
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
40
}
41
42
if (rule == float_3nan_prop_none) {
43
-#if defined(TARGET_ARM)
44
- /*
45
- * This looks different from the ARM ARM pseudocode, because the ARM ARM
46
- * puts the operands to a fused mac operation (a*b)+c in the order c,a,b
47
- */
48
- rule = float_3nan_prop_s_cab;
49
-#elif defined(TARGET_MIPS)
50
+#if defined(TARGET_MIPS)
51
if (snan_bit_is_one(status)) {
52
rule = float_3nan_prop_s_abc;
53
} else {
54
--
55
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for loongarch, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-19-peter.maydell@linaro.org
7
---
8
target/loongarch/tcg/fpu_helper.c | 1 +
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 1 insertion(+), 2 deletions(-)
11
12
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/loongarch/tcg/fpu_helper.c
15
+++ b/target/loongarch/tcg/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
17
* case sets InvalidOp and returns the input value 'c'
18
*/
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
21
}
22
23
int ieee_ex_to_loongarch(int xcpt)
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
29
} else {
30
rule = float_3nan_prop_s_cab;
31
}
32
-#elif defined(TARGET_LOONGARCH64)
33
- rule = float_3nan_prop_s_cab;
34
#elif defined(TARGET_PPC)
35
/*
36
* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for PPC, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-20-peter.maydell@linaro.org
7
---
8
target/ppc/cpu_init.c | 8 ++++++++
9
fpu/softfloat-specialize.c.inc | 6 ------
10
2 files changed, 8 insertions(+), 6 deletions(-)
11
12
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/ppc/cpu_init.c
15
+++ b/target/ppc/cpu_init.c
16
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
17
*/
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
19
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status);
20
+ /*
21
+ * NaN propagation for fused multiply-add:
22
+ * if fRA is a NaN return it; otherwise if fRB is a NaN return it;
23
+ * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
24
+ * whereas QEMU labels the operands as (a * b) + c.
25
+ */
26
+ set_float_3nan_prop_rule(float_3nan_prop_acb, &env->fp_status);
27
+ set_float_3nan_prop_rule(float_3nan_prop_acb, &env->vec_status);
28
/*
29
* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
30
* to return an input NaN if we have one (ie c) rather than generating
31
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
32
index XXXXXXX..XXXXXXX 100644
33
--- a/fpu/softfloat-specialize.c.inc
34
+++ b/fpu/softfloat-specialize.c.inc
35
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
36
} else {
37
rule = float_3nan_prop_s_cab;
38
}
39
-#elif defined(TARGET_PPC)
40
- /*
41
- * If fRA is a NaN return it; otherwise if fRB is a NaN return it;
42
- * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
43
- */
44
- rule = float_3nan_prop_acb;
45
#elif defined(TARGET_S390X)
46
rule = float_3nan_prop_s_abc;
47
#elif defined(TARGET_SPARC)
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for s390x, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-21-peter.maydell@linaro.org
7
---
8
target/s390x/cpu.c | 1 +
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 1 insertion(+), 2 deletions(-)
11
12
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/s390x/cpu.c
15
+++ b/target/s390x/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
17
set_float_detect_tininess(float_tininess_before_rounding,
18
&env->fpu_status);
19
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fpu_status);
20
+ set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
21
set_float_infzeronan_rule(float_infzeronan_dnan_always,
22
&env->fpu_status);
23
/* fall through */
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
25
index XXXXXXX..XXXXXXX 100644
26
--- a/fpu/softfloat-specialize.c.inc
27
+++ b/fpu/softfloat-specialize.c.inc
28
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
29
} else {
30
rule = float_3nan_prop_s_cab;
31
}
32
-#elif defined(TARGET_S390X)
33
- rule = float_3nan_prop_s_abc;
34
#elif defined(TARGET_SPARC)
35
rule = float_3nan_prop_s_cba;
36
#elif defined(TARGET_XTENSA)
37
--
38
2.34.1
diff view generated by jsdifflib
New patch
1
Set the Float3NaNPropRule explicitly for SPARC, and remove the
2
ifdef from pickNaNMulAdd().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-22-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 2 --
10
2 files changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/sparc/cpu.c
15
+++ b/target/sparc/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
17
* the CPU state struct so it won't get zeroed on reset.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &env->fp_status);
20
+ /* For fused-multiply add, prefer SNaN over QNaN, then C->B->A */
21
+ set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
22
/* For inf * 0 + NaN, return the input NaN */
23
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
24
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
30
} else {
31
rule = float_3nan_prop_s_cab;
32
}
33
-#elif defined(TARGET_SPARC)
34
- rule = float_3nan_prop_s_cba;
35
#elif defined(TARGET_XTENSA)
36
if (status->use_first_nan) {
37
rule = float_3nan_prop_abc;
38
--
39
2.34.1
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the Float3NaNPropRule explicitly for Arm, and remove the
2
ifdef from pickNaNMulAdd().
2
3
3
This includes FMAXNMP, FADDP, FMAXP, FMINNMP, FMINP.
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-23-peter.maydell@linaro.org
7
---
8
target/mips/fpu_helper.h | 4 ++++
9
target/mips/msa.c | 3 +++
10
fpu/softfloat-specialize.c.inc | 8 +-------
11
3 files changed, 8 insertions(+), 7 deletions(-)
4
12
5
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
13
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180227143852.11175-14-alex.bennee@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/translate-a64.c | 208 +++++++++++++++++++++++++++++----------------
11
1 file changed, 133 insertions(+), 75 deletions(-)
12
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
15
--- a/target/mips/fpu_helper.h
16
+++ b/target/arm/translate-a64.c
16
+++ b/target/mips/fpu_helper.h
17
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
17
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
18
int datasize, elements;
18
{
19
int pass;
19
bool nan2008 = env->active_fpu.fcr31 & (1 << FCR31_NAN2008);
20
TCGv_ptr fpst;
20
FloatInfZeroNaNRule izn_rule;
21
+ bool pairwise = false;
21
+ Float3NaNPropRule nan3_rule;
22
22
23
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
23
/*
24
unallocated_encoding(s);
24
* With nan2008, SNaNs are silenced in the usual way.
25
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
25
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
26
datasize = is_q ? 128 : 64;
26
*/
27
elements = datasize / 16;
27
izn_rule = nan2008 ? float_infzeronan_dnan_never : float_infzeronan_dnan_always;
28
28
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
29
+ switch (fpopcode) {
29
+ nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
30
+ case 0x10: /* FMAXNMP */
30
+ set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
31
+ case 0x12: /* FADDP */
32
+ case 0x16: /* FMAXP */
33
+ case 0x18: /* FMINNMP */
34
+ case 0x1e: /* FMINP */
35
+ pairwise = true;
36
+ break;
37
+ }
38
+
31
+
39
fpst = get_fpstatus_ptr(true);
32
}
40
33
41
- for (pass = 0; pass < elements; pass++) {
34
static inline void restore_fp_status(CPUMIPSState *env)
42
+ if (pairwise) {
35
diff --git a/target/mips/msa.c b/target/mips/msa.c
43
+ int maxpass = is_q ? 8 : 4;
36
index XXXXXXX..XXXXXXX 100644
44
TCGv_i32 tcg_op1 = tcg_temp_new_i32();
37
--- a/target/mips/msa.c
45
TCGv_i32 tcg_op2 = tcg_temp_new_i32();
38
+++ b/target/mips/msa.c
46
- TCGv_i32 tcg_res = tcg_temp_new_i32();
39
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
47
+ TCGv_i32 tcg_res[8];
40
set_float_2nan_prop_rule(float_2nan_prop_s_ab,
48
41
&env->active_tc.msa_fp_status);
49
- read_vec_element_i32(s, tcg_op1, rn, pass, MO_16);
42
50
- read_vec_element_i32(s, tcg_op2, rm, pass, MO_16);
43
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab,
51
+ for (pass = 0; pass < maxpass; pass++) {
44
+ &env->active_tc.msa_fp_status);
52
+ int passreg = pass < (maxpass / 2) ? rn : rm;
53
+ int passelt = (pass << 1) & (maxpass - 1);
54
55
- switch (fpopcode) {
56
- case 0x0: /* FMAXNM */
57
- gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
58
- break;
59
- case 0x1: /* FMLA */
60
- read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
61
- gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
62
- fpst);
63
- break;
64
- case 0x2: /* FADD */
65
- gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
66
- break;
67
- case 0x3: /* FMULX */
68
- gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
69
- break;
70
- case 0x4: /* FCMEQ */
71
- gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
72
- break;
73
- case 0x6: /* FMAX */
74
- gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
75
- break;
76
- case 0x7: /* FRECPS */
77
- gen_helper_recpsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
78
- break;
79
- case 0x8: /* FMINNM */
80
- gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
81
- break;
82
- case 0x9: /* FMLS */
83
- /* As usual for ARM, separate negation for fused multiply-add */
84
- tcg_gen_xori_i32(tcg_op1, tcg_op1, 0x8000);
85
- read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
86
- gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
87
- fpst);
88
- break;
89
- case 0xa: /* FSUB */
90
- gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
91
- break;
92
- case 0xe: /* FMIN */
93
- gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
94
- break;
95
- case 0xf: /* FRSQRTS */
96
- gen_helper_rsqrtsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
97
- break;
98
- case 0x13: /* FMUL */
99
- gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
100
- break;
101
- case 0x14: /* FCMGE */
102
- gen_helper_advsimd_cge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
103
- break;
104
- case 0x15: /* FACGE */
105
- gen_helper_advsimd_acge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
106
- break;
107
- case 0x17: /* FDIV */
108
- gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
109
- break;
110
- case 0x1a: /* FABD */
111
- gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
112
- tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
113
- break;
114
- case 0x1c: /* FCMGT */
115
- gen_helper_advsimd_cgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
116
- break;
117
- case 0x1d: /* FACGT */
118
- gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
119
- break;
120
- default:
121
- fprintf(stderr, "%s: insn %#04x, fpop %#2x @ %#" PRIx64 "\n",
122
- __func__, insn, fpopcode, s->pc);
123
- g_assert_not_reached();
124
+ read_vec_element_i32(s, tcg_op1, passreg, passelt, MO_16);
125
+ read_vec_element_i32(s, tcg_op2, passreg, passelt + 1, MO_16);
126
+ tcg_res[pass] = tcg_temp_new_i32();
127
+
45
+
128
+ switch (fpopcode) {
46
/* clear float_status exception flags */
129
+ case 0x10: /* FMAXNMP */
47
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
130
+ gen_helper_advsimd_maxnumh(tcg_res[pass], tcg_op1, tcg_op2,
48
131
+ fpst);
49
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
132
+ break;
50
index XXXXXXX..XXXXXXX 100644
133
+ case 0x12: /* FADDP */
51
--- a/fpu/softfloat-specialize.c.inc
134
+ gen_helper_advsimd_addh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
52
+++ b/fpu/softfloat-specialize.c.inc
135
+ break;
53
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
136
+ case 0x16: /* FMAXP */
137
+ gen_helper_advsimd_maxh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
138
+ break;
139
+ case 0x18: /* FMINNMP */
140
+ gen_helper_advsimd_minnumh(tcg_res[pass], tcg_op1, tcg_op2,
141
+ fpst);
142
+ break;
143
+ case 0x1e: /* FMINP */
144
+ gen_helper_advsimd_minh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
145
+ break;
146
+ default:
147
+ g_assert_not_reached();
148
+ }
149
+ }
150
+
151
+ for (pass = 0; pass < maxpass; pass++) {
152
+ write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_16);
153
+ tcg_temp_free_i32(tcg_res[pass]);
154
}
155
156
- write_vec_element_i32(s, tcg_res, rd, pass, MO_16);
157
- tcg_temp_free_i32(tcg_res);
158
tcg_temp_free_i32(tcg_op1);
159
tcg_temp_free_i32(tcg_op2);
160
+
161
+ } else {
162
+ for (pass = 0; pass < elements; pass++) {
163
+ TCGv_i32 tcg_op1 = tcg_temp_new_i32();
164
+ TCGv_i32 tcg_op2 = tcg_temp_new_i32();
165
+ TCGv_i32 tcg_res = tcg_temp_new_i32();
166
+
167
+ read_vec_element_i32(s, tcg_op1, rn, pass, MO_16);
168
+ read_vec_element_i32(s, tcg_op2, rm, pass, MO_16);
169
+
170
+ switch (fpopcode) {
171
+ case 0x0: /* FMAXNM */
172
+ gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
173
+ break;
174
+ case 0x1: /* FMLA */
175
+ read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
176
+ gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
177
+ fpst);
178
+ break;
179
+ case 0x2: /* FADD */
180
+ gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
181
+ break;
182
+ case 0x3: /* FMULX */
183
+ gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
184
+ break;
185
+ case 0x4: /* FCMEQ */
186
+ gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
187
+ break;
188
+ case 0x6: /* FMAX */
189
+ gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
190
+ break;
191
+ case 0x7: /* FRECPS */
192
+ gen_helper_recpsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
193
+ break;
194
+ case 0x8: /* FMINNM */
195
+ gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
196
+ break;
197
+ case 0x9: /* FMLS */
198
+ /* As usual for ARM, separate negation for fused multiply-add */
199
+ tcg_gen_xori_i32(tcg_op1, tcg_op1, 0x8000);
200
+ read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
201
+ gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
202
+ fpst);
203
+ break;
204
+ case 0xa: /* FSUB */
205
+ gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
206
+ break;
207
+ case 0xe: /* FMIN */
208
+ gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
209
+ break;
210
+ case 0xf: /* FRSQRTS */
211
+ gen_helper_rsqrtsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
212
+ break;
213
+ case 0x13: /* FMUL */
214
+ gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
215
+ break;
216
+ case 0x14: /* FCMGE */
217
+ gen_helper_advsimd_cge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
218
+ break;
219
+ case 0x15: /* FACGE */
220
+ gen_helper_advsimd_acge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
221
+ break;
222
+ case 0x17: /* FDIV */
223
+ gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
224
+ break;
225
+ case 0x1a: /* FABD */
226
+ gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
227
+ tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
228
+ break;
229
+ case 0x1c: /* FCMGT */
230
+ gen_helper_advsimd_cgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
231
+ break;
232
+ case 0x1d: /* FACGT */
233
+ gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
234
+ break;
235
+ default:
236
+ fprintf(stderr, "%s: insn %#04x, fpop %#2x @ %#" PRIx64 "\n",
237
+ __func__, insn, fpopcode, s->pc);
238
+ g_assert_not_reached();
239
+ }
240
+
241
+ write_vec_element_i32(s, tcg_res, rd, pass, MO_16);
242
+ tcg_temp_free_i32(tcg_res);
243
+ tcg_temp_free_i32(tcg_op1);
244
+ tcg_temp_free_i32(tcg_op2);
245
+ }
246
}
54
}
247
55
248
tcg_temp_free_ptr(fpst);
56
if (rule == float_3nan_prop_none) {
57
-#if defined(TARGET_MIPS)
58
- if (snan_bit_is_one(status)) {
59
- rule = float_3nan_prop_s_abc;
60
- } else {
61
- rule = float_3nan_prop_s_cab;
62
- }
63
-#elif defined(TARGET_XTENSA)
64
+#if defined(TARGET_XTENSA)
65
if (status->use_first_nan) {
66
rule = float_3nan_prop_abc;
67
} else {
249
--
68
--
250
2.16.2
69
2.34.1
251
252
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the Float3NaNPropRule explicitly for xtensa, and remove the
2
ifdef from pickNaNMulAdd().
2
3
3
This adds the full range of half-precision floating point to integral
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
instructions.
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-24-peter.maydell@linaro.org
7
---
8
target/xtensa/fpu_helper.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 8 --------
10
2 files changed, 2 insertions(+), 8 deletions(-)
5
11
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
12
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180227143852.11175-18-alex.bennee@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper-a64.h | 2 +
12
target/arm/helper-a64.c | 22 ++++++++
13
target/arm/translate-a64.c | 123 +++++++++++++++++++++++++++++++++++++++++++--
14
3 files changed, 142 insertions(+), 5 deletions(-)
15
16
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper-a64.h
14
--- a/target/xtensa/fpu_helper.c
19
+++ b/target/arm/helper-a64.h
15
+++ b/target/xtensa/fpu_helper.c
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(advsimd_maxnum2h, i32, i32, i32, ptr)
16
@@ -XXX,XX +XXX,XX @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
21
DEF_HELPER_3(advsimd_minnum2h, i32, i32, i32, ptr)
17
set_use_first_nan(use_first, &env->fp_status);
22
DEF_HELPER_3(advsimd_mulx2h, i32, i32, i32, ptr)
18
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
23
DEF_HELPER_4(advsimd_muladd2h, i32, i32, i32, i32, ptr)
19
&env->fp_status);
24
+DEF_HELPER_2(advsimd_rinth_exact, f16, f16, ptr)
20
+ set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
25
+DEF_HELPER_2(advsimd_rinth, f16, f16, ptr)
21
+ &env->fp_status);
26
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
22
}
23
24
void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
27
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/helper-a64.c
27
--- a/fpu/softfloat-specialize.c.inc
29
+++ b/target/arm/helper-a64.c
28
+++ b/fpu/softfloat-specialize.c.inc
30
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(advsimd_acgt_f16)(float16 a, float16 b, void *fpstp)
29
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
31
int compare = float16_compare(f0, f1, fpst);
32
return ADVSIMD_CMPRES(compare == float_relation_greater);
33
}
34
+
35
+/* round to integral */
36
+float16 HELPER(advsimd_rinth_exact)(float16 x, void *fp_status)
37
+{
38
+ return float16_round_to_int(x, fp_status);
39
+}
40
+
41
+float16 HELPER(advsimd_rinth)(float16 x, void *fp_status)
42
+{
43
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
44
+ float16 ret;
45
+
46
+ ret = float16_round_to_int(x, fp_status);
47
+
48
+ /* Suppress any inexact exceptions the conversion produced */
49
+ if (!(old_flags & float_flag_inexact)) {
50
+ new_flags = get_float_exception_flags(fp_status);
51
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
52
+ }
53
+
54
+ return ret;
55
+}
56
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/translate-a64.c
59
+++ b/target/arm/translate-a64.c
60
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
61
*/
62
static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
63
{
64
- int fpop, opcode, a;
65
+ int fpop, opcode, a, u;
66
+ int rn, rd;
67
+ bool is_q;
68
+ bool is_scalar;
69
+ bool only_in_vector = false;
70
+
71
+ int pass;
72
+ TCGv_i32 tcg_rmode = NULL;
73
+ TCGv_ptr tcg_fpstatus = NULL;
74
+ bool need_rmode = false;
75
+ int rmode;
76
77
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
78
unallocated_encoding(s);
79
return;
80
}
30
}
81
31
82
- if (!fp_access_check(s)) {
32
if (rule == float_3nan_prop_none) {
83
- return;
33
-#if defined(TARGET_XTENSA)
84
- }
34
- if (status->use_first_nan) {
85
+ rd = extract32(insn, 0, 5);
35
- rule = float_3nan_prop_abc;
86
+ rn = extract32(insn, 5, 5);
36
- } else {
87
37
- rule = float_3nan_prop_cba;
88
- opcode = extract32(insn, 12, 4);
38
- }
89
a = extract32(insn, 23, 1);
39
-#else
90
+ u = extract32(insn, 29, 1);
40
rule = float_3nan_prop_abc;
91
+ is_scalar = extract32(insn, 28, 1);
41
-#endif
92
+ is_q = extract32(insn, 30, 1);
93
+
94
+ opcode = extract32(insn, 12, 5);
95
fpop = deposit32(opcode, 5, 1, a);
96
+ fpop = deposit32(fpop, 6, 1, u);
97
98
switch (fpop) {
99
+ case 0x18: /* FRINTN */
100
+ need_rmode = true;
101
+ only_in_vector = true;
102
+ rmode = FPROUNDING_TIEEVEN;
103
+ break;
104
+ case 0x19: /* FRINTM */
105
+ need_rmode = true;
106
+ only_in_vector = true;
107
+ rmode = FPROUNDING_NEGINF;
108
+ break;
109
+ case 0x38: /* FRINTP */
110
+ need_rmode = true;
111
+ only_in_vector = true;
112
+ rmode = FPROUNDING_POSINF;
113
+ break;
114
+ case 0x39: /* FRINTZ */
115
+ need_rmode = true;
116
+ only_in_vector = true;
117
+ rmode = FPROUNDING_ZERO;
118
+ break;
119
+ case 0x58: /* FRINTA */
120
+ need_rmode = true;
121
+ only_in_vector = true;
122
+ rmode = FPROUNDING_TIEAWAY;
123
+ break;
124
+ case 0x59: /* FRINTX */
125
+ case 0x79: /* FRINTI */
126
+ only_in_vector = true;
127
+ /* current rounding mode */
128
+ break;
129
default:
130
fprintf(stderr, "%s: insn %#04x fpop %#2x\n", __func__, insn, fpop);
131
g_assert_not_reached();
132
}
42
}
133
43
134
+
44
assert(rule != float_3nan_prop_none);
135
+ /* Check additional constraints for the scalar encoding */
136
+ if (is_scalar) {
137
+ if (!is_q) {
138
+ unallocated_encoding(s);
139
+ return;
140
+ }
141
+ /* FRINTxx is only in the vector form */
142
+ if (only_in_vector) {
143
+ unallocated_encoding(s);
144
+ return;
145
+ }
146
+ }
147
+
148
+ if (!fp_access_check(s)) {
149
+ return;
150
+ }
151
+
152
+ if (need_rmode) {
153
+ tcg_fpstatus = get_fpstatus_ptr(true);
154
+ }
155
+
156
+ if (need_rmode) {
157
+ tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
158
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
159
+ }
160
+
161
+ if (is_scalar) {
162
+ /* no operations yet */
163
+ } else {
164
+ for (pass = 0; pass < (is_q ? 8 : 4); pass++) {
165
+ TCGv_i32 tcg_op = tcg_temp_new_i32();
166
+ TCGv_i32 tcg_res = tcg_temp_new_i32();
167
+
168
+ read_vec_element_i32(s, tcg_op, rn, pass, MO_16);
169
+
170
+ switch (fpop) {
171
+ case 0x18: /* FRINTN */
172
+ case 0x19: /* FRINTM */
173
+ case 0x38: /* FRINTP */
174
+ case 0x39: /* FRINTZ */
175
+ case 0x58: /* FRINTA */
176
+ case 0x79: /* FRINTI */
177
+ gen_helper_advsimd_rinth(tcg_res, tcg_op, tcg_fpstatus);
178
+ break;
179
+ case 0x59: /* FRINTX */
180
+ gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, tcg_fpstatus);
181
+ break;
182
+ default:
183
+ g_assert_not_reached();
184
+ }
185
+
186
+ write_vec_element_i32(s, tcg_res, rd, pass, MO_16);
187
+
188
+ tcg_temp_free_i32(tcg_res);
189
+ tcg_temp_free_i32(tcg_op);
190
+ }
191
+
192
+ clear_vec_high(s, is_q, rd);
193
+ }
194
+
195
+ if (tcg_rmode) {
196
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
197
+ tcg_temp_free_i32(tcg_rmode);
198
+ }
199
+
200
+ if (tcg_fpstatus) {
201
+ tcg_temp_free_ptr(tcg_fpstatus);
202
+ }
203
}
204
205
/* AdvSIMD scalar x indexed element
206
--
45
--
207
2.16.2
46
2.34.1
208
209
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the Float3NaNPropRule explicitly for i386. We had no
2
i386-specific behaviour in the old ifdef ladder, so we were using the
3
default "prefer a then b then c" fallback; this is actually the
4
correct per-the-spec handling for i386.
2
5
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180227143852.11175-4-alex.bennee@linaro.org
8
Message-id: 20241202131347.498124-25-peter.maydell@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
9
---
8
target/arm/cpu.h | 1 +
10
target/i386/tcg/fpu_helper.c | 1 +
9
1 file changed, 1 insertion(+)
11
1 file changed, 1 insertion(+)
10
12
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu.h
15
--- a/target/i386/tcg/fpu_helper.c
14
+++ b/target/arm/cpu.h
16
+++ b/target/i386/tcg/fpu_helper.c
15
@@ -XXX,XX +XXX,XX @@ typedef struct {
17
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
16
* Qn = regs[n].d[1]:regs[n].d[0]
18
* there are multiple input NaNs they are selected in the order a, b, c.
17
* Dn = regs[n].d[0]
19
*/
18
* Sn = regs[n].d[0] bits 31..0
20
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
19
+ * Hn = regs[n].d[0] bits 15..0
21
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
20
*
22
}
21
* This corresponds to the architecturally defined mapping between
23
22
* the two execution states, and means we do not need to explicitly
24
static inline uint8_t save_exception_flags(CPUX86State *env)
23
--
25
--
24
2.16.2
26
2.34.1
25
26
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the Float3NaNPropRule explicitly for HPPA, and remove the
2
ifdef from pickNaNMulAdd().
2
3
3
I've re-factored the handle_simd_intfp_conv helper to properly handle
4
HPPA is the only target that was using the default branch of the
4
half-precision as well as call plain conversion helpers when we are
5
ifdef ladder (other targets either do not use muladd or set
5
not doing fixed point conversion.
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).
6
9
7
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
We add a TODO note that the HPPA rule is probably wrong; this is
11
not a behavioural change for this refactoring.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180227143852.11175-21-alex.bennee@linaro.org
15
Message-id: 20241202131347.498124-26-peter.maydell@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
16
---
12
target/arm/helper.h | 10 ++++
17
target/hppa/fpu_helper.c | 8 ++++++++
13
target/arm/helper.c | 4 ++
18
fpu/softfloat-specialize.c.inc | 4 ----
14
target/arm/translate-a64.c | 122 ++++++++++++++++++++++++++++++++++-----------
19
2 files changed, 8 insertions(+), 4 deletions(-)
15
3 files changed, 108 insertions(+), 28 deletions(-)
16
20
17
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
18
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
23
--- a/target/hppa/fpu_helper.c
20
+++ b/target/arm/helper.h
24
+++ b/target/hppa/fpu_helper.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_cmped, void, f64, f64, env)
25
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
22
DEF_HELPER_2(vfp_fcvtds, f64, f32, env)
26
* HPPA does note implement a CPU reset method at all...
23
DEF_HELPER_2(vfp_fcvtsd, f32, f64, env)
27
*/
24
28
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
25
+DEF_HELPER_2(vfp_uitoh, f16, i32, ptr)
29
+ /*
26
DEF_HELPER_2(vfp_uitos, f32, i32, ptr)
30
+ * TODO: The HPPA architecture reference only documents its NaN
27
DEF_HELPER_2(vfp_uitod, f64, i32, ptr)
31
+ * propagation rule for 2-operand operations. Testing on real hardware
28
+DEF_HELPER_2(vfp_sitoh, f16, i32, ptr)
32
+ * might be necessary to confirm whether this order for muladd is correct.
29
DEF_HELPER_2(vfp_sitos, f32, i32, ptr)
33
+ * Not preferring the SNaN is almost certainly incorrect as it diverges
30
DEF_HELPER_2(vfp_sitod, f64, i32, ptr)
34
+ * from the documented rules for 2-operand operations.
31
35
+ */
32
+DEF_HELPER_2(vfp_touih, i32, f16, ptr)
36
+ set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
33
DEF_HELPER_2(vfp_touis, i32, f32, ptr)
37
/* For inf * 0 + NaN, return the input NaN */
34
DEF_HELPER_2(vfp_touid, i32, f64, ptr)
38
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
35
+DEF_HELPER_2(vfp_touizh, i32, f16, ptr)
39
}
36
DEF_HELPER_2(vfp_touizs, i32, f32, ptr)
40
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
37
DEF_HELPER_2(vfp_touizd, i32, f64, ptr)
38
+DEF_HELPER_2(vfp_tosih, i32, f16, ptr)
39
DEF_HELPER_2(vfp_tosis, i32, f32, ptr)
40
DEF_HELPER_2(vfp_tosid, i32, f64, ptr)
41
+DEF_HELPER_2(vfp_tosizh, i32, f16, ptr)
42
DEF_HELPER_2(vfp_tosizs, i32, f32, ptr)
43
DEF_HELPER_2(vfp_tosizd, i32, f64, ptr)
44
45
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_toshd_round_to_zero, i64, f64, i32, ptr)
46
DEF_HELPER_3(vfp_tosld_round_to_zero, i64, f64, i32, ptr)
47
DEF_HELPER_3(vfp_touhd_round_to_zero, i64, f64, i32, ptr)
48
DEF_HELPER_3(vfp_tould_round_to_zero, i64, f64, i32, ptr)
49
+DEF_HELPER_3(vfp_toulh, i32, f16, i32, ptr)
50
+DEF_HELPER_3(vfp_toslh, i32, f16, i32, ptr)
51
DEF_HELPER_3(vfp_toshs, i32, f32, i32, ptr)
52
DEF_HELPER_3(vfp_tosls, i32, f32, i32, ptr)
53
DEF_HELPER_3(vfp_tosqs, i64, f32, i32, ptr)
54
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_sqtod, f64, i64, i32, ptr)
55
DEF_HELPER_3(vfp_uhtod, f64, i64, i32, ptr)
56
DEF_HELPER_3(vfp_ultod, f64, i64, i32, ptr)
57
DEF_HELPER_3(vfp_uqtod, f64, i64, i32, ptr)
58
+DEF_HELPER_3(vfp_sltoh, f16, i32, i32, ptr)
59
+DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
60
61
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
62
DEF_HELPER_FLAGS_2(set_neon_rmode, TCG_CALL_NO_RWG, i32, i32, env)
63
diff --git a/target/arm/helper.c b/target/arm/helper.c
64
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/helper.c
42
--- a/fpu/softfloat-specialize.c.inc
66
+++ b/target/arm/helper.c
43
+++ b/fpu/softfloat-specialize.c.inc
67
@@ -XXX,XX +XXX,XX @@ CONV_ITOF(vfp_##name##to##p, fsz, sign) \
44
@@ -XXX,XX +XXX,XX @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
68
CONV_FTOI(vfp_to##name##p, fsz, sign, ) \
69
CONV_FTOI(vfp_to##name##z##p, fsz, sign, _round_to_zero)
70
71
+FLOAT_CONVS(si, h, 16, )
72
FLOAT_CONVS(si, s, 32, )
73
FLOAT_CONVS(si, d, 64, )
74
+FLOAT_CONVS(ui, h, 16, u)
75
FLOAT_CONVS(ui, s, 32, u)
76
FLOAT_CONVS(ui, d, 64, u)
77
78
@@ -XXX,XX +XXX,XX @@ VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
79
VFP_CONV_FIX(uh, s, 32, 32, uint16)
80
VFP_CONV_FIX(ul, s, 32, 32, uint32)
81
VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
82
+VFP_CONV_FIX_A64(sl, h, 16, 32, int32)
83
+VFP_CONV_FIX_A64(ul, h, 16, 32, uint32)
84
#undef VFP_CONV_FIX
85
#undef VFP_CONV_FIX_FLOAT
86
#undef VFP_CONV_FLOAT_FIX_ROUND
87
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/translate-a64.c
90
+++ b/target/arm/translate-a64.c
91
@@ -XXX,XX +XXX,XX @@ static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn,
92
int elements, int is_signed,
93
int fracbits, int size)
94
{
95
- bool is_double = size == 3 ? true : false;
96
- TCGv_ptr tcg_fpst = get_fpstatus_ptr(false);
97
- TCGv_i32 tcg_shift = tcg_const_i32(fracbits);
98
- TCGv_i64 tcg_int = tcg_temp_new_i64();
99
+ TCGv_ptr tcg_fpst = get_fpstatus_ptr(size == MO_16);
100
+ TCGv_i32 tcg_shift = NULL;
101
+
102
TCGMemOp mop = size | (is_signed ? MO_SIGN : 0);
103
int pass;
104
105
- for (pass = 0; pass < elements; pass++) {
106
- read_vec_element(s, tcg_int, rn, pass, mop);
107
+ if (fracbits || size == MO_64) {
108
+ tcg_shift = tcg_const_i32(fracbits);
109
+ }
110
+
111
+ if (size == MO_64) {
112
+ TCGv_i64 tcg_int64 = tcg_temp_new_i64();
113
+ TCGv_i64 tcg_double = tcg_temp_new_i64();
114
+
115
+ for (pass = 0; pass < elements; pass++) {
116
+ read_vec_element(s, tcg_int64, rn, pass, mop);
117
118
- if (is_double) {
119
- TCGv_i64 tcg_double = tcg_temp_new_i64();
120
if (is_signed) {
121
- gen_helper_vfp_sqtod(tcg_double, tcg_int,
122
+ gen_helper_vfp_sqtod(tcg_double, tcg_int64,
123
tcg_shift, tcg_fpst);
124
} else {
125
- gen_helper_vfp_uqtod(tcg_double, tcg_int,
126
+ gen_helper_vfp_uqtod(tcg_double, tcg_int64,
127
tcg_shift, tcg_fpst);
128
}
129
if (elements == 1) {
130
@@ -XXX,XX +XXX,XX @@ static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn,
131
} else {
132
write_vec_element(s, tcg_double, rd, pass, MO_64);
133
}
134
- tcg_temp_free_i64(tcg_double);
135
- } else {
136
- TCGv_i32 tcg_single = tcg_temp_new_i32();
137
- if (is_signed) {
138
- gen_helper_vfp_sqtos(tcg_single, tcg_int,
139
- tcg_shift, tcg_fpst);
140
- } else {
141
- gen_helper_vfp_uqtos(tcg_single, tcg_int,
142
- tcg_shift, tcg_fpst);
143
- }
144
- if (elements == 1) {
145
- write_fp_sreg(s, rd, tcg_single);
146
- } else {
147
- write_vec_element_i32(s, tcg_single, rd, pass, MO_32);
148
- }
149
- tcg_temp_free_i32(tcg_single);
150
}
45
}
151
+
152
+ tcg_temp_free_i64(tcg_int64);
153
+ tcg_temp_free_i64(tcg_double);
154
+
155
+ } else {
156
+ TCGv_i32 tcg_int32 = tcg_temp_new_i32();
157
+ TCGv_i32 tcg_float = tcg_temp_new_i32();
158
+
159
+ for (pass = 0; pass < elements; pass++) {
160
+ read_vec_element_i32(s, tcg_int32, rn, pass, mop);
161
+
162
+ switch (size) {
163
+ case MO_32:
164
+ if (fracbits) {
165
+ if (is_signed) {
166
+ gen_helper_vfp_sltos(tcg_float, tcg_int32,
167
+ tcg_shift, tcg_fpst);
168
+ } else {
169
+ gen_helper_vfp_ultos(tcg_float, tcg_int32,
170
+ tcg_shift, tcg_fpst);
171
+ }
172
+ } else {
173
+ if (is_signed) {
174
+ gen_helper_vfp_sitos(tcg_float, tcg_int32, tcg_fpst);
175
+ } else {
176
+ gen_helper_vfp_uitos(tcg_float, tcg_int32, tcg_fpst);
177
+ }
178
+ }
179
+ break;
180
+ case MO_16:
181
+ if (fracbits) {
182
+ if (is_signed) {
183
+ gen_helper_vfp_sltoh(tcg_float, tcg_int32,
184
+ tcg_shift, tcg_fpst);
185
+ } else {
186
+ gen_helper_vfp_ultoh(tcg_float, tcg_int32,
187
+ tcg_shift, tcg_fpst);
188
+ }
189
+ } else {
190
+ if (is_signed) {
191
+ gen_helper_vfp_sitoh(tcg_float, tcg_int32, tcg_fpst);
192
+ } else {
193
+ gen_helper_vfp_uitoh(tcg_float, tcg_int32, tcg_fpst);
194
+ }
195
+ }
196
+ break;
197
+ default:
198
+ g_assert_not_reached();
199
+ }
200
+
201
+ if (elements == 1) {
202
+ write_fp_sreg(s, rd, tcg_float);
203
+ } else {
204
+ write_vec_element_i32(s, tcg_float, rd, pass, size);
205
+ }
206
+ }
207
+
208
+ tcg_temp_free_i32(tcg_int32);
209
+ tcg_temp_free_i32(tcg_float);
210
}
46
}
211
47
212
- tcg_temp_free_i64(tcg_int);
48
- if (rule == float_3nan_prop_none) {
213
tcg_temp_free_ptr(tcg_fpst);
49
- rule = float_3nan_prop_abc;
214
- tcg_temp_free_i32(tcg_shift);
50
- }
215
+ if (tcg_shift) {
51
-
216
+ tcg_temp_free_i32(tcg_shift);
52
assert(rule != float_3nan_prop_none);
217
+ }
53
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
218
54
/* We have at least one SNaN input and should prefer it */
219
clear_vec_high(s, elements << size == 16, rd);
220
}
221
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
222
rn = extract32(insn, 5, 5);
223
224
switch (fpop) {
225
+ case 0x1d: /* SCVTF */
226
+ case 0x5d: /* UCVTF */
227
+ {
228
+ int elements;
229
+
230
+ if (is_scalar) {
231
+ elements = 1;
232
+ } else {
233
+ elements = (is_q ? 8 : 4);
234
+ }
235
+
236
+ if (!fp_access_check(s)) {
237
+ return;
238
+ }
239
+ handle_simd_intfp_conv(s, rd, rn, elements, !u, 0, MO_16);
240
+ return;
241
+ }
242
break;
243
case 0x2c: /* FCMGT (zero) */
244
case 0x2d: /* FCMEQ (zero) */
245
--
55
--
246
2.16.2
56
2.34.1
247
248
diff view generated by jsdifflib
New patch
1
The use_first_nan field in float_status was an xtensa-specific way to
2
select at runtime from two different NaN propagation rules. Now that
3
xtensa is using the target-agnostic NaN propagation rule selection
4
that we've just added, we can remove use_first_nan, because there is
5
no longer any code that reads it.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20241202131347.498124-27-peter.maydell@linaro.org
10
---
11
include/fpu/softfloat-helpers.h | 5 -----
12
include/fpu/softfloat-types.h | 1 -
13
target/xtensa/fpu_helper.c | 1 -
14
3 files changed, 7 deletions(-)
15
16
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/fpu/softfloat-helpers.h
19
+++ b/include/fpu/softfloat-helpers.h
20
@@ -XXX,XX +XXX,XX @@ static inline void set_snan_bit_is_one(bool val, float_status *status)
21
status->snan_bit_is_one = val;
22
}
23
24
-static inline void set_use_first_nan(bool val, float_status *status)
25
-{
26
- status->use_first_nan = val;
27
-}
28
-
29
static inline void set_no_signaling_nans(bool val, float_status *status)
30
{
31
status->no_signaling_nans = val;
32
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/fpu/softfloat-types.h
35
+++ b/include/fpu/softfloat-types.h
36
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
37
* softfloat-specialize.inc.c)
38
*/
39
bool snan_bit_is_one;
40
- bool use_first_nan;
41
bool no_signaling_nans;
42
/* should overflowed results subtract re_bias to its exponent? */
43
bool rebias_overflow;
44
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/xtensa/fpu_helper.c
47
+++ b/target/xtensa/fpu_helper.c
48
@@ -XXX,XX +XXX,XX @@ static const struct {
49
50
void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
51
{
52
- set_use_first_nan(use_first, &env->fp_status);
53
set_float_2nan_prop_rule(use_first ? float_2nan_prop_ab : float_2nan_prop_ba,
54
&env->fp_status);
55
set_float_3nan_prop_rule(use_first ? float_3nan_prop_abc : float_3nan_prop_cba,
56
--
57
2.34.1
diff view generated by jsdifflib
New patch
1
Currently m68k_cpu_reset_hold() calls floatx80_default_nan(NULL)
2
to get the NaN bit pattern to reset the FPU registers. This
3
works because it happens that our implementation of
4
floatx80_default_nan() doesn't actually look at the float_status
5
pointer except for TARGET_MIPS. However, this isn't guaranteed,
6
and to be able to remove the ifdef in floatx80_default_nan()
7
we're going to need a real float_status here.
1
8
9
Rearrange m68k_cpu_reset_hold() so that we initialize env->fp_status
10
earlier, and thus can pass it to floatx80_default_nan().
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20241202131347.498124-28-peter.maydell@linaro.org
15
---
16
target/m68k/cpu.c | 12 +++++++-----
17
1 file changed, 7 insertions(+), 5 deletions(-)
18
19
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/m68k/cpu.c
22
+++ b/target/m68k/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
24
CPUState *cs = CPU(obj);
25
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(obj);
26
CPUM68KState *env = cpu_env(cs);
27
- floatx80 nan = floatx80_default_nan(NULL);
28
+ floatx80 nan;
29
int i;
30
31
if (mcc->parent_phases.hold) {
32
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
33
#else
34
cpu_m68k_set_sr(env, SR_S | SR_I);
35
#endif
36
- for (i = 0; i < 8; i++) {
37
- env->fregs[i].d = nan;
38
- }
39
- cpu_m68k_set_fpcr(env, 0);
40
/*
41
* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
42
* 3.4 FLOATING-POINT INSTRUCTION DETAILS
43
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
44
* preceding paragraph for nonsignaling NaNs.
45
*/
46
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
47
+
48
+ nan = floatx80_default_nan(&env->fp_status);
49
+ for (i = 0; i < 8; i++) {
50
+ env->fregs[i].d = nan;
51
+ }
52
+ cpu_m68k_set_fpcr(env, 0);
53
env->fpsr = 0;
54
55
/* TODO: We should set PC from the interrupt vector. */
56
--
57
2.34.1
diff view generated by jsdifflib
New patch
1
We create our 128-bit default NaN by calling parts64_default_nan()
2
and then adjusting the result. We can do the same trick for creating
3
the floatx80 default NaN, which lets us drop a target ifdef.
1
4
5
floatx80 is used only by:
6
i386
7
m68k
8
arm nwfpe old floating-point emulation emulation support
9
(which is essentially dead, especially the parts involving floatx80)
10
PPC (only in the xsrqpxp instruction, which just rounds an input
11
value by converting to floatx80 and back, so will never generate
12
the default NaN)
13
14
The floatx80 default NaN as currently implemented is:
15
m68k: sign = 0, exp = 1...1, int = 1, frac = 1....1
16
i386: sign = 1, exp = 1...1, int = 1, frac = 10...0
17
18
These are the same as the parts64_default_nan for these architectures.
19
20
This is technically a possible behaviour change for arm linux-user
21
nwfpe emulation emulation, because the default NaN will now have the
22
sign bit clear. But we were already generating a different floatx80
23
default NaN from the real kernel emulation we are supposedly
24
following, which appears to use an all-bits-1 value:
25
https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L267
26
27
This won't affect the only "real" use of the nwfpe emulation, which
28
is ancient binaries that used it as part of the old floating point
29
calling convention; that only uses loads and stores of 32 and 64 bit
30
floats, not any of the floatx80 behaviour the original hardware had.
31
We also get the nwfpe float64 default NaN value wrong:
32
https://elixir.bootlin.com/linux/v6.12/source/arch/arm/nwfpe/softfloat-specialize#L166
33
so if we ever cared about this obscure corner the right fix would be
34
to correct that so nwfpe used its own default-NaN setting rather
35
than the Arm VFP one.
36
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
39
Message-id: 20241202131347.498124-29-peter.maydell@linaro.org
40
---
41
fpu/softfloat-specialize.c.inc | 20 ++++++++++----------
42
1 file changed, 10 insertions(+), 10 deletions(-)
43
44
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
45
index XXXXXXX..XXXXXXX 100644
46
--- a/fpu/softfloat-specialize.c.inc
47
+++ b/fpu/softfloat-specialize.c.inc
48
@@ -XXX,XX +XXX,XX @@ static void parts128_silence_nan(FloatParts128 *p, float_status *status)
49
floatx80 floatx80_default_nan(float_status *status)
50
{
51
floatx80 r;
52
+ /*
53
+ * Extrapolate from the choices made by parts64_default_nan to fill
54
+ * in the floatx80 format. We assume that floatx80's explicit
55
+ * integer bit is always set (this is true for i386 and m68k,
56
+ * which are the only real users of this format).
57
+ */
58
+ FloatParts64 p64;
59
+ parts64_default_nan(&p64, status);
60
61
- /* None of the targets that have snan_bit_is_one use floatx80. */
62
- assert(!snan_bit_is_one(status));
63
-#if defined(TARGET_M68K)
64
- r.low = UINT64_C(0xFFFFFFFFFFFFFFFF);
65
- r.high = 0x7FFF;
66
-#else
67
- /* X86 */
68
- r.low = UINT64_C(0xC000000000000000);
69
- r.high = 0xFFFF;
70
-#endif
71
+ r.high = 0x7FFF | (p64.sign << 15);
72
+ r.low = (1ULL << DECOMPOSED_BINARY_POINT) | p64.frac;
73
return r;
74
}
75
76
--
77
2.34.1
diff view generated by jsdifflib
New patch
1
In target/loongarch's helper_fclass_s() and helper_fclass_d() we pass
2
a zero-initialized float_status struct to float32_is_quiet_nan() and
3
float64_is_quiet_nan(), with the cryptic comment "for
4
snan_bit_is_one".
1
5
6
This pattern appears to have been copied from target/riscv, where it
7
is used because the functions there do not have ready access to the
8
CPU state struct. The comment presumably refers to the fact that the
9
main reason the is_quiet_nan() functions want the float_state is
10
because they want to know about the snan_bit_is_one config.
11
12
In the loongarch helpers, though, we have the CPU state struct
13
to hand. Use the usual env->fp_status here. This avoids our needing
14
to track that we need to update the initializer of the local
15
float_status structs when the core softfloat code adds new
16
options for targets to configure their behaviour.
17
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Message-id: 20241202131347.498124-30-peter.maydell@linaro.org
21
---
22
target/loongarch/tcg/fpu_helper.c | 6 ++----
23
1 file changed, 2 insertions(+), 4 deletions(-)
24
25
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/loongarch/tcg/fpu_helper.c
28
+++ b/target/loongarch/tcg/fpu_helper.c
29
@@ -XXX,XX +XXX,XX @@ uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj)
30
} else if (float32_is_zero_or_denormal(f)) {
31
return sign ? 1 << 4 : 1 << 8;
32
} else if (float32_is_any_nan(f)) {
33
- float_status s = { }; /* for snan_bit_is_one */
34
- return float32_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
35
+ return float32_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0;
36
} else {
37
return sign ? 1 << 3 : 1 << 7;
38
}
39
@@ -XXX,XX +XXX,XX @@ uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj)
40
} else if (float64_is_zero_or_denormal(f)) {
41
return sign ? 1 << 4 : 1 << 8;
42
} else if (float64_is_any_nan(f)) {
43
- float_status s = { }; /* for snan_bit_is_one */
44
- return float64_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
45
+ return float64_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0;
46
} else {
47
return sign ? 1 << 3 : 1 << 7;
48
}
49
--
50
2.34.1
diff view generated by jsdifflib
New patch
1
In the frem helper, we have a local float_status because we want to
2
execute the floatx80_div() with a custom rounding mode. Instead of
3
zero-initializing the local float_status and then having to set it up
4
with the m68k standard behaviour (including the NaN propagation rule
5
and copying the rounding precision from env->fp_status), initialize
6
it as a complete copy of env->fp_status. This will avoid our having
7
to add new code in this function for every new config knob we add
8
to fp_status.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-31-peter.maydell@linaro.org
13
---
14
target/m68k/fpu_helper.c | 6 ++----
15
1 file changed, 2 insertions(+), 4 deletions(-)
16
17
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/m68k/fpu_helper.c
20
+++ b/target/m68k/fpu_helper.c
21
@@ -XXX,XX +XXX,XX @@ void HELPER(frem)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
22
23
fp_rem = floatx80_rem(val1->d, val0->d, &env->fp_status);
24
if (!floatx80_is_any_nan(fp_rem)) {
25
- float_status fp_status = { };
26
+ /* Use local temporary fp_status to set different rounding mode */
27
+ float_status fp_status = env->fp_status;
28
uint32_t quotient;
29
int sign;
30
31
/* Calculate quotient directly using round to nearest mode */
32
- set_float_2nan_prop_rule(float_2nan_prop_ab, &fp_status);
33
set_float_rounding_mode(float_round_nearest_even, &fp_status);
34
- set_floatx80_rounding_precision(
35
- get_floatx80_rounding_precision(&env->fp_status), &fp_status);
36
fp_quot.d = floatx80_div(val1->d, val0->d, &fp_status);
37
38
sign = extractFloatx80Sign(fp_quot.d);
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
In cf_fpu_gdb_get_reg() and cf_fpu_gdb_set_reg() we do the conversion
2
from float64 to floatx80 using a scratch float_status, because we
3
don't want the conversion to affect the CPU's floating point exception
4
status. Currently we use a zero-initialized float_status. This will
5
get steadily more awkward as we add config knobs to float_status
6
that the target must initialize. Avoid having to add any of that
7
configuration here by instead initializing our local float_status
8
from the env->fp_status.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20241202131347.498124-32-peter.maydell@linaro.org
13
---
14
target/m68k/helper.c | 6 ++++--
15
1 file changed, 4 insertions(+), 2 deletions(-)
16
17
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/m68k/helper.c
20
+++ b/target/m68k/helper.c
21
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_get_reg(CPUState *cs, GByteArray *mem_buf, int n)
22
CPUM68KState *env = &cpu->env;
23
24
if (n < 8) {
25
- float_status s = {};
26
+ /* Use scratch float_status so any exceptions don't change CPU state */
27
+ float_status s = env->fp_status;
28
return gdb_get_reg64(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
29
}
30
switch (n) {
31
@@ -XXX,XX +XXX,XX @@ static int cf_fpu_gdb_set_reg(CPUState *cs, uint8_t *mem_buf, int n)
32
CPUM68KState *env = &cpu->env;
33
34
if (n < 8) {
35
- float_status s = {};
36
+ /* Use scratch float_status so any exceptions don't change CPU state */
37
+ float_status s = env->fp_status;
38
env->fregs[n].d = float64_to_floatx80(ldq_be_p(mem_buf), &s);
39
return 8;
40
}
41
--
42
2.34.1
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
In the helper functions flcmps and flcmpd we use a scratch float_status
2
so that we don't change the CPU state if the comparison raises any
3
floating point exception flags. Instead of zero-initializing this
4
scratch float_status, initialize it as a copy of env->fp_status. This
5
avoids the need to explicitly initialize settings like the NaN
6
propagation rule or others we might add to softfloat in future.
2
7
3
As some of the constants here will also be needed
8
To do this we need to pass the CPU env pointer in to the helper.
4
elsewhere (specifically for the upcoming SVE support) we move them out
5
to softfloat.h.
6
9
7
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180227143852.11175-13-alex.bennee@linaro.org
12
Message-id: 20241202131347.498124-33-peter.maydell@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
include/fpu/softfloat.h | 18 +++++++++++++-----
14
target/sparc/helper.h | 4 ++--
13
target/arm/helper-a64.h | 2 ++
15
target/sparc/fop_helper.c | 8 ++++----
14
target/arm/helper-a64.c | 34 ++++++++++++++++++++++++++++++++++
16
target/sparc/translate.c | 4 ++--
15
target/arm/translate-a64.c | 6 ++++++
17
3 files changed, 8 insertions(+), 8 deletions(-)
16
4 files changed, 55 insertions(+), 5 deletions(-)
17
18
18
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
19
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/include/fpu/softfloat.h
21
--- a/target/sparc/helper.h
21
+++ b/include/fpu/softfloat.h
22
+++ b/target/sparc/helper.h
22
@@ -XXX,XX +XXX,XX @@ static inline float16 float16_set_sign(float16 a, int sign)
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
24
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
25
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128)
26
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128)
27
-DEF_HELPER_FLAGS_2(flcmps, TCG_CALL_NO_RWG_SE, i32, f32, f32)
28
-DEF_HELPER_FLAGS_2(flcmpd, TCG_CALL_NO_RWG_SE, i32, f64, f64)
29
+DEF_HELPER_FLAGS_3(flcmps, TCG_CALL_NO_RWG_SE, i32, env, f32, f32)
30
+DEF_HELPER_FLAGS_3(flcmpd, TCG_CALL_NO_RWG_SE, i32, env, f64, f64)
31
DEF_HELPER_2(raise_exception, noreturn, env, int)
32
33
DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64)
34
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/sparc/fop_helper.c
37
+++ b/target/sparc/fop_helper.c
38
@@ -XXX,XX +XXX,XX @@ uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
39
return finish_fcmp(env, r, GETPC());
23
}
40
}
24
41
25
#define float16_zero make_float16(0)
42
-uint32_t helper_flcmps(float32 src1, float32 src2)
26
-#define float16_one make_float16(0x3c00)
43
+uint32_t helper_flcmps(CPUSPARCState *env, float32 src1, float32 src2)
27
#define float16_half make_float16(0x3800)
44
{
28
+#define float16_one make_float16(0x3c00)
45
/*
29
+#define float16_one_point_five make_float16(0x3e00)
46
* FLCMP never raises an exception nor modifies any FSR fields.
30
+#define float16_two make_float16(0x4000)
47
* Perform the comparison with a dummy fp environment.
31
+#define float16_three make_float16(0x4200)
48
*/
32
#define float16_infinity make_float16(0x7c00)
49
- float_status discard = { };
33
50
+ float_status discard = env->fp_status;
34
/*----------------------------------------------------------------------------
51
FloatRelation r;
35
@@ -XXX,XX +XXX,XX @@ static inline float32 float32_set_sign(float32 a, int sign)
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();
36
}
56
}
37
57
38
#define float32_zero make_float32(0)
58
-uint32_t helper_flcmpd(float64 src1, float64 src2)
39
-#define float32_one make_float32(0x3f800000)
59
+uint32_t helper_flcmpd(CPUSPARCState *env, float64 src1, float64 src2)
40
#define float32_half make_float32(0x3f000000)
60
{
41
+#define float32_one make_float32(0x3f800000)
61
- float_status discard = { };
42
+#define float32_one_point_five make_float32(0x3fc00000)
62
+ float_status discard = env->fp_status;
43
+#define float32_two make_float32(0x40000000)
63
FloatRelation r;
44
+#define float32_three make_float32(0x40400000)
64
45
#define float32_infinity make_float32(0x7f800000)
65
set_float_2nan_prop_rule(float_2nan_prop_s_ba, &discard);
46
66
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
47
-
67
index XXXXXXX..XXXXXXX 100644
48
/*----------------------------------------------------------------------------
68
--- a/target/sparc/translate.c
49
| The pattern for a default generated single-precision NaN.
69
+++ b/target/sparc/translate.c
50
*----------------------------------------------------------------------------*/
70
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a)
51
@@ -XXX,XX +XXX,XX @@ static inline float64 float64_set_sign(float64 a, int sign)
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);
52
}
77
}
53
78
54
#define float64_zero make_float64(0)
79
@@ -XXX,XX +XXX,XX @@ static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
55
-#define float64_one make_float64(0x3ff0000000000000LL)
80
56
-#define float64_ln2 make_float64(0x3fe62e42fefa39efLL)
81
src1 = gen_load_fpr_D(dc, a->rs1);
57
#define float64_half make_float64(0x3fe0000000000000LL)
82
src2 = gen_load_fpr_D(dc, a->rs2);
58
+#define float64_one make_float64(0x3ff0000000000000LL)
83
- gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
59
+#define float64_one_point_five make_float64(0x3FF8000000000000ULL)
84
+ gen_helper_flcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
60
+#define float64_two make_float64(0x4000000000000000ULL)
85
return advance_pc(dc);
61
+#define float64_three make_float64(0x4008000000000000ULL)
62
+#define float64_ln2 make_float64(0x3fe62e42fefa39efLL)
63
#define float64_infinity make_float64(0x7ff0000000000000LL)
64
65
/*----------------------------------------------------------------------------
66
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/helper-a64.h
69
+++ b/target/arm/helper-a64.h
70
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(vfp_mulxd, TCG_CALL_NO_RWG, f64, f64, f64, ptr)
71
DEF_HELPER_FLAGS_3(neon_ceq_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr)
72
DEF_HELPER_FLAGS_3(neon_cge_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr)
73
DEF_HELPER_FLAGS_3(neon_cgt_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr)
74
+DEF_HELPER_FLAGS_3(recpsf_f16, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
75
DEF_HELPER_FLAGS_3(recpsf_f32, TCG_CALL_NO_RWG, f32, f32, f32, ptr)
76
DEF_HELPER_FLAGS_3(recpsf_f64, TCG_CALL_NO_RWG, f64, f64, f64, ptr)
77
+DEF_HELPER_FLAGS_3(rsqrtsf_f16, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
78
DEF_HELPER_FLAGS_3(rsqrtsf_f32, TCG_CALL_NO_RWG, f32, f32, f32, ptr)
79
DEF_HELPER_FLAGS_3(rsqrtsf_f64, TCG_CALL_NO_RWG, f64, f64, f64, ptr)
80
DEF_HELPER_FLAGS_1(neon_addlp_s8, TCG_CALL_NO_RWG_SE, i64, i64)
81
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/target/arm/helper-a64.c
84
+++ b/target/arm/helper-a64.c
85
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(neon_cgt_f64)(float64 a, float64 b, void *fpstp)
86
* versions, these do a fully fused multiply-add or
87
* multiply-add-and-halve.
88
*/
89
+#define float16_two make_float16(0x4000)
90
+#define float16_three make_float16(0x4200)
91
+#define float16_one_point_five make_float16(0x3e00)
92
+
93
#define float32_two make_float32(0x40000000)
94
#define float32_three make_float32(0x40400000)
95
#define float32_one_point_five make_float32(0x3fc00000)
96
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(neon_cgt_f64)(float64 a, float64 b, void *fpstp)
97
#define float64_three make_float64(0x4008000000000000ULL)
98
#define float64_one_point_five make_float64(0x3FF8000000000000ULL)
99
100
+float16 HELPER(recpsf_f16)(float16 a, float16 b, void *fpstp)
101
+{
102
+ float_status *fpst = fpstp;
103
+
104
+ a = float16_squash_input_denormal(a, fpst);
105
+ b = float16_squash_input_denormal(b, fpst);
106
+
107
+ a = float16_chs(a);
108
+ if ((float16_is_infinity(a) && float16_is_zero(b)) ||
109
+ (float16_is_infinity(b) && float16_is_zero(a))) {
110
+ return float16_two;
111
+ }
112
+ return float16_muladd(a, b, float16_two, 0, fpst);
113
+}
114
+
115
float32 HELPER(recpsf_f32)(float32 a, float32 b, void *fpstp)
116
{
117
float_status *fpst = fpstp;
118
@@ -XXX,XX +XXX,XX @@ float64 HELPER(recpsf_f64)(float64 a, float64 b, void *fpstp)
119
return float64_muladd(a, b, float64_two, 0, fpst);
120
}
86
}
121
87
122
+float16 HELPER(rsqrtsf_f16)(float16 a, float16 b, void *fpstp)
123
+{
124
+ float_status *fpst = fpstp;
125
+
126
+ a = float16_squash_input_denormal(a, fpst);
127
+ b = float16_squash_input_denormal(b, fpst);
128
+
129
+ a = float16_chs(a);
130
+ if ((float16_is_infinity(a) && float16_is_zero(b)) ||
131
+ (float16_is_infinity(b) && float16_is_zero(a))) {
132
+ return float16_one_point_five;
133
+ }
134
+ return float16_muladd(a, b, float16_three, float_muladd_halve_result, fpst);
135
+}
136
+
137
float32 HELPER(rsqrtsf_f32)(float32 a, float32 b, void *fpstp)
138
{
139
float_status *fpst = fpstp;
140
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/target/arm/translate-a64.c
143
+++ b/target/arm/translate-a64.c
144
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
145
case 0x6: /* FMAX */
146
gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
147
break;
148
+ case 0x7: /* FRECPS */
149
+ gen_helper_recpsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
150
+ break;
151
case 0x8: /* FMINNM */
152
gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
153
break;
154
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
155
case 0xe: /* FMIN */
156
gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
157
break;
158
+ case 0xf: /* FRSQRTS */
159
+ gen_helper_rsqrtsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
160
+ break;
161
case 0x13: /* FMUL */
162
gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
163
break;
164
--
88
--
165
2.16.2
89
2.34.1
166
167
diff view generated by jsdifflib
New patch
1
In the helper_compute_fprf functions, we pass a dummy float_status
2
in to the is_signaling_nan() function. This is unnecessary, because
3
we have convenient access to the CPU env pointer here and that
4
is already set up with the correct values for the snan_bit_is_one
5
and no_signaling_nans config settings. is_signaling_nan() doesn't
6
ever update the fp_status with any exception flags, so there is
7
no reason not to use env->fp_status here.
1
8
9
Use env->fp_status instead of the dummy fp_status.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20241202131347.498124-34-peter.maydell@linaro.org
14
---
15
target/ppc/fpu_helper.c | 3 +--
16
1 file changed, 1 insertion(+), 2 deletions(-)
17
18
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/ppc/fpu_helper.c
21
+++ b/target/ppc/fpu_helper.c
22
@@ -XXX,XX +XXX,XX @@ void helper_compute_fprf_##tp(CPUPPCState *env, tp arg) \
23
} else if (tp##_is_infinity(arg)) { \
24
fprf = neg ? 0x09 << FPSCR_FPRF : 0x05 << FPSCR_FPRF; \
25
} else { \
26
- float_status dummy = { }; /* snan_bit_is_one = 0 */ \
27
- if (tp##_is_signaling_nan(arg, &dummy)) { \
28
+ if (tp##_is_signaling_nan(arg, &env->fp_status)) { \
29
fprf = 0x00 << FPSCR_FPRF; \
30
} else { \
31
fprf = 0x11 << FPSCR_FPRF; \
32
--
33
2.34.1
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This includes FMOV, FABS, FNEG, FSQRT and FRINT[NPMZAXI]. We re-use
3
Now that float_status has a bunch of fp parameters,
4
existing helpers to achieve this.
4
it is easier to copy an existing structure than create
5
one from scratch. Begin by copying the structure that
6
corresponds to the FPSR and make only the adjustments
7
required for BFloat16 semantics.
5
8
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20180227143852.11175-32-alex.bennee@linaro.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20241203203949.483774-2-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
14
---
11
target/arm/translate-a64.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++
15
target/arm/tcg/vec_helper.c | 20 +++++++-------------
12
1 file changed, 71 insertions(+)
16
1 file changed, 7 insertions(+), 13 deletions(-)
13
17
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
18
diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
20
--- a/target/arm/tcg/vec_helper.c
17
+++ b/target/arm/translate-a64.c
21
+++ b/target/arm/tcg/vec_helper.c
18
@@ -XXX,XX +XXX,XX @@ static void disas_fp_csel(DisasContext *s, uint32_t insn)
22
@@ -XXX,XX +XXX,XX @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp)
19
tcg_temp_free_i64(t_true);
23
* no effect on AArch32 instructions.
24
*/
25
bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF;
26
- *statusp = (float_status){
27
- .tininess_before_rounding = float_tininess_before_rounding,
28
- .float_rounding_mode = float_round_to_odd_inf,
29
- .flush_to_zero = true,
30
- .flush_inputs_to_zero = true,
31
- .default_nan_mode = true,
32
- };
33
+
34
+ *statusp = env->vfp.fp_status;
35
+ set_default_nan_mode(true, statusp);
36
37
if (ebf) {
38
- float_status *fpst = &env->vfp.fp_status;
39
- set_flush_to_zero(get_flush_to_zero(fpst), statusp);
40
- set_flush_inputs_to_zero(get_flush_inputs_to_zero(fpst), statusp);
41
- set_float_rounding_mode(get_float_rounding_mode(fpst), statusp);
42
-
43
/* EBF=1 needs to do a step with round-to-odd semantics */
44
*oddstatusp = *statusp;
45
set_float_rounding_mode(float_round_to_odd, oddstatusp);
46
+ } else {
47
+ set_flush_to_zero(true, statusp);
48
+ set_flush_inputs_to_zero(true, statusp);
49
+ set_float_rounding_mode(float_round_to_odd_inf, statusp);
50
}
51
-
52
return ebf;
20
}
53
}
21
54
22
+/* Floating-point data-processing (1 source) - half precision */
23
+static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
24
+{
25
+ TCGv_ptr fpst = NULL;
26
+ TCGv_i32 tcg_op = tcg_temp_new_i32();
27
+ TCGv_i32 tcg_res = tcg_temp_new_i32();
28
+
29
+ read_vec_element_i32(s, tcg_op, rn, 0, MO_16);
30
+
31
+ switch (opcode) {
32
+ case 0x0: /* FMOV */
33
+ tcg_gen_mov_i32(tcg_res, tcg_op);
34
+ break;
35
+ case 0x1: /* FABS */
36
+ tcg_gen_andi_i32(tcg_res, tcg_op, 0x7fff);
37
+ break;
38
+ case 0x2: /* FNEG */
39
+ tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
40
+ break;
41
+ case 0x3: /* FSQRT */
42
+ gen_helper_sqrt_f16(tcg_res, tcg_op, cpu_env);
43
+ break;
44
+ case 0x8: /* FRINTN */
45
+ case 0x9: /* FRINTP */
46
+ case 0xa: /* FRINTM */
47
+ case 0xb: /* FRINTZ */
48
+ case 0xc: /* FRINTA */
49
+ {
50
+ TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
51
+ fpst = get_fpstatus_ptr(true);
52
+
53
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
54
+ gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
55
+
56
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
57
+ tcg_temp_free_i32(tcg_rmode);
58
+ break;
59
+ }
60
+ case 0xe: /* FRINTX */
61
+ fpst = get_fpstatus_ptr(true);
62
+ gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, fpst);
63
+ break;
64
+ case 0xf: /* FRINTI */
65
+ fpst = get_fpstatus_ptr(true);
66
+ gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
67
+ break;
68
+ default:
69
+ abort();
70
+ }
71
+
72
+ write_fp_sreg(s, rd, tcg_res);
73
+
74
+ if (fpst) {
75
+ tcg_temp_free_ptr(fpst);
76
+ }
77
+ tcg_temp_free_i32(tcg_op);
78
+ tcg_temp_free_i32(tcg_res);
79
+}
80
+
81
/* Floating-point data-processing (1 source) - single precision */
82
static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
83
{
84
@@ -XXX,XX +XXX,XX @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
85
86
handle_fp_1src_double(s, opcode, rd, rn);
87
break;
88
+ case 3:
89
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
90
+ unallocated_encoding(s);
91
+ return;
92
+ }
93
+
94
+ if (!fp_access_check(s)) {
95
+ return;
96
+ }
97
+
98
+ handle_fp_1src_half(s, opcode, rd, rn);
99
+ break;
100
default:
101
unallocated_encoding(s);
102
}
103
--
55
--
104
2.16.2
56
2.34.1
105
57
106
58
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Currently we hardcode the default NaN value in parts64_default_nan()
2
using a compile-time ifdef ladder. This is awkward for two cases:
3
* for single-QEMU-binary we can't hard-code target-specifics like this
4
* for Arm FEAT_AFP the default NaN value depends on FPCR.AH
5
(specifically the sign bit is different)
2
6
3
A bunch of the vectorised bitwise operations just operate on larger
7
Add a field to float_status to specify the default NaN value; fall
4
chunks at a time. We can do the same for the new half-precision
8
back to the old ifdef behaviour if these are not set.
5
operations by introducing some TWOHALFOP helpers which work on each
6
half of a pair of half-precision operations at once.
7
9
8
Hopefully all this hoop jumping will get simpler once we have
10
The default NaN value is specified by setting a uint8_t to a
9
generically vectorised helpers here.
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.
10
14
11
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20180227143852.11175-16-alex.bennee@linaro.org
17
Message-id: 20241202131347.498124-35-peter.maydell@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
18
---
16
target/arm/helper-a64.h | 10 ++++++++++
19
include/fpu/softfloat-helpers.h | 11 +++++++
17
target/arm/helper-a64.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
20
include/fpu/softfloat-types.h | 10 ++++++
18
target/arm/translate-a64.c | 26 +++++++++++++++++++++-----
21
fpu/softfloat-specialize.c.inc | 55 ++++++++++++++++++++-------------
19
3 files changed, 76 insertions(+), 6 deletions(-)
22
3 files changed, 54 insertions(+), 22 deletions(-)
20
23
21
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
24
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
22
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper-a64.h
26
--- a/include/fpu/softfloat-helpers.h
24
+++ b/target/arm/helper-a64.h
27
+++ b/include/fpu/softfloat-helpers.h
25
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(advsimd_acge_f16, i32, f16, f16, ptr)
28
@@ -XXX,XX +XXX,XX @@ static inline void set_float_infzeronan_rule(FloatInfZeroNaNRule rule,
26
DEF_HELPER_3(advsimd_acgt_f16, i32, f16, f16, ptr)
29
status->float_infzeronan_rule = rule;
27
DEF_HELPER_3(advsimd_mulxh, f16, f16, f16, ptr)
30
}
28
DEF_HELPER_4(advsimd_muladdh, f16, f16, f16, f16, ptr)
31
29
+DEF_HELPER_3(advsimd_add2h, i32, i32, i32, ptr)
32
+static inline void set_float_default_nan_pattern(uint8_t dnan_pattern,
30
+DEF_HELPER_3(advsimd_sub2h, i32, i32, i32, ptr)
33
+ float_status *status)
31
+DEF_HELPER_3(advsimd_mul2h, i32, i32, i32, ptr)
34
+{
32
+DEF_HELPER_3(advsimd_div2h, i32, i32, i32, ptr)
35
+ status->default_nan_pattern = dnan_pattern;
33
+DEF_HELPER_3(advsimd_max2h, i32, i32, i32, ptr)
34
+DEF_HELPER_3(advsimd_min2h, i32, i32, i32, ptr)
35
+DEF_HELPER_3(advsimd_maxnum2h, i32, i32, i32, ptr)
36
+DEF_HELPER_3(advsimd_minnum2h, i32, i32, i32, ptr)
37
+DEF_HELPER_3(advsimd_mulx2h, i32, i32, i32, ptr)
38
+DEF_HELPER_4(advsimd_muladd2h, i32, i32, i32, i32, ptr)
39
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/helper-a64.c
42
+++ b/target/arm/helper-a64.c
43
@@ -XXX,XX +XXX,XX @@ ADVSIMD_HALFOP(max)
44
ADVSIMD_HALFOP(minnum)
45
ADVSIMD_HALFOP(maxnum)
46
47
+#define ADVSIMD_TWOHALFOP(name) \
48
+uint32_t ADVSIMD_HELPER(name, 2h)(uint32_t two_a, uint32_t two_b, void *fpstp) \
49
+{ \
50
+ float16 a1, a2, b1, b2; \
51
+ uint32_t r1, r2; \
52
+ float_status *fpst = fpstp; \
53
+ a1 = extract32(two_a, 0, 16); \
54
+ a2 = extract32(two_a, 16, 16); \
55
+ b1 = extract32(two_b, 0, 16); \
56
+ b2 = extract32(two_b, 16, 16); \
57
+ r1 = float16_ ## name(a1, b1, fpst); \
58
+ r2 = float16_ ## name(a2, b2, fpst); \
59
+ return deposit32(r1, 16, 16, r2); \
60
+}
36
+}
61
+
37
+
62
+ADVSIMD_TWOHALFOP(add)
38
static inline void set_flush_to_zero(bool val, float_status *status)
63
+ADVSIMD_TWOHALFOP(sub)
64
+ADVSIMD_TWOHALFOP(mul)
65
+ADVSIMD_TWOHALFOP(div)
66
+ADVSIMD_TWOHALFOP(min)
67
+ADVSIMD_TWOHALFOP(max)
68
+ADVSIMD_TWOHALFOP(minnum)
69
+ADVSIMD_TWOHALFOP(maxnum)
70
+
71
/* Data processing - scalar floating-point and advanced SIMD */
72
-float16 HELPER(advsimd_mulxh)(float16 a, float16 b, void *fpstp)
73
+static float16 float16_mulx(float16 a, float16 b, void *fpstp)
74
{
39
{
75
float_status *fpst = fpstp;
40
status->flush_to_zero = val;
76
41
@@ -XXX,XX +XXX,XX @@ static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status
77
@@ -XXX,XX +XXX,XX @@ float16 HELPER(advsimd_mulxh)(float16 a, float16 b, void *fpstp)
42
return status->float_infzeronan_rule;
78
return float16_mul(a, b, fpst);
79
}
43
}
80
44
81
+ADVSIMD_HALFOP(mulx)
45
+static inline uint8_t get_float_default_nan_pattern(float_status *status)
82
+ADVSIMD_TWOHALFOP(mulx)
83
+
84
/* fused multiply-accumulate */
85
float16 HELPER(advsimd_muladdh)(float16 a, float16 b, float16 c, void *fpstp)
86
{
87
@@ -XXX,XX +XXX,XX @@ float16 HELPER(advsimd_muladdh)(float16 a, float16 b, float16 c, void *fpstp)
88
return float16_muladd(a, b, c, 0, fpst);
89
}
90
91
+uint32_t HELPER(advsimd_muladd2h)(uint32_t two_a, uint32_t two_b,
92
+ uint32_t two_c, void *fpstp)
93
+{
46
+{
94
+ float_status *fpst = fpstp;
47
+ return status->default_nan_pattern;
95
+ float16 a1, a2, b1, b2, c1, c2;
96
+ uint32_t r1, r2;
97
+ a1 = extract32(two_a, 0, 16);
98
+ a2 = extract32(two_a, 16, 16);
99
+ b1 = extract32(two_b, 0, 16);
100
+ b2 = extract32(two_b, 16, 16);
101
+ c1 = extract32(two_c, 0, 16);
102
+ c2 = extract32(two_c, 16, 16);
103
+ r1 = float16_muladd(a1, b1, c1, 0, fpst);
104
+ r2 = float16_muladd(a2, b2, c2, 0, fpst);
105
+ return deposit32(r1, 16, 16, r2);
106
+}
48
+}
107
+
49
+
108
/*
50
static inline bool get_flush_to_zero(float_status *status)
109
* Floating point comparisons produce an integer result. Softfloat
51
{
110
* routines return float_relation types which we convert to the 0/-1
52
return status->flush_to_zero;
111
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
53
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
112
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
113
--- a/target/arm/translate-a64.c
55
--- a/include/fpu/softfloat-types.h
114
+++ b/target/arm/translate-a64.c
56
+++ b/include/fpu/softfloat-types.h
115
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
57
@@ -XXX,XX +XXX,XX @@ typedef struct float_status {
116
* multiply-add */
58
/* should denormalised inputs go to zero and set the input_denormal flag? */
117
tcg_gen_xori_i32(tcg_op, tcg_op, 0x80008000);
59
bool flush_inputs_to_zero;
118
}
60
bool default_nan_mode;
119
- gen_helper_advsimd_muladdh(tcg_res, tcg_op, tcg_idx,
61
+ /*
120
- tcg_res, fpst);
62
+ * The pattern to use for the default NaN. Here the high bit specifies
121
+ if (is_scalar) {
63
+ * the default NaN's sign bit, and bits 6..0 specify the high bits of the
122
+ gen_helper_advsimd_muladdh(tcg_res, tcg_op, tcg_idx,
64
+ * fractional part. The low bits of the fractional part are copies of bit 0.
123
+ tcg_res, fpst);
65
+ * The exponent of the default NaN is (as for any NaN) always all 1s.
124
+ } else {
66
+ * Note that a value of 0 here is not a valid NaN. The target must set
125
+ gen_helper_advsimd_muladd2h(tcg_res, tcg_op, tcg_idx,
67
+ * this to the correct non-zero value, or we will assert when trying to
126
+ tcg_res, fpst);
68
+ * create a default NaN.
127
+ }
69
+ */
128
break;
70
+ uint8_t default_nan_pattern;
129
case 2:
71
/*
130
if (opcode == 0x5) {
72
* The flags below are not used on all specializations and may
131
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
73
* constant fold away (see snan_bit_is_one()/no_signalling_nans() in
132
switch (size) {
74
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
133
case 1:
75
index XXXXXXX..XXXXXXX 100644
134
if (u) {
76
--- a/fpu/softfloat-specialize.c.inc
135
- gen_helper_advsimd_mulxh(tcg_res, tcg_op, tcg_idx,
77
+++ b/fpu/softfloat-specialize.c.inc
136
- fpst);
78
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
137
+ if (is_scalar) {
79
{
138
+ gen_helper_advsimd_mulxh(tcg_res, tcg_op,
80
bool sign = 0;
139
+ tcg_idx, fpst);
81
uint64_t frac;
140
+ } else {
82
+ uint8_t dnan_pattern = status->default_nan_pattern;
141
+ gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
83
142
+ tcg_idx, fpst);
84
+ if (dnan_pattern == 0) {
143
+ }
85
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
144
} else {
86
- /* !snan_bit_is_one, set all bits */
145
- g_assert_not_reached();
87
- frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
146
+ if (is_scalar) {
88
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
147
+ gen_helper_advsimd_mulh(tcg_res, tcg_op,
89
+ /* Sign bit clear, all frac bits set */
148
+ tcg_idx, fpst);
90
+ dnan_pattern = 0b01111111;
149
+ } else {
91
+#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
150
+ gen_helper_advsimd_mul2h(tcg_res, tcg_op,
92
|| defined(TARGET_MICROBLAZE)
151
+ tcg_idx, fpst);
93
- /* !snan_bit_is_one, set sign and msb */
152
+ }
94
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
153
}
95
- sign = 1;
154
break;
96
+ /* Sign bit set, most significant frac bit set */
155
case 2:
97
+ dnan_pattern = 0b11000000;
98
#elif defined(TARGET_HPPA)
99
- /* snan_bit_is_one, set msb-1. */
100
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
101
+ /* Sign bit clear, msb-1 frac bit set */
102
+ dnan_pattern = 0b00100000;
103
#elif defined(TARGET_HEXAGON)
104
- sign = 1;
105
- frac = ~0ULL;
106
+ /* Sign bit set, all frac bits set. */
107
+ dnan_pattern = 0b11111111;
108
#else
109
- /*
110
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
111
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
112
- * do not have floating-point.
113
- */
114
- if (snan_bit_is_one(status)) {
115
- /* set all bits other than msb */
116
- frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1;
117
- } else {
118
- /* set msb */
119
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
120
- }
121
+ /*
122
+ * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
123
+ * S390, SH4, TriCore, and Xtensa. Our other supported targets
124
+ * do not have floating-point.
125
+ */
126
+ if (snan_bit_is_one(status)) {
127
+ /* sign bit clear, set all frac bits other than msb */
128
+ dnan_pattern = 0b00111111;
129
+ } else {
130
+ /* sign bit clear, set frac msb */
131
+ dnan_pattern = 0b01000000;
132
+ }
133
#endif
134
+ }
135
+ assert(dnan_pattern != 0);
136
+
137
+ sign = dnan_pattern >> 7;
138
+ /*
139
+ * Place default_nan_pattern [6:0] into bits [62:56],
140
+ * and replecate bit [0] down into [55:0]
141
+ */
142
+ frac = deposit64(0, DECOMPOSED_BINARY_POINT - 7, 7, dnan_pattern);
143
+ frac = deposit64(frac, 0, DECOMPOSED_BINARY_POINT - 7, -(dnan_pattern & 1));
144
145
*p = (FloatParts64) {
146
.cls = float_class_qnan,
156
--
147
--
157
2.16.2
148
2.34.1
158
159
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for the tests/fp code.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-36-peter.maydell@linaro.org
6
---
7
tests/fp/fp-bench.c | 1 +
8
tests/fp/fp-test-log2.c | 1 +
9
tests/fp/fp-test.c | 1 +
10
3 files changed, 3 insertions(+)
11
12
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/fp/fp-bench.c
15
+++ b/tests/fp/fp-bench.c
16
@@ -XXX,XX +XXX,XX @@ static void run_bench(void)
17
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &soft_status);
18
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &soft_status);
19
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &soft_status);
20
+ set_float_default_nan_pattern(0b01000000, &soft_status);
21
22
f = bench_funcs[operation][precision];
23
g_assert(f);
24
diff --git a/tests/fp/fp-test-log2.c b/tests/fp/fp-test-log2.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/tests/fp/fp-test-log2.c
27
+++ b/tests/fp/fp-test-log2.c
28
@@ -XXX,XX +XXX,XX @@ int main(int ac, char **av)
29
int i;
30
31
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
32
+ set_float_default_nan_pattern(0b01000000, &qsf);
33
set_float_rounding_mode(float_round_nearest_even, &qsf);
34
35
test.d = 0.0;
36
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/fp/fp-test.c
39
+++ b/tests/fp/fp-test.c
40
@@ -XXX,XX +XXX,XX @@ void run_test(void)
41
*/
42
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &qsf);
43
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &qsf);
44
+ set_float_default_nan_pattern(0b01000000, &qsf);
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, &qsf);
46
47
genCases_setLevel(test_level);
48
--
49
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
parts64_default_nan().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-37-peter.maydell@linaro.org
7
---
8
target/microblaze/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 +--
10
2 files changed, 3 insertions(+), 2 deletions(-)
11
12
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/microblaze/cpu.c
15
+++ b/target/microblaze/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_reset_hold(Object *obj, ResetType type)
17
* this architecture.
18
*/
19
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
20
+ /* Default NaN: sign bit set, most significant frac bit set */
21
+ set_float_default_nan_pattern(0b11000000, &env->fp_status);
22
23
#if defined(CONFIG_USER_ONLY)
24
/* start in user mode with interrupts enabled. */
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
30
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
31
/* Sign bit clear, all frac bits set */
32
dnan_pattern = 0b01111111;
33
-#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
34
- || defined(TARGET_MICROBLAZE)
35
+#elif defined(TARGET_I386) || defined(TARGET_X86_64)
36
/* Sign bit set, most significant frac bit set */
37
dnan_pattern = 0b11000000;
38
#elif defined(TARGET_HPPA)
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
parts64_default_nan().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-38-peter.maydell@linaro.org
7
---
8
target/i386/tcg/fpu_helper.c | 4 ++++
9
fpu/softfloat-specialize.c.inc | 3 ---
10
2 files changed, 4 insertions(+), 3 deletions(-)
11
12
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/i386/tcg/fpu_helper.c
15
+++ b/target/i386/tcg/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void cpu_init_fp_statuses(CPUX86State *env)
17
*/
18
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->sse_status);
19
set_float_3nan_prop_rule(float_3nan_prop_abc, &env->sse_status);
20
+ /* Default NaN: sign bit set, most significant frac bit set */
21
+ set_float_default_nan_pattern(0b11000000, &env->fp_status);
22
+ set_float_default_nan_pattern(0b11000000, &env->mmx_status);
23
+ set_float_default_nan_pattern(0b11000000, &env->sse_status);
24
}
25
26
static inline uint8_t save_exception_flags(CPUX86State *env)
27
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
index XXXXXXX..XXXXXXX 100644
29
--- a/fpu/softfloat-specialize.c.inc
30
+++ b/fpu/softfloat-specialize.c.inc
31
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
32
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
33
/* Sign bit clear, all frac bits set */
34
dnan_pattern = 0b01111111;
35
-#elif defined(TARGET_I386) || defined(TARGET_X86_64)
36
- /* Sign bit set, most significant frac bit set */
37
- dnan_pattern = 0b11000000;
38
#elif defined(TARGET_HPPA)
39
/* Sign bit clear, msb-1 frac bit set */
40
dnan_pattern = 0b00100000;
41
--
42
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly, and remove the ifdef from
2
parts64_default_nan().
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20241202131347.498124-39-peter.maydell@linaro.org
7
---
8
target/hppa/fpu_helper.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 3 ---
10
2 files changed, 2 insertions(+), 3 deletions(-)
11
12
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/hppa/fpu_helper.c
15
+++ b/target/hppa/fpu_helper.c
16
@@ -XXX,XX +XXX,XX @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
17
set_float_3nan_prop_rule(float_3nan_prop_abc, &env->fp_status);
18
/* For inf * 0 + NaN, return the input NaN */
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
20
+ /* Default NaN: sign bit clear, msb-1 frac bit set */
21
+ set_float_default_nan_pattern(0b00100000, &env->fp_status);
22
}
23
24
void cpu_hppa_loaded_fr0(CPUHPPAState *env)
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/fpu/softfloat-specialize.c.inc
28
+++ b/fpu/softfloat-specialize.c.inc
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
30
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
31
/* Sign bit clear, all frac bits set */
32
dnan_pattern = 0b01111111;
33
-#elif defined(TARGET_HPPA)
34
- /* Sign bit clear, msb-1 frac bit set */
35
- dnan_pattern = 0b00100000;
36
#elif defined(TARGET_HEXAGON)
37
/* Sign bit set, all frac bits set. */
38
dnan_pattern = 0b11111111;
39
--
40
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for the alpha target.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-40-peter.maydell@linaro.org
6
---
7
target/alpha/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
9
10
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/alpha/cpu.c
13
+++ b/target/alpha/cpu.c
14
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_initfn(Object *obj)
15
* operand in Fa. That is float_2nan_prop_ba.
16
*/
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
18
+ /* Default NaN: sign bit clear, msb frac bit set */
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
#if defined(CONFIG_USER_ONLY)
21
env->flags = ENV_FLAG_PS_USER | ENV_FLAG_FEN;
22
cpu_alpha_store_fpcr(env, (uint64_t)(FPCR_INVD | FPCR_DZED | FPCR_OVFD
23
--
24
2.34.1
diff view generated by jsdifflib
New patch
1
Set the default NaN pattern explicitly for the arm target.
2
This includes setting it for the old linux-user nwfpe emulation.
3
For nwfpe, our default doesn't match the real kernel, but we
4
avoid making a behaviour change in this commit.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20241202131347.498124-41-peter.maydell@linaro.org
9
---
10
linux-user/arm/nwfpe/fpa11.c | 5 +++++
11
target/arm/cpu.c | 2 ++
12
2 files changed, 7 insertions(+)
13
14
diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/arm/nwfpe/fpa11.c
17
+++ b/linux-user/arm/nwfpe/fpa11.c
18
@@ -XXX,XX +XXX,XX @@ void resetFPA11(void)
19
* this late date.
20
*/
21
set_float_2nan_prop_rule(float_2nan_prop_s_ab, &fpa11->fp_status);
22
+ /*
23
+ * Use the same default NaN value as Arm VFP. This doesn't match
24
+ * the Linux kernel's nwfpe emulation, which uses an all-1s value.
25
+ */
26
+ set_float_default_nan_pattern(0b01000000, &fpa11->fp_status);
27
}
28
29
void SetRoundingMode(const unsigned int opcode)
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
34
@@ -XXX,XX +XXX,XX @@ void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
35
* the pseudocode function the arguments are in the order c, a, b.
36
* * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
37
* and the input NaN if it is signalling
38
+ * * Default NaN has sign bit clear, msb frac bit set
39
*/
40
static void arm_set_default_fp_behaviours(float_status *s)
41
{
42
@@ -XXX,XX +XXX,XX @@ static void arm_set_default_fp_behaviours(float_status *s)
43
set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
44
set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
45
set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
46
+ set_float_default_nan_pattern(0b01000000, s);
47
}
48
49
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
50
--
51
2.34.1
diff view generated by jsdifflib
1
Set the appropriate Linux hwcap bits to tell the guest binary if we
1
Set the default NaN pattern explicitly for loongarch.
2
have implemented half-precision floating point support.
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>
5
Message-id: 20241202131347.498124-42-peter.maydell@linaro.org
6
---
6
---
7
linux-user/elfload.c | 2 ++
7
target/loongarch/tcg/fpu_helper.c | 2 ++
8
1 file changed, 2 insertions(+)
8
1 file changed, 2 insertions(+)
9
9
10
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
10
diff --git a/target/loongarch/tcg/fpu_helper.c b/target/loongarch/tcg/fpu_helper.c
11
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
12
--- a/linux-user/elfload.c
12
--- a/target/loongarch/tcg/fpu_helper.c
13
+++ b/linux-user/elfload.c
13
+++ b/target/loongarch/tcg/fpu_helper.c
14
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
14
@@ -XXX,XX +XXX,XX @@ void restore_fp_status(CPULoongArchState *env)
15
GET_FEATURE(ARM_FEATURE_V8_SM3, ARM_HWCAP_A64_SM3);
15
*/
16
GET_FEATURE(ARM_FEATURE_V8_SM4, ARM_HWCAP_A64_SM4);
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
17
GET_FEATURE(ARM_FEATURE_V8_SHA512, ARM_HWCAP_A64_SHA512);
17
set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
18
+ GET_FEATURE(ARM_FEATURE_V8_FP16,
18
+ /* Default NaN: sign bit clear, msb frac bit set */
19
+ ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
20
#undef GET_FEATURE
20
}
21
21
22
return hwcaps;
22
int ieee_ex_to_loongarch(int xcpt)
23
--
23
--
24
2.16.2
24
2.34.1
25
26
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the default NaN pattern explicitly for m68k.
2
2
3
Now we have added f16 during the re-factoring we can simply call the
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
helper.
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-43-peter.maydell@linaro.org
6
---
7
target/m68k/cpu.c | 2 ++
8
fpu/softfloat-specialize.c.inc | 2 +-
9
2 files changed, 3 insertions(+), 1 deletion(-)
5
10
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
11
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180227143852.11175-24-alex.bennee@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/translate-a64.c | 8 ++++++++
12
1 file changed, 8 insertions(+)
13
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
13
--- a/target/m68k/cpu.c
17
+++ b/target/arm/translate-a64.c
14
+++ b/target/m68k/cpu.c
18
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
15
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
19
case 0x6d: /* FCMLE (zero) */
16
* preceding paragraph for nonsignaling NaNs.
20
handle_2misc_fcmp_zero(s, fpop, is_scalar, 0, is_q, MO_16, rn, rd);
17
*/
21
return;
18
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
22
+ case 0x3d: /* FRECPE */
19
+ /* Default NaN: sign bit clear, all frac bits set */
23
+ break;
20
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
24
case 0x18: /* FRINTN */
21
25
need_rmode = true;
22
nan = floatx80_default_nan(&env->fp_status);
26
only_in_vector = true;
23
for (i = 0; i < 8; i++) {
27
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
24
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
28
case 0x3b: /* FCVTZS */
25
index XXXXXXX..XXXXXXX 100644
29
gen_helper_advsimd_f16tosinth(tcg_res, tcg_op, tcg_fpstatus);
26
--- a/fpu/softfloat-specialize.c.inc
30
break;
27
+++ b/fpu/softfloat-specialize.c.inc
31
+ case 0x3d: /* FRECPE */
28
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
32
+ gen_helper_recpe_f16(tcg_res, tcg_op, tcg_fpstatus);
29
uint8_t dnan_pattern = status->default_nan_pattern;
33
+ break;
30
34
case 0x5a: /* FCVTNU */
31
if (dnan_pattern == 0) {
35
case 0x5b: /* FCVTMU */
32
-#if defined(TARGET_SPARC) || defined(TARGET_M68K)
36
case 0x5c: /* FCVTAU */
33
+#if defined(TARGET_SPARC)
37
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
34
/* Sign bit clear, all frac bits set */
38
case 0x3b: /* FCVTZS */
35
dnan_pattern = 0b01111111;
39
gen_helper_advsimd_f16tosinth(tcg_res, tcg_op, tcg_fpstatus);
36
#elif defined(TARGET_HEXAGON)
40
break;
41
+ case 0x3d: /* FRECPE */
42
+ gen_helper_recpe_f16(tcg_res, tcg_op, tcg_fpstatus);
43
+ break;
44
case 0x5a: /* FCVTNU */
45
case 0x5b: /* FCVTMU */
46
case 0x5c: /* FCVTAU */
47
--
37
--
48
2.16.2
38
2.34.1
49
50
diff view generated by jsdifflib
1
Now we have implemented FP16 we can enable it for the "any" CPU.
1
Set the default NaN pattern explicitly for MIPS. Note that this
2
is our only target which currently changes the default NaN
3
at runtime (which it was previously doing indirectly when it
4
changed the snan_bit_is_one setting).
2
5
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
[PMM: split out from an earlier patch in the series]
8
Message-id: 20241202131347.498124-44-peter.maydell@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
9
---
8
target/arm/cpu64.c | 1 +
10
target/mips/fpu_helper.h | 7 +++++++
9
1 file changed, 1 insertion(+)
11
target/mips/msa.c | 3 +++
12
2 files changed, 10 insertions(+)
10
13
11
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
14
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu64.c
16
--- a/target/mips/fpu_helper.h
14
+++ b/target/arm/cpu64.c
17
+++ b/target/mips/fpu_helper.h
15
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
18
@@ -XXX,XX +XXX,XX @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
16
set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
19
set_float_infzeronan_rule(izn_rule, &env->active_fpu.fp_status);
17
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
20
nan3_rule = nan2008 ? float_3nan_prop_s_cab : float_3nan_prop_s_abc;
18
set_feature(&cpu->env, ARM_FEATURE_CRC);
21
set_float_3nan_prop_rule(nan3_rule, &env->active_fpu.fp_status);
19
+ set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
22
+ /*
20
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
23
+ * With nan2008, the default NaN value has the sign bit clear and the
21
cpu->dcz_blocksize = 7; /* 512 bytes */
24
+ * frac msb set; with the older mode, the sign bit is clear, and all
25
+ * frac bits except the msb are set.
26
+ */
27
+ set_float_default_nan_pattern(nan2008 ? 0b01000000 : 0b00111111,
28
+ &env->active_fpu.fp_status);
29
30
}
31
32
diff --git a/target/mips/msa.c b/target/mips/msa.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/mips/msa.c
35
+++ b/target/mips/msa.c
36
@@ -XXX,XX +XXX,XX @@ void msa_reset(CPUMIPSState *env)
37
/* Inf * 0 + NaN returns the input NaN */
38
set_float_infzeronan_rule(float_infzeronan_dnan_never,
39
&env->active_tc.msa_fp_status);
40
+ /* Default NaN: sign bit clear, frac msb set */
41
+ set_float_default_nan_pattern(0b01000000,
42
+ &env->active_tc.msa_fp_status);
22
}
43
}
23
--
44
--
24
2.16.2
45
2.34.1
25
26
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the default NaN pattern explicitly for openrisc.
2
2
3
Signed-off-by: Alex Bennée <alex.bennee@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: 20180227143852.11175-12-alex.bennee@linaro.org
5
Message-id: 20241202131347.498124-45-peter.maydell@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
6
---
8
target/arm/helper-a64.h | 2 ++
7
target/openrisc/cpu.c | 2 ++
9
target/arm/helper-a64.c | 24 ++++++++++++++++++++++++
8
1 file changed, 2 insertions(+)
10
target/arm/translate-a64.c | 15 +++++++++++++++
11
3 files changed, 41 insertions(+)
12
9
13
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
10
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-a64.h
12
--- a/target/openrisc/cpu.c
16
+++ b/target/arm/helper-a64.h
13
+++ b/target/openrisc/cpu.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(advsimd_cge_f16, i32, f16, f16, ptr)
14
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_reset_hold(Object *obj, ResetType type)
18
DEF_HELPER_3(advsimd_cgt_f16, i32, f16, f16, ptr)
15
*/
19
DEF_HELPER_3(advsimd_acge_f16, i32, f16, f16, ptr)
16
set_float_2nan_prop_rule(float_2nan_prop_x87, &cpu->env.fp_status);
20
DEF_HELPER_3(advsimd_acgt_f16, i32, f16, f16, ptr)
17
21
+DEF_HELPER_3(advsimd_mulxh, f16, f16, f16, ptr)
18
+ /* Default NaN: sign bit clear, frac msb set */
22
+DEF_HELPER_4(advsimd_muladdh, f16, f16, f16, f16, ptr)
19
+ set_float_default_nan_pattern(0b01000000, &cpu->env.fp_status);
23
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
20
24
index XXXXXXX..XXXXXXX 100644
21
#ifndef CONFIG_USER_ONLY
25
--- a/target/arm/helper-a64.c
22
cpu->env.picmr = 0x00000000;
26
+++ b/target/arm/helper-a64.c
27
@@ -XXX,XX +XXX,XX @@ ADVSIMD_HALFOP(max)
28
ADVSIMD_HALFOP(minnum)
29
ADVSIMD_HALFOP(maxnum)
30
31
+/* Data processing - scalar floating-point and advanced SIMD */
32
+float16 HELPER(advsimd_mulxh)(float16 a, float16 b, void *fpstp)
33
+{
34
+ float_status *fpst = fpstp;
35
+
36
+ a = float16_squash_input_denormal(a, fpst);
37
+ b = float16_squash_input_denormal(b, fpst);
38
+
39
+ if ((float16_is_zero(a) && float16_is_infinity(b)) ||
40
+ (float16_is_infinity(a) && float16_is_zero(b))) {
41
+ /* 2.0 with the sign bit set to sign(A) XOR sign(B) */
42
+ return make_float16((1U << 14) |
43
+ ((float16_val(a) ^ float16_val(b)) & (1U << 15)));
44
+ }
45
+ return float16_mul(a, b, fpst);
46
+}
47
+
48
+/* fused multiply-accumulate */
49
+float16 HELPER(advsimd_muladdh)(float16 a, float16 b, float16 c, void *fpstp)
50
+{
51
+ float_status *fpst = fpstp;
52
+ return float16_muladd(a, b, c, 0, fpst);
53
+}
54
+
55
/*
56
* Floating point comparisons produce an integer result. Softfloat
57
* routines return float_relation types which we convert to the 0/-1
58
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/translate-a64.c
61
+++ b/target/arm/translate-a64.c
62
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
63
case 0x0: /* FMAXNM */
64
gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
65
break;
66
+ case 0x1: /* FMLA */
67
+ read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
68
+ gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
69
+ fpst);
70
+ break;
71
case 0x2: /* FADD */
72
gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
73
break;
74
+ case 0x3: /* FMULX */
75
+ gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
76
+ break;
77
case 0x4: /* FCMEQ */
78
gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
79
break;
80
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
81
case 0x8: /* FMINNM */
82
gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
83
break;
84
+ case 0x9: /* FMLS */
85
+ /* As usual for ARM, separate negation for fused multiply-add */
86
+ tcg_gen_xori_i32(tcg_op1, tcg_op1, 0x8000);
87
+ read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
88
+ gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
89
+ fpst);
90
+ break;
91
case 0xa: /* FSUB */
92
gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
93
break;
94
--
23
--
95
2.16.2
24
2.34.1
96
97
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the default NaN pattern explicitly for ppc.
2
2
3
We do implement all the opcodes.
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-46-peter.maydell@linaro.org
6
---
7
target/ppc/cpu_init.c | 4 ++++
8
1 file changed, 4 insertions(+)
4
9
5
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180227143852.11175-8-alex.bennee@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/translate-a64.c | 3 +--
11
1 file changed, 1 insertion(+), 2 deletions(-)
12
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
12
--- a/target/ppc/cpu_init.c
16
+++ b/target/arm/translate-a64.c
13
+++ b/target/ppc/cpu_init.c
17
@@ -XXX,XX +XXX,XX @@ static void handle_3same_64(DisasContext *s, int opcode, bool u,
14
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type)
18
/* Handle 64x64->64 opcodes which are shared between the scalar
15
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
19
* and vector 3-same groups. We cover every opcode where size == 3
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->vec_status);
20
* is valid in either the three-reg-same (integer, not pairwise)
17
21
- * or scalar-three-reg-same groups. (Some opcodes are not yet
18
+ /* Default NaN: sign bit clear, set frac msb */
22
- * implemented.)
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
23
+ * or scalar-three-reg-same groups.
20
+ set_float_default_nan_pattern(0b01000000, &env->vec_status);
24
*/
21
+
25
TCGCond cond;
22
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
23
ppc_spr_t *spr = &env->spr_cb[i];
26
24
27
--
25
--
28
2.16.2
26
2.34.1
29
30
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the default NaN pattern explicitly for sh4. Note that sh4
2
is one of the only three targets (the others being HPPA and
3
sometimes MIPS) that has snan_bit_is_one set.
2
4
3
We go with the localised helper.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241202131347.498124-47-peter.maydell@linaro.org
8
---
9
target/sh4/cpu.c | 2 ++
10
1 file changed, 2 insertions(+)
4
11
5
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
12
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180227143852.11175-25-alex.bennee@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/helper-a64.h | 1 +
11
target/arm/helper-a64.c | 29 +++++++++++++++++++++++++++++
12
target/arm/translate-a64.c | 4 ++++
13
3 files changed, 34 insertions(+)
14
15
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-a64.h
14
--- a/target/sh4/cpu.c
18
+++ b/target/arm/helper-a64.h
15
+++ b/target/sh4/cpu.c
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_1(neon_addlp_s16, TCG_CALL_NO_RWG_SE, i64, i64)
16
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
20
DEF_HELPER_FLAGS_1(neon_addlp_u16, TCG_CALL_NO_RWG_SE, i64, i64)
17
set_flush_to_zero(1, &env->fp_status);
21
DEF_HELPER_FLAGS_2(frecpx_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
18
#endif
22
DEF_HELPER_FLAGS_2(frecpx_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
19
set_default_nan_mode(1, &env->fp_status);
23
+DEF_HELPER_FLAGS_2(frecpx_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
20
+ /* sign bit clear, set all frac bits other than msb */
24
DEF_HELPER_FLAGS_2(fcvtx_f64_to_f32, TCG_CALL_NO_RWG, f32, f64, env)
21
+ set_float_default_nan_pattern(0b00111111, &env->fp_status);
25
DEF_HELPER_FLAGS_3(crc32_64, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32)
26
DEF_HELPER_FLAGS_3(crc32c_64, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32)
27
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/helper-a64.c
30
+++ b/target/arm/helper-a64.c
31
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(neon_addlp_u16)(uint64_t a)
32
}
22
}
33
23
34
/* Floating-point reciprocal exponent - see FPRecpX in ARM ARM */
24
static void superh_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
35
+float16 HELPER(frecpx_f16)(float16 a, void *fpstp)
36
+{
37
+ float_status *fpst = fpstp;
38
+ uint16_t val16, sbit;
39
+ int16_t exp;
40
+
41
+ if (float16_is_any_nan(a)) {
42
+ float16 nan = a;
43
+ if (float16_is_signaling_nan(a, fpst)) {
44
+ float_raise(float_flag_invalid, fpst);
45
+ nan = float16_maybe_silence_nan(a, fpst);
46
+ }
47
+ if (fpst->default_nan_mode) {
48
+ nan = float16_default_nan(fpst);
49
+ }
50
+ return nan;
51
+ }
52
+
53
+ val16 = float16_val(a);
54
+ sbit = 0x8000 & val16;
55
+ exp = extract32(val16, 10, 5);
56
+
57
+ if (exp == 0) {
58
+ return make_float16(deposit32(sbit, 10, 5, 0x1e));
59
+ } else {
60
+ return make_float16(deposit32(sbit, 10, 5, ~exp));
61
+ }
62
+}
63
+
64
float32 HELPER(frecpx_f32)(float32 a, void *fpstp)
65
{
66
float_status *fpst = fpstp;
67
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/translate-a64.c
70
+++ b/target/arm/translate-a64.c
71
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
72
handle_2misc_fcmp_zero(s, fpop, is_scalar, 0, is_q, MO_16, rn, rd);
73
return;
74
case 0x3d: /* FRECPE */
75
+ case 0x3f: /* FRECPX */
76
break;
77
case 0x18: /* FRINTN */
78
need_rmode = true;
79
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
80
case 0x3d: /* FRECPE */
81
gen_helper_recpe_f16(tcg_res, tcg_op, tcg_fpstatus);
82
break;
83
+ case 0x3f: /* FRECPX */
84
+ gen_helper_frecpx_f16(tcg_res, tcg_op, tcg_fpstatus);
85
+ break;
86
case 0x5a: /* FCVTNU */
87
case 0x5b: /* FCVTMU */
88
case 0x5c: /* FCVTAU */
89
--
25
--
90
2.16.2
26
2.34.1
91
92
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the default NaN pattern explicitly for rx.
2
2
3
The fprintf is only there for debugging as the skeleton is added to,
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
it will be removed once the skeleton is complete.
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-48-peter.maydell@linaro.org
6
---
7
target/rx/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
5
9
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180227143852.11175-10-alex.bennee@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper-a64.h | 4 ++++
12
target/arm/helper-a64.c | 4 ++++
13
target/arm/translate-a64.c | 28 ++++++++++++++++++++++++++++
14
3 files changed, 36 insertions(+)
15
16
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
17
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper-a64.h
12
--- a/target/rx/cpu.c
19
+++ b/target/arm/helper-a64.h
13
+++ b/target/rx/cpu.c
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(advsimd_maxh, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
14
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_reset_hold(Object *obj, ResetType type)
21
DEF_HELPER_FLAGS_3(advsimd_minh, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
15
* then prefer dest over source", which is float_2nan_prop_s_ab.
22
DEF_HELPER_FLAGS_3(advsimd_maxnumh, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
16
*/
23
DEF_HELPER_FLAGS_3(advsimd_minnumh, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
17
set_float_2nan_prop_rule(float_2nan_prop_x87, &env->fp_status);
24
+DEF_HELPER_3(advsimd_addh, f16, f16, f16, ptr)
18
+ /* Default NaN value: sign bit clear, set frac msb */
25
+DEF_HELPER_3(advsimd_subh, f16, f16, f16, ptr)
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
26
+DEF_HELPER_3(advsimd_mulh, f16, f16, f16, ptr)
27
+DEF_HELPER_3(advsimd_divh, f16, f16, f16, ptr)
28
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/helper-a64.c
31
+++ b/target/arm/helper-a64.c
32
@@ -XXX,XX +XXX,XX @@ float16 ADVSIMD_HELPER(name, h)(float16 a, float16 b, void *fpstp) \
33
return float16_ ## name(a, b, fpst); \
34
}
20
}
35
21
36
+ADVSIMD_HALFOP(add)
22
static ObjectClass *rx_cpu_class_by_name(const char *cpu_model)
37
+ADVSIMD_HALFOP(sub)
38
+ADVSIMD_HALFOP(mul)
39
+ADVSIMD_HALFOP(div)
40
ADVSIMD_HALFOP(min)
41
ADVSIMD_HALFOP(max)
42
ADVSIMD_HALFOP(minnum)
43
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/translate-a64.c
46
+++ b/target/arm/translate-a64.c
47
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
48
read_vec_element_i32(s, tcg_op2, rm, pass, MO_16);
49
50
switch (fpopcode) {
51
+ case 0x0: /* FMAXNM */
52
+ gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
53
+ break;
54
+ case 0x2: /* FADD */
55
+ gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
56
+ break;
57
+ case 0x6: /* FMAX */
58
+ gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
59
+ break;
60
+ case 0x8: /* FMINNM */
61
+ gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
62
+ break;
63
+ case 0xa: /* FSUB */
64
+ gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
65
+ break;
66
+ case 0xe: /* FMIN */
67
+ gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
68
+ break;
69
+ case 0x13: /* FMUL */
70
+ gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
71
+ break;
72
+ case 0x17: /* FDIV */
73
+ gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
74
+ break;
75
+ case 0x1a: /* FABD */
76
+ gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
77
+ tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
78
+ break;
79
default:
80
fprintf(stderr, "%s: insn %#04x, fpop %#2x @ %#" PRIx64 "\n",
81
__func__, insn, fpopcode, s->pc);
82
--
23
--
83
2.16.2
24
2.34.1
84
85
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the default NaN pattern explicitly for s390x.
2
2
3
These use the generic float16_compare functionality which in turn uses
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the common float_compare code from the softfloat re-factor.
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-49-peter.maydell@linaro.org
6
---
7
target/s390x/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
5
9
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180227143852.11175-11-alex.bennee@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper-a64.h | 5 +++++
12
target/arm/helper-a64.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++
13
target/arm/translate-a64.c | 15 ++++++++++++++
14
3 files changed, 69 insertions(+)
15
16
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
17
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper-a64.h
12
--- a/target/s390x/cpu.c
19
+++ b/target/arm/helper-a64.h
13
+++ b/target/s390x/cpu.c
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(advsimd_addh, f16, f16, f16, ptr)
14
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_hold(Object *obj, ResetType type)
21
DEF_HELPER_3(advsimd_subh, f16, f16, f16, ptr)
15
set_float_3nan_prop_rule(float_3nan_prop_s_abc, &env->fpu_status);
22
DEF_HELPER_3(advsimd_mulh, f16, f16, f16, ptr)
16
set_float_infzeronan_rule(float_infzeronan_dnan_always,
23
DEF_HELPER_3(advsimd_divh, f16, f16, f16, ptr)
17
&env->fpu_status);
24
+DEF_HELPER_3(advsimd_ceq_f16, i32, f16, f16, ptr)
18
+ /* Default NaN value: sign bit clear, frac msb set */
25
+DEF_HELPER_3(advsimd_cge_f16, i32, f16, f16, ptr)
19
+ set_float_default_nan_pattern(0b01000000, &env->fpu_status);
26
+DEF_HELPER_3(advsimd_cgt_f16, i32, f16, f16, ptr)
20
/* fall through */
27
+DEF_HELPER_3(advsimd_acge_f16, i32, f16, f16, ptr)
21
case RESET_TYPE_S390_CPU_NORMAL:
28
+DEF_HELPER_3(advsimd_acgt_f16, i32, f16, f16, ptr)
22
env->psw.mask &= ~PSW_MASK_RI;
29
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/helper-a64.c
32
+++ b/target/arm/helper-a64.c
33
@@ -XXX,XX +XXX,XX @@ ADVSIMD_HALFOP(min)
34
ADVSIMD_HALFOP(max)
35
ADVSIMD_HALFOP(minnum)
36
ADVSIMD_HALFOP(maxnum)
37
+
38
+/*
39
+ * Floating point comparisons produce an integer result. Softfloat
40
+ * routines return float_relation types which we convert to the 0/-1
41
+ * Neon requires.
42
+ */
43
+
44
+#define ADVSIMD_CMPRES(test) (test) ? 0xffff : 0
45
+
46
+uint32_t HELPER(advsimd_ceq_f16)(float16 a, float16 b, void *fpstp)
47
+{
48
+ float_status *fpst = fpstp;
49
+ int compare = float16_compare_quiet(a, b, fpst);
50
+ return ADVSIMD_CMPRES(compare == float_relation_equal);
51
+}
52
+
53
+uint32_t HELPER(advsimd_cge_f16)(float16 a, float16 b, void *fpstp)
54
+{
55
+ float_status *fpst = fpstp;
56
+ int compare = float16_compare(a, b, fpst);
57
+ return ADVSIMD_CMPRES(compare == float_relation_greater ||
58
+ compare == float_relation_equal);
59
+}
60
+
61
+uint32_t HELPER(advsimd_cgt_f16)(float16 a, float16 b, void *fpstp)
62
+{
63
+ float_status *fpst = fpstp;
64
+ int compare = float16_compare(a, b, fpst);
65
+ return ADVSIMD_CMPRES(compare == float_relation_greater);
66
+}
67
+
68
+uint32_t HELPER(advsimd_acge_f16)(float16 a, float16 b, void *fpstp)
69
+{
70
+ float_status *fpst = fpstp;
71
+ float16 f0 = float16_abs(a);
72
+ float16 f1 = float16_abs(b);
73
+ int compare = float16_compare(f0, f1, fpst);
74
+ return ADVSIMD_CMPRES(compare == float_relation_greater ||
75
+ compare == float_relation_equal);
76
+}
77
+
78
+uint32_t HELPER(advsimd_acgt_f16)(float16 a, float16 b, void *fpstp)
79
+{
80
+ float_status *fpst = fpstp;
81
+ float16 f0 = float16_abs(a);
82
+ float16 f1 = float16_abs(b);
83
+ int compare = float16_compare(f0, f1, fpst);
84
+ return ADVSIMD_CMPRES(compare == float_relation_greater);
85
+}
86
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/target/arm/translate-a64.c
89
+++ b/target/arm/translate-a64.c
90
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
91
case 0x2: /* FADD */
92
gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
93
break;
94
+ case 0x4: /* FCMEQ */
95
+ gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
96
+ break;
97
case 0x6: /* FMAX */
98
gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
99
break;
100
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
101
case 0x13: /* FMUL */
102
gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
103
break;
104
+ case 0x14: /* FCMGE */
105
+ gen_helper_advsimd_cge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
106
+ break;
107
+ case 0x15: /* FACGE */
108
+ gen_helper_advsimd_acge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
109
+ break;
110
case 0x17: /* FDIV */
111
gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
112
break;
113
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
114
gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
115
tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
116
break;
117
+ case 0x1c: /* FCMGT */
118
+ gen_helper_advsimd_cgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
119
+ break;
120
+ case 0x1d: /* FACGT */
121
+ gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
122
+ break;
123
default:
124
fprintf(stderr, "%s: insn %#04x, fpop %#2x @ %#" PRIx64 "\n",
125
__func__, insn, fpopcode, s->pc);
126
--
23
--
127
2.16.2
24
2.34.1
128
129
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the default NaN pattern explicitly for SPARC, and remove
2
the ifdef from parts64_default_nan.
2
3
3
This allows us to explicitly pass float16 to helpers rather than
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
assuming uint32_t and dealing with the result. Of course they will be
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
passed in i32 sized registers by default.
6
Message-id: 20241202131347.498124-50-peter.maydell@linaro.org
7
---
8
target/sparc/cpu.c | 2 ++
9
fpu/softfloat-specialize.c.inc | 5 +----
10
2 files changed, 3 insertions(+), 4 deletions(-)
6
11
7
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
12
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180227143852.11175-2-alex.bennee@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/exec/helper-head.h | 3 +++
13
1 file changed, 3 insertions(+)
14
15
diff --git a/include/exec/helper-head.h b/include/exec/helper-head.h
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/include/exec/helper-head.h
14
--- a/target/sparc/cpu.c
18
+++ b/include/exec/helper-head.h
15
+++ b/target/sparc/cpu.c
19
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
20
#define dh_alias_int i32
17
set_float_3nan_prop_rule(float_3nan_prop_s_cba, &env->fp_status);
21
#define dh_alias_i64 i64
18
/* For inf * 0 + NaN, return the input NaN */
22
#define dh_alias_s64 i64
19
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
23
+#define dh_alias_f16 i32
20
+ /* Default NaN value: sign bit clear, all frac bits set */
24
#define dh_alias_f32 i32
21
+ set_float_default_nan_pattern(0b01111111, &env->fp_status);
25
#define dh_alias_f64 i64
22
26
#define dh_alias_ptr ptr
23
cpu_exec_realizefn(cs, &local_err);
27
@@ -XXX,XX +XXX,XX @@
24
if (local_err != NULL) {
28
#define dh_ctype_int int
25
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
29
#define dh_ctype_i64 uint64_t
26
index XXXXXXX..XXXXXXX 100644
30
#define dh_ctype_s64 int64_t
27
--- a/fpu/softfloat-specialize.c.inc
31
+#define dh_ctype_f16 float16
28
+++ b/fpu/softfloat-specialize.c.inc
32
#define dh_ctype_f32 float32
29
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
33
#define dh_ctype_f64 float64
30
uint8_t dnan_pattern = status->default_nan_pattern;
34
#define dh_ctype_ptr void *
31
35
@@ -XXX,XX +XXX,XX @@
32
if (dnan_pattern == 0) {
36
#define dh_is_signed_s32 1
33
-#if defined(TARGET_SPARC)
37
#define dh_is_signed_i64 0
34
- /* Sign bit clear, all frac bits set */
38
#define dh_is_signed_s64 1
35
- dnan_pattern = 0b01111111;
39
+#define dh_is_signed_f16 0
36
-#elif defined(TARGET_HEXAGON)
40
#define dh_is_signed_f32 0
37
+#if defined(TARGET_HEXAGON)
41
#define dh_is_signed_f64 0
38
/* Sign bit set, all frac bits set. */
42
#define dh_is_signed_tl 0
39
dnan_pattern = 0b11111111;
40
#else
43
--
41
--
44
2.16.2
42
2.34.1
45
46
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the default NaN pattern explicitly for xtensa.
2
2
3
As the rounding mode is now split between FP16 and the rest of
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
floating point we need to be explicit when tweaking it. Instead of
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
passing the CPU env we now pass the appropriate fpst pointer directly.
5
Message-id: 20241202131347.498124-51-peter.maydell@linaro.org
6
---
7
target/xtensa/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
6
9
7
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180227143852.11175-6-alex.bennee@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/helper.h | 2 +-
13
target/arm/helper.c | 4 ++--
14
target/arm/translate-a64.c | 26 +++++++++++++-------------
15
target/arm/translate.c | 12 ++++++------
16
4 files changed, 22 insertions(+), 22 deletions(-)
17
18
diff --git a/target/arm/helper.h b/target/arm/helper.h
19
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.h
12
--- a/target/xtensa/cpu.c
21
+++ b/target/arm/helper.h
13
+++ b/target/xtensa/cpu.c
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_uhtod, f64, i64, i32, ptr)
14
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
23
DEF_HELPER_3(vfp_ultod, f64, i64, i32, ptr)
15
/* For inf * 0 + NaN, return the input NaN */
24
DEF_HELPER_3(vfp_uqtod, f64, i64, i32, ptr)
16
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
25
17
set_no_signaling_nans(!dfpu, &env->fp_status);
26
-DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, env)
18
+ /* Default NaN value: sign bit clear, set frac msb */
27
+DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
28
DEF_HELPER_FLAGS_2(set_neon_rmode, TCG_CALL_NO_RWG, i32, i32, env)
20
xtensa_use_first_nan(env, !dfpu);
29
30
DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
31
diff --git a/target/arm/helper.c b/target/arm/helper.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/helper.c
34
+++ b/target/arm/helper.c
35
@@ -XXX,XX +XXX,XX @@ VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
36
/* Set the current fp rounding mode and return the old one.
37
* The argument is a softfloat float_round_ value.
38
*/
39
-uint32_t HELPER(set_rmode)(uint32_t rmode, CPUARMState *env)
40
+uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
41
{
42
- float_status *fp_status = &env->vfp.fp_status;
43
+ float_status *fp_status = fpstp;
44
45
uint32_t prev_rmode = get_float_rounding_mode(fp_status);
46
set_float_rounding_mode(rmode, fp_status);
47
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate-a64.c
50
+++ b/target/arm/translate-a64.c
51
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
52
{
53
TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
54
55
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
56
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
57
gen_helper_rints(tcg_res, tcg_op, fpst);
58
59
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
60
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
61
tcg_temp_free_i32(tcg_rmode);
62
break;
63
}
64
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
65
{
66
TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
67
68
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
69
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
70
gen_helper_rintd(tcg_res, tcg_op, fpst);
71
72
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
73
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
74
tcg_temp_free_i32(tcg_rmode);
75
break;
76
}
77
@@ -XXX,XX +XXX,XX @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
78
79
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
80
81
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
82
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
83
84
if (is_double) {
85
TCGv_i64 tcg_double = read_fp_dreg(s, rn);
86
@@ -XXX,XX +XXX,XX @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
87
tcg_temp_free_i32(tcg_single);
88
}
89
90
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
91
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
92
tcg_temp_free_i32(tcg_rmode);
93
94
if (!sf) {
95
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
96
assert(!(is_scalar && is_q));
97
98
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
99
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
100
tcg_fpstatus = get_fpstatus_ptr(false);
101
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
102
tcg_shift = tcg_const_i32(fracbits);
103
104
if (is_double) {
105
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
106
107
tcg_temp_free_ptr(tcg_fpstatus);
108
tcg_temp_free_i32(tcg_shift);
109
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
110
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
111
tcg_temp_free_i32(tcg_rmode);
112
}
21
}
113
22
114
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
115
116
if (is_fcvt) {
117
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
118
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
119
tcg_fpstatus = get_fpstatus_ptr(false);
120
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
121
} else {
122
tcg_rmode = NULL;
123
tcg_fpstatus = NULL;
124
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
125
}
126
127
if (is_fcvt) {
128
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
129
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
130
tcg_temp_free_i32(tcg_rmode);
131
tcg_temp_free_ptr(tcg_fpstatus);
132
}
133
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
134
return;
135
}
136
137
- if (need_fpstatus) {
138
+ if (need_fpstatus || need_rmode) {
139
tcg_fpstatus = get_fpstatus_ptr(false);
140
} else {
141
tcg_fpstatus = NULL;
142
}
143
if (need_rmode) {
144
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
145
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
146
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
147
} else {
148
tcg_rmode = NULL;
149
}
150
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
151
clear_vec_high(s, is_q, rd);
152
153
if (need_rmode) {
154
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
155
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
156
tcg_temp_free_i32(tcg_rmode);
157
}
158
if (need_fpstatus) {
159
diff --git a/target/arm/translate.c b/target/arm/translate.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/target/arm/translate.c
162
+++ b/target/arm/translate.c
163
@@ -XXX,XX +XXX,XX @@ static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
164
TCGv_i32 tcg_rmode;
165
166
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
167
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
168
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
169
170
if (dp) {
171
TCGv_i64 tcg_op;
172
@@ -XXX,XX +XXX,XX @@ static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
173
tcg_temp_free_i32(tcg_res);
174
}
175
176
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
177
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
178
tcg_temp_free_i32(tcg_rmode);
179
180
tcg_temp_free_ptr(fpst);
181
@@ -XXX,XX +XXX,XX @@ static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
182
tcg_shift = tcg_const_i32(0);
183
184
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
185
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
186
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
187
188
if (dp) {
189
TCGv_i64 tcg_double, tcg_res;
190
@@ -XXX,XX +XXX,XX @@ static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
191
tcg_temp_free_i32(tcg_single);
192
}
193
194
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
195
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
196
tcg_temp_free_i32(tcg_rmode);
197
198
tcg_temp_free_i32(tcg_shift);
199
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
200
TCGv_ptr fpst = get_fpstatus_ptr(0);
201
TCGv_i32 tcg_rmode;
202
tcg_rmode = tcg_const_i32(float_round_to_zero);
203
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
204
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
205
if (dp) {
206
gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
207
} else {
208
gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
209
}
210
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
211
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
212
tcg_temp_free_i32(tcg_rmode);
213
tcg_temp_free_ptr(fpst);
214
break;
215
--
23
--
216
2.16.2
24
2.34.1
217
218
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Set the default NaN pattern explicitly for hexagon.
2
Remove the ifdef from parts64_default_nan(); the only
3
remaining unconverted targets all use the default case.
2
4
3
This implements the half-precision variants of the across vector
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
reduction operations. This involves a re-factor of the reduction code
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
which more closely matches the ARM ARM order (and handles 8 element
7
Message-id: 20241202131347.498124-52-peter.maydell@linaro.org
6
reductions).
8
---
9
target/hexagon/cpu.c | 2 ++
10
fpu/softfloat-specialize.c.inc | 5 -----
11
2 files changed, 2 insertions(+), 5 deletions(-)
7
12
8
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
13
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180227143852.11175-7-alex.bennee@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/helper-a64.h | 4 ++
14
target/arm/helper-a64.c | 18 ++++++
15
target/arm/translate-a64.c | 140 ++++++++++++++++++++++++++++-----------------
16
3 files changed, 109 insertions(+), 53 deletions(-)
17
18
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper-a64.h
15
--- a/target/hexagon/cpu.c
21
+++ b/target/arm/helper-a64.h
16
+++ b/target/hexagon/cpu.c
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(paired_cmpxchg64_le_parallel, TCG_CALL_NO_WG,
17
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
23
DEF_HELPER_FLAGS_4(paired_cmpxchg64_be, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
18
24
DEF_HELPER_FLAGS_4(paired_cmpxchg64_be_parallel, TCG_CALL_NO_WG,
19
set_default_nan_mode(1, &env->fp_status);
25
i64, env, i64, i64, i64)
20
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
26
+DEF_HELPER_FLAGS_3(advsimd_maxh, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
21
+ /* Default NaN value: sign bit set, all frac bits set */
27
+DEF_HELPER_FLAGS_3(advsimd_minh, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
22
+ set_float_default_nan_pattern(0b11111111, &env->fp_status);
28
+DEF_HELPER_FLAGS_3(advsimd_maxnumh, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
23
}
29
+DEF_HELPER_FLAGS_3(advsimd_minnumh, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
24
30
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
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
31
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/helper-a64.c
28
--- a/fpu/softfloat-specialize.c.inc
33
+++ b/target/arm/helper-a64.c
29
+++ b/fpu/softfloat-specialize.c.inc
34
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr,
30
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
35
{
31
uint8_t dnan_pattern = status->default_nan_pattern;
36
return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, true, GETPC());
32
37
}
33
if (dnan_pattern == 0) {
38
+
34
-#if defined(TARGET_HEXAGON)
39
+/*
35
- /* Sign bit set, all frac bits set. */
40
+ * AdvSIMD half-precision
36
- dnan_pattern = 0b11111111;
41
+ */
37
-#else
42
+
38
/*
43
+#define ADVSIMD_HELPER(name, suffix) HELPER(glue(glue(advsimd_, name), suffix))
39
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
44
+
40
* S390, SH4, TriCore, and Xtensa. Our other supported targets
45
+#define ADVSIMD_HALFOP(name) \
41
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
46
+float16 ADVSIMD_HELPER(name, h)(float16 a, float16 b, void *fpstp) \
42
/* sign bit clear, set frac msb */
47
+{ \
43
dnan_pattern = 0b01000000;
48
+ float_status *fpst = fpstp; \
49
+ return float16_ ## name(a, b, fpst); \
50
+}
51
+
52
+ADVSIMD_HALFOP(min)
53
+ADVSIMD_HALFOP(max)
54
+ADVSIMD_HALFOP(minnum)
55
+ADVSIMD_HALFOP(maxnum)
56
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/translate-a64.c
59
+++ b/target/arm/translate-a64.c
60
@@ -XXX,XX +XXX,XX @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
61
tcg_temp_free_i64(tcg_resh);
62
}
63
64
-static void do_minmaxop(DisasContext *s, TCGv_i32 tcg_elt1, TCGv_i32 tcg_elt2,
65
- int opc, bool is_min, TCGv_ptr fpst)
66
+/*
67
+ * do_reduction_op helper
68
+ *
69
+ * This mirrors the Reduce() pseudocode in the ARM ARM. It is
70
+ * important for correct NaN propagation that we do these
71
+ * operations in exactly the order specified by the pseudocode.
72
+ *
73
+ * This is a recursive function, TCG temps should be freed by the
74
+ * calling function once it is done with the values.
75
+ */
76
+static TCGv_i32 do_reduction_op(DisasContext *s, int fpopcode, int rn,
77
+ int esize, int size, int vmap, TCGv_ptr fpst)
78
{
79
- /* Helper function for disas_simd_across_lanes: do a single precision
80
- * min/max operation on the specified two inputs,
81
- * and return the result in tcg_elt1.
82
- */
83
- if (opc == 0xc) {
84
- if (is_min) {
85
- gen_helper_vfp_minnums(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
86
- } else {
87
- gen_helper_vfp_maxnums(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
88
- }
89
+ if (esize == size) {
90
+ int element;
91
+ TCGMemOp msize = esize == 16 ? MO_16 : MO_32;
92
+ TCGv_i32 tcg_elem;
93
+
94
+ /* We should have one register left here */
95
+ assert(ctpop8(vmap) == 1);
96
+ element = ctz32(vmap);
97
+ assert(element < 8);
98
+
99
+ tcg_elem = tcg_temp_new_i32();
100
+ read_vec_element_i32(s, tcg_elem, rn, element, msize);
101
+ return tcg_elem;
102
} else {
103
- assert(opc == 0xf);
104
- if (is_min) {
105
- gen_helper_vfp_mins(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
106
- } else {
107
- gen_helper_vfp_maxs(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
108
+ int bits = size / 2;
109
+ int shift = ctpop8(vmap) / 2;
110
+ int vmap_lo = (vmap >> shift) & vmap;
111
+ int vmap_hi = (vmap & ~vmap_lo);
112
+ TCGv_i32 tcg_hi, tcg_lo, tcg_res;
113
+
114
+ tcg_hi = do_reduction_op(s, fpopcode, rn, esize, bits, vmap_hi, fpst);
115
+ tcg_lo = do_reduction_op(s, fpopcode, rn, esize, bits, vmap_lo, fpst);
116
+ tcg_res = tcg_temp_new_i32();
117
+
118
+ switch (fpopcode) {
119
+ case 0x0c: /* fmaxnmv half-precision */
120
+ gen_helper_advsimd_maxnumh(tcg_res, tcg_lo, tcg_hi, fpst);
121
+ break;
122
+ case 0x0f: /* fmaxv half-precision */
123
+ gen_helper_advsimd_maxh(tcg_res, tcg_lo, tcg_hi, fpst);
124
+ break;
125
+ case 0x1c: /* fminnmv half-precision */
126
+ gen_helper_advsimd_minnumh(tcg_res, tcg_lo, tcg_hi, fpst);
127
+ break;
128
+ case 0x1f: /* fminv half-precision */
129
+ gen_helper_advsimd_minh(tcg_res, tcg_lo, tcg_hi, fpst);
130
+ break;
131
+ case 0x2c: /* fmaxnmv */
132
+ gen_helper_vfp_maxnums(tcg_res, tcg_lo, tcg_hi, fpst);
133
+ break;
134
+ case 0x2f: /* fmaxv */
135
+ gen_helper_vfp_maxs(tcg_res, tcg_lo, tcg_hi, fpst);
136
+ break;
137
+ case 0x3c: /* fminnmv */
138
+ gen_helper_vfp_minnums(tcg_res, tcg_lo, tcg_hi, fpst);
139
+ break;
140
+ case 0x3f: /* fminv */
141
+ gen_helper_vfp_mins(tcg_res, tcg_lo, tcg_hi, fpst);
142
+ break;
143
+ default:
144
+ g_assert_not_reached();
145
}
44
}
146
+
45
-#endif
147
+ tcg_temp_free_i32(tcg_hi);
148
+ tcg_temp_free_i32(tcg_lo);
149
+ return tcg_res;
150
}
46
}
151
}
47
assert(dnan_pattern != 0);
152
153
@@ -XXX,XX +XXX,XX @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
154
break;
155
case 0xc: /* FMAXNMV, FMINNMV */
156
case 0xf: /* FMAXV, FMINV */
157
- if (!is_u || !is_q || extract32(size, 0, 1)) {
158
- unallocated_encoding(s);
159
- return;
160
- }
161
- /* Bit 1 of size field encodes min vs max, and actual size is always
162
- * 32 bits: adjust the size variable so following code can rely on it
163
+ /* Bit 1 of size field encodes min vs max and the actual size
164
+ * depends on the encoding of the U bit. If not set (and FP16
165
+ * enabled) then we do half-precision float instead of single
166
+ * precision.
167
*/
168
is_min = extract32(size, 1, 1);
169
is_fp = true;
170
- size = 2;
171
+ if (!is_u && arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
172
+ size = 1;
173
+ } else if (!is_u || !is_q || extract32(size, 0, 1)) {
174
+ unallocated_encoding(s);
175
+ return;
176
+ } else {
177
+ size = 2;
178
+ }
179
break;
180
default:
181
unallocated_encoding(s);
182
@@ -XXX,XX +XXX,XX @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
183
184
}
185
} else {
186
- /* Floating point ops which work on 32 bit (single) intermediates.
187
+ /* Floating point vector reduction ops which work across 32
188
+ * bit (single) or 16 bit (half-precision) intermediates.
189
* Note that correct NaN propagation requires that we do these
190
* operations in exactly the order specified by the pseudocode.
191
*/
192
- TCGv_i32 tcg_elt1 = tcg_temp_new_i32();
193
- TCGv_i32 tcg_elt2 = tcg_temp_new_i32();
194
- TCGv_i32 tcg_elt3 = tcg_temp_new_i32();
195
- TCGv_ptr fpst = get_fpstatus_ptr(false);
196
-
197
- assert(esize == 32);
198
- assert(elements == 4);
199
-
200
- read_vec_element(s, tcg_elt, rn, 0, MO_32);
201
- tcg_gen_extrl_i64_i32(tcg_elt1, tcg_elt);
202
- read_vec_element(s, tcg_elt, rn, 1, MO_32);
203
- tcg_gen_extrl_i64_i32(tcg_elt2, tcg_elt);
204
-
205
- do_minmaxop(s, tcg_elt1, tcg_elt2, opcode, is_min, fpst);
206
-
207
- read_vec_element(s, tcg_elt, rn, 2, MO_32);
208
- tcg_gen_extrl_i64_i32(tcg_elt2, tcg_elt);
209
- read_vec_element(s, tcg_elt, rn, 3, MO_32);
210
- tcg_gen_extrl_i64_i32(tcg_elt3, tcg_elt);
211
-
212
- do_minmaxop(s, tcg_elt2, tcg_elt3, opcode, is_min, fpst);
213
-
214
- do_minmaxop(s, tcg_elt1, tcg_elt2, opcode, is_min, fpst);
215
-
216
- tcg_gen_extu_i32_i64(tcg_res, tcg_elt1);
217
- tcg_temp_free_i32(tcg_elt1);
218
- tcg_temp_free_i32(tcg_elt2);
219
- tcg_temp_free_i32(tcg_elt3);
220
+ TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16);
221
+ int fpopcode = opcode | is_min << 4 | is_u << 5;
222
+ int vmap = (1 << elements) - 1;
223
+ TCGv_i32 tcg_res32 = do_reduction_op(s, fpopcode, rn, esize,
224
+ (is_q ? 128 : 64), vmap, fpst);
225
+ tcg_gen_extu_i32_i64(tcg_res, tcg_res32);
226
+ tcg_temp_free_i32(tcg_res32);
227
tcg_temp_free_ptr(fpst);
228
}
229
48
230
--
49
--
231
2.16.2
50
2.34.1
232
233
diff view generated by jsdifflib
1
From: Linus Walleij <linus.walleij@linaro.org>
1
Set the default NaN pattern explicitly for riscv.
2
2
3
This adds the SiI9022 (and implicitly EDID I2C) device to the ARM
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Versatile Express machine, and selects the two I2C devices necessary
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
in the arm-softmmu.mak configuration so everything will build
5
Message-id: 20241202131347.498124-53-peter.maydell@linaro.org
6
smoothly.
6
---
7
target/riscv/cpu.c | 2 ++
8
1 file changed, 2 insertions(+)
7
9
8
I am implementing proper handling of the graphics in the Linux
10
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
9
kernel and adding proper emulation of SiI9022 and EDID makes the
10
driver probe as nicely as before, retrieving the resolutions
11
supported by the "QEMU monitor" and overall just working nice.
12
13
Cc: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
15
Message-id: 20180227104903.21353-6-linus.walleij@linaro.org
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
hw/arm/vexpress.c | 6 +++++-
21
default-configs/arm-softmmu.mak | 2 ++
22
2 files changed, 7 insertions(+), 1 deletion(-)
23
24
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
25
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/arm/vexpress.c
12
--- a/target/riscv/cpu.c
27
+++ b/hw/arm/vexpress.c
13
+++ b/target/riscv/cpu.c
28
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
29
#include "hw/arm/arm.h"
15
cs->exception_index = RISCV_EXCP_NONE;
30
#include "hw/arm/primecell.h"
16
env->load_res = -1;
31
#include "hw/devices.h"
17
set_default_nan_mode(1, &env->fp_status);
32
+#include "hw/i2c/i2c.h"
18
+ /* Default NaN value: sign bit clear, frac msb set */
33
#include "net/net.h"
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
34
#include "sysemu/sysemu.h"
20
env->vill = true;
35
#include "hw/boards.h"
21
36
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
22
#ifndef CONFIG_USER_ONLY
37
uint32_t sys_id;
38
DriveInfo *dinfo;
39
pflash_t *pflash0;
40
+ I2CBus *i2c;
41
ram_addr_t vram_size, sram_size;
42
MemoryRegion *sysmem = get_system_memory();
43
MemoryRegion *vram = g_new(MemoryRegion, 1);
44
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
45
sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
46
sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
47
48
- /* VE_SERIALDVI: not modelled */
49
+ dev = sysbus_create_simple("versatile_i2c", map[VE_SERIALDVI], NULL);
50
+ i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
51
+ i2c_create_slave(i2c, "sii9022", 0x39);
52
53
sysbus_create_simple("pl031", map[VE_RTC], pic[4]); /* RTC */
54
55
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
56
index XXXXXXX..XXXXXXX 100644
57
--- a/default-configs/arm-softmmu.mak
58
+++ b/default-configs/arm-softmmu.mak
59
@@ -XXX,XX +XXX,XX @@ CONFIG_STELLARIS_INPUT=y
60
CONFIG_STELLARIS_ENET=y
61
CONFIG_SSD0303=y
62
CONFIG_SSD0323=y
63
+CONFIG_DDC=y
64
+CONFIG_SII9022=y
65
CONFIG_ADS7846=y
66
CONFIG_MAX111X=y
67
CONFIG_SSI=y
68
--
23
--
69
2.16.2
24
2.34.1
70
71
diff view generated by jsdifflib
1
From: Francisco Iglesias <frasse.iglesias@gmail.com>
1
Set the default NaN pattern explicitly for tricore.
2
2
3
Assert only the lower cs on bus 0 and upper cs on bus 1 when both buses and
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
chip selects are enabled (e.g reading/writing with stripe).
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20241202131347.498124-54-peter.maydell@linaro.org
6
---
7
target/tricore/helper.c | 2 ++
8
1 file changed, 2 insertions(+)
5
9
6
Signed-off-by: Francisco Iglesias <frasse.iglesias@gmail.com>
10
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
7
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
8
Tested-by: Alistair Francis <alistair.francis@xilinx.com>
9
Message-id: 20180223232233.31482-2-frasse.iglesias@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/ssi/xilinx_spips.c | 41 +++++++++++++++++++++++++++++++++++++----
13
1 file changed, 37 insertions(+), 4 deletions(-)
14
15
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
16
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/ssi/xilinx_spips.c
12
--- a/target/tricore/helper.c
18
+++ b/hw/ssi/xilinx_spips.c
13
+++ b/target/tricore/helper.c
19
@@ -XXX,XX +XXX,XX @@ static void xilinx_spips_update_cs(XilinxSPIPS *s, int field)
14
@@ -XXX,XX +XXX,XX @@ void fpu_set_state(CPUTriCoreState *env)
20
{
15
set_flush_to_zero(1, &env->fp_status);
21
int i;
16
set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
22
17
set_default_nan_mode(1, &env->fp_status);
23
- for (i = 0; i < s->num_cs; i++) {
18
+ /* Default NaN pattern: sign bit clear, frac msb set */
24
+ for (i = 0; i < s->num_cs * s->num_busses; i++) {
19
+ set_float_default_nan_pattern(0b01000000, &env->fp_status);
25
bool old_state = s->cs_lines_state[i];
26
bool new_state = field & (1 << i);
27
28
@@ -XXX,XX +XXX,XX @@ static void xilinx_spips_update_cs(XilinxSPIPS *s, int field)
29
}
30
qemu_set_irq(s->cs_lines[i], !new_state);
31
}
32
- if (!(field & ((1 << s->num_cs) - 1))) {
33
+ if (!(field & ((1 << (s->num_cs * s->num_busses)) - 1))) {
34
s->snoop_state = SNOOP_CHECKING;
35
s->cmd_dummies = 0;
36
s->link_state = 1;
37
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_update_cs_lines(XlnxZynqMPQSPIPS *s)
38
{
39
if (s->regs[R_GQSPI_GF_SNAPSHOT]) {
40
int field = ARRAY_FIELD_EX32(s->regs, GQSPI_GF_SNAPSHOT, CHIP_SELECT);
41
- xilinx_spips_update_cs(XILINX_SPIPS(s), field);
42
+ bool upper_cs_sel = field & (1 << 1);
43
+ bool lower_cs_sel = field & 1;
44
+ bool bus0_enabled;
45
+ bool bus1_enabled;
46
+ uint8_t buses;
47
+ int cs = 0;
48
+
49
+ buses = ARRAY_FIELD_EX32(s->regs, GQSPI_GF_SNAPSHOT, DATA_BUS_SELECT);
50
+ bus0_enabled = buses & 1;
51
+ bus1_enabled = buses & (1 << 1);
52
+
53
+ if (bus0_enabled && bus1_enabled) {
54
+ if (lower_cs_sel) {
55
+ cs |= 1;
56
+ }
57
+ if (upper_cs_sel) {
58
+ cs |= 1 << 3;
59
+ }
60
+ } else if (bus0_enabled) {
61
+ if (lower_cs_sel) {
62
+ cs |= 1;
63
+ }
64
+ if (upper_cs_sel) {
65
+ cs |= 1 << 1;
66
+ }
67
+ } else if (bus1_enabled) {
68
+ if (lower_cs_sel) {
69
+ cs |= 1 << 2;
70
+ }
71
+ if (upper_cs_sel) {
72
+ cs |= 1 << 3;
73
+ }
74
+ }
75
+ xilinx_spips_update_cs(XILINX_SPIPS(s), cs);
76
}
77
}
20
}
78
21
79
@@ -XXX,XX +XXX,XX @@ static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
22
uint32_t psw_read(CPUTriCoreState *env)
80
if (num_effective_busses(s) == 2) {
81
/* Single bit chip-select for qspi */
82
field &= 0x1;
83
- field |= field << 1;
84
+ field |= field << 3;
85
/* Dual stack U-Page */
86
} else if (s->regs[R_LQSPI_CFG] & LQSPI_CFG_TWO_MEM &&
87
s->regs[R_LQSPI_STS] & LQSPI_CFG_U_PAGE) {
88
--
23
--
89
2.16.2
24
2.34.1
90
91
diff view generated by jsdifflib
1
From: Corey Minyard <cminyard@mvista.com>
1
Now that all our targets have bene converted to explicitly specify
2
their pattern for the default NaN value we can remove the remaining
3
fallback code in parts64_default_nan().
2
4
3
Some devices need access to it.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20241202131347.498124-55-peter.maydell@linaro.org
8
---
9
fpu/softfloat-specialize.c.inc | 14 --------------
10
1 file changed, 14 deletions(-)
4
11
5
Signed-off-by: Corey Minyard <cminyard@mvista.com>
12
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
8
Message-id: 20180227104903.21353-3-linus.walleij@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/i2c/i2c.h | 17 +++++++++++++++++
12
hw/i2c/core.c | 17 -----------------
13
2 files changed, 17 insertions(+), 17 deletions(-)
14
15
diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/i2c/i2c.h
14
--- a/fpu/softfloat-specialize.c.inc
18
+++ b/include/hw/i2c/i2c.h
15
+++ b/fpu/softfloat-specialize.c.inc
19
@@ -XXX,XX +XXX,XX @@ struct I2CSlave {
16
@@ -XXX,XX +XXX,XX @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
20
uint8_t address;
17
uint64_t frac;
21
};
18
uint8_t dnan_pattern = status->default_nan_pattern;
22
19
23
+#define TYPE_I2C_BUS "i2c-bus"
20
- if (dnan_pattern == 0) {
24
+#define I2C_BUS(obj) OBJECT_CHECK(I2CBus, (obj), TYPE_I2C_BUS)
21
- /*
25
+
22
- * This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
26
+typedef struct I2CNode I2CNode;
23
- * S390, SH4, TriCore, and Xtensa. Our other supported targets
27
+
24
- * do not have floating-point.
28
+struct I2CNode {
25
- */
29
+ I2CSlave *elt;
26
- if (snan_bit_is_one(status)) {
30
+ QLIST_ENTRY(I2CNode) next;
27
- /* sign bit clear, set all frac bits other than msb */
31
+};
28
- dnan_pattern = 0b00111111;
32
+
29
- } else {
33
+struct I2CBus {
30
- /* sign bit clear, set frac msb */
34
+ BusState qbus;
31
- dnan_pattern = 0b01000000;
35
+ QLIST_HEAD(, I2CNode) current_devs;
32
- }
36
+ uint8_t saved_address;
33
- }
37
+ bool broadcast;
34
assert(dnan_pattern != 0);
38
+};
35
39
+
36
sign = dnan_pattern >> 7;
40
I2CBus *i2c_init_bus(DeviceState *parent, const char *name);
41
void i2c_set_slave_address(I2CSlave *dev, uint8_t address);
42
int i2c_bus_busy(I2CBus *bus);
43
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/i2c/core.c
46
+++ b/hw/i2c/core.c
47
@@ -XXX,XX +XXX,XX @@
48
#include "qemu/osdep.h"
49
#include "hw/i2c/i2c.h"
50
51
-typedef struct I2CNode I2CNode;
52
-
53
-struct I2CNode {
54
- I2CSlave *elt;
55
- QLIST_ENTRY(I2CNode) next;
56
-};
57
-
58
#define I2C_BROADCAST 0x00
59
60
-struct I2CBus {
61
- BusState qbus;
62
- QLIST_HEAD(, I2CNode) current_devs;
63
- uint8_t saved_address;
64
- bool broadcast;
65
-};
66
-
67
static Property i2c_props[] = {
68
DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0),
69
DEFINE_PROP_END_OF_LIST(),
70
};
71
72
-#define TYPE_I2C_BUS "i2c-bus"
73
-#define I2C_BUS(obj) OBJECT_CHECK(I2CBus, (obj), TYPE_I2C_BUS)
74
-
75
static const TypeInfo i2c_bus_info = {
76
.name = TYPE_I2C_BUS,
77
.parent = TYPE_BUS,
78
--
37
--
79
2.16.2
38
2.34.1
80
81
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This covers all the floating point convert operations.
3
Inline pickNaNMulAdd into its only caller. This makes
4
one assert redundant with the immediately preceding IF.
4
5
5
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Message-id: 20180227143852.11175-19-alex.bennee@linaro.org
8
Message-id: 20241203203949.483774-3-richard.henderson@linaro.org
9
[PMM: keep comment from old code in new location]
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
target/arm/helper-a64.h | 2 ++
12
fpu/softfloat-parts.c.inc | 41 +++++++++++++++++++++++++-
11
target/arm/helper-a64.c | 32 +++++++++++++++++
13
fpu/softfloat-specialize.c.inc | 54 ----------------------------------
12
target/arm/translate-a64.c | 85 +++++++++++++++++++++++++++++++++++++++++++++-
14
2 files changed, 40 insertions(+), 55 deletions(-)
13
3 files changed, 118 insertions(+), 1 deletion(-)
14
15
15
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-a64.h
18
--- a/fpu/softfloat-parts.c.inc
18
+++ b/target/arm/helper-a64.h
19
+++ b/fpu/softfloat-parts.c.inc
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(advsimd_mulx2h, i32, i32, i32, ptr)
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
20
DEF_HELPER_4(advsimd_muladd2h, i32, i32, i32, i32, ptr)
21
DEF_HELPER_2(advsimd_rinth_exact, f16, f16, ptr)
22
DEF_HELPER_2(advsimd_rinth, f16, f16, ptr)
23
+DEF_HELPER_2(advsimd_f16tosinth, i32, f16, ptr)
24
+DEF_HELPER_2(advsimd_f16touinth, i32, f16, ptr)
25
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/helper-a64.c
28
+++ b/target/arm/helper-a64.c
29
@@ -XXX,XX +XXX,XX @@ float16 HELPER(advsimd_rinth)(float16 x, void *fp_status)
30
31
return ret;
32
}
33
+
34
+/*
35
+ * Half-precision floating point conversion functions
36
+ *
37
+ * There are a multitude of conversion functions with various
38
+ * different rounding modes. This is dealt with by the calling code
39
+ * setting the mode appropriately before calling the helper.
40
+ */
41
+
42
+uint32_t HELPER(advsimd_f16tosinth)(float16 a, void *fpstp)
43
+{
44
+ float_status *fpst = fpstp;
45
+
46
+ /* Invalid if we are passed a NaN */
47
+ if (float16_is_any_nan(a)) {
48
+ float_raise(float_flag_invalid, fpst);
49
+ return 0;
50
+ }
51
+ return float16_to_int16(a, fpst);
52
+}
53
+
54
+uint32_t HELPER(advsimd_f16touinth)(float16 a, void *fpstp)
55
+{
56
+ float_status *fpst = fpstp;
57
+
58
+ /* Invalid if we are passed a NaN */
59
+ if (float16_is_any_nan(a)) {
60
+ float_raise(float_flag_invalid, fpst);
61
+ return 0;
62
+ }
63
+ return float16_to_uint16(a, fpst);
64
+}
65
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/translate-a64.c
68
+++ b/target/arm/translate-a64.c
69
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
70
only_in_vector = true;
71
/* current rounding mode */
72
break;
73
+ case 0x1a: /* FCVTNS */
74
+ need_rmode = true;
75
+ rmode = FPROUNDING_TIEEVEN;
76
+ break;
77
+ case 0x1b: /* FCVTMS */
78
+ need_rmode = true;
79
+ rmode = FPROUNDING_NEGINF;
80
+ break;
81
+ case 0x1c: /* FCVTAS */
82
+ need_rmode = true;
83
+ rmode = FPROUNDING_TIEAWAY;
84
+ break;
85
+ case 0x3a: /* FCVTPS */
86
+ need_rmode = true;
87
+ rmode = FPROUNDING_POSINF;
88
+ break;
89
+ case 0x3b: /* FCVTZS */
90
+ need_rmode = true;
91
+ rmode = FPROUNDING_ZERO;
92
+ break;
93
+ case 0x5a: /* FCVTNU */
94
+ need_rmode = true;
95
+ rmode = FPROUNDING_TIEEVEN;
96
+ break;
97
+ case 0x5b: /* FCVTMU */
98
+ need_rmode = true;
99
+ rmode = FPROUNDING_NEGINF;
100
+ break;
101
+ case 0x5c: /* FCVTAU */
102
+ need_rmode = true;
103
+ rmode = FPROUNDING_TIEAWAY;
104
+ break;
105
+ case 0x7a: /* FCVTPU */
106
+ need_rmode = true;
107
+ rmode = FPROUNDING_POSINF;
108
+ break;
109
+ case 0x7b: /* FCVTZU */
110
+ need_rmode = true;
111
+ rmode = FPROUNDING_ZERO;
112
+ break;
113
default:
114
fprintf(stderr, "%s: insn %#04x fpop %#2x\n", __func__, insn, fpop);
115
g_assert_not_reached();
116
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
117
}
21
}
118
22
119
if (is_scalar) {
23
if (s->default_nan_mode) {
120
- /* no operations yet */
24
+ /*
121
+ TCGv_i32 tcg_op = tcg_temp_new_i32();
25
+ * We guarantee not to require the target to tell us how to
122
+ TCGv_i32 tcg_res = tcg_temp_new_i32();
26
+ * pick a NaN if we're always returning the default NaN.
123
+
27
+ * But if we're not in default-NaN mode then the target must
124
+ read_vec_element_i32(s, tcg_op, rn, 0, MO_16);
28
+ * specify.
125
+
29
+ */
126
+ switch (fpop) {
30
which = 3;
127
+ case 0x1a: /* FCVTNS */
31
+ } else if (infzero) {
128
+ case 0x1b: /* FCVTMS */
32
+ /*
129
+ case 0x1c: /* FCVTAS */
33
+ * Inf * 0 + NaN -- some implementations return the
130
+ case 0x3a: /* FCVTPS */
34
+ * default NaN here, and some return the input NaN.
131
+ case 0x3b: /* FCVTZS */
35
+ */
132
+ gen_helper_advsimd_f16tosinth(tcg_res, tcg_op, tcg_fpstatus);
36
+ switch (s->float_infzeronan_rule) {
37
+ case float_infzeronan_dnan_never:
38
+ which = 2;
133
+ break;
39
+ break;
134
+ case 0x5a: /* FCVTNU */
40
+ case float_infzeronan_dnan_always:
135
+ case 0x5b: /* FCVTMU */
41
+ which = 3;
136
+ case 0x5c: /* FCVTAU */
42
+ break;
137
+ case 0x7a: /* FCVTPU */
43
+ case float_infzeronan_dnan_if_qnan:
138
+ case 0x7b: /* FCVTZU */
44
+ which = is_qnan(c->cls) ? 3 : 2;
139
+ gen_helper_advsimd_f16touinth(tcg_res, tcg_op, tcg_fpstatus);
140
+ break;
45
+ break;
141
+ default:
46
+ default:
142
+ g_assert_not_reached();
47
+ g_assert_not_reached();
143
+ }
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;
144
+
53
+
145
+ /* limit any sign extension going on */
54
+ assert(rule != float_3nan_prop_none);
146
+ tcg_gen_andi_i32(tcg_res, tcg_res, 0xffff);
55
+ if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
147
+ write_fp_sreg(s, rd, tcg_res);
56
+ /* We have at least one SNaN input and should prefer it */
148
+
57
+ do {
149
+ tcg_temp_free_i32(tcg_res);
58
+ which = rule & R_3NAN_1ST_MASK;
150
+ tcg_temp_free_i32(tcg_op);
59
+ rule >>= R_3NAN_1ST_LENGTH;
151
} else {
60
+ } while (!is_snan(cls[which]));
152
for (pass = 0; pass < (is_q ? 8 : 4); pass++) {
61
+ } else {
153
TCGv_i32 tcg_op = tcg_temp_new_i32();
62
+ do {
154
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
63
+ which = rule & R_3NAN_1ST_MASK;
155
read_vec_element_i32(s, tcg_op, rn, pass, MO_16);
64
+ rule >>= R_3NAN_1ST_LENGTH;
156
65
+ } while (!is_nan(cls[which]));
157
switch (fpop) {
66
+ }
158
+ case 0x1a: /* FCVTNS */
67
}
159
+ case 0x1b: /* FCVTMS */
68
160
+ case 0x1c: /* FCVTAS */
69
if (which == 3) {
161
+ case 0x3a: /* FCVTPS */
70
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
162
+ case 0x3b: /* FCVTZS */
71
index XXXXXXX..XXXXXXX 100644
163
+ gen_helper_advsimd_f16tosinth(tcg_res, tcg_op, tcg_fpstatus);
72
--- a/fpu/softfloat-specialize.c.inc
164
+ break;
73
+++ b/fpu/softfloat-specialize.c.inc
165
+ case 0x5a: /* FCVTNU */
74
@@ -XXX,XX +XXX,XX @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
166
+ case 0x5b: /* FCVTMU */
75
}
167
+ case 0x5c: /* FCVTAU */
76
}
168
+ case 0x7a: /* FCVTPU */
77
169
+ case 0x7b: /* FCVTZU */
78
-/*----------------------------------------------------------------------------
170
+ gen_helper_advsimd_f16touinth(tcg_res, tcg_op, tcg_fpstatus);
79
-| Select which NaN to propagate for a three-input operation.
171
+ break;
80
-| For the moment we assume that no CPU needs the 'larger significand'
172
case 0x18: /* FRINTN */
81
-| information.
173
case 0x19: /* FRINTM */
82
-| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
174
case 0x38: /* FRINTP */
83
-*----------------------------------------------------------------------------*/
84
-static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
85
- bool infzero, bool have_snan, float_status *status)
86
-{
87
- FloatClass cls[3] = { a_cls, b_cls, c_cls };
88
- Float3NaNPropRule rule = status->float_3nan_prop_rule;
89
- int which;
90
-
91
- /*
92
- * We guarantee not to require the target to tell us how to
93
- * pick a NaN if we're always returning the default NaN.
94
- * But if we're not in default-NaN mode then the target must
95
- * specify.
96
- */
97
- assert(!status->default_nan_mode);
98
-
99
- if (infzero) {
100
- /*
101
- * Inf * 0 + NaN -- some implementations return the default NaN here,
102
- * and some return the input NaN.
103
- */
104
- switch (status->float_infzeronan_rule) {
105
- case float_infzeronan_dnan_never:
106
- return 2;
107
- case float_infzeronan_dnan_always:
108
- return 3;
109
- case float_infzeronan_dnan_if_qnan:
110
- return is_qnan(c_cls) ? 3 : 2;
111
- default:
112
- g_assert_not_reached();
113
- }
114
- }
115
-
116
- assert(rule != float_3nan_prop_none);
117
- if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
118
- /* We have at least one SNaN input and should prefer it */
119
- do {
120
- which = rule & R_3NAN_1ST_MASK;
121
- rule >>= R_3NAN_1ST_LENGTH;
122
- } while (!is_snan(cls[which]));
123
- } else {
124
- do {
125
- which = rule & R_3NAN_1ST_MASK;
126
- rule >>= R_3NAN_1ST_LENGTH;
127
- } while (!is_nan(cls[which]));
128
- }
129
- return which;
130
-}
131
-
132
/*----------------------------------------------------------------------------
133
| Returns 1 if the double-precision floating-point value `a' is a quiet
134
| NaN; otherwise returns 0.
175
--
135
--
176
2.16.2
136
2.34.1
177
137
178
138
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Neither of these operations alter the floating point status registers
3
Remove "3" as a special case for which and simply
4
so we can do a pure bitwise operation, either squashing any sign
4
branch to return the desired value.
5
bit (ABS) or inverting it (NEG).
6
5
7
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20180227143852.11175-22-alex.bennee@linaro.org
8
Message-id: 20241203203949.483774-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/translate-a64.c | 16 +++++++++++++++-
11
fpu/softfloat-parts.c.inc | 20 ++++++++++----------
13
1 file changed, 15 insertions(+), 1 deletion(-)
12
1 file changed, 10 insertions(+), 10 deletions(-)
14
13
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
16
--- a/fpu/softfloat-parts.c.inc
18
+++ b/target/arm/translate-a64.c
17
+++ b/fpu/softfloat-parts.c.inc
19
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
20
TCGv_i32 tcg_rmode = NULL;
19
* But if we're not in default-NaN mode then the target must
21
TCGv_ptr tcg_fpstatus = NULL;
20
* specify.
22
bool need_rmode = false;
21
*/
23
+ bool need_fpst = true;
22
- which = 3;
24
int rmode;
23
+ goto default_nan;
25
24
} else if (infzero) {
26
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
25
/*
27
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
26
* Inf * 0 + NaN -- some implementations return the
28
need_rmode = true;
27
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
29
rmode = FPROUNDING_ZERO;
28
*/
30
break;
29
switch (s->float_infzeronan_rule) {
31
+ case 0x2f: /* FABS */
30
case float_infzeronan_dnan_never:
32
+ case 0x6f: /* FNEG */
31
- which = 2;
33
+ need_fpst = false;
34
+ break;
35
default:
36
fprintf(stderr, "%s: insn %#04x fpop %#2x\n", __func__, insn, fpop);
37
g_assert_not_reached();
38
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
39
return;
40
}
41
42
- if (need_rmode) {
43
+ if (need_rmode || need_fpst) {
44
tcg_fpstatus = get_fpstatus_ptr(true);
45
}
46
47
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
48
case 0x7b: /* FCVTZU */
49
gen_helper_advsimd_f16touinth(tcg_res, tcg_op, tcg_fpstatus);
50
break;
32
break;
51
+ case 0x6f: /* FNEG */
33
case float_infzeronan_dnan_always:
52
+ tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
34
- which = 3;
53
+ break;
35
- break;
36
+ goto default_nan;
37
case float_infzeronan_dnan_if_qnan:
38
- which = is_qnan(c->cls) ? 3 : 2;
39
+ if (is_qnan(c->cls)) {
40
+ goto default_nan;
41
+ }
42
break;
54
default:
43
default:
55
g_assert_not_reached();
44
g_assert_not_reached();
56
}
45
}
57
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
46
+ which = 2;
58
case 0x59: /* FRINTX */
47
} else {
59
gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, tcg_fpstatus);
48
FloatClass cls[3] = { a->cls, b->cls, c->cls };
60
break;
49
Float3NaNPropRule rule = s->float_3nan_prop_rule;
61
+ case 0x2f: /* FABS */
50
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
62
+ tcg_gen_andi_i32(tcg_res, tcg_op, 0x7fff);
51
}
63
+ break;
52
}
64
+ case 0x6f: /* FNEG */
53
65
+ tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
54
- if (which == 3) {
66
+ break;
55
- parts_default_nan(a, s);
67
default:
56
- return a;
68
g_assert_not_reached();
57
- }
69
}
58
-
59
switch (which) {
60
case 0:
61
break;
62
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
63
parts_silence_nan(a, s);
64
}
65
return a;
66
+
67
+ default_nan:
68
+ parts_default_nan(a, s);
69
+ return a;
70
}
71
72
/*
70
--
73
--
71
2.16.2
74
2.34.1
72
75
73
76
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
3
Assign the pointer return value to 'a' directly,
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
rather than going through an intermediary index.
5
Message-id: 20180227143852.11175-28-alex.bennee@linaro.org
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
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/translate-a64.c | 7 +++++++
11
fpu/softfloat-parts.c.inc | 32 ++++++++++----------------------
9
1 file changed, 7 insertions(+)
12
1 file changed, 10 insertions(+), 22 deletions(-)
10
13
11
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-a64.c
16
--- a/fpu/softfloat-parts.c.inc
14
+++ b/target/arm/translate-a64.c
17
+++ b/fpu/softfloat-parts.c.inc
15
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
16
case 0x6f: /* FNEG */
19
FloatPartsN *c, float_status *s,
17
need_fpst = false;
20
int ab_mask, int abc_mask)
18
break;
21
{
19
+ case 0x7d: /* FRSQRTE */
22
- int which;
20
case 0x7f: /* FSQRT (vector) */
23
bool infzero = (ab_mask == float_cmask_infzero);
21
break;
24
bool have_snan = (abc_mask & float_cmask_snan);
22
default:
25
+ FloatPartsN *ret;
23
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
26
24
case 0x6f: /* FNEG */
27
if (unlikely(have_snan)) {
25
tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
28
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
26
break;
29
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
27
+ case 0x7d: /* FRSQRTE */
28
+ gen_helper_rsqrte_f16(tcg_res, tcg_op, tcg_fpstatus);
29
+ break;
30
default:
30
default:
31
g_assert_not_reached();
31
g_assert_not_reached();
32
}
32
}
33
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
33
- which = 2;
34
case 0x6f: /* FNEG */
34
+ ret = c;
35
tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
35
} else {
36
break;
36
- FloatClass cls[3] = { a->cls, b->cls, c->cls };
37
+ case 0x7d: /* FRSQRTE */
37
+ FloatPartsN *val[3] = { a, b, c };
38
+ gen_helper_rsqrte_f16(tcg_res, tcg_op, tcg_fpstatus);
38
Float3NaNPropRule rule = s->float_3nan_prop_rule;
39
+ break;
39
40
case 0x7f: /* FSQRT */
40
assert(rule != float_3nan_prop_none);
41
gen_helper_sqrt_f16(tcg_res, tcg_op, tcg_fpstatus);
41
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
42
break;
42
/* We have at least one SNaN input and should prefer it */
43
do {
44
- which = rule & R_3NAN_1ST_MASK;
45
+ ret = val[rule & R_3NAN_1ST_MASK];
46
rule >>= R_3NAN_1ST_LENGTH;
47
- } while (!is_snan(cls[which]));
48
+ } while (!is_snan(ret->cls));
49
} else {
50
do {
51
- which = rule & R_3NAN_1ST_MASK;
52
+ ret = val[rule & R_3NAN_1ST_MASK];
53
rule >>= R_3NAN_1ST_LENGTH;
54
- } while (!is_nan(cls[which]));
55
+ } while (!is_nan(ret->cls));
56
}
57
}
58
59
- switch (which) {
60
- case 0:
61
- break;
62
- case 1:
63
- a = b;
64
- break;
65
- case 2:
66
- a = c;
67
- break;
68
- default:
69
- g_assert_not_reached();
70
+ if (is_snan(ret->cls)) {
71
+ parts_silence_nan(ret, s);
72
}
73
- if (is_snan(a->cls)) {
74
- parts_silence_nan(a, s);
75
- }
76
- return a;
77
+ return ret;
78
79
default_nan:
80
parts_default_nan(a, s);
43
--
81
--
44
2.16.2
82
2.34.1
45
83
46
84
diff view generated by jsdifflib
1
From: Francisco Iglesias <frasse.iglesias@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Use 8 dummy cycles (4 dummy bytes) with the QIOR/QIOR4 commands in legacy mode
3
While all indices into val[] should be in [0-2], the mask
4
for matching what is expected by Micron (Numonyx) flashes (the default target
4
applied is two bits. To help static analysis see there is
5
flash type of the QSPI).
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: Francisco Iglesias <frasse.iglesias@gmail.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Tested-by: Alistair Francis <alistair.francis@xilinx.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
10
Message-id: 20241203203949.483774-6-richard.henderson@linaro.org
10
Message-id: 20180223232233.31482-3-frasse.iglesias@gmail.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
12
---
13
hw/ssi/xilinx_spips.c | 2 +-
13
fpu/softfloat-parts.c.inc | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
15
16
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
16
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/ssi/xilinx_spips.c
18
--- a/fpu/softfloat-parts.c.inc
19
+++ b/hw/ssi/xilinx_spips.c
19
+++ b/fpu/softfloat-parts.c.inc
20
@@ -XXX,XX +XXX,XX @@ static int xilinx_spips_num_dummies(XilinxQSPIPS *qs, uint8_t command)
20
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
21
return 2;
21
}
22
case QIOR:
22
ret = c;
23
case QIOR_4:
23
} else {
24
- return 5;
24
- FloatPartsN *val[3] = { a, b, c };
25
+ return 4;
25
+ FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
26
default:
26
Float3NaNPropRule rule = s->float_3nan_prop_rule;
27
return -1;
27
28
}
28
assert(rule != float_3nan_prop_none);
29
--
29
--
30
2.16.2
30
2.34.1
31
31
32
32
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This actually covers two different sections of the encoding table:
3
This function is part of the public interface and
4
is not "specialized" to any target in any way.
4
5
5
Advanced SIMD scalar two-register miscellaneous FP16
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Advanced SIMD two-register miscellaneous (FP16)
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
8
Message-id: 20241203203949.483774-7-richard.henderson@linaro.org
8
The difference between the two is covered by a combination of Q (bit
9
30) and S (bit 28). Notably the FRINTx instructions are only
10
available in the vector form.
11
12
This is just the decode skeleton which will be filled out by later
13
patches.
14
15
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20180227143852.11175-17-alex.bennee@linaro.org
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
10
---
20
target/arm/translate-a64.c | 40 ++++++++++++++++++++++++++++++++++++++++
11
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++++++++
21
1 file changed, 40 insertions(+)
12
fpu/softfloat-specialize.c.inc | 52 ----------------------------------
13
2 files changed, 52 insertions(+), 52 deletions(-)
22
14
23
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/translate-a64.c
17
--- a/fpu/softfloat.c
26
+++ b/target/arm/translate-a64.c
18
+++ b/fpu/softfloat.c
27
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
28
}
20
*zExpPtr = 1 - shiftCount;
29
}
21
}
30
22
31
+/* AdvSIMD [scalar] two register miscellaneous (FP16)
23
+/*----------------------------------------------------------------------------
32
+ *
24
+| Takes two extended double-precision floating-point values `a' and `b', one
33
+ * 31 30 29 28 27 24 23 22 21 17 16 12 11 10 9 5 4 0
25
+| of which is a NaN, and returns the appropriate NaN result. If either `a' or
34
+ * +---+---+---+---+---------+---+-------------+--------+-----+------+------+
26
+| `b' is a signaling NaN, the invalid exception is raised.
35
+ * | 0 | Q | U | S | 1 1 1 0 | a | 1 1 1 1 0 0 | opcode | 1 0 | Rn | Rd |
27
+*----------------------------------------------------------------------------*/
36
+ * +---+---+---+---+---------+---+-------------+--------+-----+------+------+
28
+
37
+ * mask: 1000 1111 0111 1110 0000 1100 0000 0000 0x8f7e 0c00
29
+floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
38
+ * val: 0000 1110 0111 1000 0000 1000 0000 0000 0x0e78 0800
39
+ *
40
+ * This actually covers two groups where scalar access is governed by
41
+ * bit 28. A bunch of the instructions (float to integral) only exist
42
+ * in the vector form and are un-allocated for the scalar decode. Also
43
+ * in the scalar decode Q is always 1.
44
+ */
45
+static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
46
+{
30
+{
47
+ int fpop, opcode, a;
31
+ bool aIsLargerSignificand;
32
+ FloatClass a_cls, b_cls;
48
+
33
+
49
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
34
+ /* This is not complete, but is good enough for pickNaN. */
50
+ unallocated_encoding(s);
35
+ a_cls = (!floatx80_is_any_nan(a)
51
+ return;
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);
52
+ }
48
+ }
53
+
49
+
54
+ if (!fp_access_check(s)) {
50
+ if (status->default_nan_mode) {
55
+ return;
51
+ return floatx80_default_nan(status);
56
+ }
52
+ }
57
+
53
+
58
+ opcode = extract32(insn, 12, 4);
54
+ if (a.low < b.low) {
59
+ a = extract32(insn, 23, 1);
55
+ aIsLargerSignificand = 0;
60
+ fpop = deposit32(opcode, 5, 1, a);
56
+ } else if (b.low < a.low) {
61
+
57
+ aIsLargerSignificand = 1;
62
+ switch (fpop) {
58
+ } else {
63
+ default:
59
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
64
+ fprintf(stderr, "%s: insn %#04x fpop %#2x\n", __func__, insn, fpop);
65
+ g_assert_not_reached();
66
+ }
60
+ }
67
+
61
+
62
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
63
+ if (is_snan(b_cls)) {
64
+ return floatx80_silence_nan(b, status);
65
+ }
66
+ return b;
67
+ } else {
68
+ if (is_snan(a_cls)) {
69
+ return floatx80_silence_nan(a, status);
70
+ }
71
+ return a;
72
+ }
68
+}
73
+}
69
+
74
+
70
/* AdvSIMD scalar x indexed element
75
/*----------------------------------------------------------------------------
71
* 31 30 29 28 24 23 22 21 20 19 16 15 12 11 10 9 5 4 0
76
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
72
* +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
77
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
73
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
78
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
74
{ 0xce800000, 0xffe00000, disas_crypto_xar },
79
index XXXXXXX..XXXXXXX 100644
75
{ 0xce408000, 0xffe0c000, disas_crypto_three_reg_imm2 },
80
--- a/fpu/softfloat-specialize.c.inc
76
{ 0x0e400400, 0x9f60c400, disas_simd_three_reg_same_fp16 },
81
+++ b/fpu/softfloat-specialize.c.inc
77
+ { 0x0e780800, 0x8f7e0c00, disas_simd_two_reg_misc_fp16 },
82
@@ -XXX,XX +XXX,XX @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
78
{ 0x00000000, 0x00000000, NULL }
83
return a;
79
};
84
}
80
85
86
-/*----------------------------------------------------------------------------
87
-| Takes two extended double-precision floating-point values `a' and `b', one
88
-| of which is a NaN, and returns the appropriate NaN result. If either `a' or
89
-| `b' is a signaling NaN, the invalid exception is raised.
90
-*----------------------------------------------------------------------------*/
91
-
92
-floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
93
-{
94
- bool aIsLargerSignificand;
95
- FloatClass a_cls, b_cls;
96
-
97
- /* This is not complete, but is good enough for pickNaN. */
98
- a_cls = (!floatx80_is_any_nan(a)
99
- ? float_class_normal
100
- : floatx80_is_signaling_nan(a, status)
101
- ? float_class_snan
102
- : float_class_qnan);
103
- b_cls = (!floatx80_is_any_nan(b)
104
- ? float_class_normal
105
- : floatx80_is_signaling_nan(b, status)
106
- ? float_class_snan
107
- : float_class_qnan);
108
-
109
- if (is_snan(a_cls) || is_snan(b_cls)) {
110
- float_raise(float_flag_invalid, status);
111
- }
112
-
113
- if (status->default_nan_mode) {
114
- return floatx80_default_nan(status);
115
- }
116
-
117
- if (a.low < b.low) {
118
- aIsLargerSignificand = 0;
119
- } else if (b.low < a.low) {
120
- aIsLargerSignificand = 1;
121
- } else {
122
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
123
- }
124
-
125
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
126
- if (is_snan(b_cls)) {
127
- return floatx80_silence_nan(b, status);
128
- }
129
- return b;
130
- } else {
131
- if (is_snan(a_cls)) {
132
- return floatx80_silence_nan(a, status);
133
- }
134
- return a;
135
- }
136
-}
137
-
138
/*----------------------------------------------------------------------------
139
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
140
| NaN; otherwise returns 0.
81
--
141
--
82
2.16.2
142
2.34.1
83
84
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Ensure that the post write hook is called during reset. This allows us
3
Unpacking and repacking the parts may be slightly more work
4
to rely on the post write functions instead of having to call them from
4
than we did before, but we get to reuse more code. For a
5
the reset() function.
5
code path handling exceptional values, this is an improvement.
6
6
7
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20241203203949.483774-8-richard.henderson@linaro.org
9
Message-id: d131e24b911653a945e46ca2d8f90f572469e1dd.1517856214.git.alistair.francis@xilinx.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
include/hw/register.h | 6 +++---
12
fpu/softfloat.c | 43 +++++--------------------------------------
13
hw/core/register.c | 8 ++++++++
13
1 file changed, 5 insertions(+), 38 deletions(-)
14
2 files changed, 11 insertions(+), 3 deletions(-)
15
14
16
diff --git a/include/hw/register.h b/include/hw/register.h
15
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/register.h
17
--- a/fpu/softfloat.c
19
+++ b/include/hw/register.h
18
+++ b/fpu/softfloat.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct RegisterInfoArray RegisterInfoArray;
19
@@ -XXX,XX +XXX,XX @@ void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
21
* immediately before the actual write. The returned value is what is written,
20
22
* giving the handler a chance to modify the written value.
21
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
23
* @post_write: Post write callback. Passed the written value. Most write side
24
- * effects should be implemented here.
25
+ * effects should be implemented here. This is called during device reset.
26
*
27
* @post_read: Post read callback. Passes the value that is about to be returned
28
* for a read. The return value from this function is what is ultimately read,
29
@@ -XXX,XX +XXX,XX @@ uint64_t register_read(RegisterInfo *reg, uint64_t re, const char* prefix,
30
bool debug);
31
32
/**
33
- * reset a register
34
- * @reg: register to reset
35
+ * Resets a register. This will also call the post_write hook if it exists.
36
+ * @reg: The register to reset.
37
*/
38
39
void register_reset(RegisterInfo *reg);
40
diff --git a/hw/core/register.c b/hw/core/register.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/core/register.c
43
+++ b/hw/core/register.c
44
@@ -XXX,XX +XXX,XX @@ uint64_t register_read(RegisterInfo *reg, uint64_t re, const char* prefix,
45
46
void register_reset(RegisterInfo *reg)
47
{
22
{
48
+ const RegisterAccessInfo *ac;
23
- bool aIsLargerSignificand;
49
+
24
- FloatClass a_cls, b_cls;
50
g_assert(reg);
25
+ FloatParts128 pa, pb, *pr;
51
26
52
if (!reg->data || !reg->access) {
27
- /* This is not complete, but is good enough for pickNaN. */
53
return;
28
- a_cls = (!floatx80_is_any_nan(a)
29
- ? float_class_normal
30
- : floatx80_is_signaling_nan(a, status)
31
- ? float_class_snan
32
- : float_class_qnan);
33
- b_cls = (!floatx80_is_any_nan(b)
34
- ? float_class_normal
35
- : floatx80_is_signaling_nan(b, status)
36
- ? float_class_snan
37
- : float_class_qnan);
38
-
39
- if (is_snan(a_cls) || is_snan(b_cls)) {
40
- float_raise(float_flag_invalid, status);
41
- }
42
-
43
- if (status->default_nan_mode) {
44
+ if (!floatx80_unpack_canonical(&pa, a, status) ||
45
+ !floatx80_unpack_canonical(&pb, b, status)) {
46
return floatx80_default_nan(status);
54
}
47
}
55
48
56
+ ac = reg->access;
49
- if (a.low < b.low) {
57
+
50
- aIsLargerSignificand = 0;
58
register_write_val(reg, reg->access->reset);
51
- } else if (b.low < a.low) {
59
+
52
- aIsLargerSignificand = 1;
60
+ if (ac->post_write) {
53
- } else {
61
+ ac->post_write(reg, reg->access->reset);
54
- aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
62
+ }
55
- }
56
-
57
- if (pickNaN(a_cls, b_cls, aIsLargerSignificand, status)) {
58
- if (is_snan(b_cls)) {
59
- return floatx80_silence_nan(b, status);
60
- }
61
- return b;
62
- } else {
63
- if (is_snan(a_cls)) {
64
- return floatx80_silence_nan(a, status);
65
- }
66
- return a;
67
- }
68
+ pr = parts_pick_nan(&pa, &pb, status);
69
+ return floatx80_round_pack_canonical(pr, status);
63
}
70
}
64
71
65
void register_init(RegisterInfo *reg)
72
/*----------------------------------------------------------------------------
66
--
73
--
67
2.16.2
74
2.34.1
68
69
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This covers the encoding group:
3
Inline pickNaN into its only caller. This makes one assert
4
4
redundant with the immediately preceding IF.
5
Advanced SIMD scalar three same FP16
5
6
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
As all the helpers are already there it is simply a case of calling the
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
existing helpers in the scalar context.
8
Message-id: 20241203203949.483774-9-richard.henderson@linaro.org
9
10
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20180227143852.11175-31-alex.bennee@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
10
---
15
target/arm/translate-a64.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++
11
fpu/softfloat-parts.c.inc | 82 +++++++++++++++++++++++++----
16
1 file changed, 99 insertions(+)
12
fpu/softfloat-specialize.c.inc | 96 ----------------------------------
17
13
2 files changed, 73 insertions(+), 105 deletions(-)
18
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
15
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate-a64.c
17
--- a/fpu/softfloat-parts.c.inc
21
+++ b/target/arm/translate-a64.c
18
+++ b/fpu/softfloat-parts.c.inc
22
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
23
tcg_temp_free_i64(tcg_rd);
20
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
24
}
21
float_status *s)
25
22
{
26
+/* AdvSIMD scalar three same FP16
23
+ int cmp, which;
27
+ * 31 30 29 28 24 23 22 21 20 16 15 14 13 11 10 9 5 4 0
28
+ * +-----+---+-----------+---+-----+------+-----+--------+---+----+----+
29
+ * | 0 1 | U | 1 1 1 1 0 | a | 1 0 | Rm | 0 0 | opcode | 1 | Rn | Rd |
30
+ * +-----+---+-----------+---+-----+------+-----+--------+---+----+----+
31
+ * v: 0101 1110 0100 0000 0000 0100 0000 0000 => 5e400400
32
+ * m: 1101 1111 0110 0000 1100 0100 0000 0000 => df60c400
33
+ */
34
+static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
35
+ uint32_t insn)
36
+{
37
+ int rd = extract32(insn, 0, 5);
38
+ int rn = extract32(insn, 5, 5);
39
+ int opcode = extract32(insn, 11, 3);
40
+ int rm = extract32(insn, 16, 5);
41
+ bool u = extract32(insn, 29, 1);
42
+ bool a = extract32(insn, 23, 1);
43
+ int fpopcode = opcode | (a << 3) | (u << 4);
44
+ TCGv_ptr fpst;
45
+ TCGv_i32 tcg_op1;
46
+ TCGv_i32 tcg_op2;
47
+ TCGv_i32 tcg_res;
48
+
24
+
49
+ switch (fpopcode) {
25
if (is_snan(a->cls) || is_snan(b->cls)) {
50
+ case 0x03: /* FMULX */
26
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
51
+ case 0x04: /* FCMEQ (reg) */
27
}
52
+ case 0x07: /* FRECPS */
28
53
+ case 0x0f: /* FRSQRTS */
29
if (s->default_nan_mode) {
54
+ case 0x14: /* FCMGE (reg) */
30
parts_default_nan(a, s);
55
+ case 0x15: /* FACGE */
31
- } else {
56
+ case 0x1a: /* FABD */
32
- int cmp = frac_cmp(a, b);
57
+ case 0x1c: /* FCMGT (reg) */
33
- if (cmp == 0) {
58
+ case 0x1d: /* FACGT */
34
- cmp = a->sign < b->sign;
59
+ break;
35
- }
60
+ default:
36
+ return a;
61
+ unallocated_encoding(s);
37
+ }
62
+ return;
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;
63
+ }
45
+ }
64
+
46
+
65
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
47
+ switch (s->float_2nan_prop_rule) {
66
+ unallocated_encoding(s);
48
+ case float_2nan_prop_s_ab:
67
+ }
49
if (is_snan(a->cls)) {
68
+
50
- parts_silence_nan(a, s);
69
+ if (!fp_access_check(s)) {
51
+ which = 0;
70
+ return;
52
+ } else if (is_snan(b->cls)) {
71
+ }
53
+ which = 1;
72
+
54
+ } else if (is_qnan(a->cls)) {
73
+ fpst = get_fpstatus_ptr(true);
55
+ which = 0;
74
+
56
+ } else {
75
+ tcg_op1 = tcg_temp_new_i32();
57
+ which = 1;
76
+ tcg_op2 = tcg_temp_new_i32();
58
}
77
+ tcg_res = tcg_temp_new_i32();
59
+ break;
78
+
60
+ case float_2nan_prop_s_ba:
79
+ read_vec_element_i32(s, tcg_op1, rn, 0, MO_16);
61
+ if (is_snan(b->cls)) {
80
+ read_vec_element_i32(s, tcg_op2, rm, 0, MO_16);
62
+ which = 1;
81
+
63
+ } else if (is_snan(a->cls)) {
82
+ switch (fpopcode) {
64
+ which = 0;
83
+ case 0x03: /* FMULX */
65
+ } else if (is_qnan(b->cls)) {
84
+ gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
66
+ which = 1;
85
+ break;
67
+ } else {
86
+ case 0x04: /* FCMEQ (reg) */
68
+ which = 0;
87
+ gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
69
+ }
88
+ break;
70
+ break;
89
+ case 0x07: /* FRECPS */
71
+ case float_2nan_prop_ab:
90
+ gen_helper_recpsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
72
+ which = is_nan(a->cls) ? 0 : 1;
91
+ break;
73
+ break;
92
+ case 0x0f: /* FRSQRTS */
74
+ case float_2nan_prop_ba:
93
+ gen_helper_rsqrtsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
75
+ which = is_nan(b->cls) ? 1 : 0;
94
+ break;
76
+ break;
95
+ case 0x14: /* FCMGE (reg) */
77
+ case float_2nan_prop_x87:
96
+ gen_helper_advsimd_cge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
78
+ /*
97
+ break;
79
+ * This implements x87 NaN propagation rules:
98
+ case 0x15: /* FACGE */
80
+ * SNaN + QNaN => return the QNaN
99
+ gen_helper_advsimd_acge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
81
+ * two SNaNs => return the one with the larger significand, silenced
100
+ break;
82
+ * two QNaNs => return the one with the larger significand
101
+ case 0x1a: /* FABD */
83
+ * SNaN and a non-NaN => return the SNaN, silenced
102
+ gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
84
+ * QNaN and a non-NaN => return the QNaN
103
+ tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
85
+ *
104
+ break;
86
+ * If we get down to comparing significands and they are the same,
105
+ case 0x1c: /* FCMGT (reg) */
87
+ * return the NaN with the positive sign bit (if any).
106
+ gen_helper_advsimd_cgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
88
+ */
107
+ break;
89
+ if (is_snan(a->cls)) {
108
+ case 0x1d: /* FACGT */
90
+ if (is_snan(b->cls)) {
109
+ gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
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
+ }
110
+ break;
104
+ break;
111
+ default:
105
+ default:
112
+ g_assert_not_reached();
106
+ g_assert_not_reached();
113
+ }
107
+ }
114
+
108
+
115
+ write_fp_sreg(s, rd, tcg_res);
109
+ if (which) {
116
+
110
+ a = b;
117
+
111
+ }
118
+ tcg_temp_free_i32(tcg_res);
112
+ if (is_snan(a->cls)) {
119
+ tcg_temp_free_i32(tcg_op1);
113
+ parts_silence_nan(a, s);
120
+ tcg_temp_free_i32(tcg_op2);
114
}
121
+ tcg_temp_free_ptr(fpst);
115
return a;
122
+}
116
}
123
+
117
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
124
static void handle_2misc_64(DisasContext *s, int opcode, bool u,
118
index XXXXXXX..XXXXXXX 100644
125
TCGv_i64 tcg_rd, TCGv_i64 tcg_rn,
119
--- a/fpu/softfloat-specialize.c.inc
126
TCGv_i32 tcg_rmode, TCGv_ptr tcg_fpstatus)
120
+++ b/fpu/softfloat-specialize.c.inc
127
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
121
@@ -XXX,XX +XXX,XX @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
128
{ 0xce408000, 0xffe0c000, disas_crypto_three_reg_imm2 },
122
}
129
{ 0x0e400400, 0x9f60c400, disas_simd_three_reg_same_fp16 },
123
}
130
{ 0x0e780800, 0x8f7e0c00, disas_simd_two_reg_misc_fp16 },
124
131
+ { 0x5e400400, 0xdf60c400, disas_simd_scalar_three_reg_same_fp16 },
125
-/*----------------------------------------------------------------------------
132
{ 0x00000000, 0x00000000, NULL }
126
-| Select which NaN to propagate for a two-input operation.
133
};
127
-| IEEE754 doesn't specify all the details of this, so the
134
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.
135
--
224
--
136
2.16.2
225
2.34.1
137
226
138
227
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
I re-use the existing handle_2misc_fcmp_zero handler and tweak it
3
Remember if there was an SNaN, and use that to simplify
4
slightly to deal with the half-precision case.
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.
5
8
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20180227143852.11175-20-alex.bennee@linaro.org
11
Message-id: 20241203203949.483774-10-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
target/arm/translate-a64.c | 80 +++++++++++++++++++++++++++++++++-------------
14
fpu/softfloat-parts.c.inc | 32 ++++++++++++--------------------
12
1 file changed, 57 insertions(+), 23 deletions(-)
15
1 file changed, 12 insertions(+), 20 deletions(-)
13
16
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
19
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/translate-a64.c
20
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
21
@@ -XXX,XX +XXX,XX @@ static void partsN(return_nan)(FloatPartsN *a, float_status *s)
19
bool is_scalar, bool is_u, bool is_q,
22
static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
20
int size, int rn, int rd)
23
float_status *s)
21
{
24
{
22
- bool is_double = (size == 3);
25
+ bool have_snan = false;
23
+ bool is_double = (size == MO_64);
26
int cmp, which;
24
TCGv_ptr fpst;
27
25
28
if (is_snan(a->cls) || is_snan(b->cls)) {
26
if (!fp_access_check(s)) {
29
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
27
return;
30
+ have_snan = true;
28
}
31
}
29
32
30
- fpst = get_fpstatus_ptr(false);
33
if (s->default_nan_mode) {
31
+ fpst = get_fpstatus_ptr(size == MO_16);
34
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
32
35
33
if (is_double) {
36
switch (s->float_2nan_prop_rule) {
34
TCGv_i64 tcg_op = tcg_temp_new_i64();
37
case float_2nan_prop_s_ab:
35
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
38
- if (is_snan(a->cls)) {
36
bool swap = false;
39
- which = 0;
37
int pass, maxpasses;
40
- } else if (is_snan(b->cls)) {
38
41
- which = 1;
39
- switch (opcode) {
42
- } else if (is_qnan(a->cls)) {
40
- case 0x2e: /* FCMLT (zero) */
43
- which = 0;
41
- swap = true;
44
- } else {
42
- /* fall through */
45
- which = 1;
43
- case 0x2c: /* FCMGT (zero) */
46
+ if (have_snan) {
44
- genfn = gen_helper_neon_cgt_f32;
47
+ which = is_snan(a->cls) ? 0 : 1;
45
- break;
48
+ break;
46
- case 0x2d: /* FCMEQ (zero) */
47
- genfn = gen_helper_neon_ceq_f32;
48
- break;
49
- case 0x6d: /* FCMLE (zero) */
50
- swap = true;
51
- /* fall through */
52
- case 0x6c: /* FCMGE (zero) */
53
- genfn = gen_helper_neon_cge_f32;
54
- break;
55
- default:
56
- g_assert_not_reached();
57
+ if (size == MO_16) {
58
+ switch (opcode) {
59
+ case 0x2e: /* FCMLT (zero) */
60
+ swap = true;
61
+ /* fall through */
62
+ case 0x2c: /* FCMGT (zero) */
63
+ genfn = gen_helper_advsimd_cgt_f16;
64
+ break;
65
+ case 0x2d: /* FCMEQ (zero) */
66
+ genfn = gen_helper_advsimd_ceq_f16;
67
+ break;
68
+ case 0x6d: /* FCMLE (zero) */
69
+ swap = true;
70
+ /* fall through */
71
+ case 0x6c: /* FCMGE (zero) */
72
+ genfn = gen_helper_advsimd_cge_f16;
73
+ break;
74
+ default:
75
+ g_assert_not_reached();
76
+ }
77
+ } else {
78
+ switch (opcode) {
79
+ case 0x2e: /* FCMLT (zero) */
80
+ swap = true;
81
+ /* fall through */
82
+ case 0x2c: /* FCMGT (zero) */
83
+ genfn = gen_helper_neon_cgt_f32;
84
+ break;
85
+ case 0x2d: /* FCMEQ (zero) */
86
+ genfn = gen_helper_neon_ceq_f32;
87
+ break;
88
+ case 0x6d: /* FCMLE (zero) */
89
+ swap = true;
90
+ /* fall through */
91
+ case 0x6c: /* FCMGE (zero) */
92
+ genfn = gen_helper_neon_cge_f32;
93
+ break;
94
+ default:
95
+ g_assert_not_reached();
96
+ }
97
}
49
}
98
50
- break;
99
if (is_scalar) {
51
- case float_2nan_prop_s_ba:
100
maxpasses = 1;
52
- if (is_snan(b->cls)) {
101
} else {
53
- which = 1;
102
- maxpasses = is_q ? 4 : 2;
54
- } else if (is_snan(a->cls)) {
103
+ int vector_size = 8 << is_q;
55
- which = 0;
104
+ maxpasses = vector_size >> size;
56
- } else if (is_qnan(b->cls)) {
105
}
57
- which = 1;
106
58
- } else {
107
for (pass = 0; pass < maxpasses; pass++) {
59
- which = 0;
108
- read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
60
- }
109
+ read_vec_element_i32(s, tcg_op, rn, pass, size);
61
- break;
110
if (swap) {
62
+ /* fall through */
111
genfn(tcg_res, tcg_zero, tcg_op, fpst);
63
case float_2nan_prop_ab:
112
} else {
64
which = is_nan(a->cls) ? 0 : 1;
113
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
65
break;
114
if (is_scalar) {
66
+ case float_2nan_prop_s_ba:
115
write_fp_sreg(s, rd, tcg_res);
67
+ if (have_snan) {
116
} else {
68
+ which = is_snan(b->cls) ? 1 : 0;
117
- write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
69
+ break;
118
+ write_vec_element_i32(s, tcg_res, rd, pass, size);
70
+ }
119
}
71
+ /* fall through */
120
}
72
case float_2nan_prop_ba:
121
tcg_temp_free_i32(tcg_res);
73
which = is_nan(b->cls) ? 1 : 0;
122
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
74
break;
123
fpop = deposit32(opcode, 5, 1, a);
124
fpop = deposit32(fpop, 6, 1, u);
125
126
+ rd = extract32(insn, 0, 5);
127
+ rn = extract32(insn, 5, 5);
128
+
129
switch (fpop) {
130
+ break;
131
+ case 0x2c: /* FCMGT (zero) */
132
+ case 0x2d: /* FCMEQ (zero) */
133
+ case 0x2e: /* FCMLT (zero) */
134
+ case 0x6c: /* FCMGE (zero) */
135
+ case 0x6d: /* FCMLE (zero) */
136
+ handle_2misc_fcmp_zero(s, fpop, is_scalar, 0, is_q, MO_16, rn, rd);
137
+ return;
138
case 0x18: /* FRINTN */
139
need_rmode = true;
140
only_in_vector = true;
141
--
75
--
142
2.16.2
76
2.34.1
143
144
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
I only needed to do a little light re-factoring to support the
3
Move the fractional comparison to the end of the
4
half-precision helpers.
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.
5
8
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20180227143852.11175-30-alex.bennee@linaro.org
11
Message-id: 20241203203949.483774-11-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
target/arm/translate-a64.c | 80 +++++++++++++++++++++++++++++++---------------
14
fpu/softfloat-parts.c.inc | 19 +++++++++----------
12
1 file changed, 54 insertions(+), 26 deletions(-)
15
1 file changed, 9 insertions(+), 10 deletions(-)
13
16
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
17
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
19
--- a/fpu/softfloat-parts.c.inc
17
+++ b/target/arm/translate-a64.c
20
+++ b/fpu/softfloat-parts.c.inc
18
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
21
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
19
case 0xf: /* FMAXP */
22
return a;
20
case 0x2c: /* FMINNMP */
23
}
21
case 0x2f: /* FMINP */
24
22
- /* FP op, size[0] is 32 or 64 bit */
25
- cmp = frac_cmp(a, b);
23
+ /* FP op, size[0] is 32 or 64 bit*/
26
- if (cmp == 0) {
24
if (!u) {
27
- cmp = a->sign < b->sign;
25
- unallocated_encoding(s);
28
- }
26
- return;
29
-
27
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
30
switch (s->float_2nan_prop_rule) {
28
+ unallocated_encoding(s);
31
case float_2nan_prop_s_ab:
29
+ return;
32
if (have_snan) {
30
+ } else {
33
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
31
+ size = MO_16;
34
* return the NaN with the positive sign bit (if any).
32
+ }
35
*/
33
+ } else {
36
if (is_snan(a->cls)) {
34
+ size = extract32(size, 0, 1) ? MO_64 : MO_32;
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;
35
}
54
}
36
+
55
+ cmp = frac_cmp(a, b);
37
if (!fp_access_check(s)) {
56
+ if (cmp == 0) {
38
return;
57
+ cmp = a->sign < b->sign;
39
}
58
+ }
40
59
+ which = cmp > 0 ? 0 : 1;
41
- size = extract32(size, 0, 1) ? 3 : 2;
42
- fpst = get_fpstatus_ptr(false);
43
+ fpst = get_fpstatus_ptr(size == MO_16);
44
break;
60
break;
45
default:
61
default:
46
unallocated_encoding(s);
62
g_assert_not_reached();
47
return;
48
}
49
50
- if (size == 3) {
51
+ if (size == MO_64) {
52
TCGv_i64 tcg_op1 = tcg_temp_new_i64();
53
TCGv_i64 tcg_op2 = tcg_temp_new_i64();
54
TCGv_i64 tcg_res = tcg_temp_new_i64();
55
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
56
TCGv_i32 tcg_op2 = tcg_temp_new_i32();
57
TCGv_i32 tcg_res = tcg_temp_new_i32();
58
59
- read_vec_element_i32(s, tcg_op1, rn, 0, MO_32);
60
- read_vec_element_i32(s, tcg_op2, rn, 1, MO_32);
61
+ read_vec_element_i32(s, tcg_op1, rn, 0, size);
62
+ read_vec_element_i32(s, tcg_op2, rn, 1, size);
63
64
- switch (opcode) {
65
- case 0xc: /* FMAXNMP */
66
- gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
67
- break;
68
- case 0xd: /* FADDP */
69
- gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
70
- break;
71
- case 0xf: /* FMAXP */
72
- gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
73
- break;
74
- case 0x2c: /* FMINNMP */
75
- gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
76
- break;
77
- case 0x2f: /* FMINP */
78
- gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
79
- break;
80
- default:
81
- g_assert_not_reached();
82
+ if (size == MO_16) {
83
+ switch (opcode) {
84
+ case 0xc: /* FMAXNMP */
85
+ gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
86
+ break;
87
+ case 0xd: /* FADDP */
88
+ gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
89
+ break;
90
+ case 0xf: /* FMAXP */
91
+ gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
92
+ break;
93
+ case 0x2c: /* FMINNMP */
94
+ gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
95
+ break;
96
+ case 0x2f: /* FMINP */
97
+ gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
98
+ break;
99
+ default:
100
+ g_assert_not_reached();
101
+ }
102
+ } else {
103
+ switch (opcode) {
104
+ case 0xc: /* FMAXNMP */
105
+ gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
106
+ break;
107
+ case 0xd: /* FADDP */
108
+ gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
109
+ break;
110
+ case 0xf: /* FMAXP */
111
+ gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
112
+ break;
113
+ case 0x2c: /* FMINNMP */
114
+ gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
115
+ break;
116
+ case 0x2f: /* FMINP */
117
+ gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
118
+ break;
119
+ default:
120
+ g_assert_not_reached();
121
+ }
122
}
123
124
write_fp_sreg(s, rd, tcg_res);
125
--
63
--
126
2.16.2
64
2.34.1
127
128
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Half-precision flush to zero behaviour is controlled by a separate
3
Replace the "index" selecting between A and B with a result variable
4
FZ16 bit in the FPCR. To handle this we pass a pointer to
4
of the proper type. This improves clarity within the function.
5
fp_status_fp16 when working on half-precision operations. The value of
6
the presented FPCR is calculated from an amalgam of the two when read.
7
5
8
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Message-id: 20180227143852.11175-5-alex.bennee@linaro.org
8
Message-id: 20241203203949.483774-12-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
target/arm/cpu.h | 32 ++++++++++++++++++++++------
11
fpu/softfloat-parts.c.inc | 28 +++++++++++++---------------
14
target/arm/helper.c | 26 ++++++++++++++++++-----
12
1 file changed, 13 insertions(+), 15 deletions(-)
15
target/arm/translate-a64.c | 53 +++++++++++++++++++++++++---------------------
16
3 files changed, 75 insertions(+), 36 deletions(-)
17
13
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
16
--- a/fpu/softfloat-parts.c.inc
21
+++ b/target/arm/cpu.h
17
+++ b/fpu/softfloat-parts.c.inc
22
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
18
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
23
/* scratch space when Tn are not sufficient. */
19
float_status *s)
24
uint32_t scratch[8];
25
26
- /* fp_status is the "normal" fp status. standard_fp_status retains
27
- * values corresponding to the ARM "Standard FPSCR Value", ie
28
- * default-NaN, flush-to-zero, round-to-nearest and is used by
29
- * any operations (generally Neon) which the architecture defines
30
- * as controlled by the standard FPSCR value rather than the FPSCR.
31
+ /* There are a number of distinct float control structures:
32
+ *
33
+ * fp_status: is the "normal" fp status.
34
+ * fp_status_fp16: used for half-precision calculations
35
+ * standard_fp_status : the ARM "Standard FPSCR Value"
36
+ *
37
+ * Half-precision operations are governed by a separate
38
+ * flush-to-zero control bit in FPSCR:FZ16. We pass a separate
39
+ * status structure to control this.
40
+ *
41
+ * The "Standard FPSCR", ie default-NaN, flush-to-zero,
42
+ * round-to-nearest and is used by any operations (generally
43
+ * Neon) which the architecture defines as controlled by the
44
+ * standard FPSCR value rather than the FPSCR.
45
*
46
* To avoid having to transfer exception bits around, we simply
47
* say that the FPSCR cumulative exception flags are the logical
48
- * OR of the flags in the two fp statuses. This relies on the
49
+ * OR of the flags in the three fp statuses. This relies on the
50
* only thing which needs to read the exception flags being
51
* an explicit FPSCR read.
52
*/
53
float_status fp_status;
54
+ float_status fp_status_f16;
55
float_status standard_fp_status;
56
57
/* ZCR_EL[1-3] */
58
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
59
uint32_t vfp_get_fpscr(CPUARMState *env);
60
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
61
62
-/* For A64 the FPSCR is split into two logically distinct registers,
63
+/* FPCR, Floating Point Control Register
64
+ * FPSR, Floating Poiht Status Register
65
+ *
66
+ * For A64 the FPSCR is split into two logically distinct registers,
67
* FPCR and FPSR. However since they still use non-overlapping bits
68
* we store the underlying state in fpscr and just mask on read/write.
69
*/
70
#define FPSR_MASK 0xf800009f
71
#define FPCR_MASK 0x07f79f00
72
+
73
+#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
74
+#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
75
+#define FPCR_DN (1 << 25) /* Default NaN enable bit */
76
+
77
static inline uint32_t vfp_get_fpsr(CPUARMState *env)
78
{
20
{
79
return vfp_get_fpscr(env) & FPSR_MASK;
21
bool have_snan = false;
80
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
- int cmp, which;
81
index XXXXXXX..XXXXXXX 100644
23
+ FloatPartsN *ret;
82
--- a/target/arm/helper.c
24
+ int cmp;
83
+++ b/target/arm/helper.c
25
84
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
26
if (is_snan(a->cls) || is_snan(b->cls)) {
85
| (env->vfp.vec_stride << 20);
27
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
86
i = get_float_exception_flags(&env->vfp.fp_status);
28
@@ -XXX,XX +XXX,XX @@ static FloatPartsN *partsN(pick_nan)(FloatPartsN *a, FloatPartsN *b,
87
i |= get_float_exception_flags(&env->vfp.standard_fp_status);
29
switch (s->float_2nan_prop_rule) {
88
+ i |= get_float_exception_flags(&env->vfp.fp_status_f16);
30
case float_2nan_prop_s_ab:
89
fpscr |= vfp_exceptbits_from_host(i);
31
if (have_snan) {
90
return fpscr;
32
- which = is_snan(a->cls) ? 0 : 1;
91
}
33
+ ret = is_snan(a->cls) ? a : b;
92
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
93
break;
34
break;
94
}
35
}
95
set_float_rounding_mode(i, &env->vfp.fp_status);
36
/* fall through */
96
+ set_float_rounding_mode(i, &env->vfp.fp_status_f16);
37
case float_2nan_prop_ab:
97
}
38
- which = is_nan(a->cls) ? 0 : 1;
98
- if (changed & (1 << 24)) {
39
+ ret = is_nan(a->cls) ? a : b;
99
- set_flush_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
40
break;
100
- set_flush_inputs_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
41
case float_2nan_prop_s_ba:
101
+ if (changed & FPCR_FZ16) {
42
if (have_snan) {
102
+ bool ftz_enabled = val & FPCR_FZ16;
43
- which = is_snan(b->cls) ? 1 : 0;
103
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
44
+ ret = is_snan(b->cls) ? b : a;
104
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
45
break;
105
+ }
106
+ if (changed & FPCR_FZ) {
107
+ bool ftz_enabled = val & FPCR_FZ;
108
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status);
109
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status);
110
+ }
111
+ if (changed & FPCR_DN) {
112
+ bool dnan_enabled = val & FPCR_DN;
113
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status);
114
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16);
115
}
116
- if (changed & (1 << 25))
117
- set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status);
118
119
+ /* The exception flags are ORed together when we read fpscr so we
120
+ * only need to preserve the current state in one of our
121
+ * float_status values.
122
+ */
123
i = vfp_exceptbits_to_host(val);
124
set_float_exception_flags(i, &env->vfp.fp_status);
125
+ set_float_exception_flags(0, &env->vfp.fp_status_f16);
126
set_float_exception_flags(0, &env->vfp.standard_fp_status);
127
}
128
129
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/target/arm/translate-a64.c
132
+++ b/target/arm/translate-a64.c
133
@@ -XXX,XX +XXX,XX @@ static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
134
tcg_temp_free_i64(tmp);
135
}
136
137
-static TCGv_ptr get_fpstatus_ptr(void)
138
+static TCGv_ptr get_fpstatus_ptr(bool is_f16)
139
{
140
TCGv_ptr statusptr = tcg_temp_new_ptr();
141
int offset;
142
143
- /* In A64 all instructions (both FP and Neon) use the FPCR;
144
- * there is no equivalent of the A32 Neon "standard FPSCR value"
145
- * and all operations use vfp.fp_status.
146
+ /* In A64 all instructions (both FP and Neon) use the FPCR; there
147
+ * is no equivalent of the A32 Neon "standard FPSCR value".
148
+ * However half-precision operations operate under a different
149
+ * FZ16 flag and use vfp.fp_status_f16 instead of vfp.fp_status.
150
*/
151
- offset = offsetof(CPUARMState, vfp.fp_status);
152
+ if (is_f16) {
153
+ offset = offsetof(CPUARMState, vfp.fp_status_f16);
154
+ } else {
155
+ offset = offsetof(CPUARMState, vfp.fp_status);
156
+ }
157
tcg_gen_addi_ptr(statusptr, cpu_env, offset);
158
return statusptr;
159
}
160
@@ -XXX,XX +XXX,XX @@ static void handle_fp_compare(DisasContext *s, bool is_double,
161
bool cmp_with_zero, bool signal_all_nans)
162
{
163
TCGv_i64 tcg_flags = tcg_temp_new_i64();
164
- TCGv_ptr fpst = get_fpstatus_ptr();
165
+ TCGv_ptr fpst = get_fpstatus_ptr(false);
166
167
if (is_double) {
168
TCGv_i64 tcg_vn, tcg_vm;
169
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
170
TCGv_i32 tcg_op;
171
TCGv_i32 tcg_res;
172
173
- fpst = get_fpstatus_ptr();
174
+ fpst = get_fpstatus_ptr(false);
175
tcg_op = read_fp_sreg(s, rn);
176
tcg_res = tcg_temp_new_i32();
177
178
@@ -XXX,XX +XXX,XX @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
179
return;
180
}
181
182
- fpst = get_fpstatus_ptr();
183
+ fpst = get_fpstatus_ptr(false);
184
tcg_op = read_fp_dreg(s, rn);
185
tcg_res = tcg_temp_new_i64();
186
187
@@ -XXX,XX +XXX,XX @@ static void handle_fp_2src_single(DisasContext *s, int opcode,
188
TCGv_ptr fpst;
189
190
tcg_res = tcg_temp_new_i32();
191
- fpst = get_fpstatus_ptr();
192
+ fpst = get_fpstatus_ptr(false);
193
tcg_op1 = read_fp_sreg(s, rn);
194
tcg_op2 = read_fp_sreg(s, rm);
195
196
@@ -XXX,XX +XXX,XX @@ static void handle_fp_2src_double(DisasContext *s, int opcode,
197
TCGv_ptr fpst;
198
199
tcg_res = tcg_temp_new_i64();
200
- fpst = get_fpstatus_ptr();
201
+ fpst = get_fpstatus_ptr(false);
202
tcg_op1 = read_fp_dreg(s, rn);
203
tcg_op2 = read_fp_dreg(s, rm);
204
205
@@ -XXX,XX +XXX,XX @@ static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1,
206
{
207
TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
208
TCGv_i32 tcg_res = tcg_temp_new_i32();
209
- TCGv_ptr fpst = get_fpstatus_ptr();
210
+ TCGv_ptr fpst = get_fpstatus_ptr(false);
211
212
tcg_op1 = read_fp_sreg(s, rn);
213
tcg_op2 = read_fp_sreg(s, rm);
214
@@ -XXX,XX +XXX,XX @@ static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1,
215
{
216
TCGv_i64 tcg_op1, tcg_op2, tcg_op3;
217
TCGv_i64 tcg_res = tcg_temp_new_i64();
218
- TCGv_ptr fpst = get_fpstatus_ptr();
219
+ TCGv_ptr fpst = get_fpstatus_ptr(false);
220
221
tcg_op1 = read_fp_dreg(s, rn);
222
tcg_op2 = read_fp_dreg(s, rm);
223
@@ -XXX,XX +XXX,XX @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
224
TCGv_ptr tcg_fpstatus;
225
TCGv_i32 tcg_shift;
226
227
- tcg_fpstatus = get_fpstatus_ptr();
228
+ tcg_fpstatus = get_fpstatus_ptr(false);
229
230
tcg_shift = tcg_const_i32(64 - scale);
231
232
@@ -XXX,XX +XXX,XX @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
233
TCGv_i32 tcg_elt1 = tcg_temp_new_i32();
234
TCGv_i32 tcg_elt2 = tcg_temp_new_i32();
235
TCGv_i32 tcg_elt3 = tcg_temp_new_i32();
236
- TCGv_ptr fpst = get_fpstatus_ptr();
237
+ TCGv_ptr fpst = get_fpstatus_ptr(false);
238
239
assert(esize == 32);
240
assert(elements == 4);
241
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
242
}
46
}
243
47
/* fall through */
244
size = extract32(size, 0, 1) ? 3 : 2;
48
case float_2nan_prop_ba:
245
- fpst = get_fpstatus_ptr();
49
- which = is_nan(b->cls) ? 1 : 0;
246
+ fpst = get_fpstatus_ptr(false);
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;
247
break;
79
break;
248
default:
80
default:
249
unallocated_encoding(s);
81
g_assert_not_reached();
250
@@ -XXX,XX +XXX,XX @@ static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn,
251
int fracbits, int size)
252
{
253
bool is_double = size == 3 ? true : false;
254
- TCGv_ptr tcg_fpst = get_fpstatus_ptr();
255
+ TCGv_ptr tcg_fpst = get_fpstatus_ptr(false);
256
TCGv_i32 tcg_shift = tcg_const_i32(fracbits);
257
TCGv_i64 tcg_int = tcg_temp_new_i64();
258
TCGMemOp mop = size | (is_signed ? MO_SIGN : 0);
259
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
260
261
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
262
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
263
- tcg_fpstatus = get_fpstatus_ptr();
264
+ tcg_fpstatus = get_fpstatus_ptr(false);
265
tcg_shift = tcg_const_i32(fracbits);
266
267
if (is_double) {
268
@@ -XXX,XX +XXX,XX @@ static void handle_3same_float(DisasContext *s, int size, int elements,
269
int fpopcode, int rd, int rn, int rm)
270
{
271
int pass;
272
- TCGv_ptr fpst = get_fpstatus_ptr();
273
+ TCGv_ptr fpst = get_fpstatus_ptr(false);
274
275
for (pass = 0; pass < elements; pass++) {
276
if (size) {
277
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
278
return;
279
}
82
}
280
83
281
- fpst = get_fpstatus_ptr();
84
- if (which) {
282
+ fpst = get_fpstatus_ptr(false);
85
- a = b;
283
86
+ if (is_snan(ret->cls)) {
284
if (is_double) {
87
+ parts_silence_nan(ret, s);
285
TCGv_i64 tcg_op = tcg_temp_new_i64();
286
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_reciprocal(DisasContext *s, int opcode,
287
int size, int rn, int rd)
288
{
289
bool is_double = (size == 3);
290
- TCGv_ptr fpst = get_fpstatus_ptr();
291
+ TCGv_ptr fpst = get_fpstatus_ptr(false);
292
293
if (is_double) {
294
TCGv_i64 tcg_op = tcg_temp_new_i64();
295
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
296
if (is_fcvt) {
297
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
298
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
299
- tcg_fpstatus = get_fpstatus_ptr();
300
+ tcg_fpstatus = get_fpstatus_ptr(false);
301
} else {
302
tcg_rmode = NULL;
303
tcg_fpstatus = NULL;
304
@@ -XXX,XX +XXX,XX @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
305
306
/* Floating point operations need fpst */
307
if (opcode >= 0x58) {
308
- fpst = get_fpstatus_ptr();
309
+ fpst = get_fpstatus_ptr(false);
310
} else {
311
fpst = NULL;
312
}
88
}
313
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
89
- if (is_snan(a->cls)) {
314
}
90
- parts_silence_nan(a, s);
315
91
- }
316
if (need_fpstatus) {
92
- return a;
317
- tcg_fpstatus = get_fpstatus_ptr();
93
+ return ret;
318
+ tcg_fpstatus = get_fpstatus_ptr(false);
94
}
319
} else {
95
320
tcg_fpstatus = NULL;
96
static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
321
}
322
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
323
}
324
325
if (is_fp) {
326
- fpst = get_fpstatus_ptr();
327
+ fpst = get_fpstatus_ptr(false);
328
} else {
329
fpst = NULL;
330
}
331
--
97
--
332
2.16.2
98
2.34.1
333
99
334
100
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Leif Lindholm <quic_llindhol@quicinc.com>
2
2
3
I am leaving Xilinx, so to avoid having an email address that bounces
3
I'm migrating to Qualcomm's new open source email infrastructure, so
4
update my maintainer address to point to my personal email address.
4
update my email address, and update the mailmap to match.
5
5
6
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
6
Signed-off-by: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
7
Signed-off-by: Alistair Francis <alistair@alistair23.me>
7
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
9
Message-id: 7bb690382e3370aa1c1e047a84e36603c787ec0e.1519749987.git.alistair.francis@xilinx.com
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20241205114047.1125842-1-leif.lindholm@oss.qualcomm.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
MAINTAINERS | 12 ++++++------
14
MAINTAINERS | 2 +-
13
1 file changed, 6 insertions(+), 6 deletions(-)
15
.mailmap | 5 +++--
16
2 files changed, 4 insertions(+), 3 deletions(-)
14
17
15
diff --git a/MAINTAINERS b/MAINTAINERS
18
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/MAINTAINERS
20
--- a/MAINTAINERS
18
+++ b/MAINTAINERS
21
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ F: hw/misc/arm_sysctl.c
22
@@ -XXX,XX +XXX,XX @@ F: include/hw/ssi/imx_spi.h
20
23
SBSA-REF
21
Xilinx Zynq
24
M: Radoslaw Biernacki <rad@semihalf.com>
22
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
25
M: Peter Maydell <peter.maydell@linaro.org>
23
-M: Alistair Francis <alistair.francis@xilinx.com>
26
-R: Leif Lindholm <quic_llindhol@quicinc.com>
24
+M: Alistair Francis <alistair@alistair23.me>
27
+R: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
28
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
25
L: qemu-arm@nongnu.org
29
L: qemu-arm@nongnu.org
26
S: Maintained
30
S: Maintained
27
F: hw/*/xilinx_*
31
diff --git a/.mailmap b/.mailmap
28
@@ -XXX,XX +XXX,XX @@ F: include/hw/misc/zynq*
32
index XXXXXXX..XXXXXXX 100644
29
X: hw/ssi/xilinx_*
33
--- a/.mailmap
30
34
+++ b/.mailmap
31
Xilinx ZynqMP
35
@@ -XXX,XX +XXX,XX @@ Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
32
-M: Alistair Francis <alistair.francis@xilinx.com>
36
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
33
+M: Alistair Francis <alistair@alistair23.me>
37
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
34
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
38
Juan Quintela <quintela@trasno.org> <quintela@redhat.com>
35
L: qemu-arm@nongnu.org
39
-Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
36
S: Maintained
40
-Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
37
@@ -XXX,XX +XXX,XX @@ T: git git://github.com/bonzini/qemu.git scsi-next
41
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <quic_llindhol@quicinc.com>
38
42
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif.lindholm@linaro.org>
39
SSI
43
+Leif Lindholm <leif.lindholm@oss.qualcomm.com> <leif@nuviainc.com>
40
M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
44
Luc Michel <luc@lmichel.fr> <luc.michel@git.antfield.fr>
41
-M: Alistair Francis <alistair.francis@xilinx.com>
45
Luc Michel <luc@lmichel.fr> <luc.michel@greensocs.com>
42
+M: Alistair Francis <alistair@alistair23.me>
46
Luc Michel <luc@lmichel.fr> <lmichel@kalray.eu>
43
S: Maintained
44
F: hw/ssi/*
45
F: hw/block/m25p80.c
46
@@ -XXX,XX +XXX,XX @@ X: hw/ssi/xilinx_*
47
F: tests/m25p80-test.c
48
49
Xilinx SPI
50
-M: Alistair Francis <alistair.francis@xilinx.com>
51
+M: Alistair Francis <alistair@alistair23.me>
52
M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
53
S: Maintained
54
F: hw/ssi/xilinx_*
55
@@ -XXX,XX +XXX,XX @@ S: Maintained
56
F: hw/net/eepro100.c
57
58
Generic Loader
59
-M: Alistair Francis <alistair.francis@xilinx.com>
60
+M: Alistair Francis <alistair@alistair23.me>
61
S: Maintained
62
F: hw/core/generic-loader.c
63
F: include/hw/core/generic-loader.h
64
@@ -XXX,XX +XXX,XX @@ F: tests/qmp-test.c
65
T: git git://repo.or.cz/qemu/armbru.git qapi-next
66
67
Register API
68
-M: Alistair Francis <alistair.francis@xilinx.com>
69
+M: Alistair Francis <alistair@alistair23.me>
70
S: Maintained
71
F: hw/core/register.c
72
F: include/hw/register.h
73
--
47
--
74
2.16.2
48
2.34.1
75
49
76
50
diff view generated by jsdifflib
1
From: Corey Minyard <cminyard@mvista.com>
1
From: Vikram Garhwal <vikram.garhwal@bytedance.com>
2
2
3
Signed-off-by: Corey Minyard <cminyard@mvista.com>
3
Previously, maintainer role was paused due to inactive email id. Commit id:
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
c009d715721861984c4987bcc78b7ee183e86d75.
5
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
5
6
Message-id: 20180227104903.21353-2-linus.walleij@linaro.org
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
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
include/hw/i2c/i2c.h | 6 ++----
11
MAINTAINERS | 2 ++
10
hw/i2c/core.c | 3 +--
12
1 file changed, 2 insertions(+)
11
2 files changed, 3 insertions(+), 6 deletions(-)
12
13
13
diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
14
diff --git a/MAINTAINERS b/MAINTAINERS
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/i2c/i2c.h
16
--- a/MAINTAINERS
16
+++ b/include/hw/i2c/i2c.h
17
+++ b/MAINTAINERS
17
@@ -XXX,XX +XXX,XX @@ typedef struct I2CSlave I2CSlave;
18
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/fuzz-sb16-test.c
18
#define I2C_SLAVE_GET_CLASS(obj) \
19
19
OBJECT_GET_CLASS(I2CSlaveClass, (obj), TYPE_I2C_SLAVE)
20
Xilinx CAN
20
21
M: Francisco Iglesias <francisco.iglesias@amd.com>
21
-typedef struct I2CSlaveClass
22
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
22
-{
23
S: Maintained
23
+typedef struct I2CSlaveClass {
24
F: hw/net/can/xlnx-*
24
DeviceClass parent_class;
25
F: include/hw/net/xlnx-*
25
26
@@ -XXX,XX +XXX,XX @@ F: include/hw/rx/
26
/* Callbacks provided by the device. */
27
CAN bus subsystem and hardware
27
@@ -XXX,XX +XXX,XX @@ typedef struct I2CSlaveClass
28
M: Pavel Pisa <pisa@cmp.felk.cvut.cz>
28
int (*event)(I2CSlave *s, enum i2c_event event);
29
M: Francisco Iglesias <francisco.iglesias@amd.com>
29
} I2CSlaveClass;
30
+M: Vikram Garhwal <vikram.garhwal@bytedance.com>
30
31
S: Maintained
31
-struct I2CSlave
32
W: https://canbus.pages.fel.cvut.cz/
32
-{
33
F: net/can/*
33
+struct I2CSlave {
34
DeviceState qdev;
35
36
/* Remaining fields for internal use by the I2C code. */
37
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/i2c/core.c
40
+++ b/hw/i2c/core.c
41
@@ -XXX,XX +XXX,XX @@ struct I2CNode {
42
43
#define I2C_BROADCAST 0x00
44
45
-struct I2CBus
46
-{
47
+struct I2CBus {
48
BusState qbus;
49
QLIST_HEAD(, I2CNode) current_devs;
50
uint8_t saved_address;
51
--
34
--
52
2.16.2
35
2.34.1
53
54
diff view generated by jsdifflib