1
Hopefully last target-arm queue before softfreeze;
1
I don't have anything else queued up at the moment, so this is just
2
this one's largest part is the remainder of the SVE patches,
2
Richard's SME patches.
3
but there are a selection of other minor things too.
4
3
5
thanks
6
-- PMM
4
-- PMM
7
5
8
The following changes since commit 109b25045b3651f9c5d02c3766c0b3ff63e6d193:
6
The following changes since commit 63b38f6c85acd312c2cab68554abf33adf4ee2b3:
9
7
10
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging (2018-06-29 12:30:29 +0100)
8
Merge tag 'pull-target-arm-20220707' of https://git.linaro.org/people/pmaydell/qemu-arm into staging (2022-07-08 06:17:11 +0530)
11
9
12
are available in the Git repository at:
10
are available in the Git repository at:
13
11
14
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180629
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220711
15
13
16
for you to fetch changes up to 802abf4024d23e48d45373ac3f2b580124b54b47:
14
for you to fetch changes up to f9982ceaf26df27d15547a3a7990a95019e9e3a8:
17
15
18
target/arm: Add ID_ISAR6 (2018-06-29 15:30:54 +0100)
16
linux-user/aarch64: Add SME related hwcap entries (2022-07-11 13:43:52 +0100)
19
17
20
----------------------------------------------------------------
18
----------------------------------------------------------------
21
target-arm queue:
19
target-arm:
22
* last of the SVE patches; SVE is now enabled for aarch64 linux-user
20
* Implement SME emulation, for both system and linux-user
23
* sd: Don't trace SDRequest crc field (coverity bugfix)
24
* target/arm: Mark PMINTENSET accesses as possibly doing IO
25
* clean up v7VE feature bit handling
26
* i.mx7d: minor cleanups
27
* target/arm: support reading of CNT[VCT|FRQ]_EL0 from user-space
28
* target/arm: Implement ARMv8.2-DotProd
29
* virt: add addresses to dt node names (which stops dtc from
30
complaining that they're not correctly named)
31
* cleanups: replace error_setg(&error_fatal) by error_report() + exit()
32
21
33
----------------------------------------------------------------
22
----------------------------------------------------------------
34
Aaron Lindsay (3):
23
Richard Henderson (45):
35
target/arm: Add ARM_FEATURE_V7VE for v7 Virtualization Extensions
24
target/arm: Handle SME in aarch64_cpu_dump_state
36
target/arm: Remove redundant DIV detection for KVM
25
target/arm: Add infrastructure for disas_sme
37
target/arm: Mark PMINTENSET accesses as possibly doing IO
26
target/arm: Trap non-streaming usage when Streaming SVE is active
27
target/arm: Mark ADR as non-streaming
28
target/arm: Mark RDFFR, WRFFR, SETFFR as non-streaming
29
target/arm: Mark BDEP, BEXT, BGRP, COMPACT, FEXPA, FTSSEL as non-streaming
30
target/arm: Mark PMULL, FMMLA as non-streaming
31
target/arm: Mark FTSMUL, FTMAD, FADDA as non-streaming
32
target/arm: Mark SMMLA, UMMLA, USMMLA as non-streaming
33
target/arm: Mark string/histo/crypto as non-streaming
34
target/arm: Mark gather/scatter load/store as non-streaming
35
target/arm: Mark gather prefetch as non-streaming
36
target/arm: Mark LDFF1 and LDNF1 as non-streaming
37
target/arm: Mark LD1RO as non-streaming
38
target/arm: Add SME enablement checks
39
target/arm: Handle SME in sve_access_check
40
target/arm: Implement SME RDSVL, ADDSVL, ADDSPL
41
target/arm: Implement SME ZERO
42
target/arm: Implement SME MOVA
43
target/arm: Implement SME LD1, ST1
44
target/arm: Export unpredicated ld/st from translate-sve.c
45
target/arm: Implement SME LDR, STR
46
target/arm: Implement SME ADDHA, ADDVA
47
target/arm: Implement FMOPA, FMOPS (non-widening)
48
target/arm: Implement BFMOPA, BFMOPS
49
target/arm: Implement FMOPA, FMOPS (widening)
50
target/arm: Implement SME integer outer product
51
target/arm: Implement PSEL
52
target/arm: Implement REVD
53
target/arm: Implement SCLAMP, UCLAMP
54
target/arm: Reset streaming sve state on exception boundaries
55
target/arm: Enable SME for -cpu max
56
linux-user/aarch64: Clear tpidr2_el0 if CLONE_SETTLS
57
linux-user/aarch64: Reset PSTATE.SM on syscalls
58
linux-user/aarch64: Add SM bit to SVE signal context
59
linux-user/aarch64: Tidy target_restore_sigframe error return
60
linux-user/aarch64: Do not allow duplicate or short sve records
61
linux-user/aarch64: Verify extra record lock succeeded
62
linux-user/aarch64: Move sve record checks into restore
63
linux-user/aarch64: Implement SME signal handling
64
linux-user: Rename sve prctls
65
linux-user/aarch64: Implement PR_SME_GET_VL, PR_SME_SET_VL
66
target/arm: Only set ZEN in reset if SVE present
67
target/arm: Enable SME for user-only
68
linux-user/aarch64: Add SME related hwcap entries
38
69
39
Alex Bennée (1):
70
docs/system/arm/emulation.rst | 4 +
40
target/arm: support reading of CNT[VCT|FRQ]_EL0 from user-space
71
linux-user/aarch64/target_cpu.h | 5 +-
41
72
linux-user/aarch64/target_prctl.h | 62 +-
42
Eric Auger (3):
73
target/arm/cpu.h | 7 +
43
device_tree: Add qemu_fdt_node_unit_path
74
target/arm/helper-sme.h | 126 ++++
44
hw/arm/virt: Silence dtc /intc warnings
75
target/arm/helper-sve.h | 4 +
45
hw/arm/virt: Silence dtc /memory warning
76
target/arm/helper.h | 18 +
46
77
target/arm/translate-a64.h | 45 ++
47
Jean-Christophe Dubois (3):
78
target/arm/translate.h | 16 +
48
i.mx7d: Remove unused header files
79
target/arm/sme-fa64.decode | 60 ++
49
i.mx7d: Change SRC unimplemented device name from sdma to src
80
target/arm/sme.decode | 88 +++
50
i.mx7d: Change IRQ number type from hwaddr to int
81
target/arm/sve.decode | 41 +-
51
82
linux-user/aarch64/cpu_loop.c | 9 +
52
Peter Maydell (1):
83
linux-user/aarch64/signal.c | 243 ++++++--
53
sd: Don't trace SDRequest crc field
84
linux-user/elfload.c | 20 +
54
85
linux-user/syscall.c | 28 +-
55
Philippe Mathieu-Daudé (4):
86
target/arm/cpu.c | 35 +-
56
hw/block/fdc: Replace error_setg(&error_abort) by assert()
87
target/arm/cpu64.c | 11 +
57
hw/arm/sysbus-fdt: Replace error_setg(&error_fatal) by error_report() + exit()
88
target/arm/helper.c | 56 +-
58
device_tree: Replace error_setg(&error_fatal) by error_report() + exit()
89
target/arm/sme_helper.c | 1140 +++++++++++++++++++++++++++++++++++++
59
sdcard: Use the ldst API
90
target/arm/sve_helper.c | 28 +
60
91
target/arm/translate-a64.c | 103 +++-
61
Richard Henderson (40):
92
target/arm/translate-sme.c | 373 ++++++++++++
62
target/arm: Implement SVE Memory Contiguous Load Group
93
target/arm/translate-sve.c | 393 ++++++++++---
63
target/arm: Implement SVE Contiguous Load, first-fault and no-fault
94
target/arm/translate-vfp.c | 12 +
64
target/arm: Implement SVE Memory Contiguous Store Group
95
target/arm/translate.c | 2 +
65
target/arm: Implement SVE load and broadcast quadword
96
target/arm/vec_helper.c | 24 +
66
target/arm: Implement SVE integer convert to floating-point
97
target/arm/meson.build | 3 +
67
target/arm: Implement SVE floating-point arithmetic (predicated)
98
28 files changed, 2821 insertions(+), 135 deletions(-)
68
target/arm: Implement SVE FP Multiply-Add Group
99
create mode 100644 target/arm/sme-fa64.decode
69
target/arm: Implement SVE Floating Point Accumulating Reduction Group
100
create mode 100644 target/arm/sme.decode
70
target/arm: Implement SVE load and broadcast element
101
create mode 100644 target/arm/translate-sme.c
71
target/arm: Implement SVE store vector/predicate register
72
target/arm: Implement SVE scatter stores
73
target/arm: Implement SVE prefetches
74
target/arm: Implement SVE gather loads
75
target/arm: Implement SVE first-fault gather loads
76
target/arm: Implement SVE scatter store vector immediate
77
target/arm: Implement SVE floating-point compare vectors
78
target/arm: Implement SVE floating-point arithmetic with immediate
79
target/arm: Implement SVE Floating Point Multiply Indexed Group
80
target/arm: Implement SVE FP Fast Reduction Group
81
target/arm: Implement SVE Floating Point Unary Operations - Unpredicated Group
82
target/arm: Implement SVE FP Compare with Zero Group
83
target/arm: Implement SVE floating-point trig multiply-add coefficient
84
target/arm: Implement SVE floating-point convert precision
85
target/arm: Implement SVE floating-point convert to integer
86
target/arm: Implement SVE floating-point round to integral value
87
target/arm: Implement SVE floating-point unary operations
88
target/arm: Implement SVE MOVPRFX
89
target/arm: Implement SVE floating-point complex add
90
target/arm: Implement SVE fp complex multiply add
91
target/arm: Pass index to AdvSIMD FCMLA (indexed)
92
target/arm: Implement SVE fp complex multiply add (indexed)
93
target/arm: Implement SVE dot product (vectors)
94
target/arm: Implement SVE dot product (indexed)
95
target/arm: Enable SVE for aarch64-linux-user
96
target/arm: Implement ARMv8.2-DotProd
97
target/arm: Fix SVE signed division vs x86 overflow exception
98
target/arm: Fix SVE system register access checks
99
target/arm: Prune a57 features from max
100
target/arm: Prune a15 features from max
101
target/arm: Add ID_ISAR6
102
103
include/sysemu/device_tree.h | 16 +
104
target/arm/cpu.h | 3 +
105
target/arm/helper-sve.h | 682 +++++++++++++++
106
target/arm/helper.h | 44 +-
107
device_tree.c | 78 +-
108
hw/arm/boot.c | 41 +-
109
hw/arm/fsl-imx7.c | 8 +-
110
hw/arm/mcimx7d-sabre.c | 2 -
111
hw/arm/sysbus-fdt.c | 53 +-
112
hw/arm/virt.c | 70 +-
113
hw/block/fdc.c | 9 +-
114
hw/sd/bcm2835_sdhost.c | 13 +-
115
hw/sd/core.c | 2 +-
116
hw/sd/milkymist-memcard.c | 3 +-
117
hw/sd/omap_mmc.c | 6 +-
118
hw/sd/pl181.c | 11 +-
119
hw/sd/sdhci.c | 15 +-
120
hw/sd/ssi-sd.c | 6 +-
121
linux-user/elfload.c | 2 +
122
target/arm/cpu.c | 36 +-
123
target/arm/cpu64.c | 13 +-
124
target/arm/helper.c | 44 +-
125
target/arm/kvm32.c | 27 +-
126
target/arm/sve_helper.c | 1875 +++++++++++++++++++++++++++++++++++++++++-
127
target/arm/translate-a64.c | 62 +-
128
target/arm/translate-sve.c | 1688 ++++++++++++++++++++++++++++++++++++-
129
target/arm/translate.c | 102 ++-
130
target/arm/vec_helper.c | 311 ++++++-
131
hw/sd/trace-events | 2 +-
132
target/arm/sve.decode | 427 ++++++++++
133
30 files changed, 5394 insertions(+), 257 deletions(-)
134
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Use assert() instead of error_setg(&error_abort),
4
as suggested by the "qapi/error.h" documentation:
5
6
Please don't error_setg(&error_fatal, ...), use error_report() and
7
exit(), because that's more obvious.
8
Likewise, don't error_setg(&error_abort, ...), use assert().
9
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Acked-by: John Snow <jsnow@redhat.com>
12
Message-id: 20180625165749.3910-2-f4bug@amsat.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/block/fdc.c | 9 +--------
16
1 file changed, 1 insertion(+), 8 deletions(-)
17
18
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/block/fdc.c
21
+++ b/hw/block/fdc.c
22
@@ -XXX,XX +XXX,XX @@ static int pick_geometry(FDrive *drv)
23
nb_sectors,
24
FloppyDriveType_str(parse->drive));
25
}
26
+ assert(type_match != -1 && "misconfigured fd_format");
27
match = type_match;
28
}
29
-
30
- /* No match of any kind found -- fd_format is misconfigured, abort. */
31
- if (match == -1) {
32
- error_setg(&error_abort, "No candidate geometries present in table "
33
- " for floppy drive type '%s'",
34
- FloppyDriveType_str(drv->drive));
35
- }
36
-
37
parse = &(fd_formats[match]);
38
39
out:
40
--
41
2.17.1
42
43
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Use error_report() + exit() instead of error_setg(&error_fatal),
4
as suggested by the "qapi/error.h" documentation:
5
6
Please don't error_setg(&error_fatal, ...), use error_report() and
7
exit(), because that's more obvious.
8
9
This fixes CID 1352173:
10
"Passing null pointer dt_name to qemu_fdt_node_path, which dereferences it."
11
12
And this also fixes:
13
14
hw/arm/sysbus-fdt.c:322:9: warning: Array access (from variable 'node_path') results in a null pointer dereference
15
if (node_path[1]) {
16
^~~~~~~~~~~~
17
18
Fixes: Coverity CID 1352173 (Dereference after null check)
19
Suggested-by: Eric Blake <eblake@redhat.com>
20
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Reviewed-by: Eric Auger <eric.auger@redhat.com>
22
Message-id: 20180625165749.3910-3-f4bug@amsat.org
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
25
hw/arm/sysbus-fdt.c | 53 +++++++++++++++++++++++++--------------------
26
1 file changed, 30 insertions(+), 23 deletions(-)
27
28
diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/arm/sysbus-fdt.c
31
+++ b/hw/arm/sysbus-fdt.c
32
@@ -XXX,XX +XXX,XX @@ static void copy_properties_from_host(HostProperty *props, int nb_props,
33
r = qemu_fdt_getprop(host_fdt, node_path,
34
props[i].name,
35
&prop_len,
36
- props[i].optional ? &err : &error_fatal);
37
+ &err);
38
if (r) {
39
qemu_fdt_setprop(guest_fdt, nodename,
40
props[i].name, r, prop_len);
41
} else {
42
- if (prop_len != -FDT_ERR_NOTFOUND) {
43
- /* optional property not returned although property exists */
44
- error_report_err(err);
45
- } else {
46
+ if (props[i].optional && prop_len == -FDT_ERR_NOTFOUND) {
47
+ /* optional property does not exist */
48
error_free(err);
49
+ } else {
50
+ error_report_err(err);
51
+ }
52
+ if (!props[i].optional) {
53
+ /* mandatory property not found: bail out */
54
+ exit(1);
55
}
56
}
57
}
58
@@ -XXX,XX +XXX,XX @@ static void fdt_build_clock_node(void *host_fdt, void *guest_fdt,
59
60
node_offset = fdt_node_offset_by_phandle(host_fdt, host_phandle);
61
if (node_offset <= 0) {
62
- error_setg(&error_fatal,
63
- "not able to locate clock handle %d in host device tree",
64
- host_phandle);
65
+ error_report("not able to locate clock handle %d in host device tree",
66
+ host_phandle);
67
+ exit(1);
68
}
69
node_path = g_malloc(path_len);
70
while ((ret = fdt_get_path(host_fdt, node_offset, node_path, path_len))
71
@@ -XXX,XX +XXX,XX @@ static void fdt_build_clock_node(void *host_fdt, void *guest_fdt,
72
node_path = g_realloc(node_path, path_len);
73
}
74
if (ret < 0) {
75
- error_setg(&error_fatal,
76
- "not able to retrieve node path for clock handle %d",
77
- host_phandle);
78
+ error_report("not able to retrieve node path for clock handle %d",
79
+ host_phandle);
80
+ exit(1);
81
}
82
83
r = qemu_fdt_getprop(host_fdt, node_path, "compatible", &prop_len,
84
&error_fatal);
85
if (strcmp(r, "fixed-clock")) {
86
- error_setg(&error_fatal,
87
- "clock handle %d is not a fixed clock", host_phandle);
88
+ error_report("clock handle %d is not a fixed clock", host_phandle);
89
+ exit(1);
90
}
91
92
nodename = strrchr(node_path, '/');
93
@@ -XXX,XX +XXX,XX @@ static int add_amd_xgbe_fdt_node(SysBusDevice *sbdev, void *opaque)
94
95
dt_name = sysfs_to_dt_name(vbasedev->name);
96
if (!dt_name) {
97
- error_setg(&error_fatal, "%s incorrect sysfs device name %s",
98
- __func__, vbasedev->name);
99
+ error_report("%s incorrect sysfs device name %s",
100
+ __func__, vbasedev->name);
101
+ exit(1);
102
}
103
node_path = qemu_fdt_node_path(host_fdt, dt_name, vdev->compat,
104
&error_fatal);
105
if (!node_path || !node_path[0]) {
106
- error_setg(&error_fatal, "%s unable to retrieve node path for %s/%s",
107
- __func__, dt_name, vdev->compat);
108
+ error_report("%s unable to retrieve node path for %s/%s",
109
+ __func__, dt_name, vdev->compat);
110
+ exit(1);
111
}
112
113
if (node_path[1]) {
114
- error_setg(&error_fatal, "%s more than one node matching %s/%s!",
115
- __func__, dt_name, vdev->compat);
116
+ error_report("%s more than one node matching %s/%s!",
117
+ __func__, dt_name, vdev->compat);
118
+ exit(1);
119
}
120
121
g_free(dt_name);
122
123
if (vbasedev->num_regions != 5) {
124
- error_setg(&error_fatal, "%s Does the host dt node combine XGBE/PHY?",
125
- __func__);
126
+ error_report("%s Does the host dt node combine XGBE/PHY?", __func__);
127
+ exit(1);
128
}
129
130
/* generate nodes for DMA_CLK and PTP_CLK */
131
r = qemu_fdt_getprop(host_fdt, node_path[0], "clocks",
132
&prop_len, &error_fatal);
133
if (prop_len != 8) {
134
- error_setg(&error_fatal, "%s clocks property should contain 2 handles",
135
- __func__);
136
+ error_report("%s clocks property should contain 2 handles", __func__);
137
+ exit(1);
138
}
139
host_clock_phandles = (uint32_t *)r;
140
guest_clock_phandles[0] = qemu_fdt_alloc_phandle(guest_fdt);
141
--
142
2.17.1
143
144
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Use error_report() + exit() instead of error_setg(&error_fatal),
4
as suggested by the "qapi/error.h" documentation:
5
6
Please don't error_setg(&error_fatal, ...), use error_report() and
7
exit(), because that's more obvious.
8
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Eric Auger <eric.auger@redhat.com>
11
Reviewed-by: Markus Armbruster <armbru@redhat.com>
12
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
13
Message-id: 20180625165749.3910-4-f4bug@amsat.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
device_tree.c | 23 +++++++++++++----------
17
1 file changed, 13 insertions(+), 10 deletions(-)
18
19
diff --git a/device_tree.c b/device_tree.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/device_tree.c
22
+++ b/device_tree.c
23
@@ -XXX,XX +XXX,XX @@ static void read_fstree(void *fdt, const char *dirname)
24
const char *parent_node;
25
26
if (strstr(dirname, root_dir) != dirname) {
27
- error_setg(&error_fatal, "%s: %s must be searched within %s",
28
- __func__, dirname, root_dir);
29
+ error_report("%s: %s must be searched within %s",
30
+ __func__, dirname, root_dir);
31
+ exit(1);
32
}
33
parent_node = &dirname[strlen(SYSFS_DT_BASEDIR)];
34
35
d = opendir(dirname);
36
if (!d) {
37
- error_setg(&error_fatal, "%s cannot open %s", __func__, dirname);
38
- return;
39
+ error_report("%s cannot open %s", __func__, dirname);
40
+ exit(1);
41
}
42
43
while ((de = readdir(d)) != NULL) {
44
@@ -XXX,XX +XXX,XX @@ static void read_fstree(void *fdt, const char *dirname)
45
tmpnam = g_strdup_printf("%s/%s", dirname, de->d_name);
46
47
if (lstat(tmpnam, &st) < 0) {
48
- error_setg(&error_fatal, "%s cannot lstat %s", __func__, tmpnam);
49
+ error_report("%s cannot lstat %s", __func__, tmpnam);
50
+ exit(1);
51
}
52
53
if (S_ISREG(st.st_mode)) {
54
@@ -XXX,XX +XXX,XX @@ static void read_fstree(void *fdt, const char *dirname)
55
gsize len;
56
57
if (!g_file_get_contents(tmpnam, &val, &len, NULL)) {
58
- error_setg(&error_fatal, "%s not able to extract info from %s",
59
- __func__, tmpnam);
60
+ error_report("%s not able to extract info from %s",
61
+ __func__, tmpnam);
62
+ exit(1);
63
}
64
65
if (strlen(parent_node) > 0) {
66
@@ -XXX,XX +XXX,XX @@ void *load_device_tree_from_sysfs(void)
67
host_fdt = create_device_tree(&host_fdt_size);
68
read_fstree(host_fdt, SYSFS_DT_BASEDIR);
69
if (fdt_check_header(host_fdt)) {
70
- error_setg(&error_fatal,
71
- "%s host device tree extracted into memory is invalid",
72
- __func__);
73
+ error_report("%s host device tree extracted into memory is invalid",
74
+ __func__);
75
+ exit(1);
76
}
77
return host_fdt;
78
}
79
--
80
2.17.1
81
82
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
This helper allows to retrieve the paths of nodes whose name
4
match node-name or node-name@unit-address patterns.
5
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
Message-id: 1530044492-24921-2-git-send-email-eric.auger@redhat.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/sysemu/device_tree.h | 16 +++++++++++
12
device_tree.c | 55 ++++++++++++++++++++++++++++++++++++
13
2 files changed, 71 insertions(+)
14
15
diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/sysemu/device_tree.h
18
+++ b/include/sysemu/device_tree.h
19
@@ -XXX,XX +XXX,XX @@ void *load_device_tree_from_sysfs(void);
20
char **qemu_fdt_node_path(void *fdt, const char *name, char *compat,
21
Error **errp);
22
23
+/**
24
+ * qemu_fdt_node_unit_path: return the paths of nodes matching a given
25
+ * node-name, ie. node-name and node-name@unit-address
26
+ * @fdt: pointer to the dt blob
27
+ * @name: node name
28
+ * @errp: handle to an error object
29
+ *
30
+ * returns a newly allocated NULL-terminated array of node paths.
31
+ * Use g_strfreev() to free it. If one or more nodes were found, the
32
+ * array contains the path of each node and the last element equals to
33
+ * NULL. If there is no error but no matching node was found, the
34
+ * returned array contains a single element equal to NULL. If an error
35
+ * was encountered when parsing the blob, the function returns NULL
36
+ */
37
+char **qemu_fdt_node_unit_path(void *fdt, const char *name, Error **errp);
38
+
39
int qemu_fdt_setprop(void *fdt, const char *node_path,
40
const char *property, const void *val, int size);
41
int qemu_fdt_setprop_cell(void *fdt, const char *node_path,
42
diff --git a/device_tree.c b/device_tree.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/device_tree.c
45
+++ b/device_tree.c
46
@@ -XXX,XX +XXX,XX @@ static int findnode_nofail(void *fdt, const char *node_path)
47
return offset;
48
}
49
50
+char **qemu_fdt_node_unit_path(void *fdt, const char *name, Error **errp)
51
+{
52
+ char *prefix = g_strdup_printf("%s@", name);
53
+ unsigned int path_len = 16, n = 0;
54
+ GSList *path_list = NULL, *iter;
55
+ const char *iter_name;
56
+ int offset, len, ret;
57
+ char **path_array;
58
+
59
+ offset = fdt_next_node(fdt, -1, NULL);
60
+
61
+ while (offset >= 0) {
62
+ iter_name = fdt_get_name(fdt, offset, &len);
63
+ if (!iter_name) {
64
+ offset = len;
65
+ break;
66
+ }
67
+ if (!strcmp(iter_name, name) || g_str_has_prefix(iter_name, prefix)) {
68
+ char *path;
69
+
70
+ path = g_malloc(path_len);
71
+ while ((ret = fdt_get_path(fdt, offset, path, path_len))
72
+ == -FDT_ERR_NOSPACE) {
73
+ path_len += 16;
74
+ path = g_realloc(path, path_len);
75
+ }
76
+ path_list = g_slist_prepend(path_list, path);
77
+ n++;
78
+ }
79
+ offset = fdt_next_node(fdt, offset, NULL);
80
+ }
81
+ g_free(prefix);
82
+
83
+ if (offset < 0 && offset != -FDT_ERR_NOTFOUND) {
84
+ error_setg(errp, "%s: abort parsing dt for %s node units: %s",
85
+ __func__, name, fdt_strerror(offset));
86
+ for (iter = path_list; iter; iter = iter->next) {
87
+ g_free(iter->data);
88
+ }
89
+ g_slist_free(path_list);
90
+ return NULL;
91
+ }
92
+
93
+ path_array = g_new(char *, n + 1);
94
+ path_array[n--] = NULL;
95
+
96
+ for (iter = path_list; iter; iter = iter->next) {
97
+ path_array[n--] = iter->data;
98
+ }
99
+
100
+ g_slist_free(path_list);
101
+
102
+ return path_array;
103
+}
104
+
105
char **qemu_fdt_node_path(void *fdt, const char *name, char *compat,
106
Error **errp)
107
{
108
--
109
2.17.1
110
111
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
When running dtc on the guest /proc/device-tree we get the
4
following warnings: "Warning (unit_address_vs_reg): Node <name>
5
has a reg or ranges property, but no unit name", with name:
6
/intc, /intc/its, /intc/v2m.
7
8
Nodes should have a name in the form <name>[@<unit-address>] where
9
unit-address is the primary address used to access the device, listed
10
in the node's reg property. This fix seems to make dtc happy.
11
12
Signed-off-by: Eric Auger <eric.auger@redhat.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 1530044492-24921-3-git-send-email-eric.auger@redhat.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/arm/virt.c | 63 +++++++++++++++++++++++++++++++--------------------
18
1 file changed, 39 insertions(+), 24 deletions(-)
19
20
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/virt.c
23
+++ b/hw/arm/virt.c
24
@@ -XXX,XX +XXX,XX @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
25
26
static void fdt_add_its_gic_node(VirtMachineState *vms)
27
{
28
+ char *nodename;
29
+
30
vms->msi_phandle = qemu_fdt_alloc_phandle(vms->fdt);
31
- qemu_fdt_add_subnode(vms->fdt, "/intc/its");
32
- qemu_fdt_setprop_string(vms->fdt, "/intc/its", "compatible",
33
+ nodename = g_strdup_printf("/intc/its@%" PRIx64,
34
+ vms->memmap[VIRT_GIC_ITS].base);
35
+ qemu_fdt_add_subnode(vms->fdt, nodename);
36
+ qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
37
"arm,gic-v3-its");
38
- qemu_fdt_setprop(vms->fdt, "/intc/its", "msi-controller", NULL, 0);
39
- qemu_fdt_setprop_sized_cells(vms->fdt, "/intc/its", "reg",
40
+ qemu_fdt_setprop(vms->fdt, nodename, "msi-controller", NULL, 0);
41
+ qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
42
2, vms->memmap[VIRT_GIC_ITS].base,
43
2, vms->memmap[VIRT_GIC_ITS].size);
44
- qemu_fdt_setprop_cell(vms->fdt, "/intc/its", "phandle", vms->msi_phandle);
45
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->msi_phandle);
46
+ g_free(nodename);
47
}
48
49
static void fdt_add_v2m_gic_node(VirtMachineState *vms)
50
{
51
+ char *nodename;
52
+
53
+ nodename = g_strdup_printf("/intc/v2m@%" PRIx64,
54
+ vms->memmap[VIRT_GIC_V2M].base);
55
vms->msi_phandle = qemu_fdt_alloc_phandle(vms->fdt);
56
- qemu_fdt_add_subnode(vms->fdt, "/intc/v2m");
57
- qemu_fdt_setprop_string(vms->fdt, "/intc/v2m", "compatible",
58
+ qemu_fdt_add_subnode(vms->fdt, nodename);
59
+ qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
60
"arm,gic-v2m-frame");
61
- qemu_fdt_setprop(vms->fdt, "/intc/v2m", "msi-controller", NULL, 0);
62
- qemu_fdt_setprop_sized_cells(vms->fdt, "/intc/v2m", "reg",
63
+ qemu_fdt_setprop(vms->fdt, nodename, "msi-controller", NULL, 0);
64
+ qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
65
2, vms->memmap[VIRT_GIC_V2M].base,
66
2, vms->memmap[VIRT_GIC_V2M].size);
67
- qemu_fdt_setprop_cell(vms->fdt, "/intc/v2m", "phandle", vms->msi_phandle);
68
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->msi_phandle);
69
+ g_free(nodename);
70
}
71
72
static void fdt_add_gic_node(VirtMachineState *vms)
73
{
74
+ char *nodename;
75
+
76
vms->gic_phandle = qemu_fdt_alloc_phandle(vms->fdt);
77
qemu_fdt_setprop_cell(vms->fdt, "/", "interrupt-parent", vms->gic_phandle);
78
79
- qemu_fdt_add_subnode(vms->fdt, "/intc");
80
- qemu_fdt_setprop_cell(vms->fdt, "/intc", "#interrupt-cells", 3);
81
- qemu_fdt_setprop(vms->fdt, "/intc", "interrupt-controller", NULL, 0);
82
- qemu_fdt_setprop_cell(vms->fdt, "/intc", "#address-cells", 0x2);
83
- qemu_fdt_setprop_cell(vms->fdt, "/intc", "#size-cells", 0x2);
84
- qemu_fdt_setprop(vms->fdt, "/intc", "ranges", NULL, 0);
85
+ nodename = g_strdup_printf("/intc@%" PRIx64,
86
+ vms->memmap[VIRT_GIC_DIST].base);
87
+ qemu_fdt_add_subnode(vms->fdt, nodename);
88
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 3);
89
+ qemu_fdt_setprop(vms->fdt, nodename, "interrupt-controller", NULL, 0);
90
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 0x2);
91
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 0x2);
92
+ qemu_fdt_setprop(vms->fdt, nodename, "ranges", NULL, 0);
93
if (vms->gic_version == 3) {
94
int nb_redist_regions = virt_gicv3_redist_region_count(vms);
95
96
- qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible",
97
+ qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
98
"arm,gic-v3");
99
100
- qemu_fdt_setprop_cell(vms->fdt, "/intc",
101
+ qemu_fdt_setprop_cell(vms->fdt, nodename,
102
"#redistributor-regions", nb_redist_regions);
103
104
if (nb_redist_regions == 1) {
105
- qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
106
+ qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
107
2, vms->memmap[VIRT_GIC_DIST].base,
108
2, vms->memmap[VIRT_GIC_DIST].size,
109
2, vms->memmap[VIRT_GIC_REDIST].base,
110
2, vms->memmap[VIRT_GIC_REDIST].size);
111
} else {
112
- qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
113
+ qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
114
2, vms->memmap[VIRT_GIC_DIST].base,
115
2, vms->memmap[VIRT_GIC_DIST].size,
116
2, vms->memmap[VIRT_GIC_REDIST].base,
117
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gic_node(VirtMachineState *vms)
118
}
119
120
if (vms->virt) {
121
- qemu_fdt_setprop_cells(vms->fdt, "/intc", "interrupts",
122
+ qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts",
123
GIC_FDT_IRQ_TYPE_PPI, ARCH_GICV3_MAINT_IRQ,
124
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
125
}
126
} else {
127
/* 'cortex-a15-gic' means 'GIC v2' */
128
- qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible",
129
+ qemu_fdt_setprop_string(vms->fdt, nodename, "compatible",
130
"arm,cortex-a15-gic");
131
- qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
132
+ qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg",
133
2, vms->memmap[VIRT_GIC_DIST].base,
134
2, vms->memmap[VIRT_GIC_DIST].size,
135
2, vms->memmap[VIRT_GIC_CPU].base,
136
2, vms->memmap[VIRT_GIC_CPU].size);
137
}
138
139
- qemu_fdt_setprop_cell(vms->fdt, "/intc", "phandle", vms->gic_phandle);
140
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->gic_phandle);
141
+ g_free(nodename);
142
}
143
144
static void fdt_add_pmu_nodes(const VirtMachineState *vms)
145
--
146
2.17.1
147
148
diff view generated by jsdifflib
Deleted patch
1
From: Eric Auger <eric.auger@redhat.com>
2
1
3
When running dtc on the guest /proc/device-tree we get the
4
following warning: Warning (unit_address_vs_reg): Node /memory
5
has a reg or ranges property, but no unit name".
6
7
Let's fix that by adding the unit address to the node name. We also
8
don't create the /memory node anymore in create_fdt(). We directly
9
create it in load_dtb. /chosen still needs to be created in create_fdt
10
as the uart needs it. In case the user provided his own dtb, we nop
11
all memory nodes found in root and create new one(s).
12
13
Signed-off-by: Eric Auger <eric.auger@redhat.com>
14
Message-id: 1530044492-24921-4-git-send-email-eric.auger@redhat.com
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/arm/boot.c | 41 +++++++++++++++++++++++------------------
19
hw/arm/virt.c | 7 +------
20
2 files changed, 24 insertions(+), 24 deletions(-)
21
22
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/arm/boot.c
25
+++ b/hw/arm/boot.c
26
@@ -XXX,XX +XXX,XX @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
27
hwaddr addr_limit, AddressSpace *as)
28
{
29
void *fdt = NULL;
30
- int size, rc;
31
+ int size, rc, n = 0;
32
uint32_t acells, scells;
33
char *nodename;
34
unsigned int i;
35
hwaddr mem_base, mem_len;
36
+ char **node_path;
37
+ Error *err = NULL;
38
39
if (binfo->dtb_filename) {
40
char *filename;
41
@@ -XXX,XX +XXX,XX @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
42
goto fail;
43
}
44
45
+ /* nop all root nodes matching /memory or /memory@unit-address */
46
+ node_path = qemu_fdt_node_unit_path(fdt, "memory", &err);
47
+ if (err) {
48
+ error_report_err(err);
49
+ goto fail;
50
+ }
51
+ while (node_path[n]) {
52
+ if (g_str_has_prefix(node_path[n], "/memory")) {
53
+ qemu_fdt_nop_node(fdt, node_path[n]);
54
+ }
55
+ n++;
56
+ }
57
+ g_strfreev(node_path);
58
+
59
if (nb_numa_nodes > 0) {
60
- /*
61
- * Turn the /memory node created before into a NOP node, then create
62
- * /memory@addr nodes for all numa nodes respectively.
63
- */
64
- qemu_fdt_nop_node(fdt, "/memory");
65
mem_base = binfo->loader_start;
66
for (i = 0; i < nb_numa_nodes; i++) {
67
mem_len = numa_info[i].node_mem;
68
@@ -XXX,XX +XXX,XX @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
69
g_free(nodename);
70
}
71
} else {
72
- Error *err = NULL;
73
+ nodename = g_strdup_printf("/memory@%" PRIx64, binfo->loader_start);
74
+ qemu_fdt_add_subnode(fdt, nodename);
75
+ qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
76
77
- rc = fdt_path_offset(fdt, "/memory");
78
- if (rc < 0) {
79
- qemu_fdt_add_subnode(fdt, "/memory");
80
- }
81
-
82
- if (!qemu_fdt_getprop(fdt, "/memory", "device_type", NULL, &err)) {
83
- qemu_fdt_setprop_string(fdt, "/memory", "device_type", "memory");
84
- }
85
-
86
- rc = qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg",
87
+ rc = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg",
88
acells, binfo->loader_start,
89
scells, binfo->ram_size);
90
if (rc < 0) {
91
- fprintf(stderr, "couldn't set /memory/reg\n");
92
+ fprintf(stderr, "couldn't set %s reg\n", nodename);
93
goto fail;
94
}
95
+ g_free(nodename);
96
}
97
98
rc = fdt_path_offset(fdt, "/chosen");
99
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/hw/arm/virt.c
102
+++ b/hw/arm/virt.c
103
@@ -XXX,XX +XXX,XX @@ static void create_fdt(VirtMachineState *vms)
104
qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
105
qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
106
107
- /*
108
- * /chosen and /memory nodes must exist for load_dtb
109
- * to fill in necessary properties later
110
- */
111
+ /* /chosen must exist for load_dtb to fill in necessary properties later */
112
qemu_fdt_add_subnode(fdt, "/chosen");
113
- qemu_fdt_add_subnode(fdt, "/memory");
114
- qemu_fdt_setprop_string(fdt, "/memory", "device_type", "memory");
115
116
/* Clock node, for the benefit of the UART. The kernel device tree
117
* binding documentation claims the PL011 node clock properties are
118
--
119
2.17.1
120
121
diff view generated by jsdifflib
1
From: Aaron Lindsay <alindsay@codeaurora.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Aaron Lindsay <alindsay@codeaurora.org>
3
Dump SVCR, plus use the correct access check for Streaming Mode.
4
Message-id: 1529699547-17044-5-git-send-email-alindsay@codeaurora.org
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220708151540.18136-2-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
---
9
---
7
target/arm/cpu.h | 1 +
10
target/arm/cpu.c | 17 ++++++++++++++++-
8
target/arm/cpu.c | 21 ++++++++++++++-------
11
1 file changed, 16 insertions(+), 1 deletion(-)
9
target/arm/kvm32.c | 8 ++++----
10
3 files changed, 19 insertions(+), 11 deletions(-)
11
12
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.h
15
+++ b/target/arm/cpu.h
16
@@ -XXX,XX +XXX,XX @@ enum arm_features {
17
ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */
18
ARM_FEATURE_THUMB2EE,
19
ARM_FEATURE_V7MP, /* v7 Multiprocessing Extensions */
20
+ ARM_FEATURE_V7VE, /* v7 Virtualization Extensions (non-EL2 parts) */
21
ARM_FEATURE_V4T,
22
ARM_FEATURE_V5,
23
ARM_FEATURE_STRONGARM,
24
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
25
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.c
15
--- a/target/arm/cpu.c
27
+++ b/target/arm/cpu.c
16
+++ b/target/arm/cpu.c
28
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
17
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
29
18
int i;
30
/* Some features automatically imply others: */
19
int el = arm_current_el(env);
31
if (arm_feature(env, ARM_FEATURE_V8)) {
20
const char *ns_status;
32
- set_feature(env, ARM_FEATURE_V7);
21
+ bool sve;
33
+ set_feature(env, ARM_FEATURE_V7VE);
22
23
qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
24
for (i = 0; i < 32; i++) {
25
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
26
el,
27
psr & PSTATE_SP ? 'h' : 't');
28
29
+ if (cpu_isar_feature(aa64_sme, cpu)) {
30
+ qemu_fprintf(f, " SVCR=%08" PRIx64 " %c%c",
31
+ env->svcr,
32
+ (FIELD_EX64(env->svcr, SVCR, ZA) ? 'Z' : '-'),
33
+ (FIELD_EX64(env->svcr, SVCR, SM) ? 'S' : '-'));
34
+ }
34
+ }
35
+ if (arm_feature(env, ARM_FEATURE_V7VE)) {
35
if (cpu_isar_feature(aa64_bti, cpu)) {
36
+ /* v7 Virtualization Extensions. In real hardware this implies
36
qemu_fprintf(f, " BTYPE=%d", (psr & PSTATE_BTYPE) >> 10);
37
+ * EL2 and also the presence of the Security Extensions.
38
+ * For QEMU, for backwards-compatibility we implement some
39
+ * CPUs or CPU configs which have no actual EL2 or EL3 but do
40
+ * include the various other features that V7VE implies.
41
+ * Presence of EL2 itself is ARM_FEATURE_EL2, and of the
42
+ * Security Extensions is ARM_FEATURE_EL3.
43
+ */
44
set_feature(env, ARM_FEATURE_ARM_DIV);
45
set_feature(env, ARM_FEATURE_LPAE);
46
+ set_feature(env, ARM_FEATURE_V7);
47
}
37
}
48
if (arm_feature(env, ARM_FEATURE_V7)) {
38
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
49
set_feature(env, ARM_FEATURE_VAPA);
39
qemu_fprintf(f, " FPCR=%08x FPSR=%08x\n",
50
@@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj)
40
vfp_get_fpcr(env), vfp_get_fpsr(env));
51
ARMCPU *cpu = ARM_CPU(obj);
41
52
42
- if (cpu_isar_feature(aa64_sve, cpu) && sve_exception_el(env, el) == 0) {
53
cpu->dtb_compatible = "arm,cortex-a7";
43
+ if (cpu_isar_feature(aa64_sme, cpu) && FIELD_EX64(env->svcr, SVCR, SM)) {
54
- set_feature(&cpu->env, ARM_FEATURE_V7);
44
+ sve = sme_exception_el(env, el) == 0;
55
+ set_feature(&cpu->env, ARM_FEATURE_V7VE);
45
+ } else if (cpu_isar_feature(aa64_sve, cpu)) {
56
set_feature(&cpu->env, ARM_FEATURE_VFP4);
46
+ sve = sve_exception_el(env, el) == 0;
57
set_feature(&cpu->env, ARM_FEATURE_NEON);
47
+ } else {
58
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
48
+ sve = false;
59
- set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
49
+ }
60
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
50
+
61
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
51
+ if (sve) {
62
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
52
int j, zcr_len = sve_vqm1_for_el(env, el);
63
- set_feature(&cpu->env, ARM_FEATURE_LPAE);
53
64
set_feature(&cpu->env, ARM_FEATURE_EL3);
54
for (i = 0; i <= FFR_PRED_NUM; i++) {
65
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
66
cpu->midr = 0x410fc075;
67
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
68
ARMCPU *cpu = ARM_CPU(obj);
69
70
cpu->dtb_compatible = "arm,cortex-a15";
71
- set_feature(&cpu->env, ARM_FEATURE_V7);
72
+ set_feature(&cpu->env, ARM_FEATURE_V7VE);
73
set_feature(&cpu->env, ARM_FEATURE_VFP4);
74
set_feature(&cpu->env, ARM_FEATURE_NEON);
75
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
76
- set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
77
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
78
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
79
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
80
- set_feature(&cpu->env, ARM_FEATURE_LPAE);
81
set_feature(&cpu->env, ARM_FEATURE_EL3);
82
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
83
cpu->midr = 0x412fc0f1;
84
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/kvm32.c
87
+++ b/target/arm/kvm32.c
88
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
89
/* Now we've retrieved all the register information we can
90
* set the feature bits based on the ID register fields.
91
* We can assume any KVM supporting CPU is at least a v7
92
- * with VFPv3, LPAE and the generic timers; this in turn implies
93
- * most of the other feature bits, but a few must be tested.
94
+ * with VFPv3, virtualization extensions, and the generic
95
+ * timers; this in turn implies most of the other feature
96
+ * bits, but a few must be tested.
97
*/
98
- set_feature(&features, ARM_FEATURE_V7);
99
+ set_feature(&features, ARM_FEATURE_V7VE);
100
set_feature(&features, ARM_FEATURE_VFP3);
101
- set_feature(&features, ARM_FEATURE_LPAE);
102
set_feature(&features, ARM_FEATURE_GENERIC_TIMER);
103
104
switch (extract32(id_isar0, 24, 4)) {
105
--
55
--
106
2.17.1
56
2.25.1
107
108
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Leave ARM_CP_SVE, removing ARM_CP_FPU; the sve_access_check
3
This includes the build rules for the decoder, and the
4
produced by the flag already includes fp_access_check. If
4
new file for translation, but excludes any instructions.
5
we also check ARM_CP_FPU the double fp_access_check asserts.
6
5
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20220708151540.18136-3-richard.henderson@linaro.org
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
12
Message-id: 20180629001538.11415-3-richard.henderson@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/helper.c | 8 ++++----
11
target/arm/translate-a64.h | 1 +
16
target/arm/translate-a64.c | 5 ++---
12
target/arm/sme.decode | 20 ++++++++++++++++++++
17
2 files changed, 6 insertions(+), 7 deletions(-)
13
target/arm/translate-a64.c | 7 ++++++-
14
target/arm/translate-sme.c | 35 +++++++++++++++++++++++++++++++++++
15
target/arm/meson.build | 2 ++
16
5 files changed, 64 insertions(+), 1 deletion(-)
17
create mode 100644 target/arm/sme.decode
18
create mode 100644 target/arm/translate-sme.c
18
19
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
20
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.c
22
--- a/target/arm/translate-a64.h
22
+++ b/target/arm/helper.c
23
+++ b/target/arm/translate-a64.h
23
@@ -XXX,XX +XXX,XX @@ static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
24
@@ -XXX,XX +XXX,XX @@ static inline int pred_gvec_reg_size(DisasContext *s)
24
static const ARMCPRegInfo zcr_el1_reginfo = {
25
}
25
.name = "ZCR_EL1", .state = ARM_CP_STATE_AA64,
26
26
.opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0,
27
bool disas_sve(DisasContext *, uint32_t);
27
- .access = PL1_RW, .type = ARM_CP_SVE | ARM_CP_FPU,
28
+bool disas_sme(DisasContext *, uint32_t);
28
+ .access = PL1_RW, .type = ARM_CP_SVE,
29
29
.fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]),
30
void gen_gvec_rax1(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
30
.writefn = zcr_write, .raw_writefn = raw_write
31
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
31
};
32
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
32
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo zcr_el1_reginfo = {
33
new file mode 100644
33
static const ARMCPRegInfo zcr_el2_reginfo = {
34
index XXXXXXX..XXXXXXX
34
.name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
35
--- /dev/null
35
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
36
+++ b/target/arm/sme.decode
36
- .access = PL2_RW, .type = ARM_CP_SVE | ARM_CP_FPU,
37
@@ -XXX,XX +XXX,XX @@
37
+ .access = PL2_RW, .type = ARM_CP_SVE,
38
+# AArch64 SME instruction descriptions
38
.fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]),
39
+#
39
.writefn = zcr_write, .raw_writefn = raw_write
40
+# Copyright (c) 2022 Linaro, Ltd
40
};
41
+#
41
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo zcr_el2_reginfo = {
42
+# This library is free software; you can redistribute it and/or
42
static const ARMCPRegInfo zcr_no_el2_reginfo = {
43
+# modify it under the terms of the GNU Lesser General Public
43
.name = "ZCR_EL2", .state = ARM_CP_STATE_AA64,
44
+# License as published by the Free Software Foundation; either
44
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0,
45
+# version 2.1 of the License, or (at your option) any later version.
45
- .access = PL2_RW, .type = ARM_CP_SVE | ARM_CP_FPU,
46
+#
46
+ .access = PL2_RW, .type = ARM_CP_SVE,
47
+# This library is distributed in the hope that it will be useful,
47
.readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore
48
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
48
};
49
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
49
50
+# Lesser General Public License for more details.
50
static const ARMCPRegInfo zcr_el3_reginfo = {
51
+#
51
.name = "ZCR_EL3", .state = ARM_CP_STATE_AA64,
52
+# You should have received a copy of the GNU Lesser General Public
52
.opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0,
53
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
53
- .access = PL3_RW, .type = ARM_CP_SVE | ARM_CP_FPU,
54
+
54
+ .access = PL3_RW, .type = ARM_CP_SVE,
55
+#
55
.fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]),
56
+# This file is processed by scripts/decodetree.py
56
.writefn = zcr_write, .raw_writefn = raw_write
57
+#
57
};
58
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
58
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
59
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/translate-a64.c
60
--- a/target/arm/translate-a64.c
61
+++ b/target/arm/translate-a64.c
61
+++ b/target/arm/translate-a64.c
62
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
62
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
63
default:
63
}
64
65
switch (extract32(insn, 25, 4)) {
66
- case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
67
+ case 0x0:
68
+ if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
69
+ unallocated_encoding(s);
70
+ }
71
+ break;
72
+ case 0x1: case 0x3: /* UNALLOCATED */
73
unallocated_encoding(s);
64
break;
74
break;
65
}
75
case 0x2:
66
- if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
76
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
67
- return;
77
new file mode 100644
68
- }
78
index XXXXXXX..XXXXXXX
69
if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
79
--- /dev/null
70
return;
80
+++ b/target/arm/translate-sme.c
71
+ } else if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
81
@@ -XXX,XX +XXX,XX @@
72
+ return;
82
+/*
73
}
83
+ * AArch64 SME translation
74
84
+ *
75
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
85
+ * Copyright (c) 2022 Linaro, Ltd
86
+ *
87
+ * This library is free software; you can redistribute it and/or
88
+ * modify it under the terms of the GNU Lesser General Public
89
+ * License as published by the Free Software Foundation; either
90
+ * version 2.1 of the License, or (at your option) any later version.
91
+ *
92
+ * This library is distributed in the hope that it will be useful,
93
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
94
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
95
+ * Lesser General Public License for more details.
96
+ *
97
+ * You should have received a copy of the GNU Lesser General Public
98
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
99
+ */
100
+
101
+#include "qemu/osdep.h"
102
+#include "cpu.h"
103
+#include "tcg/tcg-op.h"
104
+#include "tcg/tcg-op-gvec.h"
105
+#include "tcg/tcg-gvec-desc.h"
106
+#include "translate.h"
107
+#include "exec/helper-gen.h"
108
+#include "translate-a64.h"
109
+#include "fpu/softfloat.h"
110
+
111
+
112
+/*
113
+ * Include the generated decoder.
114
+ */
115
+
116
+#include "decode-sme.c.inc"
117
diff --git a/target/arm/meson.build b/target/arm/meson.build
118
index XXXXXXX..XXXXXXX 100644
119
--- a/target/arm/meson.build
120
+++ b/target/arm/meson.build
121
@@ -XXX,XX +XXX,XX @@
122
gen = [
123
decodetree.process('sve.decode', extra_args: '--decode=disas_sve'),
124
+ decodetree.process('sme.decode', extra_args: '--decode=disas_sme'),
125
decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'),
126
decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'),
127
decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'),
128
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
129
'sme_helper.c',
130
'translate-a64.c',
131
'translate-sve.c',
132
+ 'translate-sme.c',
133
))
134
135
arm_softmmu_ss = ss.source_set()
76
--
136
--
77
2.17.1
137
2.25.1
78
79
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We've already added the helpers with an SVE patch, all that remains
3
This new behaviour is in the ARM pseudocode function
4
is to wire up the aa64 and aa32 translators. Enable the feature
4
AArch64.CheckFPAdvSIMDEnabled, which applies to AArch32
5
within -cpu max for CONFIG_USER_ONLY.
5
via AArch32.CheckAdvSIMDOrFPEnabled when the EL to which
6
the trap would be delivered is in AArch64 mode.
7
8
Given that ARMv9 drops support for AArch32 outside EL0, the trap EL
9
detection ought to be trivially true, but the pseudocode still contains
10
a number of conditions, and QEMU has not yet committed to dropping A32
11
support for EL[12] when v9 features are present.
12
13
Since the computation of SME_TRAP_NONSTREAMING is necessarily different
14
for the two modes, we might as well preserve bits within TBFLAG_ANY and
15
allocate separate bits within TBFLAG_A32 and TBFLAG_A64 instead.
16
17
Note that DDI0616A.a has typos for bits [22:21] of LD1RO in the table
18
of instructions illegal in streaming mode.
6
19
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
21
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180627043328.11531-36-richard.henderson@linaro.org
22
Message-id: 20220708151540.18136-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
24
---
12
target/arm/cpu.h | 1 +
25
target/arm/cpu.h | 7 +++
13
linux-user/elfload.c | 1 +
26
target/arm/translate.h | 4 ++
14
target/arm/cpu.c | 1 +
27
target/arm/sme-fa64.decode | 90 ++++++++++++++++++++++++++++++++++++++
15
target/arm/cpu64.c | 1 +
28
target/arm/helper.c | 41 +++++++++++++++++
16
target/arm/translate-a64.c | 36 +++++++++++++++++++
29
target/arm/translate-a64.c | 40 ++++++++++++++++-
17
target/arm/translate.c | 74 +++++++++++++++++++++++++++-----------
30
target/arm/translate-vfp.c | 12 +++++
18
6 files changed, 93 insertions(+), 21 deletions(-)
31
target/arm/translate.c | 2 +
32
target/arm/meson.build | 1 +
33
8 files changed, 195 insertions(+), 2 deletions(-)
34
create mode 100644 target/arm/sme-fa64.decode
19
35
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
36
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
38
--- a/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
39
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@ enum arm_features {
40
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, HSTR_ACTIVE, 9, 1)
25
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
41
* the same thing as the current security state of the processor!
26
ARM_FEATURE_V8_ATOMICS, /* ARMv8.1-Atomics feature */
42
*/
27
ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
43
FIELD(TBFLAG_A32, NS, 10, 1)
28
+ ARM_FEATURE_V8_DOTPROD, /* implements v8.2 simd dot product */
44
+/*
29
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
45
+ * Indicates that SME Streaming mode is active, and SMCR_ELx.FA64 is not.
30
ARM_FEATURE_V8_FCMA, /* has complex number part of v8.3 extensions. */
46
+ * This requires an SME trap from AArch32 mode when using NEON.
31
ARM_FEATURE_M_MAIN, /* M profile Main Extension */
47
+ */
32
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
48
+FIELD(TBFLAG_A32, SME_TRAP_NONSTREAMING, 11, 1)
33
index XXXXXXX..XXXXXXX 100644
49
34
--- a/linux-user/elfload.c
50
/*
35
+++ b/linux-user/elfload.c
51
* Bit usage when in AArch32 state, for M-profile only.
36
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
52
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A64, SMEEXC_EL, 20, 2)
37
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
53
FIELD(TBFLAG_A64, PSTATE_SM, 22, 1)
38
GET_FEATURE(ARM_FEATURE_V8_ATOMICS, ARM_HWCAP_A64_ATOMICS);
54
FIELD(TBFLAG_A64, PSTATE_ZA, 23, 1)
39
GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
55
FIELD(TBFLAG_A64, SVL, 24, 4)
40
+ GET_FEATURE(ARM_FEATURE_V8_DOTPROD, ARM_HWCAP_A64_ASIMDDP);
56
+/* Indicates that SME Streaming mode is active, and SMCR_ELx.FA64 is not. */
41
GET_FEATURE(ARM_FEATURE_V8_FCMA, ARM_HWCAP_A64_FCMA);
57
+FIELD(TBFLAG_A64, SME_TRAP_NONSTREAMING, 28, 1)
42
GET_FEATURE(ARM_FEATURE_SVE, ARM_HWCAP_A64_SVE);
58
43
#undef GET_FEATURE
59
/*
44
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
60
* Helpers for using the above.
45
index XXXXXXX..XXXXXXX 100644
61
diff --git a/target/arm/translate.h b/target/arm/translate.h
46
--- a/target/arm/cpu.c
62
index XXXXXXX..XXXXXXX 100644
47
+++ b/target/arm/cpu.c
63
--- a/target/arm/translate.h
48
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
64
+++ b/target/arm/translate.h
49
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
65
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
50
set_feature(&cpu->env, ARM_FEATURE_CRC);
66
bool pstate_sm;
51
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
67
/* True if PSTATE.ZA is set. */
52
+ set_feature(&cpu->env, ARM_FEATURE_V8_DOTPROD);
68
bool pstate_za;
53
set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
69
+ /* True if non-streaming insns should raise an SME Streaming exception. */
54
#endif
70
+ bool sme_trap_nonstreaming;
55
}
71
+ /* True if the current instruction is non-streaming. */
56
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
72
+ bool is_nonstreaming;
57
index XXXXXXX..XXXXXXX 100644
73
/* True if MVE insns are definitely not predicated by VPR or LTPSIZE */
58
--- a/target/arm/cpu64.c
74
bool mve_no_pred;
59
+++ b/target/arm/cpu64.c
75
/*
60
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
76
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
61
set_feature(&cpu->env, ARM_FEATURE_CRC);
77
new file mode 100644
62
set_feature(&cpu->env, ARM_FEATURE_V8_ATOMICS);
78
index XXXXXXX..XXXXXXX
63
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
79
--- /dev/null
64
+ set_feature(&cpu->env, ARM_FEATURE_V8_DOTPROD);
80
+++ b/target/arm/sme-fa64.decode
65
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
81
@@ -XXX,XX +XXX,XX @@
66
set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
82
+# AArch64 SME allowed instruction decoding
67
set_feature(&cpu->env, ARM_FEATURE_SVE);
83
+#
84
+# Copyright (c) 2022 Linaro, Ltd
85
+#
86
+# This library is free software; you can redistribute it and/or
87
+# modify it under the terms of the GNU Lesser General Public
88
+# License as published by the Free Software Foundation; either
89
+# version 2.1 of the License, or (at your option) any later version.
90
+#
91
+# This library is distributed in the hope that it will be useful,
92
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
93
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
94
+# Lesser General Public License for more details.
95
+#
96
+# You should have received a copy of the GNU Lesser General Public
97
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
98
+
99
+#
100
+# This file is processed by scripts/decodetree.py
101
+#
102
+
103
+# These patterns are taken from Appendix E1.1 of DDI0616 A.a,
104
+# Arm Architecture Reference Manual Supplement,
105
+# The Scalable Matrix Extension (SME), for Armv9-A
106
+
107
+{
108
+ [
109
+ OK 0-00 1110 0000 0001 0010 11-- ---- ---- # SMOV W|Xd,Vn.B[0]
110
+ OK 0-00 1110 0000 0010 0010 11-- ---- ---- # SMOV W|Xd,Vn.H[0]
111
+ OK 0100 1110 0000 0100 0010 11-- ---- ---- # SMOV Xd,Vn.S[0]
112
+ OK 0000 1110 0000 0001 0011 11-- ---- ---- # UMOV Wd,Vn.B[0]
113
+ OK 0000 1110 0000 0010 0011 11-- ---- ---- # UMOV Wd,Vn.H[0]
114
+ OK 0000 1110 0000 0100 0011 11-- ---- ---- # UMOV Wd,Vn.S[0]
115
+ OK 0100 1110 0000 1000 0011 11-- ---- ---- # UMOV Xd,Vn.D[0]
116
+ ]
117
+ FAIL 0--0 111- ---- ---- ---- ---- ---- ---- # Advanced SIMD vector operations
118
+}
119
+
120
+{
121
+ [
122
+ OK 0101 1110 --1- ---- 11-1 11-- ---- ---- # FMULX/FRECPS/FRSQRTS (scalar)
123
+ OK 0101 1110 -10- ---- 00-1 11-- ---- ---- # FMULX/FRECPS/FRSQRTS (scalar, FP16)
124
+ OK 01-1 1110 1-10 0001 11-1 10-- ---- ---- # FRECPE/FRSQRTE/FRECPX (scalar)
125
+ OK 01-1 1110 1111 1001 11-1 10-- ---- ---- # FRECPE/FRSQRTE/FRECPX (scalar, FP16)
126
+ ]
127
+ FAIL 01-1 111- ---- ---- ---- ---- ---- ---- # Advanced SIMD single-element operations
128
+}
129
+
130
+FAIL 0-00 110- ---- ---- ---- ---- ---- ---- # Advanced SIMD structure load/store
131
+FAIL 1100 1110 ---- ---- ---- ---- ---- ---- # Advanced SIMD cryptography extensions
132
+FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
133
+
134
+# These are the "avoidance of doubt" final table of Illegal Advanced SIMD instructions
135
+# We don't actually need to include these, as the default is OK.
136
+# -001 111- ---- ---- ---- ---- ---- ---- # Scalar floating-point operations
137
+# --10 110- ---- ---- ---- ---- ---- ---- # Load/store pair of FP registers
138
+# --01 1100 ---- ---- ---- ---- ---- ---- # Load FP register (PC-relative literal)
139
+# --11 1100 --0- ---- ---- ---- ---- ---- # Load/store FP register (unscaled imm)
140
+# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
141
+# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
142
+
143
+FAIL 0000 0100 --1- ---- 1010 ---- ---- ---- # ADR
144
+FAIL 0000 0100 --1- ---- 1011 -0-- ---- ---- # FTSSEL, FEXPA
145
+FAIL 0000 0101 --10 0001 100- ---- ---- ---- # COMPACT
146
+FAIL 0010 0101 --01 100- 1111 000- ---0 ---- # RDFFR, RDFFRS
147
+FAIL 0010 0101 --10 1--- 1001 ---- ---- ---- # WRFFR, SETFFR
148
+FAIL 0100 0101 --0- ---- 1011 ---- ---- ---- # BDEP, BEXT, BGRP
149
+FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
150
+FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
151
+FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
152
+FAIL 0110 0101 --01 0--- 100- ---- ---- ---- # FTMAD
153
+FAIL 0110 0101 --01 1--- 001- ---- ---- ---- # FADDA
154
+FAIL 0100 0101 --0- ---- 1001 10-- ---- ---- # SMMLA, UMMLA, USMMLA
155
+FAIL 0100 0101 --1- ---- 1--- ---- ---- ---- # SVE2 string/histo/crypto instructions
156
+FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
157
+FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
158
+FAIL 1000 0100 0-1- ---- 0--- ---- ---- ---- # SVE 32-bit gather prefetch (scalar+vector)
159
+FAIL 1000 010- -01- ---- 1--- ---- ---- ---- # SVE 32-bit gather load (vector+imm)
160
+FAIL 1000 0100 0-0- ---- 0--- ---- ---- ---- # SVE 32-bit gather load byte (scalar+vector)
161
+FAIL 1000 0100 1--- ---- 0--- ---- ---- ---- # SVE 32-bit gather load half (scalar+vector)
162
+FAIL 1000 0101 0--- ---- 0--- ---- ---- ---- # SVE 32-bit gather load word (scalar+vector)
163
+FAIL 1010 010- ---- ---- 011- ---- ---- ---- # SVE contiguous FF load (scalar+scalar)
164
+FAIL 1010 010- ---1 ---- 101- ---- ---- ---- # SVE contiguous NF load (scalar+imm)
165
+FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
166
+FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
167
+FAIL 1100 010- ---- ---- ---- ---- ---- ---- # SVE 64-bit gather load/prefetch
168
+FAIL 1110 010- -00- ---- 001- ---- ---- ---- # SVE2 64-bit scatter NT store (vector+scalar)
169
+FAIL 1110 010- -10- ---- 001- ---- ---- ---- # SVE2 32-bit scatter NT store (vector+scalar)
170
+FAIL 1110 010- ---- ---- 1-0- ---- ---- ---- # SVE scatter store (scalar+32-bit vector)
171
+FAIL 1110 010- ---- ---- 101- ---- ---- ---- # SVE scatter store (misc)
172
diff --git a/target/arm/helper.c b/target/arm/helper.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/target/arm/helper.c
175
+++ b/target/arm/helper.c
176
@@ -XXX,XX +XXX,XX @@ int sme_exception_el(CPUARMState *env, int el)
177
return 0;
178
}
179
180
+/* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */
181
+static bool sme_fa64(CPUARMState *env, int el)
182
+{
183
+ if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) {
184
+ return false;
185
+ }
186
+
187
+ if (el <= 1 && !el_is_in_host(env, el)) {
188
+ if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) {
189
+ return false;
190
+ }
191
+ }
192
+ if (el <= 2 && arm_is_el2_enabled(env)) {
193
+ if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) {
194
+ return false;
195
+ }
196
+ }
197
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
198
+ if (!FIELD_EX64(env->vfp.smcr_el[3], SMCR, FA64)) {
199
+ return false;
200
+ }
201
+ }
202
+
203
+ return true;
204
+}
205
+
206
/*
207
* Given that SVE is enabled, return the vector length for EL.
208
*/
209
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
210
DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
211
}
212
213
+ /*
214
+ * The SME exception we are testing for is raised via
215
+ * AArch64.CheckFPAdvSIMDEnabled(), as called from
216
+ * AArch32.CheckAdvSIMDOrFPEnabled().
217
+ */
218
+ if (el == 0
219
+ && FIELD_EX64(env->svcr, SVCR, SM)
220
+ && (!arm_is_el2_enabled(env)
221
+ || (arm_el_is_aa64(env, 2) && !(env->cp15.hcr_el2 & HCR_TGE)))
222
+ && arm_el_is_aa64(env, 1)
223
+ && !sme_fa64(env, el)) {
224
+ DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1);
225
+ }
226
+
227
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
228
}
229
230
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
231
}
232
if (FIELD_EX64(env->svcr, SVCR, SM)) {
233
DP_TBFLAG_A64(flags, PSTATE_SM, 1);
234
+ DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el));
235
}
236
DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA));
237
}
68
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
238
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
69
index XXXXXXX..XXXXXXX 100644
239
index XXXXXXX..XXXXXXX 100644
70
--- a/target/arm/translate-a64.c
240
--- a/target/arm/translate-a64.c
71
+++ b/target/arm/translate-a64.c
241
+++ b/target/arm/translate-a64.c
72
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
242
@@ -XXX,XX +XXX,XX @@ static void do_vec_ld(DisasContext *s, int destidx, int element,
73
vec_full_reg_size(s), gvec_op);
243
* unallocated-encoding checks (otherwise the syndrome information
244
* for the resulting exception will be incorrect).
245
*/
246
-static bool fp_access_check(DisasContext *s)
247
+static bool fp_access_check_only(DisasContext *s)
248
{
249
if (s->fp_excp_el) {
250
assert(!s->fp_access_checked);
251
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check(DisasContext *s)
252
return true;
74
}
253
}
75
254
76
+/* Expand a 3-operand operation using an out-of-line helper. */
255
+static bool fp_access_check(DisasContext *s)
77
+static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd,
256
+{
78
+ int rn, int rm, int data, gen_helper_gvec_3 *fn)
257
+ if (!fp_access_check_only(s)) {
79
+{
258
+ return false;
80
+ tcg_gen_gvec_3_ool(vec_full_reg_offset(s, rd),
259
+ }
81
+ vec_full_reg_offset(s, rn),
260
+ if (s->sme_trap_nonstreaming && s->is_nonstreaming) {
82
+ vec_full_reg_offset(s, rm),
261
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
83
+ is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
262
+ syn_smetrap(SME_ET_Streaming, false));
84
+}
263
+ return false;
85
+
264
+ }
86
/* Expand a 3-operand + env pointer operation using
265
+ return true;
87
* an out-of-line helper.
266
+}
267
+
268
/* Check that SVE access is enabled. If it is, return true.
269
* If not, emit code to generate an appropriate exception and return false.
88
*/
270
*/
89
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
271
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
272
default:
273
g_assert_not_reached();
274
}
275
- if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
276
+ if ((ri->type & ARM_CP_FPU) && !fp_access_check_only(s)) {
277
return;
278
} else if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
279
return;
280
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
281
}
282
}
283
284
+/*
285
+ * Include the generated SME FA64 decoder.
286
+ */
287
+
288
+#include "decode-sme-fa64.c.inc"
289
+
290
+static bool trans_OK(DisasContext *s, arg_OK *a)
291
+{
292
+ return true;
293
+}
294
+
295
+static bool trans_FAIL(DisasContext *s, arg_OK *a)
296
+{
297
+ s->is_nonstreaming = true;
298
+ return true;
299
+}
300
+
301
/**
302
* is_guarded_page:
303
* @env: The cpu environment
304
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
305
dc->mte_active[1] = EX_TBFLAG_A64(tb_flags, MTE0_ACTIVE);
306
dc->pstate_sm = EX_TBFLAG_A64(tb_flags, PSTATE_SM);
307
dc->pstate_za = EX_TBFLAG_A64(tb_flags, PSTATE_ZA);
308
+ dc->sme_trap_nonstreaming = EX_TBFLAG_A64(tb_flags, SME_TRAP_NONSTREAMING);
309
dc->vec_len = 0;
310
dc->vec_stride = 0;
311
dc->cp_regs = arm_cpu->cp_regs;
312
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
90
}
313
}
91
feature = ARM_FEATURE_V8_RDM;
314
}
92
break;
315
93
+ case 0x02: /* SDOT (vector) */
316
+ s->is_nonstreaming = false;
94
+ case 0x12: /* UDOT (vector) */
317
+ if (s->sme_trap_nonstreaming) {
95
+ if (size != MO_32) {
318
+ disas_sme_fa64(s, insn);
96
+ unallocated_encoding(s);
319
+ }
97
+ return;
320
+
98
+ }
321
switch (extract32(insn, 25, 4)) {
99
+ feature = ARM_FEATURE_V8_DOTPROD;
322
case 0x0:
100
+ break;
323
if (!extract32(insn, 31, 1) || !disas_sme(s, insn)) {
101
case 0x8: /* FCMLA, #0 */
324
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
102
case 0x9: /* FCMLA, #90 */
325
index XXXXXXX..XXXXXXX 100644
103
case 0xa: /* FCMLA, #180 */
326
--- a/target/arm/translate-vfp.c
104
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
327
+++ b/target/arm/translate-vfp.c
105
}
328
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
106
return;
329
return false;
107
330
}
108
+ case 0x2: /* SDOT / UDOT */
331
109
+ gen_gvec_op3_ool(s, is_q, rd, rn, rm, 0,
332
+ /*
110
+ u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b);
333
+ * Note that rebuild_hflags_a32 has already accounted for being in EL0
111
+ return;
334
+ * and the higher EL in A64 mode, etc. Unlike A64 mode, there do not
112
+
335
+ * appear to be any insns which touch VFP which are allowed.
113
case 0x8: /* FCMLA, #0 */
336
+ */
114
case 0x9: /* FCMLA, #90 */
337
+ if (s->sme_trap_nonstreaming) {
115
case 0xa: /* FCMLA, #180 */
338
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
116
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
339
+ syn_smetrap(SME_ET_Streaming,
117
return;
340
+ s->base.pc_next - s->pc_curr == 2));
118
}
341
+ return false;
119
break;
342
+ }
120
+ case 0x0e: /* SDOT */
343
+
121
+ case 0x1e: /* UDOT */
344
if (!s->vfp_enabled && !ignore_vfp_enabled) {
122
+ if (size != MO_32 || !arm_dc_feature(s, ARM_FEATURE_V8_DOTPROD)) {
345
assert(!arm_dc_feature(s, ARM_FEATURE_M));
123
+ unallocated_encoding(s);
346
unallocated_encoding(s);
124
+ return;
125
+ }
126
+ break;
127
case 0x11: /* FCMLA #0 */
128
case 0x13: /* FCMLA #90 */
129
case 0x15: /* FCMLA #180 */
130
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
131
}
132
133
switch (16 * u + opcode) {
134
+ case 0x0e: /* SDOT */
135
+ case 0x1e: /* UDOT */
136
+ gen_gvec_op3_ool(s, is_q, rd, rn, rm, index,
137
+ u ? gen_helper_gvec_udot_idx_b
138
+ : gen_helper_gvec_sdot_idx_b);
139
+ return;
140
case 0x11: /* FCMLA #0 */
141
case 0x13: /* FCMLA #90 */
142
case 0x15: /* FCMLA #180 */
143
diff --git a/target/arm/translate.c b/target/arm/translate.c
347
diff --git a/target/arm/translate.c b/target/arm/translate.c
144
index XXXXXXX..XXXXXXX 100644
348
index XXXXXXX..XXXXXXX 100644
145
--- a/target/arm/translate.c
349
--- a/target/arm/translate.c
146
+++ b/target/arm/translate.c
350
+++ b/target/arm/translate.c
147
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
351
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
148
*/
352
dc->vec_len = EX_TBFLAG_A32(tb_flags, VECLEN);
149
static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
353
dc->vec_stride = EX_TBFLAG_A32(tb_flags, VECSTRIDE);
150
{
151
- gen_helper_gvec_3_ptr *fn_gvec_ptr;
152
- int rd, rn, rm, rot, size, opr_sz;
153
- TCGv_ptr fpst;
154
+ gen_helper_gvec_3 *fn_gvec = NULL;
155
+ gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
156
+ int rd, rn, rm, opr_sz;
157
+ int data = 0;
158
bool q;
159
160
q = extract32(insn, 6, 1);
161
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
162
163
if ((insn & 0xfe200f10) == 0xfc200800) {
164
/* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
165
- size = extract32(insn, 20, 1);
166
- rot = extract32(insn, 23, 2);
167
+ int size = extract32(insn, 20, 1);
168
+ data = extract32(insn, 23, 2); /* rot */
169
if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
170
|| (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
171
return 1;
172
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
173
fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
174
} else if ((insn & 0xfea00f10) == 0xfc800800) {
175
/* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
176
- size = extract32(insn, 20, 1);
177
- rot = extract32(insn, 24, 1);
178
+ int size = extract32(insn, 20, 1);
179
+ data = extract32(insn, 24, 1); /* rot */
180
if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
181
|| (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
182
return 1;
183
}
354
}
184
fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
355
+ dc->sme_trap_nonstreaming =
185
+ } else if ((insn & 0xfeb00f00) == 0xfc200d00) {
356
+ EX_TBFLAG_A32(tb_flags, SME_TRAP_NONSTREAMING);
186
+ /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
357
}
187
+ bool u = extract32(insn, 4, 1);
358
dc->cp_regs = cpu->cp_regs;
188
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_DOTPROD)) {
359
dc->features = env->features;
189
+ return 1;
360
diff --git a/target/arm/meson.build b/target/arm/meson.build
190
+ }
361
index XXXXXXX..XXXXXXX 100644
191
+ fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
362
--- a/target/arm/meson.build
192
} else {
363
+++ b/target/arm/meson.build
193
return 1;
364
@@ -XXX,XX +XXX,XX @@
194
}
365
gen = [
195
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
366
decodetree.process('sve.decode', extra_args: '--decode=disas_sve'),
196
}
367
decodetree.process('sme.decode', extra_args: '--decode=disas_sme'),
197
368
+ decodetree.process('sme-fa64.decode', extra_args: '--static-decode=disas_sme_fa64'),
198
opr_sz = (1 + q) * 8;
369
decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'),
199
- fpst = get_fpstatus_ptr(1);
370
decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'),
200
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
371
decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'),
201
- vfp_reg_offset(1, rn),
202
- vfp_reg_offset(1, rm), fpst,
203
- opr_sz, opr_sz, rot, fn_gvec_ptr);
204
- tcg_temp_free_ptr(fpst);
205
+ if (fn_gvec_ptr) {
206
+ TCGv_ptr fpst = get_fpstatus_ptr(1);
207
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
208
+ vfp_reg_offset(1, rn),
209
+ vfp_reg_offset(1, rm), fpst,
210
+ opr_sz, opr_sz, data, fn_gvec_ptr);
211
+ tcg_temp_free_ptr(fpst);
212
+ } else {
213
+ tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
214
+ vfp_reg_offset(1, rn),
215
+ vfp_reg_offset(1, rm),
216
+ opr_sz, opr_sz, data, fn_gvec);
217
+ }
218
return 0;
219
}
220
221
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
222
223
static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
224
{
225
- gen_helper_gvec_3_ptr *fn_gvec_ptr;
226
+ gen_helper_gvec_3 *fn_gvec = NULL;
227
+ gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
228
int rd, rn, rm, opr_sz, data;
229
- TCGv_ptr fpst;
230
bool q;
231
232
q = extract32(insn, 6, 1);
233
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
234
data = (index << 2) | rot;
235
fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
236
: gen_helper_gvec_fcmlah_idx);
237
+ } else if ((insn & 0xffb00f00) == 0xfe200d00) {
238
+ /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
239
+ int u = extract32(insn, 4, 1);
240
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_DOTPROD)) {
241
+ return 1;
242
+ }
243
+ fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
244
+ /* rm is just Vm, and index is M. */
245
+ data = extract32(insn, 5, 1); /* index */
246
+ rm = extract32(insn, 0, 4);
247
} else {
248
return 1;
249
}
250
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
251
}
252
253
opr_sz = (1 + q) * 8;
254
- fpst = get_fpstatus_ptr(1);
255
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
256
- vfp_reg_offset(1, rn),
257
- vfp_reg_offset(1, rm), fpst,
258
- opr_sz, opr_sz, data, fn_gvec_ptr);
259
- tcg_temp_free_ptr(fpst);
260
+ if (fn_gvec_ptr) {
261
+ TCGv_ptr fpst = get_fpstatus_ptr(1);
262
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
263
+ vfp_reg_offset(1, rn),
264
+ vfp_reg_offset(1, rm), fpst,
265
+ opr_sz, opr_sz, data, fn_gvec_ptr);
266
+ tcg_temp_free_ptr(fpst);
267
+ } else {
268
+ tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
269
+ vfp_reg_offset(1, rn),
270
+ vfp_reg_offset(1, rm),
271
+ opr_sz, opr_sz, data, fn_gvec);
272
+ }
273
return 0;
274
}
275
276
--
372
--
277
2.17.1
373
2.25.1
278
279
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Mark ADR as a non-streaming instruction, which should trap
4
if full a64 support is not enabled in streaming mode.
5
6
Removing entries from sme-fa64.decode is an easy way to see
7
what remains to be done.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20220708151540.18136-5-richard.henderson@linaro.org
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 20180627043328.11531-34-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
13
---
9
target/arm/helper.h | 5 ++
14
target/arm/translate.h | 7 +++++++
10
target/arm/translate-sve.c | 18 ++++++
15
target/arm/sme-fa64.decode | 1 -
11
target/arm/vec_helper.c | 124 +++++++++++++++++++++++++++++++++++++
16
target/arm/translate-sve.c | 8 ++++----
12
target/arm/sve.decode | 6 ++
17
3 files changed, 11 insertions(+), 5 deletions(-)
13
4 files changed, 153 insertions(+)
14
18
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
19
diff --git a/target/arm/translate.h b/target/arm/translate.h
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
21
--- a/target/arm/translate.h
18
+++ b/target/arm/helper.h
22
+++ b/target/arm/translate.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_udot_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
@@ -XXX,XX +XXX,XX @@ uint64_t asimd_imm_const(uint32_t imm, int cmode, int op);
20
DEF_HELPER_FLAGS_4(gvec_sdot_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
21
DEF_HELPER_FLAGS_4(gvec_udot_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
{ return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); }
22
26
23
+DEF_HELPER_FLAGS_4(gvec_sdot_idx_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
+#define TRANS_FEAT_NONSTREAMING(NAME, FEAT, FUNC, ...) \
24
+DEF_HELPER_FLAGS_4(gvec_udot_idx_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
+ static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
25
+DEF_HELPER_FLAGS_4(gvec_sdot_idx_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
+ { \
26
+DEF_HELPER_FLAGS_4(gvec_udot_idx_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
30
+ s->is_nonstreaming = true; \
31
+ return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); \
32
+ }
27
+
33
+
28
DEF_HELPER_FLAGS_5(gvec_fcaddh, TCG_CALL_NO_RWG,
34
#endif /* TARGET_ARM_TRANSLATE_H */
29
void, ptr, ptr, ptr, ptr, i32)
35
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
30
DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/sme-fa64.decode
38
+++ b/target/arm/sme-fa64.decode
39
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
40
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
41
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
42
43
-FAIL 0000 0100 --1- ---- 1010 ---- ---- ---- # ADR
44
FAIL 0000 0100 --1- ---- 1011 -0-- ---- ---- # FTSSEL, FEXPA
45
FAIL 0000 0101 --10 0001 100- ---- ---- ---- # COMPACT
46
FAIL 0010 0101 --01 100- 1111 000- ---0 ---- # RDFFR, RDFFRS
31
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
47
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
32
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-sve.c
49
--- a/target/arm/translate-sve.c
34
+++ b/target/arm/translate-sve.c
50
+++ b/target/arm/translate-sve.c
35
@@ -XXX,XX +XXX,XX @@ static bool trans_DOT_zzz(DisasContext *s, arg_DOT_zzz *a, uint32_t insn)
51
@@ -XXX,XX +XXX,XX @@ static bool do_adr(DisasContext *s, arg_rrri *a, gen_helper_gvec_3 *fn)
36
return true;
52
return gen_gvec_ool_zzz(s, fn, a->rd, a->rn, a->rm, a->imm);
37
}
53
}
38
54
39
+static bool trans_DOT_zzx(DisasContext *s, arg_DOT_zzx *a, uint32_t insn)
55
-TRANS_FEAT(ADR_p32, aa64_sve, do_adr, a, gen_helper_sve_adr_p32)
40
+{
56
-TRANS_FEAT(ADR_p64, aa64_sve, do_adr, a, gen_helper_sve_adr_p64)
41
+ static gen_helper_gvec_3 * const fns[2][2] = {
57
-TRANS_FEAT(ADR_s32, aa64_sve, do_adr, a, gen_helper_sve_adr_s32)
42
+ { gen_helper_gvec_sdot_idx_b, gen_helper_gvec_sdot_idx_h },
58
-TRANS_FEAT(ADR_u32, aa64_sve, do_adr, a, gen_helper_sve_adr_u32)
43
+ { gen_helper_gvec_udot_idx_b, gen_helper_gvec_udot_idx_h }
59
+TRANS_FEAT_NONSTREAMING(ADR_p32, aa64_sve, do_adr, a, gen_helper_sve_adr_p32)
44
+ };
60
+TRANS_FEAT_NONSTREAMING(ADR_p64, aa64_sve, do_adr, a, gen_helper_sve_adr_p64)
45
+
61
+TRANS_FEAT_NONSTREAMING(ADR_s32, aa64_sve, do_adr, a, gen_helper_sve_adr_s32)
46
+ if (sve_access_check(s)) {
62
+TRANS_FEAT_NONSTREAMING(ADR_u32, aa64_sve, do_adr, a, gen_helper_sve_adr_u32)
47
+ unsigned vsz = vec_full_reg_size(s);
63
48
+ tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd),
49
+ vec_full_reg_offset(s, a->rn),
50
+ vec_full_reg_offset(s, a->rm),
51
+ vsz, vsz, a->index, fns[a->u][a->sz]);
52
+ }
53
+ return true;
54
+}
55
+
56
+
57
/*
64
/*
58
*** SVE Floating Point Multiply-Add Indexed Group
65
*** SVE Integer Misc - Unpredicated Group
59
*/
60
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/vec_helper.c
63
+++ b/target/arm/vec_helper.c
64
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_udot_h)(void *vd, void *vn, void *vm, uint32_t desc)
65
clear_tail(d, opr_sz, simd_maxsz(desc));
66
}
67
68
+void HELPER(gvec_sdot_idx_b)(void *vd, void *vn, void *vm, uint32_t desc)
69
+{
70
+ intptr_t i, segend, opr_sz = simd_oprsz(desc), opr_sz_4 = opr_sz / 4;
71
+ intptr_t index = simd_data(desc);
72
+ uint32_t *d = vd;
73
+ int8_t *n = vn;
74
+ int8_t *m_indexed = (int8_t *)vm + index * 4;
75
+
76
+ /* Notice the special case of opr_sz == 8, from aa64/aa32 advsimd.
77
+ * Otherwise opr_sz is a multiple of 16.
78
+ */
79
+ segend = MIN(4, opr_sz_4);
80
+ i = 0;
81
+ do {
82
+ int8_t m0 = m_indexed[i * 4 + 0];
83
+ int8_t m1 = m_indexed[i * 4 + 1];
84
+ int8_t m2 = m_indexed[i * 4 + 2];
85
+ int8_t m3 = m_indexed[i * 4 + 3];
86
+
87
+ do {
88
+ d[i] += n[i * 4 + 0] * m0
89
+ + n[i * 4 + 1] * m1
90
+ + n[i * 4 + 2] * m2
91
+ + n[i * 4 + 3] * m3;
92
+ } while (++i < segend);
93
+ segend = i + 4;
94
+ } while (i < opr_sz_4);
95
+
96
+ clear_tail(d, opr_sz, simd_maxsz(desc));
97
+}
98
+
99
+void HELPER(gvec_udot_idx_b)(void *vd, void *vn, void *vm, uint32_t desc)
100
+{
101
+ intptr_t i, segend, opr_sz = simd_oprsz(desc), opr_sz_4 = opr_sz / 4;
102
+ intptr_t index = simd_data(desc);
103
+ uint32_t *d = vd;
104
+ uint8_t *n = vn;
105
+ uint8_t *m_indexed = (uint8_t *)vm + index * 4;
106
+
107
+ /* Notice the special case of opr_sz == 8, from aa64/aa32 advsimd.
108
+ * Otherwise opr_sz is a multiple of 16.
109
+ */
110
+ segend = MIN(4, opr_sz_4);
111
+ i = 0;
112
+ do {
113
+ uint8_t m0 = m_indexed[i * 4 + 0];
114
+ uint8_t m1 = m_indexed[i * 4 + 1];
115
+ uint8_t m2 = m_indexed[i * 4 + 2];
116
+ uint8_t m3 = m_indexed[i * 4 + 3];
117
+
118
+ do {
119
+ d[i] += n[i * 4 + 0] * m0
120
+ + n[i * 4 + 1] * m1
121
+ + n[i * 4 + 2] * m2
122
+ + n[i * 4 + 3] * m3;
123
+ } while (++i < segend);
124
+ segend = i + 4;
125
+ } while (i < opr_sz_4);
126
+
127
+ clear_tail(d, opr_sz, simd_maxsz(desc));
128
+}
129
+
130
+void HELPER(gvec_sdot_idx_h)(void *vd, void *vn, void *vm, uint32_t desc)
131
+{
132
+ intptr_t i, opr_sz = simd_oprsz(desc), opr_sz_8 = opr_sz / 8;
133
+ intptr_t index = simd_data(desc);
134
+ uint64_t *d = vd;
135
+ int16_t *n = vn;
136
+ int16_t *m_indexed = (int16_t *)vm + index * 4;
137
+
138
+ /* This is supported by SVE only, so opr_sz is always a multiple of 16.
139
+ * Process the entire segment all at once, writing back the results
140
+ * only after we've consumed all of the inputs.
141
+ */
142
+ for (i = 0; i < opr_sz_8 ; i += 2) {
143
+ uint64_t d0, d1;
144
+
145
+ d0 = n[i * 4 + 0] * (int64_t)m_indexed[i * 4 + 0];
146
+ d0 += n[i * 4 + 1] * (int64_t)m_indexed[i * 4 + 1];
147
+ d0 += n[i * 4 + 2] * (int64_t)m_indexed[i * 4 + 2];
148
+ d0 += n[i * 4 + 3] * (int64_t)m_indexed[i * 4 + 3];
149
+ d1 = n[i * 4 + 4] * (int64_t)m_indexed[i * 4 + 0];
150
+ d1 += n[i * 4 + 5] * (int64_t)m_indexed[i * 4 + 1];
151
+ d1 += n[i * 4 + 6] * (int64_t)m_indexed[i * 4 + 2];
152
+ d1 += n[i * 4 + 7] * (int64_t)m_indexed[i * 4 + 3];
153
+
154
+ d[i + 0] += d0;
155
+ d[i + 1] += d1;
156
+ }
157
+
158
+ clear_tail(d, opr_sz, simd_maxsz(desc));
159
+}
160
+
161
+void HELPER(gvec_udot_idx_h)(void *vd, void *vn, void *vm, uint32_t desc)
162
+{
163
+ intptr_t i, opr_sz = simd_oprsz(desc), opr_sz_8 = opr_sz / 8;
164
+ intptr_t index = simd_data(desc);
165
+ uint64_t *d = vd;
166
+ uint16_t *n = vn;
167
+ uint16_t *m_indexed = (uint16_t *)vm + index * 4;
168
+
169
+ /* This is supported by SVE only, so opr_sz is always a multiple of 16.
170
+ * Process the entire segment all at once, writing back the results
171
+ * only after we've consumed all of the inputs.
172
+ */
173
+ for (i = 0; i < opr_sz_8 ; i += 2) {
174
+ uint64_t d0, d1;
175
+
176
+ d0 = n[i * 4 + 0] * (uint64_t)m_indexed[i * 4 + 0];
177
+ d0 += n[i * 4 + 1] * (uint64_t)m_indexed[i * 4 + 1];
178
+ d0 += n[i * 4 + 2] * (uint64_t)m_indexed[i * 4 + 2];
179
+ d0 += n[i * 4 + 3] * (uint64_t)m_indexed[i * 4 + 3];
180
+ d1 = n[i * 4 + 4] * (uint64_t)m_indexed[i * 4 + 0];
181
+ d1 += n[i * 4 + 5] * (uint64_t)m_indexed[i * 4 + 1];
182
+ d1 += n[i * 4 + 6] * (uint64_t)m_indexed[i * 4 + 2];
183
+ d1 += n[i * 4 + 7] * (uint64_t)m_indexed[i * 4 + 3];
184
+
185
+ d[i + 0] += d0;
186
+ d[i + 1] += d1;
187
+ }
188
+
189
+ clear_tail(d, opr_sz, simd_maxsz(desc));
190
+}
191
+
192
void HELPER(gvec_fcaddh)(void *vd, void *vn, void *vm,
193
void *vfpst, uint32_t desc)
194
{
195
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
196
index XXXXXXX..XXXXXXX 100644
197
--- a/target/arm/sve.decode
198
+++ b/target/arm/sve.decode
199
@@ -XXX,XX +XXX,XX @@ MUL_zzi 00100101 .. 110 000 110 ........ ..... @rdn_i8s
200
# SVE integer dot product (unpredicated)
201
DOT_zzz 01000100 1 sz:1 0 rm:5 00000 u:1 rn:5 rd:5 ra=%reg_movprfx
202
203
+# SVE integer dot product (indexed)
204
+DOT_zzx 01000100 101 index:2 rm:3 00000 u:1 rn:5 rd:5 \
205
+ sz=0 ra=%reg_movprfx
206
+DOT_zzx 01000100 111 index:1 rm:4 00000 u:1 rn:5 rd:5 \
207
+ sz=1 ra=%reg_movprfx
208
+
209
# SVE floating-point complex add (predicated)
210
FCADD 01100100 esz:2 00000 rot:1 100 pg:3 rm:5 rd:5 \
211
rn=%reg_movprfx
212
--
66
--
213
2.17.1
67
2.25.1
214
215
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-33-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-6-richard.henderson@linaro.org
6
[PMM: moved 'ra=%reg_movprfx' here from following patch]
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
target/arm/helper.h | 5 +++
11
target/arm/sme-fa64.decode | 2 --
10
target/arm/translate-sve.c | 17 ++++++++++
12
target/arm/translate-sve.c | 9 ++++++---
11
target/arm/vec_helper.c | 67 ++++++++++++++++++++++++++++++++++++++
13
2 files changed, 6 insertions(+), 5 deletions(-)
12
target/arm/sve.decode | 3 ++
13
4 files changed, 92 insertions(+)
14
14
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/helper.h
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
20
21
void, ptr, ptr, ptr, ptr, i32)
21
FAIL 0000 0100 --1- ---- 1011 -0-- ---- ---- # FTSSEL, FEXPA
22
22
FAIL 0000 0101 --10 0001 100- ---- ---- ---- # COMPACT
23
+DEF_HELPER_FLAGS_4(gvec_sdot_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
-FAIL 0010 0101 --01 100- 1111 000- ---0 ---- # RDFFR, RDFFRS
24
+DEF_HELPER_FLAGS_4(gvec_udot_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
-FAIL 0010 0101 --10 1--- 1001 ---- ---- ---- # WRFFR, SETFFR
25
+DEF_HELPER_FLAGS_4(gvec_sdot_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
FAIL 0100 0101 --0- ---- 1011 ---- ---- ---- # BDEP, BEXT, BGRP
26
+DEF_HELPER_FLAGS_4(gvec_udot_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
27
+
27
FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
28
DEF_HELPER_FLAGS_5(gvec_fcaddh, TCG_CALL_NO_RWG,
29
void, ptr, ptr, ptr, ptr, i32)
30
DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
31
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
28
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
32
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-sve.c
30
--- a/target/arm/translate-sve.c
34
+++ b/target/arm/translate-sve.c
31
+++ b/target/arm/translate-sve.c
35
@@ -XXX,XX +XXX,XX @@ DO_ZZI(UMIN, umin)
32
@@ -XXX,XX +XXX,XX @@ static bool do_predset(DisasContext *s, int esz, int rd, int pat, bool setflag)
36
33
TRANS_FEAT(PTRUE, aa64_sve, do_predset, a->esz, a->rd, a->pat, a->s)
37
#undef DO_ZZI
34
38
35
/* Note pat == 31 is #all, to set all elements. */
39
+static bool trans_DOT_zzz(DisasContext *s, arg_DOT_zzz *a, uint32_t insn)
36
-TRANS_FEAT(SETFFR, aa64_sve, do_predset, 0, FFR_PRED_NUM, 31, false)
40
+{
37
+TRANS_FEAT_NONSTREAMING(SETFFR, aa64_sve,
41
+ static gen_helper_gvec_3 * const fns[2][2] = {
38
+ do_predset, 0, FFR_PRED_NUM, 31, false)
42
+ { gen_helper_gvec_sdot_b, gen_helper_gvec_sdot_h },
39
43
+ { gen_helper_gvec_udot_b, gen_helper_gvec_udot_h }
40
/* Note pat == 32 is #unimp, to set no elements. */
44
+ };
41
TRANS_FEAT(PFALSE, aa64_sve, do_predset, 0, a->rd, 32, false)
42
@@ -XXX,XX +XXX,XX @@ static bool trans_RDFFR_p(DisasContext *s, arg_RDFFR_p *a)
43
.rd = a->rd, .pg = a->pg, .s = a->s,
44
.rn = FFR_PRED_NUM, .rm = FFR_PRED_NUM,
45
};
45
+
46
+
46
+ if (sve_access_check(s)) {
47
+ s->is_nonstreaming = true;
47
+ unsigned vsz = vec_full_reg_size(s);
48
return trans_AND_pppp(s, &alt_a);
48
+ tcg_gen_gvec_3_ool(vec_full_reg_offset(s, a->rd),
49
+ vec_full_reg_offset(s, a->rn),
50
+ vec_full_reg_offset(s, a->rm),
51
+ vsz, vsz, 0, fns[a->u][a->sz]);
52
+ }
53
+ return true;
54
+}
55
+
56
/*
57
*** SVE Floating Point Multiply-Add Indexed Group
58
*/
59
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/vec_helper.c
62
+++ b/target/arm/vec_helper.c
63
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
64
clear_tail(d, opr_sz, simd_maxsz(desc));
65
}
49
}
66
50
67
+/* Integer 8 and 16-bit dot-product.
51
-TRANS_FEAT(RDFFR, aa64_sve, do_mov_p, a->rd, FFR_PRED_NUM)
68
+ *
52
-TRANS_FEAT(WRFFR, aa64_sve, do_mov_p, FFR_PRED_NUM, a->rn)
69
+ * Note that for the loops herein, host endianness does not matter
53
+TRANS_FEAT_NONSTREAMING(RDFFR, aa64_sve, do_mov_p, a->rd, FFR_PRED_NUM)
70
+ * with respect to the ordering of data within the 64-bit lanes.
54
+TRANS_FEAT_NONSTREAMING(WRFFR, aa64_sve, do_mov_p, FFR_PRED_NUM, a->rn)
71
+ * All elements are treated equally, no matter where they are.
55
72
+ */
56
static bool do_pfirst_pnext(DisasContext *s, arg_rr_esz *a,
73
+
57
void (*gen_fn)(TCGv_i32, TCGv_ptr,
74
+void HELPER(gvec_sdot_b)(void *vd, void *vn, void *vm, uint32_t desc)
75
+{
76
+ intptr_t i, opr_sz = simd_oprsz(desc);
77
+ uint32_t *d = vd;
78
+ int8_t *n = vn, *m = vm;
79
+
80
+ for (i = 0; i < opr_sz / 4; ++i) {
81
+ d[i] += n[i * 4 + 0] * m[i * 4 + 0]
82
+ + n[i * 4 + 1] * m[i * 4 + 1]
83
+ + n[i * 4 + 2] * m[i * 4 + 2]
84
+ + n[i * 4 + 3] * m[i * 4 + 3];
85
+ }
86
+ clear_tail(d, opr_sz, simd_maxsz(desc));
87
+}
88
+
89
+void HELPER(gvec_udot_b)(void *vd, void *vn, void *vm, uint32_t desc)
90
+{
91
+ intptr_t i, opr_sz = simd_oprsz(desc);
92
+ uint32_t *d = vd;
93
+ uint8_t *n = vn, *m = vm;
94
+
95
+ for (i = 0; i < opr_sz / 4; ++i) {
96
+ d[i] += n[i * 4 + 0] * m[i * 4 + 0]
97
+ + n[i * 4 + 1] * m[i * 4 + 1]
98
+ + n[i * 4 + 2] * m[i * 4 + 2]
99
+ + n[i * 4 + 3] * m[i * 4 + 3];
100
+ }
101
+ clear_tail(d, opr_sz, simd_maxsz(desc));
102
+}
103
+
104
+void HELPER(gvec_sdot_h)(void *vd, void *vn, void *vm, uint32_t desc)
105
+{
106
+ intptr_t i, opr_sz = simd_oprsz(desc);
107
+ uint64_t *d = vd;
108
+ int16_t *n = vn, *m = vm;
109
+
110
+ for (i = 0; i < opr_sz / 8; ++i) {
111
+ d[i] += (int64_t)n[i * 4 + 0] * m[i * 4 + 0]
112
+ + (int64_t)n[i * 4 + 1] * m[i * 4 + 1]
113
+ + (int64_t)n[i * 4 + 2] * m[i * 4 + 2]
114
+ + (int64_t)n[i * 4 + 3] * m[i * 4 + 3];
115
+ }
116
+ clear_tail(d, opr_sz, simd_maxsz(desc));
117
+}
118
+
119
+void HELPER(gvec_udot_h)(void *vd, void *vn, void *vm, uint32_t desc)
120
+{
121
+ intptr_t i, opr_sz = simd_oprsz(desc);
122
+ uint64_t *d = vd;
123
+ uint16_t *n = vn, *m = vm;
124
+
125
+ for (i = 0; i < opr_sz / 8; ++i) {
126
+ d[i] += (uint64_t)n[i * 4 + 0] * m[i * 4 + 0]
127
+ + (uint64_t)n[i * 4 + 1] * m[i * 4 + 1]
128
+ + (uint64_t)n[i * 4 + 2] * m[i * 4 + 2]
129
+ + (uint64_t)n[i * 4 + 3] * m[i * 4 + 3];
130
+ }
131
+ clear_tail(d, opr_sz, simd_maxsz(desc));
132
+}
133
+
134
void HELPER(gvec_fcaddh)(void *vd, void *vn, void *vm,
135
void *vfpst, uint32_t desc)
136
{
137
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
138
index XXXXXXX..XXXXXXX 100644
139
--- a/target/arm/sve.decode
140
+++ b/target/arm/sve.decode
141
@@ -XXX,XX +XXX,XX @@ UMIN_zzi 00100101 .. 101 011 110 ........ ..... @rdn_i8u
142
# SVE integer multiply immediate (unpredicated)
143
MUL_zzi 00100101 .. 110 000 110 ........ ..... @rdn_i8s
144
145
+# SVE integer dot product (unpredicated)
146
+DOT_zzz 01000100 1 sz:1 0 rm:5 00000 u:1 rn:5 rd:5 ra=%reg_movprfx
147
+
148
# SVE floating-point complex add (predicated)
149
FCADD 01100100 esz:2 00000 rot:1 100 pg:3 rm:5 rd:5 \
150
rn=%reg_movprfx
151
--
58
--
152
2.17.1
59
2.25.1
153
154
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-7-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-7-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 77 +++++++++++++++++++++++++++++++++
11
target/arm/sme-fa64.decode | 3 ---
9
target/arm/sve_helper.c | 89 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-sve.c | 22 ++++++++++++----------
10
target/arm/translate-sve.c | 46 ++++++++++++++++++++
13
2 files changed, 12 insertions(+), 13 deletions(-)
11
target/arm/sve.decode | 17 ++++++++
12
4 files changed, 229 insertions(+)
13
14
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
17
--- a/target/arm/sme-fa64.decode
17
+++ b/target/arm/helper-sve.h
18
+++ b/target/arm/sme-fa64.decode
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_rsqrts_s, TCG_CALL_NO_RWG,
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
19
DEF_HELPER_FLAGS_5(gvec_rsqrts_d, TCG_CALL_NO_RWG,
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
20
void, ptr, ptr, ptr, ptr, i32)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
21
22
22
+DEF_HELPER_FLAGS_6(sve_fadd_h, TCG_CALL_NO_RWG,
23
-FAIL 0000 0100 --1- ---- 1011 -0-- ---- ---- # FTSSEL, FEXPA
23
+ void, ptr, ptr, ptr, ptr, ptr, i32)
24
-FAIL 0000 0101 --10 0001 100- ---- ---- ---- # COMPACT
24
+DEF_HELPER_FLAGS_6(sve_fadd_s, TCG_CALL_NO_RWG,
25
-FAIL 0100 0101 --0- ---- 1011 ---- ---- ---- # BDEP, BEXT, BGRP
25
+ void, ptr, ptr, ptr, ptr, ptr, i32)
26
FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
26
+DEF_HELPER_FLAGS_6(sve_fadd_d, TCG_CALL_NO_RWG,
27
FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
27
+ void, ptr, ptr, ptr, ptr, ptr, i32)
28
FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
28
+
29
+DEF_HELPER_FLAGS_6(sve_fsub_h, TCG_CALL_NO_RWG,
30
+ void, ptr, ptr, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_6(sve_fsub_s, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_6(sve_fsub_d, TCG_CALL_NO_RWG,
34
+ void, ptr, ptr, ptr, ptr, ptr, i32)
35
+
36
+DEF_HELPER_FLAGS_6(sve_fmul_h, TCG_CALL_NO_RWG,
37
+ void, ptr, ptr, ptr, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_6(sve_fmul_s, TCG_CALL_NO_RWG,
39
+ void, ptr, ptr, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_6(sve_fmul_d, TCG_CALL_NO_RWG,
41
+ void, ptr, ptr, ptr, ptr, ptr, i32)
42
+
43
+DEF_HELPER_FLAGS_6(sve_fdiv_h, TCG_CALL_NO_RWG,
44
+ void, ptr, ptr, ptr, ptr, ptr, i32)
45
+DEF_HELPER_FLAGS_6(sve_fdiv_s, TCG_CALL_NO_RWG,
46
+ void, ptr, ptr, ptr, ptr, ptr, i32)
47
+DEF_HELPER_FLAGS_6(sve_fdiv_d, TCG_CALL_NO_RWG,
48
+ void, ptr, ptr, ptr, ptr, ptr, i32)
49
+
50
+DEF_HELPER_FLAGS_6(sve_fmin_h, TCG_CALL_NO_RWG,
51
+ void, ptr, ptr, ptr, ptr, ptr, i32)
52
+DEF_HELPER_FLAGS_6(sve_fmin_s, TCG_CALL_NO_RWG,
53
+ void, ptr, ptr, ptr, ptr, ptr, i32)
54
+DEF_HELPER_FLAGS_6(sve_fmin_d, TCG_CALL_NO_RWG,
55
+ void, ptr, ptr, ptr, ptr, ptr, i32)
56
+
57
+DEF_HELPER_FLAGS_6(sve_fmax_h, TCG_CALL_NO_RWG,
58
+ void, ptr, ptr, ptr, ptr, ptr, i32)
59
+DEF_HELPER_FLAGS_6(sve_fmax_s, TCG_CALL_NO_RWG,
60
+ void, ptr, ptr, ptr, ptr, ptr, i32)
61
+DEF_HELPER_FLAGS_6(sve_fmax_d, TCG_CALL_NO_RWG,
62
+ void, ptr, ptr, ptr, ptr, ptr, i32)
63
+
64
+DEF_HELPER_FLAGS_6(sve_fminnum_h, TCG_CALL_NO_RWG,
65
+ void, ptr, ptr, ptr, ptr, ptr, i32)
66
+DEF_HELPER_FLAGS_6(sve_fminnum_s, TCG_CALL_NO_RWG,
67
+ void, ptr, ptr, ptr, ptr, ptr, i32)
68
+DEF_HELPER_FLAGS_6(sve_fminnum_d, TCG_CALL_NO_RWG,
69
+ void, ptr, ptr, ptr, ptr, ptr, i32)
70
+
71
+DEF_HELPER_FLAGS_6(sve_fmaxnum_h, TCG_CALL_NO_RWG,
72
+ void, ptr, ptr, ptr, ptr, ptr, i32)
73
+DEF_HELPER_FLAGS_6(sve_fmaxnum_s, TCG_CALL_NO_RWG,
74
+ void, ptr, ptr, ptr, ptr, ptr, i32)
75
+DEF_HELPER_FLAGS_6(sve_fmaxnum_d, TCG_CALL_NO_RWG,
76
+ void, ptr, ptr, ptr, ptr, ptr, i32)
77
+
78
+DEF_HELPER_FLAGS_6(sve_fabd_h, TCG_CALL_NO_RWG,
79
+ void, ptr, ptr, ptr, ptr, ptr, i32)
80
+DEF_HELPER_FLAGS_6(sve_fabd_s, TCG_CALL_NO_RWG,
81
+ void, ptr, ptr, ptr, ptr, ptr, i32)
82
+DEF_HELPER_FLAGS_6(sve_fabd_d, TCG_CALL_NO_RWG,
83
+ void, ptr, ptr, ptr, ptr, ptr, i32)
84
+
85
+DEF_HELPER_FLAGS_6(sve_fscalbn_h, TCG_CALL_NO_RWG,
86
+ void, ptr, ptr, ptr, ptr, ptr, i32)
87
+DEF_HELPER_FLAGS_6(sve_fscalbn_s, TCG_CALL_NO_RWG,
88
+ void, ptr, ptr, ptr, ptr, ptr, i32)
89
+DEF_HELPER_FLAGS_6(sve_fscalbn_d, TCG_CALL_NO_RWG,
90
+ void, ptr, ptr, ptr, ptr, ptr, i32)
91
+
92
+DEF_HELPER_FLAGS_6(sve_fmulx_h, TCG_CALL_NO_RWG,
93
+ void, ptr, ptr, ptr, ptr, ptr, i32)
94
+DEF_HELPER_FLAGS_6(sve_fmulx_s, TCG_CALL_NO_RWG,
95
+ void, ptr, ptr, ptr, ptr, ptr, i32)
96
+DEF_HELPER_FLAGS_6(sve_fmulx_d, TCG_CALL_NO_RWG,
97
+ void, ptr, ptr, ptr, ptr, ptr, i32)
98
+
99
DEF_HELPER_FLAGS_5(sve_scvt_hh, TCG_CALL_NO_RWG,
100
void, ptr, ptr, ptr, ptr, i32)
101
DEF_HELPER_FLAGS_5(sve_scvt_sh, TCG_CALL_NO_RWG,
102
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/target/arm/sve_helper.c
105
+++ b/target/arm/sve_helper.c
106
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_while)(void *vd, uint32_t count, uint32_t pred_desc)
107
return predtest_ones(d, oprsz, esz_mask);
108
}
109
110
+/* Fully general three-operand expander, controlled by a predicate,
111
+ * With the extra float_status parameter.
112
+ */
113
+#define DO_ZPZZ_FP(NAME, TYPE, H, OP) \
114
+void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, \
115
+ void *status, uint32_t desc) \
116
+{ \
117
+ intptr_t i = simd_oprsz(desc); \
118
+ uint64_t *g = vg; \
119
+ do { \
120
+ uint64_t pg = g[(i - 1) >> 6]; \
121
+ do { \
122
+ i -= sizeof(TYPE); \
123
+ if (likely((pg >> (i & 63)) & 1)) { \
124
+ TYPE nn = *(TYPE *)(vn + H(i)); \
125
+ TYPE mm = *(TYPE *)(vm + H(i)); \
126
+ *(TYPE *)(vd + H(i)) = OP(nn, mm, status); \
127
+ } \
128
+ } while (i & 63); \
129
+ } while (i != 0); \
130
+}
131
+
132
+DO_ZPZZ_FP(sve_fadd_h, uint16_t, H1_2, float16_add)
133
+DO_ZPZZ_FP(sve_fadd_s, uint32_t, H1_4, float32_add)
134
+DO_ZPZZ_FP(sve_fadd_d, uint64_t, , float64_add)
135
+
136
+DO_ZPZZ_FP(sve_fsub_h, uint16_t, H1_2, float16_sub)
137
+DO_ZPZZ_FP(sve_fsub_s, uint32_t, H1_4, float32_sub)
138
+DO_ZPZZ_FP(sve_fsub_d, uint64_t, , float64_sub)
139
+
140
+DO_ZPZZ_FP(sve_fmul_h, uint16_t, H1_2, float16_mul)
141
+DO_ZPZZ_FP(sve_fmul_s, uint32_t, H1_4, float32_mul)
142
+DO_ZPZZ_FP(sve_fmul_d, uint64_t, , float64_mul)
143
+
144
+DO_ZPZZ_FP(sve_fdiv_h, uint16_t, H1_2, float16_div)
145
+DO_ZPZZ_FP(sve_fdiv_s, uint32_t, H1_4, float32_div)
146
+DO_ZPZZ_FP(sve_fdiv_d, uint64_t, , float64_div)
147
+
148
+DO_ZPZZ_FP(sve_fmin_h, uint16_t, H1_2, float16_min)
149
+DO_ZPZZ_FP(sve_fmin_s, uint32_t, H1_4, float32_min)
150
+DO_ZPZZ_FP(sve_fmin_d, uint64_t, , float64_min)
151
+
152
+DO_ZPZZ_FP(sve_fmax_h, uint16_t, H1_2, float16_max)
153
+DO_ZPZZ_FP(sve_fmax_s, uint32_t, H1_4, float32_max)
154
+DO_ZPZZ_FP(sve_fmax_d, uint64_t, , float64_max)
155
+
156
+DO_ZPZZ_FP(sve_fminnum_h, uint16_t, H1_2, float16_minnum)
157
+DO_ZPZZ_FP(sve_fminnum_s, uint32_t, H1_4, float32_minnum)
158
+DO_ZPZZ_FP(sve_fminnum_d, uint64_t, , float64_minnum)
159
+
160
+DO_ZPZZ_FP(sve_fmaxnum_h, uint16_t, H1_2, float16_maxnum)
161
+DO_ZPZZ_FP(sve_fmaxnum_s, uint32_t, H1_4, float32_maxnum)
162
+DO_ZPZZ_FP(sve_fmaxnum_d, uint64_t, , float64_maxnum)
163
+
164
+static inline float16 abd_h(float16 a, float16 b, float_status *s)
165
+{
166
+ return float16_abs(float16_sub(a, b, s));
167
+}
168
+
169
+static inline float32 abd_s(float32 a, float32 b, float_status *s)
170
+{
171
+ return float32_abs(float32_sub(a, b, s));
172
+}
173
+
174
+static inline float64 abd_d(float64 a, float64 b, float_status *s)
175
+{
176
+ return float64_abs(float64_sub(a, b, s));
177
+}
178
+
179
+DO_ZPZZ_FP(sve_fabd_h, uint16_t, H1_2, abd_h)
180
+DO_ZPZZ_FP(sve_fabd_s, uint32_t, H1_4, abd_s)
181
+DO_ZPZZ_FP(sve_fabd_d, uint64_t, , abd_d)
182
+
183
+static inline float64 scalbn_d(float64 a, int64_t b, float_status *s)
184
+{
185
+ int b_int = MIN(MAX(b, INT_MIN), INT_MAX);
186
+ return float64_scalbn(a, b_int, s);
187
+}
188
+
189
+DO_ZPZZ_FP(sve_fscalbn_h, int16_t, H1_2, float16_scalbn)
190
+DO_ZPZZ_FP(sve_fscalbn_s, int32_t, H1_4, float32_scalbn)
191
+DO_ZPZZ_FP(sve_fscalbn_d, int64_t, , scalbn_d)
192
+
193
+DO_ZPZZ_FP(sve_fmulx_h, uint16_t, H1_2, helper_advsimd_mulxh)
194
+DO_ZPZZ_FP(sve_fmulx_s, uint32_t, H1_4, helper_vfp_mulxs)
195
+DO_ZPZZ_FP(sve_fmulx_d, uint64_t, , helper_vfp_mulxd)
196
+
197
+#undef DO_ZPZZ_FP
198
+
199
/* Fully general two-operand expander, controlled by a predicate,
200
* With the extra float_status parameter.
201
*/
202
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
29
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
203
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
204
--- a/target/arm/translate-sve.c
31
--- a/target/arm/translate-sve.c
205
+++ b/target/arm/translate-sve.c
32
+++ b/target/arm/translate-sve.c
206
@@ -XXX,XX +XXX,XX @@ DO_FP3(FRSQRTS, rsqrts)
33
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_2 * const fexpa_fns[4] = {
207
34
NULL, gen_helper_sve_fexpa_h,
208
#undef DO_FP3
35
gen_helper_sve_fexpa_s, gen_helper_sve_fexpa_d,
209
36
};
210
+/*
37
-TRANS_FEAT(FEXPA, aa64_sve, gen_gvec_ool_zz,
211
+ *** SVE Floating Point Arithmetic - Predicated Group
38
- fexpa_fns[a->esz], a->rd, a->rn, 0)
212
+ */
39
+TRANS_FEAT_NONSTREAMING(FEXPA, aa64_sve, gen_gvec_ool_zz,
213
+
40
+ fexpa_fns[a->esz], a->rd, a->rn, 0)
214
+static bool do_zpzz_fp(DisasContext *s, arg_rprr_esz *a,
41
215
+ gen_helper_gvec_4_ptr *fn)
42
static gen_helper_gvec_3 * const ftssel_fns[4] = {
216
+{
43
NULL, gen_helper_sve_ftssel_h,
217
+ if (fn == NULL) {
44
gen_helper_sve_ftssel_s, gen_helper_sve_ftssel_d,
218
+ return false;
45
};
219
+ }
46
-TRANS_FEAT(FTSSEL, aa64_sve, gen_gvec_ool_arg_zzz, ftssel_fns[a->esz], a, 0)
220
+ if (sve_access_check(s)) {
47
+TRANS_FEAT_NONSTREAMING(FTSSEL, aa64_sve, gen_gvec_ool_arg_zzz,
221
+ unsigned vsz = vec_full_reg_size(s);
48
+ ftssel_fns[a->esz], a, 0)
222
+ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
223
+ tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, a->rd),
224
+ vec_full_reg_offset(s, a->rn),
225
+ vec_full_reg_offset(s, a->rm),
226
+ pred_full_reg_offset(s, a->pg),
227
+ status, vsz, vsz, 0, fn);
228
+ tcg_temp_free_ptr(status);
229
+ }
230
+ return true;
231
+}
232
+
233
+#define DO_FP3(NAME, name) \
234
+static bool trans_##NAME(DisasContext *s, arg_rprr_esz *a, uint32_t insn) \
235
+{ \
236
+ static gen_helper_gvec_4_ptr * const fns[4] = { \
237
+ NULL, gen_helper_sve_##name##_h, \
238
+ gen_helper_sve_##name##_s, gen_helper_sve_##name##_d \
239
+ }; \
240
+ return do_zpzz_fp(s, a, fns[a->esz]); \
241
+}
242
+
243
+DO_FP3(FADD_zpzz, fadd)
244
+DO_FP3(FSUB_zpzz, fsub)
245
+DO_FP3(FMUL_zpzz, fmul)
246
+DO_FP3(FMIN_zpzz, fmin)
247
+DO_FP3(FMAX_zpzz, fmax)
248
+DO_FP3(FMINNM_zpzz, fminnum)
249
+DO_FP3(FMAXNM_zpzz, fmaxnum)
250
+DO_FP3(FABD, fabd)
251
+DO_FP3(FSCALE, fscalbn)
252
+DO_FP3(FDIV, fdiv)
253
+DO_FP3(FMULX, fmulx)
254
+
255
+#undef DO_FP3
256
49
257
/*
50
/*
258
*** SVE Floating Point Unary Operations Predicated Group
51
*** SVE Predicate Logical Operations Group
259
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
52
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(TRN2_q, aa64_sve_f64mm, gen_gvec_ool_arg_zzz,
260
index XXXXXXX..XXXXXXX 100644
53
static gen_helper_gvec_3 * const compact_fns[4] = {
261
--- a/target/arm/sve.decode
54
NULL, NULL, gen_helper_sve_compact_s, gen_helper_sve_compact_d
262
+++ b/target/arm/sve.decode
55
};
263
@@ -XXX,XX +XXX,XX @@ FTSMUL 01100101 .. 0 ..... 000 011 ..... ..... @rd_rn_rm
56
-TRANS_FEAT(COMPACT, aa64_sve, gen_gvec_ool_arg_zpz, compact_fns[a->esz], a, 0)
264
FRECPS 01100101 .. 0 ..... 000 110 ..... ..... @rd_rn_rm
57
+TRANS_FEAT_NONSTREAMING(COMPACT, aa64_sve, gen_gvec_ool_arg_zpz,
265
FRSQRTS 01100101 .. 0 ..... 000 111 ..... ..... @rd_rn_rm
58
+ compact_fns[a->esz], a, 0)
266
59
267
+### SVE FP Arithmetic Predicated Group
60
/* Call the helper that computes the ARM LastActiveElement pseudocode
268
+
61
* function, scaled by the element size. This includes the not found
269
+# SVE floating-point arithmetic (predicated)
62
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3 * const bext_fns[4] = {
270
+FADD_zpzz 01100101 .. 00 0000 100 ... ..... ..... @rdn_pg_rm
63
gen_helper_sve2_bext_b, gen_helper_sve2_bext_h,
271
+FSUB_zpzz 01100101 .. 00 0001 100 ... ..... ..... @rdn_pg_rm
64
gen_helper_sve2_bext_s, gen_helper_sve2_bext_d,
272
+FMUL_zpzz 01100101 .. 00 0010 100 ... ..... ..... @rdn_pg_rm
65
};
273
+FSUB_zpzz 01100101 .. 00 0011 100 ... ..... ..... @rdm_pg_rn # FSUBR
66
-TRANS_FEAT(BEXT, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
274
+FMAXNM_zpzz 01100101 .. 00 0100 100 ... ..... ..... @rdn_pg_rm
67
- bext_fns[a->esz], a, 0)
275
+FMINNM_zpzz 01100101 .. 00 0101 100 ... ..... ..... @rdn_pg_rm
68
+TRANS_FEAT_NONSTREAMING(BEXT, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
276
+FMAX_zpzz 01100101 .. 00 0110 100 ... ..... ..... @rdn_pg_rm
69
+ bext_fns[a->esz], a, 0)
277
+FMIN_zpzz 01100101 .. 00 0111 100 ... ..... ..... @rdn_pg_rm
70
278
+FABD 01100101 .. 00 1000 100 ... ..... ..... @rdn_pg_rm
71
static gen_helper_gvec_3 * const bdep_fns[4] = {
279
+FSCALE 01100101 .. 00 1001 100 ... ..... ..... @rdn_pg_rm
72
gen_helper_sve2_bdep_b, gen_helper_sve2_bdep_h,
280
+FMULX 01100101 .. 00 1010 100 ... ..... ..... @rdn_pg_rm
73
gen_helper_sve2_bdep_s, gen_helper_sve2_bdep_d,
281
+FDIV 01100101 .. 00 1100 100 ... ..... ..... @rdm_pg_rn # FDIVR
74
};
282
+FDIV 01100101 .. 00 1101 100 ... ..... ..... @rdn_pg_rm
75
-TRANS_FEAT(BDEP, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
283
+
76
- bdep_fns[a->esz], a, 0)
284
### SVE FP Unary Operations Predicated Group
77
+TRANS_FEAT_NONSTREAMING(BDEP, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
285
78
+ bdep_fns[a->esz], a, 0)
286
# SVE integer convert to floating-point
79
80
static gen_helper_gvec_3 * const bgrp_fns[4] = {
81
gen_helper_sve2_bgrp_b, gen_helper_sve2_bgrp_h,
82
gen_helper_sve2_bgrp_s, gen_helper_sve2_bgrp_d,
83
};
84
-TRANS_FEAT(BGRP, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
85
- bgrp_fns[a->esz], a, 0)
86
+TRANS_FEAT_NONSTREAMING(BGRP, aa64_sve2_bitperm, gen_gvec_ool_arg_zzz,
87
+ bgrp_fns[a->esz], a, 0)
88
89
static gen_helper_gvec_3 * const cadd_fns[4] = {
90
gen_helper_sve2_cadd_b, gen_helper_sve2_cadd_h,
287
--
91
--
288
2.17.1
92
2.25.1
289
290
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-30-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-8-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 4 +
11
target/arm/sme-fa64.decode | 2 --
9
target/arm/sve_helper.c | 162 +++++++++++++++++++++++++++++++++++++
12
target/arm/translate-sve.c | 24 +++++++++++++++---------
10
target/arm/translate-sve.c | 37 +++++++++
13
2 files changed, 15 insertions(+), 11 deletions(-)
11
target/arm/sve.decode | 4 +
12
4 files changed, 207 insertions(+)
13
14
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
17
--- a/target/arm/sme-fa64.decode
17
+++ b/target/arm/helper-sve.h
18
+++ b/target/arm/sme-fa64.decode
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(sve_fnmls_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32)
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
19
DEF_HELPER_FLAGS_3(sve_fnmls_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32)
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
20
DEF_HELPER_FLAGS_3(sve_fnmls_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
21
22
22
+DEF_HELPER_FLAGS_3(sve_fcmla_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32)
23
-FAIL 0100 0101 000- ---- 0110 1--- ---- ---- # PMULLB, PMULLT (128b result)
23
+DEF_HELPER_FLAGS_3(sve_fcmla_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32)
24
-FAIL 0110 0100 --1- ---- 1110 01-- ---- ---- # FMMLA, BFMMLA
24
+DEF_HELPER_FLAGS_3(sve_fcmla_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32)
25
FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
25
+
26
FAIL 0110 0101 --01 0--- 100- ---- ---- ---- # FTMAD
26
DEF_HELPER_FLAGS_5(sve_ftmad_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
FAIL 0110 0101 --01 1--- 001- ---- ---- ---- # FADDA
27
DEF_HELPER_FLAGS_5(sve_ftmad_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
28
DEF_HELPER_FLAGS_5(sve_ftmad_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
29
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/sve_helper.c
32
+++ b/target/arm/sve_helper.c
33
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_fcadd_d)(void *vd, void *vn, void *vm, void *vg,
34
} while (i != 0);
35
}
36
37
+/*
38
+ * FP Complex Multiply
39
+ */
40
+
41
+QEMU_BUILD_BUG_ON(SIMD_DATA_SHIFT + 22 > 32);
42
+
43
+void HELPER(sve_fcmla_zpzzz_h)(CPUARMState *env, void *vg, uint32_t desc)
44
+{
45
+ intptr_t j, i = simd_oprsz(desc);
46
+ unsigned rd = extract32(desc, SIMD_DATA_SHIFT, 5);
47
+ unsigned rn = extract32(desc, SIMD_DATA_SHIFT + 5, 5);
48
+ unsigned rm = extract32(desc, SIMD_DATA_SHIFT + 10, 5);
49
+ unsigned ra = extract32(desc, SIMD_DATA_SHIFT + 15, 5);
50
+ unsigned rot = extract32(desc, SIMD_DATA_SHIFT + 20, 2);
51
+ bool flip = rot & 1;
52
+ float16 neg_imag, neg_real;
53
+ void *vd = &env->vfp.zregs[rd];
54
+ void *vn = &env->vfp.zregs[rn];
55
+ void *vm = &env->vfp.zregs[rm];
56
+ void *va = &env->vfp.zregs[ra];
57
+ uint64_t *g = vg;
58
+
59
+ neg_imag = float16_set_sign(0, (rot & 2) != 0);
60
+ neg_real = float16_set_sign(0, rot == 1 || rot == 2);
61
+
62
+ do {
63
+ uint64_t pg = g[(i - 1) >> 6];
64
+ do {
65
+ float16 e1, e2, e3, e4, nr, ni, mr, mi, d;
66
+
67
+ /* I holds the real index; J holds the imag index. */
68
+ j = i - sizeof(float16);
69
+ i -= 2 * sizeof(float16);
70
+
71
+ nr = *(float16 *)(vn + H1_2(i));
72
+ ni = *(float16 *)(vn + H1_2(j));
73
+ mr = *(float16 *)(vm + H1_2(i));
74
+ mi = *(float16 *)(vm + H1_2(j));
75
+
76
+ e2 = (flip ? ni : nr);
77
+ e1 = (flip ? mi : mr) ^ neg_real;
78
+ e4 = e2;
79
+ e3 = (flip ? mr : mi) ^ neg_imag;
80
+
81
+ if (likely((pg >> (i & 63)) & 1)) {
82
+ d = *(float16 *)(va + H1_2(i));
83
+ d = float16_muladd(e2, e1, d, 0, &env->vfp.fp_status_f16);
84
+ *(float16 *)(vd + H1_2(i)) = d;
85
+ }
86
+ if (likely((pg >> (j & 63)) & 1)) {
87
+ d = *(float16 *)(va + H1_2(j));
88
+ d = float16_muladd(e4, e3, d, 0, &env->vfp.fp_status_f16);
89
+ *(float16 *)(vd + H1_2(j)) = d;
90
+ }
91
+ } while (i & 63);
92
+ } while (i != 0);
93
+}
94
+
95
+void HELPER(sve_fcmla_zpzzz_s)(CPUARMState *env, void *vg, uint32_t desc)
96
+{
97
+ intptr_t j, i = simd_oprsz(desc);
98
+ unsigned rd = extract32(desc, SIMD_DATA_SHIFT, 5);
99
+ unsigned rn = extract32(desc, SIMD_DATA_SHIFT + 5, 5);
100
+ unsigned rm = extract32(desc, SIMD_DATA_SHIFT + 10, 5);
101
+ unsigned ra = extract32(desc, SIMD_DATA_SHIFT + 15, 5);
102
+ unsigned rot = extract32(desc, SIMD_DATA_SHIFT + 20, 2);
103
+ bool flip = rot & 1;
104
+ float32 neg_imag, neg_real;
105
+ void *vd = &env->vfp.zregs[rd];
106
+ void *vn = &env->vfp.zregs[rn];
107
+ void *vm = &env->vfp.zregs[rm];
108
+ void *va = &env->vfp.zregs[ra];
109
+ uint64_t *g = vg;
110
+
111
+ neg_imag = float32_set_sign(0, (rot & 2) != 0);
112
+ neg_real = float32_set_sign(0, rot == 1 || rot == 2);
113
+
114
+ do {
115
+ uint64_t pg = g[(i - 1) >> 6];
116
+ do {
117
+ float32 e1, e2, e3, e4, nr, ni, mr, mi, d;
118
+
119
+ /* I holds the real index; J holds the imag index. */
120
+ j = i - sizeof(float32);
121
+ i -= 2 * sizeof(float32);
122
+
123
+ nr = *(float32 *)(vn + H1_2(i));
124
+ ni = *(float32 *)(vn + H1_2(j));
125
+ mr = *(float32 *)(vm + H1_2(i));
126
+ mi = *(float32 *)(vm + H1_2(j));
127
+
128
+ e2 = (flip ? ni : nr);
129
+ e1 = (flip ? mi : mr) ^ neg_real;
130
+ e4 = e2;
131
+ e3 = (flip ? mr : mi) ^ neg_imag;
132
+
133
+ if (likely((pg >> (i & 63)) & 1)) {
134
+ d = *(float32 *)(va + H1_2(i));
135
+ d = float32_muladd(e2, e1, d, 0, &env->vfp.fp_status);
136
+ *(float32 *)(vd + H1_2(i)) = d;
137
+ }
138
+ if (likely((pg >> (j & 63)) & 1)) {
139
+ d = *(float32 *)(va + H1_2(j));
140
+ d = float32_muladd(e4, e3, d, 0, &env->vfp.fp_status);
141
+ *(float32 *)(vd + H1_2(j)) = d;
142
+ }
143
+ } while (i & 63);
144
+ } while (i != 0);
145
+}
146
+
147
+void HELPER(sve_fcmla_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc)
148
+{
149
+ intptr_t j, i = simd_oprsz(desc);
150
+ unsigned rd = extract32(desc, SIMD_DATA_SHIFT, 5);
151
+ unsigned rn = extract32(desc, SIMD_DATA_SHIFT + 5, 5);
152
+ unsigned rm = extract32(desc, SIMD_DATA_SHIFT + 10, 5);
153
+ unsigned ra = extract32(desc, SIMD_DATA_SHIFT + 15, 5);
154
+ unsigned rot = extract32(desc, SIMD_DATA_SHIFT + 20, 2);
155
+ bool flip = rot & 1;
156
+ float64 neg_imag, neg_real;
157
+ void *vd = &env->vfp.zregs[rd];
158
+ void *vn = &env->vfp.zregs[rn];
159
+ void *vm = &env->vfp.zregs[rm];
160
+ void *va = &env->vfp.zregs[ra];
161
+ uint64_t *g = vg;
162
+
163
+ neg_imag = float64_set_sign(0, (rot & 2) != 0);
164
+ neg_real = float64_set_sign(0, rot == 1 || rot == 2);
165
+
166
+ do {
167
+ uint64_t pg = g[(i - 1) >> 6];
168
+ do {
169
+ float64 e1, e2, e3, e4, nr, ni, mr, mi, d;
170
+
171
+ /* I holds the real index; J holds the imag index. */
172
+ j = i - sizeof(float64);
173
+ i -= 2 * sizeof(float64);
174
+
175
+ nr = *(float64 *)(vn + H1_2(i));
176
+ ni = *(float64 *)(vn + H1_2(j));
177
+ mr = *(float64 *)(vm + H1_2(i));
178
+ mi = *(float64 *)(vm + H1_2(j));
179
+
180
+ e2 = (flip ? ni : nr);
181
+ e1 = (flip ? mi : mr) ^ neg_real;
182
+ e4 = e2;
183
+ e3 = (flip ? mr : mi) ^ neg_imag;
184
+
185
+ if (likely((pg >> (i & 63)) & 1)) {
186
+ d = *(float64 *)(va + H1_2(i));
187
+ d = float64_muladd(e2, e1, d, 0, &env->vfp.fp_status);
188
+ *(float64 *)(vd + H1_2(i)) = d;
189
+ }
190
+ if (likely((pg >> (j & 63)) & 1)) {
191
+ d = *(float64 *)(va + H1_2(j));
192
+ d = float64_muladd(e4, e3, d, 0, &env->vfp.fp_status);
193
+ *(float64 *)(vd + H1_2(j)) = d;
194
+ }
195
+ } while (i & 63);
196
+ } while (i != 0);
197
+}
198
+
199
/*
200
* Load contiguous data, protected by a governing predicate.
201
*/
202
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
28
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
203
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
204
--- a/target/arm/translate-sve.c
30
--- a/target/arm/translate-sve.c
205
+++ b/target/arm/translate-sve.c
31
+++ b/target/arm/translate-sve.c
206
@@ -XXX,XX +XXX,XX @@ DO_FMLA(FNMLS_zpzzz, fnmls_zpzzz)
32
@@ -XXX,XX +XXX,XX @@ static bool do_trans_pmull(DisasContext *s, arg_rrr_esz *a, bool sel)
207
33
gen_helper_gvec_pmull_q, gen_helper_sve2_pmull_h,
208
#undef DO_FMLA
34
NULL, gen_helper_sve2_pmull_d,
209
35
};
210
+static bool trans_FCMLA_zpzzz(DisasContext *s,
36
- if (a->esz == 0
211
+ arg_FCMLA_zpzzz *a, uint32_t insn)
37
- ? !dc_isar_feature(aa64_sve2_pmull128, s)
212
+{
38
- : !dc_isar_feature(aa64_sve, s)) {
213
+ static gen_helper_sve_fmla * const fns[3] = {
214
+ gen_helper_sve_fcmla_zpzzz_h,
215
+ gen_helper_sve_fcmla_zpzzz_s,
216
+ gen_helper_sve_fcmla_zpzzz_d,
217
+ };
218
+
39
+
219
+ if (a->esz == 0) {
40
+ if (a->esz == 0) {
220
+ return false;
41
+ if (!dc_isar_feature(aa64_sve2_pmull128, s)) {
221
+ }
42
+ return false;
222
+ if (sve_access_check(s)) {
43
+ }
223
+ unsigned vsz = vec_full_reg_size(s);
44
+ s->is_nonstreaming = true;
224
+ unsigned desc;
45
+ } else if (!dc_isar_feature(aa64_sve, s)) {
225
+ TCGv_i32 t_desc;
46
return false;
226
+ TCGv_ptr pg = tcg_temp_new_ptr();
47
}
227
+
48
return gen_gvec_ool_arg_zzz(s, fns[a->esz], a, sel);
228
+ /* We would need 7 operands to pass these arguments "properly".
49
@@ -XXX,XX +XXX,XX @@ DO_ZPZZ_FP(FMINP, aa64_sve2, sve2_fminp_zpzz)
229
+ * So we encode all the register numbers into the descriptor.
50
* SVE Integer Multiply-Add (unpredicated)
230
+ */
231
+ desc = deposit32(a->rd, 5, 5, a->rn);
232
+ desc = deposit32(desc, 10, 5, a->rm);
233
+ desc = deposit32(desc, 15, 5, a->ra);
234
+ desc = deposit32(desc, 20, 2, a->rot);
235
+ desc = sextract32(desc, 0, 22);
236
+ desc = simd_desc(vsz, vsz, desc);
237
+
238
+ t_desc = tcg_const_i32(desc);
239
+ tcg_gen_addi_ptr(pg, cpu_env, pred_full_reg_offset(s, a->pg));
240
+ fns[a->esz - 1](cpu_env, pg, t_desc);
241
+ tcg_temp_free_i32(t_desc);
242
+ tcg_temp_free_ptr(pg);
243
+ }
244
+ return true;
245
+}
246
+
247
/*
248
*** SVE Floating Point Unary Operations Predicated Group
249
*/
51
*/
250
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
52
251
index XXXXXXX..XXXXXXX 100644
53
-TRANS_FEAT(FMMLA_s, aa64_sve_f32mm, gen_gvec_fpst_zzzz, gen_helper_fmmla_s,
252
--- a/target/arm/sve.decode
54
- a->rd, a->rn, a->rm, a->ra, 0, FPST_FPCR)
253
+++ b/target/arm/sve.decode
55
-TRANS_FEAT(FMMLA_d, aa64_sve_f64mm, gen_gvec_fpst_zzzz, gen_helper_fmmla_d,
254
@@ -XXX,XX +XXX,XX @@ MUL_zzi 00100101 .. 110 000 110 ........ ..... @rdn_i8s
56
- a->rd, a->rn, a->rm, a->ra, 0, FPST_FPCR)
255
FCADD 01100100 esz:2 00000 rot:1 100 pg:3 rm:5 rd:5 \
57
+TRANS_FEAT_NONSTREAMING(FMMLA_s, aa64_sve_f32mm, gen_gvec_fpst_zzzz,
256
rn=%reg_movprfx
58
+ gen_helper_fmmla_s, a->rd, a->rn, a->rm, a->ra,
257
59
+ 0, FPST_FPCR)
258
+# SVE floating-point complex multiply-add (predicated)
60
+TRANS_FEAT_NONSTREAMING(FMMLA_d, aa64_sve_f64mm, gen_gvec_fpst_zzzz,
259
+FCMLA_zpzzz 01100100 esz:2 0 rm:5 0 rot:2 pg:3 rn:5 rd:5 \
61
+ gen_helper_fmmla_d, a->rd, a->rn, a->rm, a->ra,
260
+ ra=%reg_movprfx
62
+ 0, FPST_FPCR)
261
+
63
262
### SVE FP Multiply-Add Indexed Group
64
static gen_helper_gvec_4 * const sqdmlal_zzzw_fns[] = {
263
65
NULL, gen_helper_sve2_sqdmlal_zzzw_h,
264
# SVE floating-point multiply-add (indexed)
66
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(BFDOT_zzzz, aa64_sve_bf16, gen_gvec_ool_arg_zzzz,
67
TRANS_FEAT(BFDOT_zzxz, aa64_sve_bf16, gen_gvec_ool_arg_zzxz,
68
gen_helper_gvec_bfdot_idx, a)
69
70
-TRANS_FEAT(BFMMLA, aa64_sve_bf16, gen_gvec_ool_arg_zzzz,
71
- gen_helper_gvec_bfmmla, a, 0)
72
+TRANS_FEAT_NONSTREAMING(BFMMLA, aa64_sve_bf16, gen_gvec_ool_arg_zzzz,
73
+ gen_helper_gvec_bfmmla, a, 0)
74
75
static bool do_BFMLAL_zzzw(DisasContext *s, arg_rrrr_esz *a, bool sel)
76
{
265
--
77
--
266
2.17.1
78
2.25.1
267
268
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
[PMM: fixed typo]
8
Message-id: 20220708151540.18136-9-richard.henderson@linaro.org
6
Message-id: 20180627043328.11531-6-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
target/arm/helper-sve.h | 30 +++++++++++++
11
target/arm/sme-fa64.decode | 3 ---
10
target/arm/sve_helper.c | 38 ++++++++++++++++
12
target/arm/translate-sve.c | 15 +++++++++++----
11
target/arm/translate-sve.c | 90 ++++++++++++++++++++++++++++++++++++++
13
2 files changed, 11 insertions(+), 7 deletions(-)
12
target/arm/sve.decode | 22 ++++++++++
13
4 files changed, 180 insertions(+)
14
14
15
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-sve.h
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/helper-sve.h
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_rsqrts_s, TCG_CALL_NO_RWG,
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
DEF_HELPER_FLAGS_5(gvec_rsqrts_d, TCG_CALL_NO_RWG,
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
void, ptr, ptr, ptr, ptr, i32)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
22
23
+DEF_HELPER_FLAGS_5(sve_scvt_hh, TCG_CALL_NO_RWG,
23
-FAIL 0110 0101 --0- ---- 0000 11-- ---- ---- # FTSMUL
24
+ void, ptr, ptr, ptr, ptr, i32)
24
-FAIL 0110 0101 --01 0--- 100- ---- ---- ---- # FTMAD
25
+DEF_HELPER_FLAGS_5(sve_scvt_sh, TCG_CALL_NO_RWG,
25
-FAIL 0110 0101 --01 1--- 001- ---- ---- ---- # FADDA
26
+ void, ptr, ptr, ptr, ptr, i32)
26
FAIL 0100 0101 --0- ---- 1001 10-- ---- ---- # SMMLA, UMMLA, USMMLA
27
+DEF_HELPER_FLAGS_5(sve_scvt_dh, TCG_CALL_NO_RWG,
27
FAIL 0100 0101 --1- ---- 1--- ---- ---- ---- # SVE2 string/histo/crypto instructions
28
+ void, ptr, ptr, ptr, ptr, i32)
28
FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
29
+DEF_HELPER_FLAGS_5(sve_scvt_ss, TCG_CALL_NO_RWG,
30
+ void, ptr, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_5(sve_scvt_sd, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_5(sve_scvt_ds, TCG_CALL_NO_RWG,
34
+ void, ptr, ptr, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_5(sve_scvt_dd, TCG_CALL_NO_RWG,
36
+ void, ptr, ptr, ptr, ptr, i32)
37
+
38
+DEF_HELPER_FLAGS_5(sve_ucvt_hh, TCG_CALL_NO_RWG,
39
+ void, ptr, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_5(sve_ucvt_sh, TCG_CALL_NO_RWG,
41
+ void, ptr, ptr, ptr, ptr, i32)
42
+DEF_HELPER_FLAGS_5(sve_ucvt_dh, TCG_CALL_NO_RWG,
43
+ void, ptr, ptr, ptr, ptr, i32)
44
+DEF_HELPER_FLAGS_5(sve_ucvt_ss, TCG_CALL_NO_RWG,
45
+ void, ptr, ptr, ptr, ptr, i32)
46
+DEF_HELPER_FLAGS_5(sve_ucvt_sd, TCG_CALL_NO_RWG,
47
+ void, ptr, ptr, ptr, ptr, i32)
48
+DEF_HELPER_FLAGS_5(sve_ucvt_ds, TCG_CALL_NO_RWG,
49
+ void, ptr, ptr, ptr, ptr, i32)
50
+DEF_HELPER_FLAGS_5(sve_ucvt_dd, TCG_CALL_NO_RWG,
51
+ void, ptr, ptr, ptr, ptr, i32)
52
+
53
DEF_HELPER_FLAGS_4(sve_ld1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
54
DEF_HELPER_FLAGS_4(sve_ld2bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
55
DEF_HELPER_FLAGS_4(sve_ld3bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
56
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/sve_helper.c
59
+++ b/target/arm/sve_helper.c
60
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_while)(void *vd, uint32_t count, uint32_t pred_desc)
61
return predtest_ones(d, oprsz, esz_mask);
62
}
63
64
+/* Fully general two-operand expander, controlled by a predicate,
65
+ * With the extra float_status parameter.
66
+ */
67
+#define DO_ZPZ_FP(NAME, TYPE, H, OP) \
68
+void HELPER(NAME)(void *vd, void *vn, void *vg, void *status, uint32_t desc) \
69
+{ \
70
+ intptr_t i = simd_oprsz(desc); \
71
+ uint64_t *g = vg; \
72
+ do { \
73
+ uint64_t pg = g[(i - 1) >> 6]; \
74
+ do { \
75
+ i -= sizeof(TYPE); \
76
+ if (likely((pg >> (i & 63)) & 1)) { \
77
+ TYPE nn = *(TYPE *)(vn + H(i)); \
78
+ *(TYPE *)(vd + H(i)) = OP(nn, status); \
79
+ } \
80
+ } while (i & 63); \
81
+ } while (i != 0); \
82
+}
83
+
84
+DO_ZPZ_FP(sve_scvt_hh, uint16_t, H1_2, int16_to_float16)
85
+DO_ZPZ_FP(sve_scvt_sh, uint32_t, H1_4, int32_to_float16)
86
+DO_ZPZ_FP(sve_scvt_ss, uint32_t, H1_4, int32_to_float32)
87
+DO_ZPZ_FP(sve_scvt_sd, uint64_t, , int32_to_float64)
88
+DO_ZPZ_FP(sve_scvt_dh, uint64_t, , int64_to_float16)
89
+DO_ZPZ_FP(sve_scvt_ds, uint64_t, , int64_to_float32)
90
+DO_ZPZ_FP(sve_scvt_dd, uint64_t, , int64_to_float64)
91
+
92
+DO_ZPZ_FP(sve_ucvt_hh, uint16_t, H1_2, uint16_to_float16)
93
+DO_ZPZ_FP(sve_ucvt_sh, uint32_t, H1_4, uint32_to_float16)
94
+DO_ZPZ_FP(sve_ucvt_ss, uint32_t, H1_4, uint32_to_float32)
95
+DO_ZPZ_FP(sve_ucvt_sd, uint64_t, , uint32_to_float64)
96
+DO_ZPZ_FP(sve_ucvt_dh, uint64_t, , uint64_to_float16)
97
+DO_ZPZ_FP(sve_ucvt_ds, uint64_t, , uint64_to_float32)
98
+DO_ZPZ_FP(sve_ucvt_dd, uint64_t, , uint64_to_float64)
99
+
100
+#undef DO_ZPZ_FP
101
+
102
/*
103
* Load contiguous data, protected by a governing predicate.
104
*/
105
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
29
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
106
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/translate-sve.c
31
--- a/target/arm/translate-sve.c
108
+++ b/target/arm/translate-sve.c
32
+++ b/target/arm/translate-sve.c
109
@@ -XXX,XX +XXX,XX @@ DO_FP3(FRSQRTS, rsqrts)
33
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_3_ptr * const ftmad_fns[4] = {
34
NULL, gen_helper_sve_ftmad_h,
35
gen_helper_sve_ftmad_s, gen_helper_sve_ftmad_d,
36
};
37
-TRANS_FEAT(FTMAD, aa64_sve, gen_gvec_fpst_zzz,
38
- ftmad_fns[a->esz], a->rd, a->rn, a->rm, a->imm,
39
- a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR)
40
+TRANS_FEAT_NONSTREAMING(FTMAD, aa64_sve, gen_gvec_fpst_zzz,
41
+ ftmad_fns[a->esz], a->rd, a->rn, a->rm, a->imm,
42
+ a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR)
43
44
/*
45
*** SVE Floating Point Accumulating Reduction Group
46
@@ -XXX,XX +XXX,XX @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a)
47
if (a->esz == 0 || !dc_isar_feature(aa64_sve, s)) {
48
return false;
49
}
50
+ s->is_nonstreaming = true;
51
if (!sve_access_check(s)) {
52
return true;
53
}
54
@@ -XXX,XX +XXX,XX @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a)
55
DO_FP3(FADD_zzz, fadd)
56
DO_FP3(FSUB_zzz, fsub)
57
DO_FP3(FMUL_zzz, fmul)
58
-DO_FP3(FTSMUL, ftsmul)
59
DO_FP3(FRECPS, recps)
60
DO_FP3(FRSQRTS, rsqrts)
110
61
111
#undef DO_FP3
62
#undef DO_FP3
112
63
113
+
64
+static gen_helper_gvec_3_ptr * const ftsmul_fns[4] = {
114
+/*
65
+ NULL, gen_helper_gvec_ftsmul_h,
115
+ *** SVE Floating Point Unary Operations Predicated Group
66
+ gen_helper_gvec_ftsmul_s, gen_helper_gvec_ftsmul_d
116
+ */
67
+};
117
+
68
+TRANS_FEAT_NONSTREAMING(FTSMUL, aa64_sve, gen_gvec_fpst_arg_zzz,
118
+static bool do_zpz_ptr(DisasContext *s, int rd, int rn, int pg,
69
+ ftsmul_fns[a->esz], a, 0)
119
+ bool is_fp16, gen_helper_gvec_3_ptr *fn)
120
+{
121
+ if (sve_access_check(s)) {
122
+ unsigned vsz = vec_full_reg_size(s);
123
+ TCGv_ptr status = get_fpstatus_ptr(is_fp16);
124
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
125
+ vec_full_reg_offset(s, rn),
126
+ pred_full_reg_offset(s, pg),
127
+ status, vsz, vsz, 0, fn);
128
+ tcg_temp_free_ptr(status);
129
+ }
130
+ return true;
131
+}
132
+
133
+static bool trans_SCVTF_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
134
+{
135
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_scvt_hh);
136
+}
137
+
138
+static bool trans_SCVTF_sh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
139
+{
140
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_scvt_sh);
141
+}
142
+
143
+static bool trans_SCVTF_dh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
144
+{
145
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_scvt_dh);
146
+}
147
+
148
+static bool trans_SCVTF_ss(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
149
+{
150
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_scvt_ss);
151
+}
152
+
153
+static bool trans_SCVTF_ds(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
154
+{
155
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_scvt_ds);
156
+}
157
+
158
+static bool trans_SCVTF_sd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
159
+{
160
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_scvt_sd);
161
+}
162
+
163
+static bool trans_SCVTF_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
164
+{
165
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_scvt_dd);
166
+}
167
+
168
+static bool trans_UCVTF_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
169
+{
170
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_ucvt_hh);
171
+}
172
+
173
+static bool trans_UCVTF_sh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
174
+{
175
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_ucvt_sh);
176
+}
177
+
178
+static bool trans_UCVTF_dh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
179
+{
180
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_ucvt_dh);
181
+}
182
+
183
+static bool trans_UCVTF_ss(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
184
+{
185
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_ucvt_ss);
186
+}
187
+
188
+static bool trans_UCVTF_ds(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
189
+{
190
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_ucvt_ds);
191
+}
192
+
193
+static bool trans_UCVTF_sd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
194
+{
195
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_ucvt_sd);
196
+}
197
+
198
+static bool trans_UCVTF_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
199
+{
200
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_ucvt_dd);
201
+}
202
+
70
+
203
/*
71
/*
204
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
72
*** SVE Floating Point Arithmetic - Predicated Group
205
*/
73
*/
206
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
207
index XXXXXXX..XXXXXXX 100644
208
--- a/target/arm/sve.decode
209
+++ b/target/arm/sve.decode
210
@@ -XXX,XX +XXX,XX @@
211
@rd_pg_rn ........ esz:2 ... ... ... pg:3 rn:5 rd:5 &rpr_esz
212
@rd_pg4_pn ........ esz:2 ... ... .. pg:4 . rn:4 rd:5 &rpr_esz
213
214
+# One register operand, with governing predicate, no vector element size
215
+@rd_pg_rn_e0 ........ .. ... ... ... pg:3 rn:5 rd:5 &rpr_esz esz=0
216
+
217
# Two register operands with a 6-bit signed immediate.
218
@rd_rn_i6 ........ ... rn:5 ..... imm:s6 rd:5 &rri
219
220
@@ -XXX,XX +XXX,XX @@ FTSMUL 01100101 .. 0 ..... 000 011 ..... ..... @rd_rn_rm
221
FRECPS 01100101 .. 0 ..... 000 110 ..... ..... @rd_rn_rm
222
FRSQRTS 01100101 .. 0 ..... 000 111 ..... ..... @rd_rn_rm
223
224
+### SVE FP Unary Operations Predicated Group
225
+
226
+# SVE integer convert to floating-point
227
+SCVTF_hh 01100101 01 010 01 0 101 ... ..... ..... @rd_pg_rn_e0
228
+SCVTF_sh 01100101 01 010 10 0 101 ... ..... ..... @rd_pg_rn_e0
229
+SCVTF_dh 01100101 01 010 11 0 101 ... ..... ..... @rd_pg_rn_e0
230
+SCVTF_ss 01100101 10 010 10 0 101 ... ..... ..... @rd_pg_rn_e0
231
+SCVTF_sd 01100101 11 010 00 0 101 ... ..... ..... @rd_pg_rn_e0
232
+SCVTF_ds 01100101 11 010 10 0 101 ... ..... ..... @rd_pg_rn_e0
233
+SCVTF_dd 01100101 11 010 11 0 101 ... ..... ..... @rd_pg_rn_e0
234
+
235
+UCVTF_hh 01100101 01 010 01 1 101 ... ..... ..... @rd_pg_rn_e0
236
+UCVTF_sh 01100101 01 010 10 1 101 ... ..... ..... @rd_pg_rn_e0
237
+UCVTF_dh 01100101 01 010 11 1 101 ... ..... ..... @rd_pg_rn_e0
238
+UCVTF_ss 01100101 10 010 10 1 101 ... ..... ..... @rd_pg_rn_e0
239
+UCVTF_sd 01100101 11 010 00 1 101 ... ..... ..... @rd_pg_rn_e0
240
+UCVTF_ds 01100101 11 010 10 1 101 ... ..... ..... @rd_pg_rn_e0
241
+UCVTF_dd 01100101 11 010 11 1 101 ... ..... ..... @rd_pg_rn_e0
242
+
243
### SVE Memory - 32-bit Gather and Unsized Contiguous Group
244
245
# SVE load predicate register
246
--
74
--
247
2.17.1
75
2.25.1
248
249
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Enhance the existing helpers to support SVE, which takes the
3
Mark these as a non-streaming instructions, which should trap
4
index from each 128-bit segment. The change has no effect
4
if full a64 support is not enabled in streaming mode.
5
for AdvSIMD, since there is only one such segment.
6
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220708151540.18136-10-richard.henderson@linaro.org
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Message-id: 20180627043328.11531-32-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/translate-sve.c | 23 ++++++++++++++++++
11
target/arm/sme-fa64.decode | 1 -
14
target/arm/vec_helper.c | 50 +++++++++++++++++++++++---------------
12
target/arm/translate-sve.c | 12 ++++++------
15
target/arm/sve.decode | 6 +++++
13
2 files changed, 6 insertions(+), 7 deletions(-)
16
3 files changed, 59 insertions(+), 20 deletions(-)
17
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 0100 0101 --0- ---- 1001 10-- ---- ---- # SMMLA, UMMLA, USMMLA
24
FAIL 0100 0101 --1- ---- 1--- ---- ---- ---- # SVE2 string/histo/crypto instructions
25
FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
26
FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
18
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
27
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
19
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate-sve.c
29
--- a/target/arm/translate-sve.c
21
+++ b/target/arm/translate-sve.c
30
+++ b/target/arm/translate-sve.c
22
@@ -XXX,XX +XXX,XX @@ static bool trans_FCMLA_zpzzz(DisasContext *s,
31
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(FMLALT_zzxw, aa64_sve2, do_FMLAL_zzxw, a, false, true)
23
return true;
32
TRANS_FEAT(FMLSLB_zzxw, aa64_sve2, do_FMLAL_zzxw, a, true, false)
24
}
33
TRANS_FEAT(FMLSLT_zzxw, aa64_sve2, do_FMLAL_zzxw, a, true, true)
25
34
26
+static bool trans_FCMLA_zzxz(DisasContext *s, arg_FCMLA_zzxz *a, uint32_t insn)
35
-TRANS_FEAT(SMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
27
+{
36
- gen_helper_gvec_smmla_b, a, 0)
28
+ static gen_helper_gvec_3_ptr * const fns[2] = {
37
-TRANS_FEAT(USMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
29
+ gen_helper_gvec_fcmlah_idx,
38
- gen_helper_gvec_usmmla_b, a, 0)
30
+ gen_helper_gvec_fcmlas_idx,
39
-TRANS_FEAT(UMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
31
+ };
40
- gen_helper_gvec_ummla_b, a, 0)
32
+
41
+TRANS_FEAT_NONSTREAMING(SMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
33
+ tcg_debug_assert(a->esz == 1 || a->esz == 2);
42
+ gen_helper_gvec_smmla_b, a, 0)
34
+ tcg_debug_assert(a->rd == a->ra);
43
+TRANS_FEAT_NONSTREAMING(USMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
35
+ if (sve_access_check(s)) {
44
+ gen_helper_gvec_usmmla_b, a, 0)
36
+ unsigned vsz = vec_full_reg_size(s);
45
+TRANS_FEAT_NONSTREAMING(UMMLA, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
37
+ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
46
+ gen_helper_gvec_ummla_b, a, 0)
38
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
47
39
+ vec_full_reg_offset(s, a->rn),
48
TRANS_FEAT(BFDOT_zzzz, aa64_sve_bf16, gen_gvec_ool_arg_zzzz,
40
+ vec_full_reg_offset(s, a->rm),
49
gen_helper_gvec_bfdot, a, 0)
41
+ status, vsz, vsz,
42
+ a->index * 4 + a->rot,
43
+ fns[a->esz - 1]);
44
+ tcg_temp_free_ptr(status);
45
+ }
46
+ return true;
47
+}
48
+
49
/*
50
*** SVE Floating Point Unary Operations Predicated Group
51
*/
52
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/vec_helper.c
55
+++ b/target/arm/vec_helper.c
56
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcmlah_idx)(void *vd, void *vn, void *vm,
57
uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
58
intptr_t index = extract32(desc, SIMD_DATA_SHIFT + 2, 2);
59
uint32_t neg_real = flip ^ neg_imag;
60
- uintptr_t i;
61
- float16 e1 = m[H2(2 * index + flip)];
62
- float16 e3 = m[H2(2 * index + 1 - flip)];
63
+ intptr_t elements = opr_sz / sizeof(float16);
64
+ intptr_t eltspersegment = 16 / sizeof(float16);
65
+ intptr_t i, j;
66
67
/* Shift boolean to the sign bit so we can xor to negate. */
68
neg_real <<= 15;
69
neg_imag <<= 15;
70
- e1 ^= neg_real;
71
- e3 ^= neg_imag;
72
73
- for (i = 0; i < opr_sz / 2; i += 2) {
74
- float16 e2 = n[H2(i + flip)];
75
- float16 e4 = e2;
76
+ for (i = 0; i < elements; i += eltspersegment) {
77
+ float16 mr = m[H2(i + 2 * index + 0)];
78
+ float16 mi = m[H2(i + 2 * index + 1)];
79
+ float16 e1 = neg_real ^ (flip ? mi : mr);
80
+ float16 e3 = neg_imag ^ (flip ? mr : mi);
81
82
- d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
83
- d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
84
+ for (j = i; j < i + eltspersegment; j += 2) {
85
+ float16 e2 = n[H2(j + flip)];
86
+ float16 e4 = e2;
87
+
88
+ d[H2(j)] = float16_muladd(e2, e1, d[H2(j)], 0, fpst);
89
+ d[H2(j + 1)] = float16_muladd(e4, e3, d[H2(j + 1)], 0, fpst);
90
+ }
91
}
92
clear_tail(d, opr_sz, simd_maxsz(desc));
93
}
94
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm,
95
uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
96
intptr_t index = extract32(desc, SIMD_DATA_SHIFT + 2, 2);
97
uint32_t neg_real = flip ^ neg_imag;
98
- uintptr_t i;
99
- float32 e1 = m[H4(2 * index + flip)];
100
- float32 e3 = m[H4(2 * index + 1 - flip)];
101
+ intptr_t elements = opr_sz / sizeof(float32);
102
+ intptr_t eltspersegment = 16 / sizeof(float32);
103
+ intptr_t i, j;
104
105
/* Shift boolean to the sign bit so we can xor to negate. */
106
neg_real <<= 31;
107
neg_imag <<= 31;
108
- e1 ^= neg_real;
109
- e3 ^= neg_imag;
110
111
- for (i = 0; i < opr_sz / 4; i += 2) {
112
- float32 e2 = n[H4(i + flip)];
113
- float32 e4 = e2;
114
+ for (i = 0; i < elements; i += eltspersegment) {
115
+ float32 mr = m[H4(i + 2 * index + 0)];
116
+ float32 mi = m[H4(i + 2 * index + 1)];
117
+ float32 e1 = neg_real ^ (flip ? mi : mr);
118
+ float32 e3 = neg_imag ^ (flip ? mr : mi);
119
120
- d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
121
- d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
122
+ for (j = i; j < i + eltspersegment; j += 2) {
123
+ float32 e2 = n[H4(j + flip)];
124
+ float32 e4 = e2;
125
+
126
+ d[H4(j)] = float32_muladd(e2, e1, d[H4(j)], 0, fpst);
127
+ d[H4(j + 1)] = float32_muladd(e4, e3, d[H4(j + 1)], 0, fpst);
128
+ }
129
}
130
clear_tail(d, opr_sz, simd_maxsz(desc));
131
}
132
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
133
index XXXXXXX..XXXXXXX 100644
134
--- a/target/arm/sve.decode
135
+++ b/target/arm/sve.decode
136
@@ -XXX,XX +XXX,XX @@ FCADD 01100100 esz:2 00000 rot:1 100 pg:3 rm:5 rd:5 \
137
FCMLA_zpzzz 01100100 esz:2 0 rm:5 0 rot:2 pg:3 rn:5 rd:5 \
138
ra=%reg_movprfx
139
140
+# SVE floating-point complex multiply-add (indexed)
141
+FCMLA_zzxz 01100100 10 1 index:2 rm:3 0001 rot:2 rn:5 rd:5 \
142
+ ra=%reg_movprfx esz=1
143
+FCMLA_zzxz 01100100 11 1 index:1 rm:4 0001 rot:2 rn:5 rd:5 \
144
+ ra=%reg_movprfx esz=2
145
+
146
### SVE FP Multiply-Add Indexed Group
147
148
# SVE floating-point multiply-add (indexed)
149
--
50
--
150
2.17.1
51
2.25.1
151
152
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Mark these as non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-17-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-11-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 49 ++++++++++++++++++++++++++++++
11
target/arm/sme-fa64.decode | 1 -
9
target/arm/sve_helper.c | 62 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-sve.c | 35 ++++++++++++++++++-----------------
10
target/arm/translate-sve.c | 40 ++++++++++++++++++++++++
13
2 files changed, 18 insertions(+), 18 deletions(-)
11
target/arm/sve.decode | 11 +++++++
12
4 files changed, 162 insertions(+)
13
14
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
17
--- a/target/arm/sme-fa64.decode
17
+++ b/target/arm/helper-sve.h
18
+++ b/target/arm/sme-fa64.decode
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_ucvt_ds, TCG_CALL_NO_RWG,
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
19
DEF_HELPER_FLAGS_5(sve_ucvt_dd, TCG_CALL_NO_RWG,
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
20
void, ptr, ptr, ptr, ptr, i32)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
21
22
22
+DEF_HELPER_FLAGS_6(sve_fcmge_h, TCG_CALL_NO_RWG,
23
-FAIL 0100 0101 --1- ---- 1--- ---- ---- ---- # SVE2 string/histo/crypto instructions
23
+ void, ptr, ptr, ptr, ptr, ptr, i32)
24
FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
24
+DEF_HELPER_FLAGS_6(sve_fcmge_s, TCG_CALL_NO_RWG,
25
FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
25
+ void, ptr, ptr, ptr, ptr, ptr, i32)
26
FAIL 1000 0100 0-1- ---- 0--- ---- ---- ---- # SVE 32-bit gather prefetch (scalar+vector)
26
+DEF_HELPER_FLAGS_6(sve_fcmge_d, TCG_CALL_NO_RWG,
27
+ void, ptr, ptr, ptr, ptr, ptr, i32)
28
+
29
+DEF_HELPER_FLAGS_6(sve_fcmgt_h, TCG_CALL_NO_RWG,
30
+ void, ptr, ptr, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_6(sve_fcmgt_s, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_6(sve_fcmgt_d, TCG_CALL_NO_RWG,
34
+ void, ptr, ptr, ptr, ptr, ptr, i32)
35
+
36
+DEF_HELPER_FLAGS_6(sve_fcmeq_h, TCG_CALL_NO_RWG,
37
+ void, ptr, ptr, ptr, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_6(sve_fcmeq_s, TCG_CALL_NO_RWG,
39
+ void, ptr, ptr, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_6(sve_fcmeq_d, TCG_CALL_NO_RWG,
41
+ void, ptr, ptr, ptr, ptr, ptr, i32)
42
+
43
+DEF_HELPER_FLAGS_6(sve_fcmne_h, TCG_CALL_NO_RWG,
44
+ void, ptr, ptr, ptr, ptr, ptr, i32)
45
+DEF_HELPER_FLAGS_6(sve_fcmne_s, TCG_CALL_NO_RWG,
46
+ void, ptr, ptr, ptr, ptr, ptr, i32)
47
+DEF_HELPER_FLAGS_6(sve_fcmne_d, TCG_CALL_NO_RWG,
48
+ void, ptr, ptr, ptr, ptr, ptr, i32)
49
+
50
+DEF_HELPER_FLAGS_6(sve_fcmuo_h, TCG_CALL_NO_RWG,
51
+ void, ptr, ptr, ptr, ptr, ptr, i32)
52
+DEF_HELPER_FLAGS_6(sve_fcmuo_s, TCG_CALL_NO_RWG,
53
+ void, ptr, ptr, ptr, ptr, ptr, i32)
54
+DEF_HELPER_FLAGS_6(sve_fcmuo_d, TCG_CALL_NO_RWG,
55
+ void, ptr, ptr, ptr, ptr, ptr, i32)
56
+
57
+DEF_HELPER_FLAGS_6(sve_facge_h, TCG_CALL_NO_RWG,
58
+ void, ptr, ptr, ptr, ptr, ptr, i32)
59
+DEF_HELPER_FLAGS_6(sve_facge_s, TCG_CALL_NO_RWG,
60
+ void, ptr, ptr, ptr, ptr, ptr, i32)
61
+DEF_HELPER_FLAGS_6(sve_facge_d, TCG_CALL_NO_RWG,
62
+ void, ptr, ptr, ptr, ptr, ptr, i32)
63
+
64
+DEF_HELPER_FLAGS_6(sve_facgt_h, TCG_CALL_NO_RWG,
65
+ void, ptr, ptr, ptr, ptr, ptr, i32)
66
+DEF_HELPER_FLAGS_6(sve_facgt_s, TCG_CALL_NO_RWG,
67
+ void, ptr, ptr, ptr, ptr, ptr, i32)
68
+DEF_HELPER_FLAGS_6(sve_facgt_d, TCG_CALL_NO_RWG,
69
+ void, ptr, ptr, ptr, ptr, ptr, i32)
70
+
71
DEF_HELPER_FLAGS_3(sve_fmla_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32)
72
DEF_HELPER_FLAGS_3(sve_fmla_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32)
73
DEF_HELPER_FLAGS_3(sve_fmla_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32)
74
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/sve_helper.c
77
+++ b/target/arm/sve_helper.c
78
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_fnmls_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc)
79
do_fmla_zpzzz_d(env, vg, desc, 0, INT64_MIN);
80
}
81
82
+/* Two operand floating-point comparison controlled by a predicate.
83
+ * Unlike the integer version, we are not allowed to optimistically
84
+ * compare operands, since the comparison may have side effects wrt
85
+ * the FPSR.
86
+ */
87
+#define DO_FPCMP_PPZZ(NAME, TYPE, H, OP) \
88
+void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, \
89
+ void *status, uint32_t desc) \
90
+{ \
91
+ intptr_t i = simd_oprsz(desc), j = (i - 1) >> 6; \
92
+ uint64_t *d = vd, *g = vg; \
93
+ do { \
94
+ uint64_t out = 0, pg = g[j]; \
95
+ do { \
96
+ i -= sizeof(TYPE), out <<= sizeof(TYPE); \
97
+ if (likely((pg >> (i & 63)) & 1)) { \
98
+ TYPE nn = *(TYPE *)(vn + H(i)); \
99
+ TYPE mm = *(TYPE *)(vm + H(i)); \
100
+ out |= OP(TYPE, nn, mm, status); \
101
+ } \
102
+ } while (i & 63); \
103
+ d[j--] = out; \
104
+ } while (i > 0); \
105
+}
106
+
107
+#define DO_FPCMP_PPZZ_H(NAME, OP) \
108
+ DO_FPCMP_PPZZ(NAME##_h, float16, H1_2, OP)
109
+#define DO_FPCMP_PPZZ_S(NAME, OP) \
110
+ DO_FPCMP_PPZZ(NAME##_s, float32, H1_4, OP)
111
+#define DO_FPCMP_PPZZ_D(NAME, OP) \
112
+ DO_FPCMP_PPZZ(NAME##_d, float64, , OP)
113
+
114
+#define DO_FPCMP_PPZZ_ALL(NAME, OP) \
115
+ DO_FPCMP_PPZZ_H(NAME, OP) \
116
+ DO_FPCMP_PPZZ_S(NAME, OP) \
117
+ DO_FPCMP_PPZZ_D(NAME, OP)
118
+
119
+#define DO_FCMGE(TYPE, X, Y, ST) TYPE##_compare(Y, X, ST) <= 0
120
+#define DO_FCMGT(TYPE, X, Y, ST) TYPE##_compare(Y, X, ST) < 0
121
+#define DO_FCMEQ(TYPE, X, Y, ST) TYPE##_compare_quiet(X, Y, ST) == 0
122
+#define DO_FCMNE(TYPE, X, Y, ST) TYPE##_compare_quiet(X, Y, ST) != 0
123
+#define DO_FCMUO(TYPE, X, Y, ST) \
124
+ TYPE##_compare_quiet(X, Y, ST) == float_relation_unordered
125
+#define DO_FACGE(TYPE, X, Y, ST) \
126
+ TYPE##_compare(TYPE##_abs(Y), TYPE##_abs(X), ST) <= 0
127
+#define DO_FACGT(TYPE, X, Y, ST) \
128
+ TYPE##_compare(TYPE##_abs(Y), TYPE##_abs(X), ST) < 0
129
+
130
+DO_FPCMP_PPZZ_ALL(sve_fcmge, DO_FCMGE)
131
+DO_FPCMP_PPZZ_ALL(sve_fcmgt, DO_FCMGT)
132
+DO_FPCMP_PPZZ_ALL(sve_fcmeq, DO_FCMEQ)
133
+DO_FPCMP_PPZZ_ALL(sve_fcmne, DO_FCMNE)
134
+DO_FPCMP_PPZZ_ALL(sve_fcmuo, DO_FCMUO)
135
+DO_FPCMP_PPZZ_ALL(sve_facge, DO_FACGE)
136
+DO_FPCMP_PPZZ_ALL(sve_facgt, DO_FACGT)
137
+
138
+#undef DO_FPCMP_PPZZ_ALL
139
+#undef DO_FPCMP_PPZZ_D
140
+#undef DO_FPCMP_PPZZ_S
141
+#undef DO_FPCMP_PPZZ_H
142
+#undef DO_FPCMP_PPZZ
143
+
144
/*
145
* Load contiguous data, protected by a governing predicate.
146
*/
147
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
27
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
148
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
149
--- a/target/arm/translate-sve.c
29
--- a/target/arm/translate-sve.c
150
+++ b/target/arm/translate-sve.c
30
+++ b/target/arm/translate-sve.c
151
@@ -XXX,XX +XXX,XX @@ DO_FP3(FMULX, fmulx)
31
@@ -XXX,XX +XXX,XX @@ DO_SVE2_ZZZ_NARROW(RSUBHNT, rsubhnt)
152
32
static gen_helper_gvec_flags_4 * const match_fns[4] = {
153
#undef DO_FP3
33
gen_helper_sve2_match_ppzz_b, gen_helper_sve2_match_ppzz_h, NULL, NULL
154
34
};
155
+static bool do_fp_cmp(DisasContext *s, arg_rprr_esz *a,
35
-TRANS_FEAT(MATCH, aa64_sve2, do_ppzz_flags, a, match_fns[a->esz])
156
+ gen_helper_gvec_4_ptr *fn)
36
+TRANS_FEAT_NONSTREAMING(MATCH, aa64_sve2, do_ppzz_flags, a, match_fns[a->esz])
157
+{
37
158
+ if (fn == NULL) {
38
static gen_helper_gvec_flags_4 * const nmatch_fns[4] = {
159
+ return false;
39
gen_helper_sve2_nmatch_ppzz_b, gen_helper_sve2_nmatch_ppzz_h, NULL, NULL
160
+ }
40
};
161
+ if (sve_access_check(s)) {
41
-TRANS_FEAT(NMATCH, aa64_sve2, do_ppzz_flags, a, nmatch_fns[a->esz])
162
+ unsigned vsz = vec_full_reg_size(s);
42
+TRANS_FEAT_NONSTREAMING(NMATCH, aa64_sve2, do_ppzz_flags, a, nmatch_fns[a->esz])
163
+ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
43
164
+ tcg_gen_gvec_4_ptr(pred_full_reg_offset(s, a->rd),
44
static gen_helper_gvec_4 * const histcnt_fns[4] = {
165
+ vec_full_reg_offset(s, a->rn),
45
NULL, NULL, gen_helper_sve2_histcnt_s, gen_helper_sve2_histcnt_d
166
+ vec_full_reg_offset(s, a->rm),
46
};
167
+ pred_full_reg_offset(s, a->pg),
47
-TRANS_FEAT(HISTCNT, aa64_sve2, gen_gvec_ool_arg_zpzz,
168
+ status, vsz, vsz, 0, fn);
48
- histcnt_fns[a->esz], a, 0)
169
+ tcg_temp_free_ptr(status);
49
+TRANS_FEAT_NONSTREAMING(HISTCNT, aa64_sve2, gen_gvec_ool_arg_zpzz,
170
+ }
50
+ histcnt_fns[a->esz], a, 0)
171
+ return true;
51
172
+}
52
-TRANS_FEAT(HISTSEG, aa64_sve2, gen_gvec_ool_arg_zzz,
173
+
53
- a->esz == 0 ? gen_helper_sve2_histseg : NULL, a, 0)
174
+#define DO_FPCMP(NAME, name) \
54
+TRANS_FEAT_NONSTREAMING(HISTSEG, aa64_sve2, gen_gvec_ool_arg_zzz,
175
+static bool trans_##NAME##_ppzz(DisasContext *s, arg_rprr_esz *a, \
55
+ a->esz == 0 ? gen_helper_sve2_histseg : NULL, a, 0)
176
+ uint32_t insn) \
56
177
+{ \
57
DO_ZPZZ_FP(FADDP, aa64_sve2, sve2_faddp_zpzz)
178
+ static gen_helper_gvec_4_ptr * const fns[4] = { \
58
DO_ZPZZ_FP(FMAXNMP, aa64_sve2, sve2_fmaxnmp_zpzz)
179
+ NULL, gen_helper_sve_##name##_h, \
59
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(SQRDCMLAH_zzzz, aa64_sve2, gen_gvec_ool_zzzz,
180
+ gen_helper_sve_##name##_s, gen_helper_sve_##name##_d \
60
TRANS_FEAT(USDOT_zzzz, aa64_sve_i8mm, gen_gvec_ool_arg_zzzz,
181
+ }; \
61
a->esz == 2 ? gen_helper_gvec_usdot_b : NULL, a, 0)
182
+ return do_fp_cmp(s, a, fns[a->esz]); \
62
183
+}
63
-TRANS_FEAT(AESMC, aa64_sve2_aes, gen_gvec_ool_zz,
184
+
64
- gen_helper_crypto_aesmc, a->rd, a->rd, a->decrypt)
185
+DO_FPCMP(FCMGE, fcmge)
65
+TRANS_FEAT_NONSTREAMING(AESMC, aa64_sve2_aes, gen_gvec_ool_zz,
186
+DO_FPCMP(FCMGT, fcmgt)
66
+ gen_helper_crypto_aesmc, a->rd, a->rd, a->decrypt)
187
+DO_FPCMP(FCMEQ, fcmeq)
67
188
+DO_FPCMP(FCMNE, fcmne)
68
-TRANS_FEAT(AESE, aa64_sve2_aes, gen_gvec_ool_arg_zzz,
189
+DO_FPCMP(FCMUO, fcmuo)
69
- gen_helper_crypto_aese, a, false)
190
+DO_FPCMP(FACGE, facge)
70
-TRANS_FEAT(AESD, aa64_sve2_aes, gen_gvec_ool_arg_zzz,
191
+DO_FPCMP(FACGT, facgt)
71
- gen_helper_crypto_aese, a, true)
192
+
72
+TRANS_FEAT_NONSTREAMING(AESE, aa64_sve2_aes, gen_gvec_ool_arg_zzz,
193
+#undef DO_FPCMP
73
+ gen_helper_crypto_aese, a, false)
194
+
74
+TRANS_FEAT_NONSTREAMING(AESD, aa64_sve2_aes, gen_gvec_ool_arg_zzz,
195
typedef void gen_helper_sve_fmla(TCGv_env, TCGv_ptr, TCGv_i32);
75
+ gen_helper_crypto_aese, a, true)
196
76
197
static bool do_fmla(DisasContext *s, arg_rprrr_esz *a, gen_helper_sve_fmla *fn)
77
-TRANS_FEAT(SM4E, aa64_sve2_sm4, gen_gvec_ool_arg_zzz,
198
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
78
- gen_helper_crypto_sm4e, a, 0)
199
index XXXXXXX..XXXXXXX 100644
79
-TRANS_FEAT(SM4EKEY, aa64_sve2_sm4, gen_gvec_ool_arg_zzz,
200
--- a/target/arm/sve.decode
80
- gen_helper_crypto_sm4ekey, a, 0)
201
+++ b/target/arm/sve.decode
81
+TRANS_FEAT_NONSTREAMING(SM4E, aa64_sve2_sm4, gen_gvec_ool_arg_zzz,
202
@@ -XXX,XX +XXX,XX @@ UXTH 00000100 .. 010 011 101 ... ..... ..... @rd_pg_rn
82
+ gen_helper_crypto_sm4e, a, 0)
203
SXTW 00000100 .. 010 100 101 ... ..... ..... @rd_pg_rn
83
+TRANS_FEAT_NONSTREAMING(SM4EKEY, aa64_sve2_sm4, gen_gvec_ool_arg_zzz,
204
UXTW 00000100 .. 010 101 101 ... ..... ..... @rd_pg_rn
84
+ gen_helper_crypto_sm4ekey, a, 0)
205
85
206
+### SVE Floating Point Compare - Vectors Group
86
-TRANS_FEAT(RAX1, aa64_sve2_sha3, gen_gvec_fn_arg_zzz, gen_gvec_rax1, a)
207
+
87
+TRANS_FEAT_NONSTREAMING(RAX1, aa64_sve2_sha3, gen_gvec_fn_arg_zzz,
208
+# SVE floating-point compare vectors
88
+ gen_gvec_rax1, a)
209
+FCMGE_ppzz 01100101 .. 0 ..... 010 ... ..... 0 .... @pd_pg_rn_rm
89
210
+FCMGT_ppzz 01100101 .. 0 ..... 010 ... ..... 1 .... @pd_pg_rn_rm
90
TRANS_FEAT(FCVTNT_sh, aa64_sve2, gen_gvec_fpst_arg_zpz,
211
+FCMEQ_ppzz 01100101 .. 0 ..... 011 ... ..... 0 .... @pd_pg_rn_rm
91
gen_helper_sve2_fcvtnt_sh, a, 0, FPST_FPCR)
212
+FCMNE_ppzz 01100101 .. 0 ..... 011 ... ..... 1 .... @pd_pg_rn_rm
213
+FCMUO_ppzz 01100101 .. 0 ..... 110 ... ..... 0 .... @pd_pg_rn_rm
214
+FACGE_ppzz 01100101 .. 0 ..... 110 ... ..... 1 .... @pd_pg_rn_rm
215
+FACGT_ppzz 01100101 .. 0 ..... 111 ... ..... 1 .... @pd_pg_rn_rm
216
+
217
### SVE Integer Multiply-Add Group
218
219
# SVE integer multiply-add writing addend (predicated)
220
--
92
--
221
2.17.1
93
2.25.1
222
223
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-28-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-12-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/translate-sve.c | 60 +++++++++++++++++++++++++++++++++++++-
11
target/arm/sme-fa64.decode | 9 ---------
9
target/arm/sve.decode | 7 +++++
12
target/arm/translate-sve.c | 6 ++++++
10
2 files changed, 66 insertions(+), 1 deletion(-)
13
2 files changed, 6 insertions(+), 9 deletions(-)
11
14
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sme-fa64.decode
18
+++ b/target/arm/sme-fa64.decode
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
23
-FAIL 1000 010- -00- ---- 10-- ---- ---- ---- # SVE2 32-bit gather NT load (vector+scalar)
24
FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
25
FAIL 1000 0100 0-1- ---- 0--- ---- ---- ---- # SVE 32-bit gather prefetch (scalar+vector)
26
-FAIL 1000 010- -01- ---- 1--- ---- ---- ---- # SVE 32-bit gather load (vector+imm)
27
-FAIL 1000 0100 0-0- ---- 0--- ---- ---- ---- # SVE 32-bit gather load byte (scalar+vector)
28
-FAIL 1000 0100 1--- ---- 0--- ---- ---- ---- # SVE 32-bit gather load half (scalar+vector)
29
-FAIL 1000 0101 0--- ---- 0--- ---- ---- ---- # SVE 32-bit gather load word (scalar+vector)
30
FAIL 1010 010- ---- ---- 011- ---- ---- ---- # SVE contiguous FF load (scalar+scalar)
31
FAIL 1010 010- ---1 ---- 101- ---- ---- ---- # SVE contiguous NF load (scalar+imm)
32
FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
33
FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
34
FAIL 1100 010- ---- ---- ---- ---- ---- ---- # SVE 64-bit gather load/prefetch
35
-FAIL 1110 010- -00- ---- 001- ---- ---- ---- # SVE2 64-bit scatter NT store (vector+scalar)
36
-FAIL 1110 010- -10- ---- 001- ---- ---- ---- # SVE2 32-bit scatter NT store (vector+scalar)
37
-FAIL 1110 010- ---- ---- 1-0- ---- ---- ---- # SVE scatter store (scalar+32-bit vector)
38
-FAIL 1110 010- ---- ---- 101- ---- ---- ---- # SVE scatter store (misc)
12
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
39
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
13
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-sve.c
41
--- a/target/arm/translate-sve.c
15
+++ b/target/arm/translate-sve.c
42
+++ b/target/arm/translate-sve.c
16
@@ -XXX,XX +XXX,XX @@ static bool do_zpzz_ool(DisasContext *s, arg_rprr_esz *a, gen_helper_gvec_4 *fn)
43
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a)
17
return true;
44
if (!dc_isar_feature(aa64_sve, s)) {
18
}
45
return false;
19
46
}
20
+/* Select active elememnts from Zn and inactive elements from Zm,
47
+ s->is_nonstreaming = true;
21
+ * storing the result in Zd.
48
if (!sve_access_check(s)) {
22
+ */
49
return true;
23
+static void do_sel_z(DisasContext *s, int rd, int rn, int rm, int pg, int esz)
50
}
24
+{
51
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a)
25
+ static gen_helper_gvec_4 * const fns[4] = {
52
if (!dc_isar_feature(aa64_sve, s)) {
26
+ gen_helper_sve_sel_zpzz_b, gen_helper_sve_sel_zpzz_h,
53
return false;
27
+ gen_helper_sve_sel_zpzz_s, gen_helper_sve_sel_zpzz_d
54
}
28
+ };
55
+ s->is_nonstreaming = true;
29
+ unsigned vsz = vec_full_reg_size(s);
56
if (!sve_access_check(s)) {
30
+ tcg_gen_gvec_4_ool(vec_full_reg_offset(s, rd),
57
return true;
31
+ vec_full_reg_offset(s, rn),
58
}
32
+ vec_full_reg_offset(s, rm),
59
@@ -XXX,XX +XXX,XX @@ static bool trans_LDNT1_zprz(DisasContext *s, arg_LD1_zprz *a)
33
+ pred_full_reg_offset(s, pg),
60
if (!dc_isar_feature(aa64_sve2, s)) {
34
+ vsz, vsz, 0, fns[esz]);
61
return false;
35
+}
62
}
36
+
63
+ s->is_nonstreaming = true;
37
#define DO_ZPZZ(NAME, name) \
64
if (!sve_access_check(s)) {
38
static bool trans_##NAME##_zpzz(DisasContext *s, arg_rprr_esz *a, \
65
return true;
39
uint32_t insn) \
66
}
40
@@ -XXX,XX +XXX,XX @@ static bool trans_UDIV_zpzz(DisasContext *s, arg_rprr_esz *a, uint32_t insn)
67
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a)
41
return do_zpzz_ool(s, a, fns[a->esz]);
68
if (!dc_isar_feature(aa64_sve, s)) {
42
}
69
return false;
43
70
}
44
-DO_ZPZZ(SEL, sel)
71
+ s->is_nonstreaming = true;
45
+static bool trans_SEL_zpzz(DisasContext *s, arg_rprr_esz *a, uint32_t insn)
72
if (!sve_access_check(s)) {
46
+{
73
return true;
47
+ if (sve_access_check(s)) {
74
}
48
+ do_sel_z(s, a->rd, a->rn, a->rm, a->pg, a->esz);
75
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a)
49
+ }
76
if (!dc_isar_feature(aa64_sve, s)) {
50
+ return true;
77
return false;
51
+}
78
}
52
79
+ s->is_nonstreaming = true;
53
#undef DO_ZPZZ
80
if (!sve_access_check(s)) {
54
81
return true;
55
@@ -XXX,XX +XXX,XX @@ static bool trans_PRF_rr(DisasContext *s, arg_PRF_rr *a, uint32_t insn)
82
}
56
sve_access_check(s);
83
@@ -XXX,XX +XXX,XX @@ static bool trans_STNT1_zprz(DisasContext *s, arg_ST1_zprz *a)
57
return true;
84
if (!dc_isar_feature(aa64_sve2, s)) {
58
}
85
return false;
59
+
86
}
60
+/*
87
+ s->is_nonstreaming = true;
61
+ * Move Prefix
88
if (!sve_access_check(s)) {
62
+ *
89
return true;
63
+ * TODO: The implementation so far could handle predicated merging movprfx.
90
}
64
+ * The helper functions as written take an extra source register to
65
+ * use in the operation, but the result is only written when predication
66
+ * succeeds. For unpredicated movprfx, we need to rearrange the helpers
67
+ * to allow the final write back to the destination to be unconditional.
68
+ * For predicated zeroing movprfx, we need to rearrange the helpers to
69
+ * allow the final write back to zero inactives.
70
+ *
71
+ * In the meantime, just emit the moves.
72
+ */
73
+
74
+static bool trans_MOVPRFX(DisasContext *s, arg_MOVPRFX *a, uint32_t insn)
75
+{
76
+ return do_mov_z(s, a->rd, a->rn);
77
+}
78
+
79
+static bool trans_MOVPRFX_m(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
80
+{
81
+ if (sve_access_check(s)) {
82
+ do_sel_z(s, a->rd, a->rn, a->rd, a->pg, a->esz);
83
+ }
84
+ return true;
85
+}
86
+
87
+static bool trans_MOVPRFX_z(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
88
+{
89
+ if (sve_access_check(s)) {
90
+ do_movz_zpz(s, a->rd, a->rn, a->pg, a->esz);
91
+ }
92
+ return true;
93
+}
94
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
95
index XXXXXXX..XXXXXXX 100644
96
--- a/target/arm/sve.decode
97
+++ b/target/arm/sve.decode
98
@@ -XXX,XX +XXX,XX @@ ORV 00000100 .. 011 000 001 ... ..... ..... @rd_pg_rn
99
EORV 00000100 .. 011 001 001 ... ..... ..... @rd_pg_rn
100
ANDV 00000100 .. 011 010 001 ... ..... ..... @rd_pg_rn
101
102
+# SVE constructive prefix (predicated)
103
+MOVPRFX_z 00000100 .. 010 000 001 ... ..... ..... @rd_pg_rn
104
+MOVPRFX_m 00000100 .. 010 001 001 ... ..... ..... @rd_pg_rn
105
+
106
# SVE integer add reduction (predicated)
107
# Note that saddv requires size != 3.
108
UADDV 00000100 .. 000 001 001 ... ..... ..... @rd_pg_rn
109
@@ -XXX,XX +XXX,XX @@ ADR_p64 00000100 11 1 ..... 1010 .. ..... ..... @rd_rn_msz_rm
110
111
### SVE Integer Misc - Unpredicated Group
112
113
+# SVE constructive prefix (unpredicated)
114
+MOVPRFX 00000100 00 1 00000 101111 rn:5 rd:5
115
+
116
# SVE floating-point exponential accelerator
117
# Note esz != 0
118
FEXPA 00000100 .. 1 00000 101110 ..... ..... @rd_rn
119
--
91
--
120
2.17.1
92
2.25.1
121
122
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Mark these as a non-streaming instructions, which should trap if full
4
a64 support is not enabled in streaming mode. In this case, introduce
5
PRF_ns (prefetch non-streaming) to handle the checks.
2
6
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-16-richard.henderson@linaro.org
9
Message-id: 20220708151540.18136-13-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
target/arm/translate-sve.c | 85 ++++++++++++++++++++++++++------------
12
target/arm/sme-fa64.decode | 3 ---
9
target/arm/sve.decode | 11 +++++
13
target/arm/sve.decode | 10 +++++-----
10
2 files changed, 70 insertions(+), 26 deletions(-)
14
target/arm/translate-sve.c | 11 +++++++++++
15
3 files changed, 16 insertions(+), 8 deletions(-)
11
16
17
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/sme-fa64.decode
20
+++ b/target/arm/sme-fa64.decode
21
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
22
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
23
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
24
25
-FAIL 1000 010- -00- ---- 111- ---- ---- ---- # SVE 32-bit gather prefetch (vector+imm)
26
-FAIL 1000 0100 0-1- ---- 0--- ---- ---- ---- # SVE 32-bit gather prefetch (scalar+vector)
27
FAIL 1010 010- ---- ---- 011- ---- ---- ---- # SVE contiguous FF load (scalar+scalar)
28
FAIL 1010 010- ---1 ---- 101- ---- ---- ---- # SVE contiguous NF load (scalar+imm)
29
FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
30
FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
31
-FAIL 1100 010- ---- ---- ---- ---- ---- ---- # SVE 64-bit gather load/prefetch
32
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/sve.decode
35
+++ b/target/arm/sve.decode
36
@@ -XXX,XX +XXX,XX @@ LD1RO_zpri 1010010 .. 01 0.... 001 ... ..... ..... \
37
@rpri_load_msz nreg=0
38
39
# SVE 32-bit gather prefetch (scalar plus 32-bit scaled offsets)
40
-PRF 1000010 00 -1 ----- 0-- --- ----- 0 ----
41
+PRF_ns 1000010 00 -1 ----- 0-- --- ----- 0 ----
42
43
# SVE 32-bit gather prefetch (vector plus immediate)
44
-PRF 1000010 -- 00 ----- 111 --- ----- 0 ----
45
+PRF_ns 1000010 -- 00 ----- 111 --- ----- 0 ----
46
47
# SVE contiguous prefetch (scalar plus immediate)
48
PRF 1000010 11 1- ----- 0-- --- ----- 0 ----
49
@@ -XXX,XX +XXX,XX @@ LD1_zpiz 1100010 .. 01 ..... 1.. ... ..... ..... \
50
@rpri_g_load esz=3
51
52
# SVE 64-bit gather prefetch (scalar plus 64-bit scaled offsets)
53
-PRF 1100010 00 11 ----- 1-- --- ----- 0 ----
54
+PRF_ns 1100010 00 11 ----- 1-- --- ----- 0 ----
55
56
# SVE 64-bit gather prefetch (scalar plus unpacked 32-bit scaled offsets)
57
-PRF 1100010 00 -1 ----- 0-- --- ----- 0 ----
58
+PRF_ns 1100010 00 -1 ----- 0-- --- ----- 0 ----
59
60
# SVE 64-bit gather prefetch (vector plus immediate)
61
-PRF 1100010 -- 00 ----- 111 --- ----- 0 ----
62
+PRF_ns 1100010 -- 00 ----- 111 --- ----- 0 ----
63
64
### SVE Memory Store Group
65
12
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
66
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
13
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-sve.c
68
--- a/target/arm/translate-sve.c
15
+++ b/target/arm/translate-sve.c
69
+++ b/target/arm/translate-sve.c
16
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a, uint32_t insn)
70
@@ -XXX,XX +XXX,XX @@ static bool trans_PRF_rr(DisasContext *s, arg_PRF_rr *a)
17
return true;
71
return true;
18
}
72
}
19
73
20
+/* Indexed by [xs][msz]. */
74
+static bool trans_PRF_ns(DisasContext *s, arg_PRF_ns *a)
21
+static gen_helper_gvec_mem_scatter * const scatter_store_fn32[2][3] = {
22
+ { gen_helper_sve_stbs_zsu,
23
+ gen_helper_sve_sths_zsu,
24
+ gen_helper_sve_stss_zsu, },
25
+ { gen_helper_sve_stbs_zss,
26
+ gen_helper_sve_sths_zss,
27
+ gen_helper_sve_stss_zss, },
28
+};
29
+
30
+/* Note that we overload xs=2 to indicate 64-bit offset. */
31
+static gen_helper_gvec_mem_scatter * const scatter_store_fn64[3][4] = {
32
+ { gen_helper_sve_stbd_zsu,
33
+ gen_helper_sve_sthd_zsu,
34
+ gen_helper_sve_stsd_zsu,
35
+ gen_helper_sve_stdd_zsu, },
36
+ { gen_helper_sve_stbd_zss,
37
+ gen_helper_sve_sthd_zss,
38
+ gen_helper_sve_stsd_zss,
39
+ gen_helper_sve_stdd_zss, },
40
+ { gen_helper_sve_stbd_zd,
41
+ gen_helper_sve_sthd_zd,
42
+ gen_helper_sve_stsd_zd,
43
+ gen_helper_sve_stdd_zd, },
44
+};
45
+
46
static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
47
{
48
- /* Indexed by [xs][msz]. */
49
- static gen_helper_gvec_mem_scatter * const fn32[2][3] = {
50
- { gen_helper_sve_stbs_zsu,
51
- gen_helper_sve_sths_zsu,
52
- gen_helper_sve_stss_zsu, },
53
- { gen_helper_sve_stbs_zss,
54
- gen_helper_sve_sths_zss,
55
- gen_helper_sve_stss_zss, },
56
- };
57
- /* Note that we overload xs=2 to indicate 64-bit offset. */
58
- static gen_helper_gvec_mem_scatter * const fn64[3][4] = {
59
- { gen_helper_sve_stbd_zsu,
60
- gen_helper_sve_sthd_zsu,
61
- gen_helper_sve_stsd_zsu,
62
- gen_helper_sve_stdd_zsu, },
63
- { gen_helper_sve_stbd_zss,
64
- gen_helper_sve_sthd_zss,
65
- gen_helper_sve_stsd_zss,
66
- gen_helper_sve_stdd_zss, },
67
- { gen_helper_sve_stbd_zd,
68
- gen_helper_sve_sthd_zd,
69
- gen_helper_sve_stsd_zd,
70
- gen_helper_sve_stdd_zd, },
71
- };
72
gen_helper_gvec_mem_scatter *fn;
73
74
if (a->esz < a->msz || (a->msz == 0 && a->scale)) {
75
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
76
}
77
switch (a->esz) {
78
case MO_32:
79
- fn = fn32[a->xs][a->msz];
80
+ fn = scatter_store_fn32[a->xs][a->msz];
81
break;
82
case MO_64:
83
- fn = fn64[a->xs][a->msz];
84
+ fn = scatter_store_fn64[a->xs][a->msz];
85
break;
86
default:
87
g_assert_not_reached();
88
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
89
return true;
90
}
91
92
+static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a, uint32_t insn)
93
+{
75
+{
94
+ gen_helper_gvec_mem_scatter *fn = NULL;
76
+ if (!dc_isar_feature(aa64_sve, s)) {
95
+ TCGv_i64 imm;
96
+
97
+ if (a->esz < a->msz) {
98
+ return false;
77
+ return false;
99
+ }
78
+ }
100
+ if (!sve_access_check(s)) {
79
+ /* Prefetch is a nop within QEMU. */
101
+ return true;
80
+ s->is_nonstreaming = true;
102
+ }
81
+ (void)sve_access_check(s);
103
+
104
+ switch (a->esz) {
105
+ case MO_32:
106
+ fn = scatter_store_fn32[0][a->msz];
107
+ break;
108
+ case MO_64:
109
+ fn = scatter_store_fn64[2][a->msz];
110
+ break;
111
+ }
112
+ assert(fn != NULL);
113
+
114
+ /* Treat ST1_zpiz (zn[x] + imm) the same way as ST1_zprz (rn + zm[x])
115
+ * by loading the immediate into the scalar parameter.
116
+ */
117
+ imm = tcg_const_i64(a->imm << a->msz);
118
+ do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, fn);
119
+ tcg_temp_free_i64(imm);
120
+ return true;
82
+ return true;
121
+}
83
+}
122
+
84
+
123
/*
85
/*
124
* Prefetches
86
* Move Prefix
125
*/
87
*
126
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
127
index XXXXXXX..XXXXXXX 100644
128
--- a/target/arm/sve.decode
129
+++ b/target/arm/sve.decode
130
@@ -XXX,XX +XXX,XX @@
131
&rprr_gather_load rd pg rn rm esz msz u ff xs scale
132
&rpri_gather_load rd pg rn imm esz msz u ff
133
&rprr_scatter_store rd pg rn rm esz msz xs scale
134
+&rpri_scatter_store rd pg rn imm esz msz
135
136
###########################################################################
137
# Named instruction formats. These are generally used to
138
@@ -XXX,XX +XXX,XX @@
139
&rprr_store nreg=0
140
@rprr_scatter_store ....... msz:2 .. rm:5 ... pg:3 rn:5 rd:5 \
141
&rprr_scatter_store
142
+@rpri_scatter_store ....... msz:2 .. imm:5 ... pg:3 rn:5 rd:5 \
143
+ &rpri_scatter_store
144
145
###########################################################################
146
# Instruction patterns. Grouped according to the SVE encodingindex.xhtml.
147
@@ -XXX,XX +XXX,XX @@ ST1_zprz 1110010 .. 01 ..... 101 ... ..... ..... \
148
ST1_zprz 1110010 .. 00 ..... 101 ... ..... ..... \
149
@rprr_scatter_store xs=2 esz=3 scale=0
150
151
+# SVE 64-bit scatter store (vector plus immediate)
152
+ST1_zpiz 1110010 .. 10 ..... 101 ... ..... ..... \
153
+ @rpri_scatter_store esz=3
154
+
155
+# SVE 32-bit scatter store (vector plus immediate)
156
+ST1_zpiz 1110010 .. 11 ..... 101 ... ..... ..... \
157
+ @rpri_scatter_store esz=2
158
+
159
# SVE 64-bit scatter store (scalar plus unpacked 32-bit scaled offset)
160
# Require msz > 0
161
ST1_zprz 1110010 .. 01 ..... 100 ... ..... ..... \
162
--
88
--
163
2.17.1
89
2.25.1
164
165
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-27-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-14-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 14 ++++++++++++++
11
target/arm/sme-fa64.decode | 2 --
9
target/arm/sve_helper.c | 8 ++++++++
12
target/arm/translate-sve.c | 2 ++
10
target/arm/translate-sve.c | 26 ++++++++++++++++++++++++++
13
2 files changed, 2 insertions(+), 2 deletions(-)
11
target/arm/sve.decode | 4 ++++
12
4 files changed, 52 insertions(+)
13
14
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
17
--- a/target/arm/sme-fa64.decode
17
+++ b/target/arm/helper-sve.h
18
+++ b/target/arm/sme-fa64.decode
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_frintx_s, TCG_CALL_NO_RWG,
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
19
DEF_HELPER_FLAGS_5(sve_frintx_d, TCG_CALL_NO_RWG,
20
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
20
void, ptr, ptr, ptr, ptr, i32)
21
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
21
22
22
+DEF_HELPER_FLAGS_5(sve_frecpx_h, TCG_CALL_NO_RWG,
23
-FAIL 1010 010- ---- ---- 011- ---- ---- ---- # SVE contiguous FF load (scalar+scalar)
23
+ void, ptr, ptr, ptr, ptr, i32)
24
-FAIL 1010 010- ---1 ---- 101- ---- ---- ---- # SVE contiguous NF load (scalar+imm)
24
+DEF_HELPER_FLAGS_5(sve_frecpx_s, TCG_CALL_NO_RWG,
25
FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
25
+ void, ptr, ptr, ptr, ptr, i32)
26
FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
26
+DEF_HELPER_FLAGS_5(sve_frecpx_d, TCG_CALL_NO_RWG,
27
+ void, ptr, ptr, ptr, ptr, i32)
28
+
29
+DEF_HELPER_FLAGS_5(sve_fsqrt_h, TCG_CALL_NO_RWG,
30
+ void, ptr, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_5(sve_fsqrt_s, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_5(sve_fsqrt_d, TCG_CALL_NO_RWG,
34
+ void, ptr, ptr, ptr, ptr, i32)
35
+
36
DEF_HELPER_FLAGS_5(sve_scvt_hh, TCG_CALL_NO_RWG,
37
void, ptr, ptr, ptr, ptr, i32)
38
DEF_HELPER_FLAGS_5(sve_scvt_sh, TCG_CALL_NO_RWG,
39
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/sve_helper.c
42
+++ b/target/arm/sve_helper.c
43
@@ -XXX,XX +XXX,XX @@ DO_ZPZ_FP(sve_frintx_h, uint16_t, H1_2, float16_round_to_int)
44
DO_ZPZ_FP(sve_frintx_s, uint32_t, H1_4, float32_round_to_int)
45
DO_ZPZ_FP(sve_frintx_d, uint64_t, , float64_round_to_int)
46
47
+DO_ZPZ_FP(sve_frecpx_h, uint16_t, H1_2, helper_frecpx_f16)
48
+DO_ZPZ_FP(sve_frecpx_s, uint32_t, H1_4, helper_frecpx_f32)
49
+DO_ZPZ_FP(sve_frecpx_d, uint64_t, , helper_frecpx_f64)
50
+
51
+DO_ZPZ_FP(sve_fsqrt_h, uint16_t, H1_2, float16_sqrt)
52
+DO_ZPZ_FP(sve_fsqrt_s, uint32_t, H1_4, float32_sqrt)
53
+DO_ZPZ_FP(sve_fsqrt_d, uint64_t, , float64_sqrt)
54
+
55
DO_ZPZ_FP(sve_scvt_hh, uint16_t, H1_2, int16_to_float16)
56
DO_ZPZ_FP(sve_scvt_sh, uint32_t, H1_4, int32_to_float16)
57
DO_ZPZ_FP(sve_scvt_ss, uint32_t, H1_4, int32_to_float32)
58
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
27
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
59
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/translate-sve.c
29
--- a/target/arm/translate-sve.c
61
+++ b/target/arm/translate-sve.c
30
+++ b/target/arm/translate-sve.c
62
@@ -XXX,XX +XXX,XX @@ static bool trans_FRINTA(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
31
@@ -XXX,XX +XXX,XX @@ static bool trans_LDFF1_zprr(DisasContext *s, arg_rprr_load *a)
63
return do_frint_mode(s, a, float_round_ties_away);
32
if (!dc_isar_feature(aa64_sve, s)) {
64
}
33
return false;
65
34
}
66
+static bool trans_FRECPX(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
35
+ s->is_nonstreaming = true;
67
+{
36
if (sve_access_check(s)) {
68
+ static gen_helper_gvec_3_ptr * const fns[3] = {
37
TCGv_i64 addr = new_tmp_a64(s);
69
+ gen_helper_sve_frecpx_h,
38
tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
70
+ gen_helper_sve_frecpx_s,
39
@@ -XXX,XX +XXX,XX @@ static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a)
71
+ gen_helper_sve_frecpx_d
40
if (!dc_isar_feature(aa64_sve, s)) {
72
+ };
41
return false;
73
+ if (a->esz == 0) {
42
}
74
+ return false;
43
+ s->is_nonstreaming = true;
75
+ }
44
if (sve_access_check(s)) {
76
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, a->esz == MO_16, fns[a->esz - 1]);
45
int vsz = vec_full_reg_size(s);
77
+}
46
int elements = vsz >> dtype_esz[a->dtype];
78
+
79
+static bool trans_FSQRT(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
80
+{
81
+ static gen_helper_gvec_3_ptr * const fns[3] = {
82
+ gen_helper_sve_fsqrt_h,
83
+ gen_helper_sve_fsqrt_s,
84
+ gen_helper_sve_fsqrt_d
85
+ };
86
+ if (a->esz == 0) {
87
+ return false;
88
+ }
89
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, a->esz == MO_16, fns[a->esz - 1]);
90
+}
91
+
92
static bool trans_SCVTF_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
93
{
94
return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_scvt_hh);
95
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
96
index XXXXXXX..XXXXXXX 100644
97
--- a/target/arm/sve.decode
98
+++ b/target/arm/sve.decode
99
@@ -XXX,XX +XXX,XX @@ FRINTA 01100101 .. 000 100 101 ... ..... ..... @rd_pg_rn
100
FRINTX 01100101 .. 000 110 101 ... ..... ..... @rd_pg_rn
101
FRINTI 01100101 .. 000 111 101 ... ..... ..... @rd_pg_rn
102
103
+# SVE floating-point unary operations
104
+FRECPX 01100101 .. 001 100 101 ... ..... ..... @rd_pg_rn
105
+FSQRT 01100101 .. 001 101 101 ... ..... ..... @rd_pg_rn
106
+
107
# SVE integer convert to floating-point
108
SCVTF_hh 01100101 01 010 01 0 101 ... ..... ..... @rd_pg_rn_e0
109
SCVTF_sh 01100101 01 010 10 0 101 ... ..... ..... @rd_pg_rn_e0
110
--
47
--
111
2.17.1
48
2.25.1
112
113
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Mark these as a non-streaming instructions, which should trap
4
if full a64 support is not enabled in streaming mode.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-22-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-15-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 42 +++++++++++++++++++++++++++++++++++++
11
target/arm/sme-fa64.decode | 3 ---
9
target/arm/sve_helper.c | 43 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-sve.c | 2 ++
10
target/arm/translate-sve.c | 43 ++++++++++++++++++++++++++++++++++++++
13
2 files changed, 2 insertions(+), 3 deletions(-)
11
target/arm/sve.decode | 10 +++++++++
12
4 files changed, 138 insertions(+)
13
14
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
17
--- a/target/arm/sme-fa64.decode
17
+++ b/target/arm/helper-sve.h
18
+++ b/target/arm/sme-fa64.decode
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_fadda_s, TCG_CALL_NO_RWG,
19
@@ -XXX,XX +XXX,XX @@ FAIL 0001 1110 0111 1110 0000 00-- ---- ---- # FJCVTZS
19
DEF_HELPER_FLAGS_5(sve_fadda_d, TCG_CALL_NO_RWG,
20
# --11 1100 --0- ---- ---- ---- ---- ---- # Load/store FP register (unscaled imm)
20
i64, i64, ptr, ptr, ptr, i32)
21
# --11 1100 --1- ---- ---- ---- ---- --10 # Load/store FP register (register offset)
21
22
# --11 1101 ---- ---- ---- ---- ---- ---- # Load/store FP register (scaled imm)
22
+DEF_HELPER_FLAGS_5(sve_fcmge0_h, TCG_CALL_NO_RWG,
23
-
23
+ void, ptr, ptr, ptr, ptr, i32)
24
-FAIL 1010 010- -01- ---- 000- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+scalar)
24
+DEF_HELPER_FLAGS_5(sve_fcmge0_s, TCG_CALL_NO_RWG,
25
-FAIL 1010 010- -010 ---- 001- ---- ---- ---- # SVE load & replicate 32 bytes (scalar+imm)
25
+ void, ptr, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_5(sve_fcmge0_d, TCG_CALL_NO_RWG,
27
+ void, ptr, ptr, ptr, ptr, i32)
28
+
29
+DEF_HELPER_FLAGS_5(sve_fcmgt0_h, TCG_CALL_NO_RWG,
30
+ void, ptr, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_5(sve_fcmgt0_s, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_5(sve_fcmgt0_d, TCG_CALL_NO_RWG,
34
+ void, ptr, ptr, ptr, ptr, i32)
35
+
36
+DEF_HELPER_FLAGS_5(sve_fcmlt0_h, TCG_CALL_NO_RWG,
37
+ void, ptr, ptr, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_5(sve_fcmlt0_s, TCG_CALL_NO_RWG,
39
+ void, ptr, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_5(sve_fcmlt0_d, TCG_CALL_NO_RWG,
41
+ void, ptr, ptr, ptr, ptr, i32)
42
+
43
+DEF_HELPER_FLAGS_5(sve_fcmle0_h, TCG_CALL_NO_RWG,
44
+ void, ptr, ptr, ptr, ptr, i32)
45
+DEF_HELPER_FLAGS_5(sve_fcmle0_s, TCG_CALL_NO_RWG,
46
+ void, ptr, ptr, ptr, ptr, i32)
47
+DEF_HELPER_FLAGS_5(sve_fcmle0_d, TCG_CALL_NO_RWG,
48
+ void, ptr, ptr, ptr, ptr, i32)
49
+
50
+DEF_HELPER_FLAGS_5(sve_fcmeq0_h, TCG_CALL_NO_RWG,
51
+ void, ptr, ptr, ptr, ptr, i32)
52
+DEF_HELPER_FLAGS_5(sve_fcmeq0_s, TCG_CALL_NO_RWG,
53
+ void, ptr, ptr, ptr, ptr, i32)
54
+DEF_HELPER_FLAGS_5(sve_fcmeq0_d, TCG_CALL_NO_RWG,
55
+ void, ptr, ptr, ptr, ptr, i32)
56
+
57
+DEF_HELPER_FLAGS_5(sve_fcmne0_h, TCG_CALL_NO_RWG,
58
+ void, ptr, ptr, ptr, ptr, i32)
59
+DEF_HELPER_FLAGS_5(sve_fcmne0_s, TCG_CALL_NO_RWG,
60
+ void, ptr, ptr, ptr, ptr, i32)
61
+DEF_HELPER_FLAGS_5(sve_fcmne0_d, TCG_CALL_NO_RWG,
62
+ void, ptr, ptr, ptr, ptr, i32)
63
+
64
DEF_HELPER_FLAGS_6(sve_fadd_h, TCG_CALL_NO_RWG,
65
void, ptr, ptr, ptr, ptr, ptr, i32)
66
DEF_HELPER_FLAGS_6(sve_fadd_s, TCG_CALL_NO_RWG,
67
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/sve_helper.c
70
+++ b/target/arm/sve_helper.c
71
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, \
72
73
#define DO_FCMGE(TYPE, X, Y, ST) TYPE##_compare(Y, X, ST) <= 0
74
#define DO_FCMGT(TYPE, X, Y, ST) TYPE##_compare(Y, X, ST) < 0
75
+#define DO_FCMLE(TYPE, X, Y, ST) TYPE##_compare(X, Y, ST) <= 0
76
+#define DO_FCMLT(TYPE, X, Y, ST) TYPE##_compare(X, Y, ST) < 0
77
#define DO_FCMEQ(TYPE, X, Y, ST) TYPE##_compare_quiet(X, Y, ST) == 0
78
#define DO_FCMNE(TYPE, X, Y, ST) TYPE##_compare_quiet(X, Y, ST) != 0
79
#define DO_FCMUO(TYPE, X, Y, ST) \
80
@@ -XXX,XX +XXX,XX @@ DO_FPCMP_PPZZ_ALL(sve_facgt, DO_FACGT)
81
#undef DO_FPCMP_PPZZ_H
82
#undef DO_FPCMP_PPZZ
83
84
+/* One operand floating-point comparison against zero, controlled
85
+ * by a predicate.
86
+ */
87
+#define DO_FPCMP_PPZ0(NAME, TYPE, H, OP) \
88
+void HELPER(NAME)(void *vd, void *vn, void *vg, \
89
+ void *status, uint32_t desc) \
90
+{ \
91
+ intptr_t i = simd_oprsz(desc), j = (i - 1) >> 6; \
92
+ uint64_t *d = vd, *g = vg; \
93
+ do { \
94
+ uint64_t out = 0, pg = g[j]; \
95
+ do { \
96
+ i -= sizeof(TYPE), out <<= sizeof(TYPE); \
97
+ if ((pg >> (i & 63)) & 1) { \
98
+ TYPE nn = *(TYPE *)(vn + H(i)); \
99
+ out |= OP(TYPE, nn, 0, status); \
100
+ } \
101
+ } while (i & 63); \
102
+ d[j--] = out; \
103
+ } while (i > 0); \
104
+}
105
+
106
+#define DO_FPCMP_PPZ0_H(NAME, OP) \
107
+ DO_FPCMP_PPZ0(NAME##_h, float16, H1_2, OP)
108
+#define DO_FPCMP_PPZ0_S(NAME, OP) \
109
+ DO_FPCMP_PPZ0(NAME##_s, float32, H1_4, OP)
110
+#define DO_FPCMP_PPZ0_D(NAME, OP) \
111
+ DO_FPCMP_PPZ0(NAME##_d, float64, , OP)
112
+
113
+#define DO_FPCMP_PPZ0_ALL(NAME, OP) \
114
+ DO_FPCMP_PPZ0_H(NAME, OP) \
115
+ DO_FPCMP_PPZ0_S(NAME, OP) \
116
+ DO_FPCMP_PPZ0_D(NAME, OP)
117
+
118
+DO_FPCMP_PPZ0_ALL(sve_fcmge0, DO_FCMGE)
119
+DO_FPCMP_PPZ0_ALL(sve_fcmgt0, DO_FCMGT)
120
+DO_FPCMP_PPZ0_ALL(sve_fcmle0, DO_FCMLE)
121
+DO_FPCMP_PPZ0_ALL(sve_fcmlt0, DO_FCMLT)
122
+DO_FPCMP_PPZ0_ALL(sve_fcmeq0, DO_FCMEQ)
123
+DO_FPCMP_PPZ0_ALL(sve_fcmne0, DO_FCMNE)
124
+
125
/*
126
* Load contiguous data, protected by a governing predicate.
127
*/
128
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
26
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
129
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
130
--- a/target/arm/translate-sve.c
28
--- a/target/arm/translate-sve.c
131
+++ b/target/arm/translate-sve.c
29
+++ b/target/arm/translate-sve.c
132
@@ -XXX,XX +XXX,XX @@ static bool trans_FRSQRTE(DisasContext *s, arg_rr_esz *a, uint32_t insn)
30
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1RO_zprr(DisasContext *s, arg_rprr_load *a)
133
return true;
31
if (a->rm == 31) {
134
}
32
return false;
135
33
}
136
+/*
34
+ s->is_nonstreaming = true;
137
+ *** SVE Floating Point Compare with Zero Group
35
if (sve_access_check(s)) {
138
+ */
36
TCGv_i64 addr = new_tmp_a64(s);
139
+
37
tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
140
+static void do_ppz_fp(DisasContext *s, arg_rpr_esz *a,
38
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1RO_zpri(DisasContext *s, arg_rpri_load *a)
141
+ gen_helper_gvec_3_ptr *fn)
39
if (!dc_isar_feature(aa64_sve_f64mm, s)) {
142
+{
40
return false;
143
+ unsigned vsz = vec_full_reg_size(s);
41
}
144
+ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
42
+ s->is_nonstreaming = true;
145
+
43
if (sve_access_check(s)) {
146
+ tcg_gen_gvec_3_ptr(pred_full_reg_offset(s, a->rd),
44
TCGv_i64 addr = new_tmp_a64(s);
147
+ vec_full_reg_offset(s, a->rn),
45
tcg_gen_addi_i64(addr, cpu_reg_sp(s, a->rn), a->imm * 32);
148
+ pred_full_reg_offset(s, a->pg),
149
+ status, vsz, vsz, 0, fn);
150
+ tcg_temp_free_ptr(status);
151
+}
152
+
153
+#define DO_PPZ(NAME, name) \
154
+static bool trans_##NAME(DisasContext *s, arg_rpr_esz *a, uint32_t insn) \
155
+{ \
156
+ static gen_helper_gvec_3_ptr * const fns[3] = { \
157
+ gen_helper_sve_##name##_h, \
158
+ gen_helper_sve_##name##_s, \
159
+ gen_helper_sve_##name##_d, \
160
+ }; \
161
+ if (a->esz == 0) { \
162
+ return false; \
163
+ } \
164
+ if (sve_access_check(s)) { \
165
+ do_ppz_fp(s, a, fns[a->esz - 1]); \
166
+ } \
167
+ return true; \
168
+}
169
+
170
+DO_PPZ(FCMGE_ppz0, fcmge0)
171
+DO_PPZ(FCMGT_ppz0, fcmgt0)
172
+DO_PPZ(FCMLE_ppz0, fcmle0)
173
+DO_PPZ(FCMLT_ppz0, fcmlt0)
174
+DO_PPZ(FCMEQ_ppz0, fcmeq0)
175
+DO_PPZ(FCMNE_ppz0, fcmne0)
176
+
177
+#undef DO_PPZ
178
+
179
/*
180
*** SVE Floating Point Accumulating Reduction Group
181
*/
182
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
183
index XXXXXXX..XXXXXXX 100644
184
--- a/target/arm/sve.decode
185
+++ b/target/arm/sve.decode
186
@@ -XXX,XX +XXX,XX @@
187
# One register operand, with governing predicate, vector element size
188
@rd_pg_rn ........ esz:2 ... ... ... pg:3 rn:5 rd:5 &rpr_esz
189
@rd_pg4_pn ........ esz:2 ... ... .. pg:4 . rn:4 rd:5 &rpr_esz
190
+@pd_pg_rn ........ esz:2 ... ... ... pg:3 rn:5 . rd:4 &rpr_esz
191
192
# One register operand, with governing predicate, no vector element size
193
@rd_pg_rn_e0 ........ .. ... ... ... pg:3 rn:5 rd:5 &rpr_esz esz=0
194
@@ -XXX,XX +XXX,XX @@ FMINV 01100101 .. 000 111 001 ... ..... ..... @rd_pg_rn
195
FRECPE 01100101 .. 001 110 001100 ..... ..... @rd_rn
196
FRSQRTE 01100101 .. 001 111 001100 ..... ..... @rd_rn
197
198
+### SVE FP Compare with Zero Group
199
+
200
+FCMGE_ppz0 01100101 .. 0100 00 001 ... ..... 0 .... @pd_pg_rn
201
+FCMGT_ppz0 01100101 .. 0100 00 001 ... ..... 1 .... @pd_pg_rn
202
+FCMLT_ppz0 01100101 .. 0100 01 001 ... ..... 0 .... @pd_pg_rn
203
+FCMLE_ppz0 01100101 .. 0100 01 001 ... ..... 1 .... @pd_pg_rn
204
+FCMEQ_ppz0 01100101 .. 0100 10 001 ... ..... 0 .... @pd_pg_rn
205
+FCMNE_ppz0 01100101 .. 0100 11 001 ... ..... 0 .... @pd_pg_rn
206
+
207
### SVE FP Accumulating Reduction Group
208
209
# SVE floating-point serial reduction (predicated)
210
--
46
--
211
2.17.1
47
2.25.1
212
213
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
These functions will be used to verify that the cpu
4
is in the correct state for a given instruction.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-23-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-16-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 4 +++
11
target/arm/translate-a64.h | 21 +++++++++++++++++++++
9
target/arm/sve_helper.c | 70 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-a64.c | 34 ++++++++++++++++++++++++++++++++++
10
target/arm/translate-sve.c | 27 +++++++++++++++
13
2 files changed, 55 insertions(+)
11
target/arm/sve.decode | 3 ++
12
4 files changed, 104 insertions(+)
13
14
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
17
--- a/target/arm/translate-a64.h
17
+++ b/target/arm/helper-sve.h
18
+++ b/target/arm/translate-a64.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(sve_fnmls_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32)
19
@@ -XXX,XX +XXX,XX @@ void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v);
19
DEF_HELPER_FLAGS_3(sve_fnmls_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32)
20
bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
20
DEF_HELPER_FLAGS_3(sve_fnmls_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32)
21
unsigned int imms, unsigned int immr);
21
22
bool sve_access_check(DisasContext *s);
22
+DEF_HELPER_FLAGS_5(sve_ftmad_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
23
+bool sme_enabled_check(DisasContext *s);
23
+DEF_HELPER_FLAGS_5(sve_ftmad_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
24
+bool sme_enabled_check_with_svcr(DisasContext *s, unsigned);
24
+DEF_HELPER_FLAGS_5(sve_ftmad_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
25
+
25
+
26
DEF_HELPER_FLAGS_4(sve_ld1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
26
+/* This function corresponds to CheckStreamingSVEEnabled. */
27
DEF_HELPER_FLAGS_4(sve_ld2bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
27
+static inline bool sme_sm_enabled_check(DisasContext *s)
28
DEF_HELPER_FLAGS_4(sve_ld3bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
29
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/sve_helper.c
32
+++ b/target/arm/sve_helper.c
33
@@ -XXX,XX +XXX,XX @@ DO_FPCMP_PPZ0_ALL(sve_fcmlt0, DO_FCMLT)
34
DO_FPCMP_PPZ0_ALL(sve_fcmeq0, DO_FCMEQ)
35
DO_FPCMP_PPZ0_ALL(sve_fcmne0, DO_FCMNE)
36
37
+/* FP Trig Multiply-Add. */
38
+
39
+void HELPER(sve_ftmad_h)(void *vd, void *vn, void *vm, void *vs, uint32_t desc)
40
+{
28
+{
41
+ static const float16 coeff[16] = {
29
+ return sme_enabled_check_with_svcr(s, R_SVCR_SM_MASK);
42
+ 0x3c00, 0xb155, 0x2030, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
43
+ 0x3c00, 0xb800, 0x293a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
44
+ };
45
+ intptr_t i, opr_sz = simd_oprsz(desc) / sizeof(float16);
46
+ intptr_t x = simd_data(desc);
47
+ float16 *d = vd, *n = vn, *m = vm;
48
+ for (i = 0; i < opr_sz; i++) {
49
+ float16 mm = m[i];
50
+ intptr_t xx = x;
51
+ if (float16_is_neg(mm)) {
52
+ mm = float16_abs(mm);
53
+ xx += 8;
54
+ }
55
+ d[i] = float16_muladd(n[i], mm, coeff[xx], 0, vs);
56
+ }
57
+}
30
+}
58
+
31
+
59
+void HELPER(sve_ftmad_s)(void *vd, void *vn, void *vm, void *vs, uint32_t desc)
32
+/* This function corresponds to CheckSMEAndZAEnabled. */
33
+static inline bool sme_za_enabled_check(DisasContext *s)
60
+{
34
+{
61
+ static const float32 coeff[16] = {
35
+ return sme_enabled_check_with_svcr(s, R_SVCR_ZA_MASK);
62
+ 0x3f800000, 0xbe2aaaab, 0x3c088886, 0xb95008b9,
63
+ 0x36369d6d, 0x00000000, 0x00000000, 0x00000000,
64
+ 0x3f800000, 0xbf000000, 0x3d2aaaa6, 0xbab60705,
65
+ 0x37cd37cc, 0x00000000, 0x00000000, 0x00000000,
66
+ };
67
+ intptr_t i, opr_sz = simd_oprsz(desc) / sizeof(float32);
68
+ intptr_t x = simd_data(desc);
69
+ float32 *d = vd, *n = vn, *m = vm;
70
+ for (i = 0; i < opr_sz; i++) {
71
+ float32 mm = m[i];
72
+ intptr_t xx = x;
73
+ if (float32_is_neg(mm)) {
74
+ mm = float32_abs(mm);
75
+ xx += 8;
76
+ }
77
+ d[i] = float32_muladd(n[i], mm, coeff[xx], 0, vs);
78
+ }
79
+}
36
+}
80
+
37
+
81
+void HELPER(sve_ftmad_d)(void *vd, void *vn, void *vm, void *vs, uint32_t desc)
38
+/* Note that this function corresponds to CheckStreamingSVEAndZAEnabled. */
39
+static inline bool sme_smza_enabled_check(DisasContext *s)
82
+{
40
+{
83
+ static const float64 coeff[16] = {
41
+ return sme_enabled_check_with_svcr(s, R_SVCR_SM_MASK | R_SVCR_ZA_MASK);
84
+ 0x3ff0000000000000ull, 0xbfc5555555555543ull,
85
+ 0x3f8111111110f30cull, 0xbf2a01a019b92fc6ull,
86
+ 0x3ec71de351f3d22bull, 0xbe5ae5e2b60f7b91ull,
87
+ 0x3de5d8408868552full, 0x0000000000000000ull,
88
+ 0x3ff0000000000000ull, 0xbfe0000000000000ull,
89
+ 0x3fa5555555555536ull, 0xbf56c16c16c13a0bull,
90
+ 0x3efa01a019b1e8d8ull, 0xbe927e4f7282f468ull,
91
+ 0x3e21ee96d2641b13ull, 0xbda8f76380fbb401ull,
92
+ };
93
+ intptr_t i, opr_sz = simd_oprsz(desc) / sizeof(float64);
94
+ intptr_t x = simd_data(desc);
95
+ float64 *d = vd, *n = vn, *m = vm;
96
+ for (i = 0; i < opr_sz; i++) {
97
+ float64 mm = m[i];
98
+ intptr_t xx = x;
99
+ if (float64_is_neg(mm)) {
100
+ mm = float64_abs(mm);
101
+ xx += 8;
102
+ }
103
+ d[i] = float64_muladd(n[i], mm, coeff[xx], 0, vs);
104
+ }
105
+}
42
+}
106
+
43
+
107
/*
44
TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr);
108
* Load contiguous data, protected by a governing predicate.
45
TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
109
*/
46
bool tag_checked, int log2_size);
110
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
47
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
111
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
112
--- a/target/arm/translate-sve.c
49
--- a/target/arm/translate-a64.c
113
+++ b/target/arm/translate-sve.c
50
+++ b/target/arm/translate-a64.c
114
@@ -XXX,XX +XXX,XX @@ DO_PPZ(FCMNE_ppz0, fcmne0)
51
@@ -XXX,XX +XXX,XX @@ static bool sme_access_check(DisasContext *s)
115
52
return true;
116
#undef DO_PPZ
53
}
117
54
118
+/*
55
+/* This function corresponds to CheckSMEEnabled. */
119
+ *** SVE floating-point trig multiply-add coefficient
56
+bool sme_enabled_check(DisasContext *s)
120
+ */
57
+{
58
+ /*
59
+ * Note that unlike sve_excp_el, we have not constrained sme_excp_el
60
+ * to be zero when fp_excp_el has priority. This is because we need
61
+ * sme_excp_el by itself for cpregs access checks.
62
+ */
63
+ if (!s->fp_excp_el || s->sme_excp_el < s->fp_excp_el) {
64
+ s->fp_access_checked = true;
65
+ return sme_access_check(s);
66
+ }
67
+ return fp_access_check_only(s);
68
+}
121
+
69
+
122
+static bool trans_FTMAD(DisasContext *s, arg_FTMAD *a, uint32_t insn)
70
+/* Common subroutine for CheckSMEAnd*Enabled. */
71
+bool sme_enabled_check_with_svcr(DisasContext *s, unsigned req)
123
+{
72
+{
124
+ static gen_helper_gvec_3_ptr * const fns[3] = {
73
+ if (!sme_enabled_check(s)) {
125
+ gen_helper_sve_ftmad_h,
126
+ gen_helper_sve_ftmad_s,
127
+ gen_helper_sve_ftmad_d,
128
+ };
129
+
130
+ if (a->esz == 0) {
131
+ return false;
74
+ return false;
132
+ }
75
+ }
133
+ if (sve_access_check(s)) {
76
+ if (FIELD_EX64(req, SVCR, SM) && !s->pstate_sm) {
134
+ unsigned vsz = vec_full_reg_size(s);
77
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
135
+ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
78
+ syn_smetrap(SME_ET_NotStreaming, false));
136
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
79
+ return false;
137
+ vec_full_reg_offset(s, a->rn),
80
+ }
138
+ vec_full_reg_offset(s, a->rm),
81
+ if (FIELD_EX64(req, SVCR, ZA) && !s->pstate_za) {
139
+ status, vsz, vsz, a->imm, fns[a->esz - 1]);
82
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
140
+ tcg_temp_free_ptr(status);
83
+ syn_smetrap(SME_ET_InactiveZA, false));
84
+ return false;
141
+ }
85
+ }
142
+ return true;
86
+ return true;
143
+}
87
+}
144
+
88
+
145
/*
89
/*
146
*** SVE Floating Point Accumulating Reduction Group
90
* This utility function is for doing register extension with an
147
*/
91
* optional shift. You will likely want to pass a temporary for the
148
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
149
index XXXXXXX..XXXXXXX 100644
150
--- a/target/arm/sve.decode
151
+++ b/target/arm/sve.decode
152
@@ -XXX,XX +XXX,XX @@ FMINNM_zpzi 01100101 .. 011 101 100 ... 0000 . ..... @rdn_i1
153
FMAX_zpzi 01100101 .. 011 110 100 ... 0000 . ..... @rdn_i1
154
FMIN_zpzi 01100101 .. 011 111 100 ... 0000 . ..... @rdn_i1
155
156
+# SVE floating-point trig multiply-add coefficient
157
+FTMAD 01100101 esz:2 010 imm:3 100000 rm:5 rd:5 rn=%reg_movprfx
158
+
159
### SVE FP Multiply-Add Group
160
161
# SVE floating-point multiply-accumulate writing addend
162
--
92
--
163
2.17.1
93
2.25.1
164
165
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
For aa64 advsimd, we had been passing the pre-indexed vector.
3
The pseudocode for CheckSVEEnabled gains a check for Streaming
4
However, sve applies the index to each 128-bit segment, so we
4
SVE mode, and for SME present but SVE absent.
5
need to pass in the index separately.
6
5
7
For aa32 advsimd, the fp32 operation always has index 0, but
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
we failed to interpret the fp16 index correctly.
9
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20220708151540.18136-17-richard.henderson@linaro.org
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Message-id: 20180627043328.11531-31-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
10
---
16
target/arm/translate-a64.c | 21 ++++++++++++---------
11
target/arm/translate-a64.c | 22 ++++++++++++++++------
17
target/arm/translate.c | 32 +++++++++++++++++++++++---------
12
1 file changed, 16 insertions(+), 6 deletions(-)
18
target/arm/vec_helper.c | 10 ++++++----
19
3 files changed, 41 insertions(+), 22 deletions(-)
20
13
21
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/translate-a64.c
16
--- a/target/arm/translate-a64.c
24
+++ b/target/arm/translate-a64.c
17
+++ b/target/arm/translate-a64.c
25
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static bool fp_access_check(DisasContext *s)
26
case 0x13: /* FCMLA #90 */
19
return true;
27
case 0x15: /* FCMLA #180 */
20
}
28
case 0x17: /* FCMLA #270 */
21
29
- tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
22
-/* Check that SVE access is enabled. If it is, return true.
30
- vec_full_reg_offset(s, rn),
23
+/*
31
- vec_reg_offset(s, rm, index, size), fpst,
24
+ * Check that SVE access is enabled. If it is, return true.
32
- is_q ? 16 : 8, vec_full_reg_size(s),
25
* If not, emit code to generate an appropriate exception and return false.
33
- extract32(insn, 13, 2), /* rot */
26
+ * This function corresponds to CheckSVEEnabled().
34
- size == MO_64
27
*/
35
- ? gen_helper_gvec_fcmlas_idx
28
bool sve_access_check(DisasContext *s)
36
- : gen_helper_gvec_fcmlah_idx);
29
{
37
- tcg_temp_free_ptr(fpst);
30
- if (s->sve_excp_el) {
38
+ {
31
- assert(!s->sve_access_checked);
39
+ int rot = extract32(insn, 13, 2);
32
- s->sve_access_checked = true;
40
+ int data = (index << 2) | rot;
33
-
41
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
34
+ if (s->pstate_sm || !dc_isar_feature(aa64_sve, s)) {
42
+ vec_full_reg_offset(s, rn),
35
+ assert(dc_isar_feature(aa64_sme, s));
43
+ vec_full_reg_offset(s, rm), fpst,
36
+ if (!sme_sm_enabled_check(s)) {
44
+ is_q ? 16 : 8, vec_full_reg_size(s), data,
37
+ goto fail_exit;
45
+ size == MO_64
46
+ ? gen_helper_gvec_fcmlas_idx
47
+ : gen_helper_gvec_fcmlah_idx);
48
+ tcg_temp_free_ptr(fpst);
49
+ }
38
+ }
50
return;
39
+ } else if (s->sve_excp_el) {
40
gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
41
syn_sve_access_trap(), s->sve_excp_el);
42
- return false;
43
+ goto fail_exit;
51
}
44
}
52
45
s->sve_access_checked = true;
53
diff --git a/target/arm/translate.c b/target/arm/translate.c
46
return fp_access_check(s);
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/translate.c
56
+++ b/target/arm/translate.c
57
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
58
59
static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
60
{
61
- int rd, rn, rm, rot, size, opr_sz;
62
+ gen_helper_gvec_3_ptr *fn_gvec_ptr;
63
+ int rd, rn, rm, opr_sz, data;
64
TCGv_ptr fpst;
65
bool q;
66
67
q = extract32(insn, 6, 1);
68
VFP_DREG_D(rd, insn);
69
VFP_DREG_N(rn, insn);
70
- VFP_DREG_M(rm, insn);
71
if ((rd | rn) & q) {
72
return 1;
73
}
74
75
if ((insn & 0xff000f10) == 0xfe000800) {
76
/* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
77
- rot = extract32(insn, 20, 2);
78
- size = extract32(insn, 23, 1);
79
- if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
80
- || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
81
+ int rot = extract32(insn, 20, 2);
82
+ int size = extract32(insn, 23, 1);
83
+ int index;
84
+
47
+
85
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)) {
48
+ fail_exit:
86
return 1;
49
+ /* Assert that we only raise one exception per instruction. */
87
}
50
+ assert(!s->sve_access_checked);
88
+ if (size == 0) {
51
+ s->sve_access_checked = true;
89
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
52
+ return false;
90
+ return 1;
91
+ }
92
+ /* For fp16, rm is just Vm, and index is M. */
93
+ rm = extract32(insn, 0, 4);
94
+ index = extract32(insn, 5, 1);
95
+ } else {
96
+ /* For fp32, rm is the usual M:Vm, and index is 0. */
97
+ VFP_DREG_M(rm, insn);
98
+ index = 0;
99
+ }
100
+ data = (index << 2) | rot;
101
+ fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
102
+ : gen_helper_gvec_fcmlah_idx);
103
} else {
104
return 1;
105
}
106
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
107
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
108
vfp_reg_offset(1, rn),
109
vfp_reg_offset(1, rm), fpst,
110
- opr_sz, opr_sz, rot,
111
- size ? gen_helper_gvec_fcmlas_idx
112
- : gen_helper_gvec_fcmlah_idx);
113
+ opr_sz, opr_sz, data, fn_gvec_ptr);
114
tcg_temp_free_ptr(fpst);
115
return 0;
116
}
53
}
117
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
54
118
index XXXXXXX..XXXXXXX 100644
55
/*
119
--- a/target/arm/vec_helper.c
120
+++ b/target/arm/vec_helper.c
121
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcmlah_idx)(void *vd, void *vn, void *vm,
122
float_status *fpst = vfpst;
123
intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
124
uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
125
+ intptr_t index = extract32(desc, SIMD_DATA_SHIFT + 2, 2);
126
uint32_t neg_real = flip ^ neg_imag;
127
uintptr_t i;
128
- float16 e1 = m[H2(flip)];
129
- float16 e3 = m[H2(1 - flip)];
130
+ float16 e1 = m[H2(2 * index + flip)];
131
+ float16 e3 = m[H2(2 * index + 1 - flip)];
132
133
/* Shift boolean to the sign bit so we can xor to negate. */
134
neg_real <<= 15;
135
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm,
136
float_status *fpst = vfpst;
137
intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
138
uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
139
+ intptr_t index = extract32(desc, SIMD_DATA_SHIFT + 2, 2);
140
uint32_t neg_real = flip ^ neg_imag;
141
uintptr_t i;
142
- float32 e1 = m[H4(flip)];
143
- float32 e3 = m[H4(1 - flip)];
144
+ float32 e1 = m[H4(2 * index + flip)];
145
+ float32 e3 = m[H4(2 * index + 1 - flip)];
146
147
/* Shift boolean to the sign bit so we can xor to negate. */
148
neg_real <<= 31;
149
--
56
--
150
2.17.1
57
2.25.1
151
152
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
These SME instructions are nominally within the SVE decode space,
4
so we add them to sve.decode and translate-sve.c.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-21-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-18-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper.h | 8 +++++++
11
target/arm/translate-a64.h | 12 ++++++++++++
9
target/arm/translate-sve.c | 47 ++++++++++++++++++++++++++++++++++++++
12
target/arm/sve.decode | 5 ++++-
10
target/arm/vec_helper.c | 20 ++++++++++++++++
13
target/arm/translate-sve.c | 38 ++++++++++++++++++++++++++++++++++++++
11
target/arm/sve.decode | 5 ++++
14
3 files changed, 54 insertions(+), 1 deletion(-)
12
4 files changed, 80 insertions(+)
13
15
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.h
18
--- a/target/arm/translate-a64.h
17
+++ b/target/arm/helper.h
19
+++ b/target/arm/translate-a64.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fcmlas_idx, TCG_CALL_NO_RWG,
20
@@ -XXX,XX +XXX,XX @@ static inline int vec_full_reg_size(DisasContext *s)
19
DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG,
21
return s->vl;
20
void, ptr, ptr, ptr, ptr, i32)
22
}
21
23
22
+DEF_HELPER_FLAGS_4(gvec_frecpe_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+/* Return the byte size of the vector register, SVL / 8. */
23
+DEF_HELPER_FLAGS_4(gvec_frecpe_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+static inline int streaming_vec_reg_size(DisasContext *s)
24
+DEF_HELPER_FLAGS_4(gvec_frecpe_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
+{
27
+ return s->svl;
28
+}
25
+
29
+
26
+DEF_HELPER_FLAGS_4(gvec_frsqrte_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
30
/*
27
+DEF_HELPER_FLAGS_4(gvec_frsqrte_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
* Return the offset info CPUARMState of the predicate vector register Pn.
28
+DEF_HELPER_FLAGS_4(gvec_frsqrte_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
32
* Note for this purpose, FFR is P16.
33
@@ -XXX,XX +XXX,XX @@ static inline int pred_full_reg_size(DisasContext *s)
34
return s->vl >> 3;
35
}
36
37
+/* Return the byte size of the predicate register, SVL / 64. */
38
+static inline int streaming_pred_reg_size(DisasContext *s)
39
+{
40
+ return s->svl >> 3;
41
+}
29
+
42
+
30
DEF_HELPER_FLAGS_5(gvec_fadd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
43
/*
31
DEF_HELPER_FLAGS_5(gvec_fadd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
44
* Round up the size of a register to a size allowed by
32
DEF_HELPER_FLAGS_5(gvec_fadd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
45
* the tcg vector infrastructure. Any operation which uses this
46
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/sve.decode
49
+++ b/target/arm/sve.decode
50
@@ -XXX,XX +XXX,XX @@ INDEX_ri 00000100 esz:2 1 imm:s5 010001 rn:5 rd:5
51
# SVE index generation (register start, register increment)
52
INDEX_rr 00000100 .. 1 ..... 010011 ..... ..... @rd_rn_rm
53
54
-### SVE Stack Allocation Group
55
+### SVE / Streaming SVE Stack Allocation Group
56
57
# SVE stack frame adjustment
58
ADDVL 00000100 001 ..... 01010 ...... ..... @rd_rn_i6
59
+ADDSVL 00000100 001 ..... 01011 ...... ..... @rd_rn_i6
60
ADDPL 00000100 011 ..... 01010 ...... ..... @rd_rn_i6
61
+ADDSPL 00000100 011 ..... 01011 ...... ..... @rd_rn_i6
62
63
# SVE stack frame size
64
RDVL 00000100 101 11111 01010 imm:s6 rd:5
65
+RDSVL 00000100 101 11111 01011 imm:s6 rd:5
66
67
### SVE Bitwise Shift - Unpredicated Group
68
33
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
69
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
34
index XXXXXXX..XXXXXXX 100644
70
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-sve.c
71
--- a/target/arm/translate-sve.c
36
+++ b/target/arm/translate-sve.c
72
+++ b/target/arm/translate-sve.c
37
@@ -XXX,XX +XXX,XX @@ DO_VPZ(FMAXNMV, fmaxnmv)
73
@@ -XXX,XX +XXX,XX @@ static bool trans_ADDVL(DisasContext *s, arg_ADDVL *a)
38
DO_VPZ(FMINV, fminv)
74
return true;
39
DO_VPZ(FMAXV, fmaxv)
75
}
40
76
41
+/*
77
+static bool trans_ADDSVL(DisasContext *s, arg_ADDSVL *a)
42
+ *** SVE Floating Point Unary Operations - Unpredicated Group
43
+ */
44
+
45
+static void do_zz_fp(DisasContext *s, arg_rr_esz *a, gen_helper_gvec_2_ptr *fn)
46
+{
78
+{
47
+ unsigned vsz = vec_full_reg_size(s);
79
+ if (!dc_isar_feature(aa64_sme, s)) {
48
+ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
49
+
50
+ tcg_gen_gvec_2_ptr(vec_full_reg_offset(s, a->rd),
51
+ vec_full_reg_offset(s, a->rn),
52
+ status, vsz, vsz, 0, fn);
53
+ tcg_temp_free_ptr(status);
54
+}
55
+
56
+static bool trans_FRECPE(DisasContext *s, arg_rr_esz *a, uint32_t insn)
57
+{
58
+ static gen_helper_gvec_2_ptr * const fns[3] = {
59
+ gen_helper_gvec_frecpe_h,
60
+ gen_helper_gvec_frecpe_s,
61
+ gen_helper_gvec_frecpe_d,
62
+ };
63
+ if (a->esz == 0) {
64
+ return false;
80
+ return false;
65
+ }
81
+ }
66
+ if (sve_access_check(s)) {
82
+ if (sme_enabled_check(s)) {
67
+ do_zz_fp(s, a, fns[a->esz - 1]);
83
+ TCGv_i64 rd = cpu_reg_sp(s, a->rd);
84
+ TCGv_i64 rn = cpu_reg_sp(s, a->rn);
85
+ tcg_gen_addi_i64(rd, rn, a->imm * streaming_vec_reg_size(s));
68
+ }
86
+ }
69
+ return true;
87
+ return true;
70
+}
88
+}
71
+
89
+
72
+static bool trans_FRSQRTE(DisasContext *s, arg_rr_esz *a, uint32_t insn)
90
static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a)
91
{
92
if (!dc_isar_feature(aa64_sve, s)) {
93
@@ -XXX,XX +XXX,XX @@ static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a)
94
return true;
95
}
96
97
+static bool trans_ADDSPL(DisasContext *s, arg_ADDSPL *a)
73
+{
98
+{
74
+ static gen_helper_gvec_2_ptr * const fns[3] = {
99
+ if (!dc_isar_feature(aa64_sme, s)) {
75
+ gen_helper_gvec_frsqrte_h,
76
+ gen_helper_gvec_frsqrte_s,
77
+ gen_helper_gvec_frsqrte_d,
78
+ };
79
+ if (a->esz == 0) {
80
+ return false;
100
+ return false;
81
+ }
101
+ }
82
+ if (sve_access_check(s)) {
102
+ if (sme_enabled_check(s)) {
83
+ do_zz_fp(s, a, fns[a->esz - 1]);
103
+ TCGv_i64 rd = cpu_reg_sp(s, a->rd);
104
+ TCGv_i64 rn = cpu_reg_sp(s, a->rn);
105
+ tcg_gen_addi_i64(rd, rn, a->imm * streaming_pred_reg_size(s));
106
+ }
107
+ return true;
108
+}
109
+
110
static bool trans_RDVL(DisasContext *s, arg_RDVL *a)
111
{
112
if (!dc_isar_feature(aa64_sve, s)) {
113
@@ -XXX,XX +XXX,XX @@ static bool trans_RDVL(DisasContext *s, arg_RDVL *a)
114
return true;
115
}
116
117
+static bool trans_RDSVL(DisasContext *s, arg_RDSVL *a)
118
+{
119
+ if (!dc_isar_feature(aa64_sme, s)) {
120
+ return false;
121
+ }
122
+ if (sme_enabled_check(s)) {
123
+ TCGv_i64 reg = cpu_reg(s, a->rd);
124
+ tcg_gen_movi_i64(reg, a->imm * streaming_vec_reg_size(s));
84
+ }
125
+ }
85
+ return true;
126
+ return true;
86
+}
127
+}
87
+
128
+
88
/*
129
/*
89
*** SVE Floating Point Accumulating Reduction Group
130
*** SVE Compute Vector Address Group
90
*/
131
*/
91
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/target/arm/vec_helper.c
94
+++ b/target/arm/vec_helper.c
95
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
96
clear_tail(d, opr_sz, simd_maxsz(desc));
97
}
98
99
+#define DO_2OP(NAME, FUNC, TYPE) \
100
+void HELPER(NAME)(void *vd, void *vn, void *stat, uint32_t desc) \
101
+{ \
102
+ intptr_t i, oprsz = simd_oprsz(desc); \
103
+ TYPE *d = vd, *n = vn; \
104
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
105
+ d[i] = FUNC(n[i], stat); \
106
+ } \
107
+}
108
+
109
+DO_2OP(gvec_frecpe_h, helper_recpe_f16, float16)
110
+DO_2OP(gvec_frecpe_s, helper_recpe_f32, float32)
111
+DO_2OP(gvec_frecpe_d, helper_recpe_f64, float64)
112
+
113
+DO_2OP(gvec_frsqrte_h, helper_rsqrte_f16, float16)
114
+DO_2OP(gvec_frsqrte_s, helper_rsqrte_f32, float32)
115
+DO_2OP(gvec_frsqrte_d, helper_rsqrte_f64, float64)
116
+
117
+#undef DO_2OP
118
+
119
/* Floating-point trigonometric starting value.
120
* See the ARM ARM pseudocode function FPTrigSMul.
121
*/
122
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
123
index XXXXXXX..XXXXXXX 100644
124
--- a/target/arm/sve.decode
125
+++ b/target/arm/sve.decode
126
@@ -XXX,XX +XXX,XX @@ FMINNMV 01100101 .. 000 101 001 ... ..... ..... @rd_pg_rn
127
FMAXV 01100101 .. 000 110 001 ... ..... ..... @rd_pg_rn
128
FMINV 01100101 .. 000 111 001 ... ..... ..... @rd_pg_rn
129
130
+## SVE Floating Point Unary Operations - Unpredicated Group
131
+
132
+FRECPE 01100101 .. 001 110 001100 ..... ..... @rd_rn
133
+FRSQRTE 01100101 .. 001 111 001100 ..... ..... @rd_rn
134
+
135
### SVE FP Accumulating Reduction Group
136
137
# SVE floating-point serial reduction (predicated)
138
--
132
--
139
2.17.1
133
2.25.1
140
141
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-29-richard.henderson@linaro.org
5
Message-id: 20220708151540.18136-19-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
7
---
8
target/arm/helper-sve.h | 7 +++
8
target/arm/helper-sme.h | 2 ++
9
target/arm/sve_helper.c | 100 +++++++++++++++++++++++++++++++++++++
9
target/arm/sme.decode | 4 ++++
10
target/arm/translate-sve.c | 24 +++++++++
10
target/arm/sme_helper.c | 25 +++++++++++++++++++++++++
11
target/arm/sve.decode | 4 ++
11
target/arm/translate-sme.c | 13 +++++++++++++
12
4 files changed, 135 insertions(+)
12
4 files changed, 44 insertions(+)
13
13
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
16
--- a/target/arm/helper-sme.h
17
+++ b/target/arm/helper-sve.h
17
+++ b/target/arm/helper-sme.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(sve_facgt_s, TCG_CALL_NO_RWG,
18
@@ -XXX,XX +XXX,XX @@
19
DEF_HELPER_FLAGS_6(sve_facgt_d, TCG_CALL_NO_RWG,
19
20
void, ptr, ptr, ptr, ptr, ptr, i32)
20
DEF_HELPER_FLAGS_2(set_pstate_sm, TCG_CALL_NO_RWG, void, env, i32)
21
21
DEF_HELPER_FLAGS_2(set_pstate_za, TCG_CALL_NO_RWG, void, env, i32)
22
+DEF_HELPER_FLAGS_6(sve_fcadd_h, TCG_CALL_NO_RWG,
23
+ void, ptr, ptr, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_6(sve_fcadd_s, TCG_CALL_NO_RWG,
25
+ void, ptr, ptr, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_6(sve_fcadd_d, TCG_CALL_NO_RWG,
27
+ void, ptr, ptr, ptr, ptr, ptr, i32)
28
+
22
+
29
DEF_HELPER_FLAGS_3(sve_fmla_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32)
23
+DEF_HELPER_FLAGS_3(sme_zero, TCG_CALL_NO_RWG, void, env, i32, i32)
30
DEF_HELPER_FLAGS_3(sve_fmla_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32)
24
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
31
DEF_HELPER_FLAGS_3(sve_fmla_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32)
32
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
33
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/sve_helper.c
26
--- a/target/arm/sme.decode
35
+++ b/target/arm/sve_helper.c
27
+++ b/target/arm/sme.decode
36
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_ftmad_d)(void *vd, void *vn, void *vm, void *vs, uint32_t desc)
28
@@ -XXX,XX +XXX,XX @@
29
#
30
# This file is processed by scripts/decodetree.py
31
#
32
+
33
+### SME Misc
34
+
35
+ZERO 11000000 00 001 00000000000 imm:8
36
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/sme_helper.c
39
+++ b/target/arm/sme_helper.c
40
@@ -XXX,XX +XXX,XX @@ void helper_set_pstate_za(CPUARMState *env, uint32_t i)
41
memset(env->zarray, 0, sizeof(env->zarray));
37
}
42
}
38
}
43
}
39
40
+/*
41
+ * FP Complex Add
42
+ */
43
+
44
+
44
+void HELPER(sve_fcadd_h)(void *vd, void *vn, void *vm, void *vg,
45
+void helper_sme_zero(CPUARMState *env, uint32_t imm, uint32_t svl)
45
+ void *vs, uint32_t desc)
46
+{
46
+{
47
+ intptr_t j, i = simd_oprsz(desc);
47
+ uint32_t i;
48
+ uint64_t *g = vg;
49
+ float16 neg_imag = float16_set_sign(0, simd_data(desc));
50
+ float16 neg_real = float16_chs(neg_imag);
51
+
48
+
52
+ do {
49
+ /*
53
+ uint64_t pg = g[(i - 1) >> 6];
50
+ * Special case clearing the entire ZA space.
54
+ do {
51
+ * This falls into the CONSTRAINED UNPREDICTABLE zeroing of any
55
+ float16 e0, e1, e2, e3;
52
+ * parts of the ZA storage outside of SVL.
53
+ */
54
+ if (imm == 0xff) {
55
+ memset(env->zarray, 0, sizeof(env->zarray));
56
+ return;
57
+ }
56
+
58
+
57
+ /* I holds the real index; J holds the imag index. */
59
+ /*
58
+ j = i - sizeof(float16);
60
+ * Recall that ZAnH.D[m] is spread across ZA[n+8*m],
59
+ i -= 2 * sizeof(float16);
61
+ * so each row is discontiguous within ZA[].
62
+ */
63
+ for (i = 0; i < svl; i++) {
64
+ if (imm & (1 << (i % 8))) {
65
+ memset(&env->zarray[i], 0, svl);
66
+ }
67
+ }
68
+}
69
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/translate-sme.c
72
+++ b/target/arm/translate-sme.c
73
@@ -XXX,XX +XXX,XX @@
74
*/
75
76
#include "decode-sme.c.inc"
60
+
77
+
61
+ e0 = *(float16 *)(vn + H1_2(i));
62
+ e1 = *(float16 *)(vm + H1_2(j)) ^ neg_real;
63
+ e2 = *(float16 *)(vn + H1_2(j));
64
+ e3 = *(float16 *)(vm + H1_2(i)) ^ neg_imag;
65
+
78
+
66
+ if (likely((pg >> (i & 63)) & 1)) {
79
+static bool trans_ZERO(DisasContext *s, arg_ZERO *a)
67
+ *(float16 *)(vd + H1_2(i)) = float16_add(e0, e1, vs);
68
+ }
69
+ if (likely((pg >> (j & 63)) & 1)) {
70
+ *(float16 *)(vd + H1_2(j)) = float16_add(e2, e3, vs);
71
+ }
72
+ } while (i & 63);
73
+ } while (i != 0);
74
+}
75
+
76
+void HELPER(sve_fcadd_s)(void *vd, void *vn, void *vm, void *vg,
77
+ void *vs, uint32_t desc)
78
+{
80
+{
79
+ intptr_t j, i = simd_oprsz(desc);
81
+ if (!dc_isar_feature(aa64_sme, s)) {
80
+ uint64_t *g = vg;
81
+ float32 neg_imag = float32_set_sign(0, simd_data(desc));
82
+ float32 neg_real = float32_chs(neg_imag);
83
+
84
+ do {
85
+ uint64_t pg = g[(i - 1) >> 6];
86
+ do {
87
+ float32 e0, e1, e2, e3;
88
+
89
+ /* I holds the real index; J holds the imag index. */
90
+ j = i - sizeof(float32);
91
+ i -= 2 * sizeof(float32);
92
+
93
+ e0 = *(float32 *)(vn + H1_2(i));
94
+ e1 = *(float32 *)(vm + H1_2(j)) ^ neg_real;
95
+ e2 = *(float32 *)(vn + H1_2(j));
96
+ e3 = *(float32 *)(vm + H1_2(i)) ^ neg_imag;
97
+
98
+ if (likely((pg >> (i & 63)) & 1)) {
99
+ *(float32 *)(vd + H1_2(i)) = float32_add(e0, e1, vs);
100
+ }
101
+ if (likely((pg >> (j & 63)) & 1)) {
102
+ *(float32 *)(vd + H1_2(j)) = float32_add(e2, e3, vs);
103
+ }
104
+ } while (i & 63);
105
+ } while (i != 0);
106
+}
107
+
108
+void HELPER(sve_fcadd_d)(void *vd, void *vn, void *vm, void *vg,
109
+ void *vs, uint32_t desc)
110
+{
111
+ intptr_t j, i = simd_oprsz(desc);
112
+ uint64_t *g = vg;
113
+ float64 neg_imag = float64_set_sign(0, simd_data(desc));
114
+ float64 neg_real = float64_chs(neg_imag);
115
+
116
+ do {
117
+ uint64_t pg = g[(i - 1) >> 6];
118
+ do {
119
+ float64 e0, e1, e2, e3;
120
+
121
+ /* I holds the real index; J holds the imag index. */
122
+ j = i - sizeof(float64);
123
+ i -= 2 * sizeof(float64);
124
+
125
+ e0 = *(float64 *)(vn + H1_2(i));
126
+ e1 = *(float64 *)(vm + H1_2(j)) ^ neg_real;
127
+ e2 = *(float64 *)(vn + H1_2(j));
128
+ e3 = *(float64 *)(vm + H1_2(i)) ^ neg_imag;
129
+
130
+ if (likely((pg >> (i & 63)) & 1)) {
131
+ *(float64 *)(vd + H1_2(i)) = float64_add(e0, e1, vs);
132
+ }
133
+ if (likely((pg >> (j & 63)) & 1)) {
134
+ *(float64 *)(vd + H1_2(j)) = float64_add(e2, e3, vs);
135
+ }
136
+ } while (i & 63);
137
+ } while (i != 0);
138
+}
139
+
140
/*
141
* Load contiguous data, protected by a governing predicate.
142
*/
143
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/target/arm/translate-sve.c
146
+++ b/target/arm/translate-sve.c
147
@@ -XXX,XX +XXX,XX @@ DO_FPCMP(FACGT, facgt)
148
149
#undef DO_FPCMP
150
151
+static bool trans_FCADD(DisasContext *s, arg_FCADD *a, uint32_t insn)
152
+{
153
+ static gen_helper_gvec_4_ptr * const fns[3] = {
154
+ gen_helper_sve_fcadd_h,
155
+ gen_helper_sve_fcadd_s,
156
+ gen_helper_sve_fcadd_d
157
+ };
158
+
159
+ if (a->esz == 0) {
160
+ return false;
82
+ return false;
161
+ }
83
+ }
162
+ if (sve_access_check(s)) {
84
+ if (sme_za_enabled_check(s)) {
163
+ unsigned vsz = vec_full_reg_size(s);
85
+ gen_helper_sme_zero(cpu_env, tcg_constant_i32(a->imm),
164
+ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
86
+ tcg_constant_i32(streaming_vec_reg_size(s)));
165
+ tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, a->rd),
166
+ vec_full_reg_offset(s, a->rn),
167
+ vec_full_reg_offset(s, a->rm),
168
+ pred_full_reg_offset(s, a->pg),
169
+ status, vsz, vsz, a->rot, fns[a->esz - 1]);
170
+ tcg_temp_free_ptr(status);
171
+ }
87
+ }
172
+ return true;
88
+ return true;
173
+}
89
+}
174
+
175
typedef void gen_helper_sve_fmla(TCGv_env, TCGv_ptr, TCGv_i32);
176
177
static bool do_fmla(DisasContext *s, arg_rprrr_esz *a, gen_helper_sve_fmla *fn)
178
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
179
index XXXXXXX..XXXXXXX 100644
180
--- a/target/arm/sve.decode
181
+++ b/target/arm/sve.decode
182
@@ -XXX,XX +XXX,XX @@ UMIN_zzi 00100101 .. 101 011 110 ........ ..... @rdn_i8u
183
# SVE integer multiply immediate (unpredicated)
184
MUL_zzi 00100101 .. 110 000 110 ........ ..... @rdn_i8s
185
186
+# SVE floating-point complex add (predicated)
187
+FCADD 01100100 esz:2 00000 rot:1 100 pg:3 rm:5 rd:5 \
188
+ rn=%reg_movprfx
189
+
190
### SVE FP Multiply-Add Indexed Group
191
192
# SVE floating-point multiply-add (indexed)
193
--
90
--
194
2.17.1
91
2.25.1
195
196
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
We can reuse the SVE functions for implementing moves to/from
4
horizontal tile slices, but we need new ones for moves to/from
5
vertical tile slices.
2
6
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-12-richard.henderson@linaro.org
9
Message-id: 20220708151540.18136-20-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
target/arm/helper-sve.h | 41 +++++++++++++++++++++
12
target/arm/helper-sme.h | 12 +++
9
target/arm/sve_helper.c | 61 +++++++++++++++++++++++++++++++
13
target/arm/helper-sve.h | 2 +
10
target/arm/translate-sve.c | 75 ++++++++++++++++++++++++++++++++++++++
14
target/arm/translate-a64.h | 8 ++
11
target/arm/sve.decode | 39 ++++++++++++++++++++
15
target/arm/translate.h | 5 ++
12
4 files changed, 216 insertions(+)
16
target/arm/sme.decode | 15 ++++
17
target/arm/sme_helper.c | 151 ++++++++++++++++++++++++++++++++++++-
18
target/arm/sve_helper.c | 12 +++
19
target/arm/translate-sme.c | 127 +++++++++++++++++++++++++++++++
20
8 files changed, 331 insertions(+), 1 deletion(-)
13
21
22
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/helper-sme.h
25
+++ b/target/arm/helper-sme.h
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(set_pstate_sm, TCG_CALL_NO_RWG, void, env, i32)
27
DEF_HELPER_FLAGS_2(set_pstate_za, TCG_CALL_NO_RWG, void, env, i32)
28
29
DEF_HELPER_FLAGS_3(sme_zero, TCG_CALL_NO_RWG, void, env, i32, i32)
30
+
31
+/* Move to/from vertical array slices, i.e. columns, so 'c'. */
32
+DEF_HELPER_FLAGS_4(sme_mova_cz_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_4(sme_mova_zc_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(sme_mova_cz_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_4(sme_mova_zc_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
36
+DEF_HELPER_FLAGS_4(sme_mova_cz_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
+DEF_HELPER_FLAGS_4(sme_mova_zc_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_4(sme_mova_cz_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_4(sme_mova_zc_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_4(sme_mova_cz_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
41
+DEF_HELPER_FLAGS_4(sme_mova_zc_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
42
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
44
--- a/target/arm/helper-sve.h
17
+++ b/target/arm/helper-sve.h
45
+++ b/target/arm/helper-sve.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_st1hs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
46
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_sel_zpzz_s, TCG_CALL_NO_RWG,
19
DEF_HELPER_FLAGS_4(sve_st1hd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
47
void, ptr, ptr, ptr, ptr, i32)
20
48
DEF_HELPER_FLAGS_5(sve_sel_zpzz_d, TCG_CALL_NO_RWG,
21
DEF_HELPER_FLAGS_4(sve_st1sd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
49
void, ptr, ptr, ptr, ptr, i32)
22
+
50
+DEF_HELPER_FLAGS_5(sve_sel_zpzz_q, TCG_CALL_NO_RWG,
23
+DEF_HELPER_FLAGS_6(sve_stbs_zsu, TCG_CALL_NO_WG,
51
+ void, ptr, ptr, ptr, ptr, i32)
24
+ void, env, ptr, ptr, ptr, tl, i32)
52
25
+DEF_HELPER_FLAGS_6(sve_sths_zsu, TCG_CALL_NO_WG,
53
DEF_HELPER_FLAGS_5(sve2_addp_zpzz_b, TCG_CALL_NO_RWG,
26
+ void, env, ptr, ptr, ptr, tl, i32)
54
void, ptr, ptr, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_6(sve_stss_zsu, TCG_CALL_NO_WG,
55
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
28
+ void, env, ptr, ptr, ptr, tl, i32)
56
index XXXXXXX..XXXXXXX 100644
29
+
57
--- a/target/arm/translate-a64.h
30
+DEF_HELPER_FLAGS_6(sve_stbs_zss, TCG_CALL_NO_WG,
58
+++ b/target/arm/translate-a64.h
31
+ void, env, ptr, ptr, ptr, tl, i32)
59
@@ -XXX,XX +XXX,XX @@ static inline int pred_gvec_reg_size(DisasContext *s)
32
+DEF_HELPER_FLAGS_6(sve_sths_zss, TCG_CALL_NO_WG,
60
return size_for_gvec(pred_full_reg_size(s));
33
+ void, env, ptr, ptr, ptr, tl, i32)
61
}
34
+DEF_HELPER_FLAGS_6(sve_stss_zss, TCG_CALL_NO_WG,
62
35
+ void, env, ptr, ptr, ptr, tl, i32)
63
+/* Return a newly allocated pointer to the predicate register. */
36
+
64
+static inline TCGv_ptr pred_full_reg_ptr(DisasContext *s, int regno)
37
+DEF_HELPER_FLAGS_6(sve_stbd_zsu, TCG_CALL_NO_WG,
65
+{
38
+ void, env, ptr, ptr, ptr, tl, i32)
66
+ TCGv_ptr ret = tcg_temp_new_ptr();
39
+DEF_HELPER_FLAGS_6(sve_sthd_zsu, TCG_CALL_NO_WG,
67
+ tcg_gen_addi_ptr(ret, cpu_env, pred_full_reg_offset(s, regno));
40
+ void, env, ptr, ptr, ptr, tl, i32)
68
+ return ret;
41
+DEF_HELPER_FLAGS_6(sve_stsd_zsu, TCG_CALL_NO_WG,
69
+}
42
+ void, env, ptr, ptr, ptr, tl, i32)
70
+
43
+DEF_HELPER_FLAGS_6(sve_stdd_zsu, TCG_CALL_NO_WG,
71
bool disas_sve(DisasContext *, uint32_t);
44
+ void, env, ptr, ptr, ptr, tl, i32)
72
bool disas_sme(DisasContext *, uint32_t);
45
+
73
46
+DEF_HELPER_FLAGS_6(sve_stbd_zss, TCG_CALL_NO_WG,
74
diff --git a/target/arm/translate.h b/target/arm/translate.h
47
+ void, env, ptr, ptr, ptr, tl, i32)
75
index XXXXXXX..XXXXXXX 100644
48
+DEF_HELPER_FLAGS_6(sve_sthd_zss, TCG_CALL_NO_WG,
76
--- a/target/arm/translate.h
49
+ void, env, ptr, ptr, ptr, tl, i32)
77
+++ b/target/arm/translate.h
50
+DEF_HELPER_FLAGS_6(sve_stsd_zss, TCG_CALL_NO_WG,
78
@@ -XXX,XX +XXX,XX @@ static inline int plus_2(DisasContext *s, int x)
51
+ void, env, ptr, ptr, ptr, tl, i32)
79
return x + 2;
52
+DEF_HELPER_FLAGS_6(sve_stdd_zss, TCG_CALL_NO_WG,
80
}
53
+ void, env, ptr, ptr, ptr, tl, i32)
81
54
+
82
+static inline int plus_12(DisasContext *s, int x)
55
+DEF_HELPER_FLAGS_6(sve_stbd_zd, TCG_CALL_NO_WG,
83
+{
56
+ void, env, ptr, ptr, ptr, tl, i32)
84
+ return x + 12;
57
+DEF_HELPER_FLAGS_6(sve_sthd_zd, TCG_CALL_NO_WG,
85
+}
58
+ void, env, ptr, ptr, ptr, tl, i32)
86
+
59
+DEF_HELPER_FLAGS_6(sve_stsd_zd, TCG_CALL_NO_WG,
87
static inline int times_2(DisasContext *s, int x)
60
+ void, env, ptr, ptr, ptr, tl, i32)
88
{
61
+DEF_HELPER_FLAGS_6(sve_stdd_zd, TCG_CALL_NO_WG,
89
return x * 2;
62
+ void, env, ptr, ptr, ptr, tl, i32)
90
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
63
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
91
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/sme.decode
65
--- a/target/arm/sve_helper.c
93
+++ b/target/arm/sme.decode
66
+++ b/target/arm/sve_helper.c
94
@@ -XXX,XX +XXX,XX @@
67
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_st4dd_r)(CPUARMState *env, void *vg,
95
### SME Misc
68
addr += 4 * 8;
96
97
ZERO 11000000 00 001 00000000000 imm:8
98
+
99
+### SME Move into/from Array
100
+
101
+%mova_rs 13:2 !function=plus_12
102
+&mova esz rs pg zr za_imm v:bool to_vec:bool
103
+
104
+MOVA 11000000 esz:2 00000 0 v:1 .. pg:3 zr:5 0 za_imm:4 \
105
+ &mova to_vec=0 rs=%mova_rs
106
+MOVA 11000000 11 00000 1 v:1 .. pg:3 zr:5 0 za_imm:4 \
107
+ &mova to_vec=0 rs=%mova_rs esz=4
108
+
109
+MOVA 11000000 esz:2 00001 0 v:1 .. pg:3 0 za_imm:4 zr:5 \
110
+ &mova to_vec=1 rs=%mova_rs
111
+MOVA 11000000 11 00001 1 v:1 .. pg:3 0 za_imm:4 zr:5 \
112
+ &mova to_vec=1 rs=%mova_rs esz=4
113
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/sme_helper.c
116
+++ b/target/arm/sme_helper.c
117
@@ -XXX,XX +XXX,XX @@
118
119
#include "qemu/osdep.h"
120
#include "cpu.h"
121
-#include "internals.h"
122
+#include "tcg/tcg-gvec-desc.h"
123
#include "exec/helper-proto.h"
124
+#include "qemu/int128.h"
125
+#include "vec_internal.h"
126
127
/* ResetSVEState */
128
void arm_reset_sve_state(CPUARMState *env)
129
@@ -XXX,XX +XXX,XX @@ void helper_sme_zero(CPUARMState *env, uint32_t imm, uint32_t svl)
130
}
69
}
131
}
70
}
132
}
71
+
133
+
72
+/* Stores with a vector index. */
134
+
73
+
135
+/*
74
+#define DO_ST1_ZPZ_S(NAME, TYPEI, FN) \
136
+ * When considering the ZA storage as an array of elements of
75
+void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
137
+ * type T, the index within that array of the Nth element of
76
+ target_ulong base, uint32_t desc) \
138
+ * a vertical slice of a tile can be calculated like this,
139
+ * regardless of the size of type T. This is because the tiles
140
+ * are interleaved, so if type T is size N bytes then row 1 of
141
+ * the tile is N rows away from row 0. The division by N to
142
+ * convert a byte offset into an array index and the multiplication
143
+ * by N to convert from vslice-index-within-the-tile to
144
+ * the index within the ZA storage cancel out.
145
+ */
146
+#define tile_vslice_index(i) ((i) * sizeof(ARMVectorReg))
147
+
148
+/*
149
+ * When doing byte arithmetic on the ZA storage, the element
150
+ * byteoff bytes away in a tile vertical slice is always this
151
+ * many bytes away in the ZA storage, regardless of the
152
+ * size of the tile element, assuming that byteoff is a multiple
153
+ * of the element size. Again this is because of the interleaving
154
+ * of the tiles. For instance if we have 1 byte per element then
155
+ * each row of the ZA storage has one byte of the vslice data,
156
+ * and (counting from 0) byte 8 goes in row 8 of the storage
157
+ * at offset (8 * row-size-in-bytes).
158
+ * If we have 8 bytes per element then each row of the ZA storage
159
+ * has 8 bytes of the data, but there are 8 interleaved tiles and
160
+ * so byte 8 of the data goes into row 1 of the tile,
161
+ * which is again row 8 of the storage, so the offset is still
162
+ * (8 * row-size-in-bytes). Similarly for other element sizes.
163
+ */
164
+#define tile_vslice_offset(byteoff) ((byteoff) * sizeof(ARMVectorReg))
165
+
166
+
167
+/*
168
+ * Move Zreg vector to ZArray column.
169
+ */
170
+#define DO_MOVA_C(NAME, TYPE, H) \
171
+void HELPER(NAME)(void *za, void *vn, void *vg, uint32_t desc) \
77
+{ \
172
+{ \
78
+ intptr_t i, oprsz = simd_oprsz(desc); \
173
+ int i, oprsz = simd_oprsz(desc); \
79
+ unsigned scale = simd_data(desc); \
80
+ uintptr_t ra = GETPC(); \
81
+ for (i = 0; i < oprsz; ) { \
174
+ for (i = 0; i < oprsz; ) { \
82
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
175
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
83
+ do { \
176
+ do { \
84
+ if (likely(pg & 1)) { \
177
+ if (pg & 1) { \
85
+ target_ulong off = *(TYPEI *)(vm + H1_4(i)); \
178
+ *(TYPE *)(za + tile_vslice_offset(i)) = *(TYPE *)(vn + H(i)); \
86
+ uint32_t d = *(uint32_t *)(vd + H1_4(i)); \
87
+ FN(env, base + (off << scale), d, ra); \
88
+ } \
179
+ } \
89
+ i += sizeof(uint32_t), pg >>= sizeof(uint32_t); \
180
+ i += sizeof(TYPE); \
181
+ pg >>= sizeof(TYPE); \
90
+ } while (i & 15); \
182
+ } while (i & 15); \
91
+ } \
183
+ } \
92
+}
184
+}
93
+
185
+
94
+#define DO_ST1_ZPZ_D(NAME, TYPEI, FN) \
186
+DO_MOVA_C(sme_mova_cz_b, uint8_t, H1)
95
+void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
187
+DO_MOVA_C(sme_mova_cz_h, uint16_t, H1_2)
96
+ target_ulong base, uint32_t desc) \
188
+DO_MOVA_C(sme_mova_cz_s, uint32_t, H1_4)
189
+
190
+void HELPER(sme_mova_cz_d)(void *za, void *vn, void *vg, uint32_t desc)
191
+{
192
+ int i, oprsz = simd_oprsz(desc) / 8;
193
+ uint8_t *pg = vg;
194
+ uint64_t *n = vn;
195
+ uint64_t *a = za;
196
+
197
+ for (i = 0; i < oprsz; i++) {
198
+ if (pg[H1(i)] & 1) {
199
+ a[tile_vslice_index(i)] = n[i];
200
+ }
201
+ }
202
+}
203
+
204
+void HELPER(sme_mova_cz_q)(void *za, void *vn, void *vg, uint32_t desc)
205
+{
206
+ int i, oprsz = simd_oprsz(desc) / 16;
207
+ uint16_t *pg = vg;
208
+ Int128 *n = vn;
209
+ Int128 *a = za;
210
+
211
+ /*
212
+ * Int128 is used here simply to copy 16 bytes, and to simplify
213
+ * the address arithmetic.
214
+ */
215
+ for (i = 0; i < oprsz; i++) {
216
+ if (pg[H2(i)] & 1) {
217
+ a[tile_vslice_index(i)] = n[i];
218
+ }
219
+ }
220
+}
221
+
222
+#undef DO_MOVA_C
223
+
224
+/*
225
+ * Move ZArray column to Zreg vector.
226
+ */
227
+#define DO_MOVA_Z(NAME, TYPE, H) \
228
+void HELPER(NAME)(void *vd, void *za, void *vg, uint32_t desc) \
97
+{ \
229
+{ \
98
+ intptr_t i, oprsz = simd_oprsz(desc) / 8; \
230
+ int i, oprsz = simd_oprsz(desc); \
99
+ unsigned scale = simd_data(desc); \
231
+ for (i = 0; i < oprsz; ) { \
100
+ uintptr_t ra = GETPC(); \
232
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
101
+ uint64_t *d = vd, *m = vm; uint8_t *pg = vg; \
233
+ do { \
102
+ for (i = 0; i < oprsz; i++) { \
234
+ if (pg & 1) { \
103
+ if (likely(pg[H1(i)] & 1)) { \
235
+ *(TYPE *)(vd + H(i)) = *(TYPE *)(za + tile_vslice_offset(i)); \
104
+ target_ulong off = (target_ulong)(TYPEI)m[i] << scale; \
236
+ } \
105
+ FN(env, base + off, d[i], ra); \
237
+ i += sizeof(TYPE); \
106
+ } \
238
+ pg >>= sizeof(TYPE); \
239
+ } while (i & 15); \
107
+ } \
240
+ } \
108
+}
241
+}
109
+
242
+
110
+DO_ST1_ZPZ_S(sve_stbs_zsu, uint32_t, cpu_stb_data_ra)
243
+DO_MOVA_Z(sme_mova_zc_b, uint8_t, H1)
111
+DO_ST1_ZPZ_S(sve_sths_zsu, uint32_t, cpu_stw_data_ra)
244
+DO_MOVA_Z(sme_mova_zc_h, uint16_t, H1_2)
112
+DO_ST1_ZPZ_S(sve_stss_zsu, uint32_t, cpu_stl_data_ra)
245
+DO_MOVA_Z(sme_mova_zc_s, uint32_t, H1_4)
113
+
246
+
114
+DO_ST1_ZPZ_S(sve_stbs_zss, int32_t, cpu_stb_data_ra)
247
+void HELPER(sme_mova_zc_d)(void *vd, void *za, void *vg, uint32_t desc)
115
+DO_ST1_ZPZ_S(sve_sths_zss, int32_t, cpu_stw_data_ra)
248
+{
116
+DO_ST1_ZPZ_S(sve_stss_zss, int32_t, cpu_stl_data_ra)
249
+ int i, oprsz = simd_oprsz(desc) / 8;
117
+
250
+ uint8_t *pg = vg;
118
+DO_ST1_ZPZ_D(sve_stbd_zsu, uint32_t, cpu_stb_data_ra)
251
+ uint64_t *d = vd;
119
+DO_ST1_ZPZ_D(sve_sthd_zsu, uint32_t, cpu_stw_data_ra)
252
+ uint64_t *a = za;
120
+DO_ST1_ZPZ_D(sve_stsd_zsu, uint32_t, cpu_stl_data_ra)
253
+
121
+DO_ST1_ZPZ_D(sve_stdd_zsu, uint32_t, cpu_stq_data_ra)
254
+ for (i = 0; i < oprsz; i++) {
122
+
255
+ if (pg[H1(i)] & 1) {
123
+DO_ST1_ZPZ_D(sve_stbd_zss, int32_t, cpu_stb_data_ra)
256
+ d[i] = a[tile_vslice_index(i)];
124
+DO_ST1_ZPZ_D(sve_sthd_zss, int32_t, cpu_stw_data_ra)
257
+ }
125
+DO_ST1_ZPZ_D(sve_stsd_zss, int32_t, cpu_stl_data_ra)
258
+ }
126
+DO_ST1_ZPZ_D(sve_stdd_zss, int32_t, cpu_stq_data_ra)
259
+}
127
+
260
+
128
+DO_ST1_ZPZ_D(sve_stbd_zd, uint64_t, cpu_stb_data_ra)
261
+void HELPER(sme_mova_zc_q)(void *vd, void *za, void *vg, uint32_t desc)
129
+DO_ST1_ZPZ_D(sve_sthd_zd, uint64_t, cpu_stw_data_ra)
262
+{
130
+DO_ST1_ZPZ_D(sve_stsd_zd, uint64_t, cpu_stl_data_ra)
263
+ int i, oprsz = simd_oprsz(desc) / 16;
131
+DO_ST1_ZPZ_D(sve_stdd_zd, uint64_t, cpu_stq_data_ra)
264
+ uint16_t *pg = vg;
132
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
265
+ Int128 *d = vd;
133
index XXXXXXX..XXXXXXX 100644
266
+ Int128 *a = za;
134
--- a/target/arm/translate-sve.c
267
+
135
+++ b/target/arm/translate-sve.c
268
+ /*
136
@@ -XXX,XX +XXX,XX @@ typedef void gen_helper_gvec_flags_4(TCGv_i32, TCGv_ptr, TCGv_ptr,
269
+ * Int128 is used here simply to copy 16 bytes, and to simplify
137
TCGv_ptr, TCGv_ptr, TCGv_i32);
270
+ * the address arithmetic.
138
271
+ */
139
typedef void gen_helper_gvec_mem(TCGv_env, TCGv_ptr, TCGv_i64, TCGv_i32);
272
+ for (i = 0; i < oprsz; i++, za += sizeof(ARMVectorReg)) {
140
+typedef void gen_helper_gvec_mem_scatter(TCGv_env, TCGv_ptr, TCGv_ptr,
273
+ if (pg[H2(i)] & 1) {
141
+ TCGv_ptr, TCGv_i64, TCGv_i32);
274
+ d[i] = a[tile_vslice_index(i)];
142
275
+ }
143
/*
276
+ }
144
* Helpers for extracting complex instruction fields.
277
+}
145
@@ -XXX,XX +XXX,XX @@ static bool trans_ST_zpri(DisasContext *s, arg_rpri_store *a, uint32_t insn)
278
+
279
+#undef DO_MOVA_Z
280
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
281
index XXXXXXX..XXXXXXX 100644
282
--- a/target/arm/sve_helper.c
283
+++ b/target/arm/sve_helper.c
284
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_sel_zpzz_d)(void *vd, void *vn, void *vm,
285
}
286
}
287
288
+void HELPER(sve_sel_zpzz_q)(void *vd, void *vn, void *vm,
289
+ void *vg, uint32_t desc)
290
+{
291
+ intptr_t i, opr_sz = simd_oprsz(desc) / 16;
292
+ Int128 *d = vd, *n = vn, *m = vm;
293
+ uint16_t *pg = vg;
294
+
295
+ for (i = 0; i < opr_sz; i += 1) {
296
+ d[i] = (pg[H2(i)] & 1 ? n : m)[i];
297
+ }
298
+}
299
+
300
/* Two operand comparison controlled by a predicate.
301
* ??? It is very tempting to want to be able to expand this inline
302
* with x86 instructions, e.g.
303
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
304
index XXXXXXX..XXXXXXX 100644
305
--- a/target/arm/translate-sme.c
306
+++ b/target/arm/translate-sme.c
307
@@ -XXX,XX +XXX,XX @@
308
#include "decode-sme.c.inc"
309
310
311
+/*
312
+ * Resolve tile.size[index] to a host pointer, where tile and index
313
+ * are always decoded together, dependent on the element size.
314
+ */
315
+static TCGv_ptr get_tile_rowcol(DisasContext *s, int esz, int rs,
316
+ int tile_index, bool vertical)
317
+{
318
+ int tile = tile_index >> (4 - esz);
319
+ int index = esz == MO_128 ? 0 : extract32(tile_index, 0, 4 - esz);
320
+ int pos, len, offset;
321
+ TCGv_i32 tmp;
322
+ TCGv_ptr addr;
323
+
324
+ /* Compute the final index, which is Rs+imm. */
325
+ tmp = tcg_temp_new_i32();
326
+ tcg_gen_trunc_tl_i32(tmp, cpu_reg(s, rs));
327
+ tcg_gen_addi_i32(tmp, tmp, index);
328
+
329
+ /* Prepare a power-of-two modulo via extraction of @len bits. */
330
+ len = ctz32(streaming_vec_reg_size(s)) - esz;
331
+
332
+ if (vertical) {
333
+ /*
334
+ * Compute the byte offset of the index within the tile:
335
+ * (index % (svl / size)) * size
336
+ * = (index % (svl >> esz)) << esz
337
+ * Perform the power-of-two modulo via extraction of the low @len bits.
338
+ * Perform the multiply by shifting left by @pos bits.
339
+ * Perform these operations simultaneously via deposit into zero.
340
+ */
341
+ pos = esz;
342
+ tcg_gen_deposit_z_i32(tmp, tmp, pos, len);
343
+
344
+ /*
345
+ * For big-endian, adjust the indexed column byte offset within
346
+ * the uint64_t host words that make up env->zarray[].
347
+ */
348
+ if (HOST_BIG_ENDIAN && esz < MO_64) {
349
+ tcg_gen_xori_i32(tmp, tmp, 8 - (1 << esz));
350
+ }
351
+ } else {
352
+ /*
353
+ * Compute the byte offset of the index within the tile:
354
+ * (index % (svl / size)) * (size * sizeof(row))
355
+ * = (index % (svl >> esz)) << (esz + log2(sizeof(row)))
356
+ */
357
+ pos = esz + ctz32(sizeof(ARMVectorReg));
358
+ tcg_gen_deposit_z_i32(tmp, tmp, pos, len);
359
+
360
+ /* Row slices are always aligned and need no endian adjustment. */
361
+ }
362
+
363
+ /* The tile byte offset within env->zarray is the row. */
364
+ offset = tile * sizeof(ARMVectorReg);
365
+
366
+ /* Include the byte offset of zarray to make this relative to env. */
367
+ offset += offsetof(CPUARMState, zarray);
368
+ tcg_gen_addi_i32(tmp, tmp, offset);
369
+
370
+ /* Add the byte offset to env to produce the final pointer. */
371
+ addr = tcg_temp_new_ptr();
372
+ tcg_gen_ext_i32_ptr(addr, tmp);
373
+ tcg_temp_free_i32(tmp);
374
+ tcg_gen_add_ptr(addr, addr, cpu_env);
375
+
376
+ return addr;
377
+}
378
+
379
static bool trans_ZERO(DisasContext *s, arg_ZERO *a)
380
{
381
if (!dc_isar_feature(aa64_sme, s)) {
382
@@ -XXX,XX +XXX,XX @@ static bool trans_ZERO(DisasContext *s, arg_ZERO *a)
146
}
383
}
147
return true;
384
return true;
148
}
385
}
149
+
386
+
150
+/*
387
+static bool trans_MOVA(DisasContext *s, arg_MOVA *a)
151
+ *** SVE gather loads / scatter stores
388
+{
152
+ */
389
+ static gen_helper_gvec_4 * const h_fns[5] = {
153
+
390
+ gen_helper_sve_sel_zpzz_b, gen_helper_sve_sel_zpzz_h,
154
+static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm, int scale,
391
+ gen_helper_sve_sel_zpzz_s, gen_helper_sve_sel_zpzz_d,
155
+ TCGv_i64 scalar, gen_helper_gvec_mem_scatter *fn)
392
+ gen_helper_sve_sel_zpzz_q
156
+{
393
+ };
157
+ unsigned vsz = vec_full_reg_size(s);
394
+ static gen_helper_gvec_3 * const cz_fns[5] = {
158
+ TCGv_i32 desc = tcg_const_i32(simd_desc(vsz, vsz, scale));
395
+ gen_helper_sme_mova_cz_b, gen_helper_sme_mova_cz_h,
159
+ TCGv_ptr t_zm = tcg_temp_new_ptr();
396
+ gen_helper_sme_mova_cz_s, gen_helper_sme_mova_cz_d,
160
+ TCGv_ptr t_pg = tcg_temp_new_ptr();
397
+ gen_helper_sme_mova_cz_q,
161
+ TCGv_ptr t_zt = tcg_temp_new_ptr();
398
+ };
162
+
399
+ static gen_helper_gvec_3 * const zc_fns[5] = {
163
+ tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
400
+ gen_helper_sme_mova_zc_b, gen_helper_sme_mova_zc_h,
164
+ tcg_gen_addi_ptr(t_zm, cpu_env, vec_full_reg_offset(s, zm));
401
+ gen_helper_sme_mova_zc_s, gen_helper_sme_mova_zc_d,
165
+ tcg_gen_addi_ptr(t_zt, cpu_env, vec_full_reg_offset(s, zt));
402
+ gen_helper_sme_mova_zc_q,
166
+ fn(cpu_env, t_zt, t_pg, t_zm, scalar, desc);
403
+ };
167
+
404
+
168
+ tcg_temp_free_ptr(t_zt);
405
+ TCGv_ptr t_za, t_zr, t_pg;
169
+ tcg_temp_free_ptr(t_zm);
406
+ TCGv_i32 t_desc;
407
+ int svl;
408
+
409
+ if (!dc_isar_feature(aa64_sme, s)) {
410
+ return false;
411
+ }
412
+ if (!sme_smza_enabled_check(s)) {
413
+ return true;
414
+ }
415
+
416
+ t_za = get_tile_rowcol(s, a->esz, a->rs, a->za_imm, a->v);
417
+ t_zr = vec_full_reg_ptr(s, a->zr);
418
+ t_pg = pred_full_reg_ptr(s, a->pg);
419
+
420
+ svl = streaming_vec_reg_size(s);
421
+ t_desc = tcg_constant_i32(simd_desc(svl, svl, 0));
422
+
423
+ if (a->v) {
424
+ /* Vertical slice -- use sme mova helpers. */
425
+ if (a->to_vec) {
426
+ zc_fns[a->esz](t_zr, t_za, t_pg, t_desc);
427
+ } else {
428
+ cz_fns[a->esz](t_za, t_zr, t_pg, t_desc);
429
+ }
430
+ } else {
431
+ /* Horizontal slice -- reuse sve sel helpers. */
432
+ if (a->to_vec) {
433
+ h_fns[a->esz](t_zr, t_za, t_zr, t_pg, t_desc);
434
+ } else {
435
+ h_fns[a->esz](t_za, t_zr, t_za, t_pg, t_desc);
436
+ }
437
+ }
438
+
439
+ tcg_temp_free_ptr(t_za);
440
+ tcg_temp_free_ptr(t_zr);
170
+ tcg_temp_free_ptr(t_pg);
441
+ tcg_temp_free_ptr(t_pg);
171
+ tcg_temp_free_i32(desc);
442
+
172
+}
173
+
174
+static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
175
+{
176
+ /* Indexed by [xs][msz]. */
177
+ static gen_helper_gvec_mem_scatter * const fn32[2][3] = {
178
+ { gen_helper_sve_stbs_zsu,
179
+ gen_helper_sve_sths_zsu,
180
+ gen_helper_sve_stss_zsu, },
181
+ { gen_helper_sve_stbs_zss,
182
+ gen_helper_sve_sths_zss,
183
+ gen_helper_sve_stss_zss, },
184
+ };
185
+ /* Note that we overload xs=2 to indicate 64-bit offset. */
186
+ static gen_helper_gvec_mem_scatter * const fn64[3][4] = {
187
+ { gen_helper_sve_stbd_zsu,
188
+ gen_helper_sve_sthd_zsu,
189
+ gen_helper_sve_stsd_zsu,
190
+ gen_helper_sve_stdd_zsu, },
191
+ { gen_helper_sve_stbd_zss,
192
+ gen_helper_sve_sthd_zss,
193
+ gen_helper_sve_stsd_zss,
194
+ gen_helper_sve_stdd_zss, },
195
+ { gen_helper_sve_stbd_zd,
196
+ gen_helper_sve_sthd_zd,
197
+ gen_helper_sve_stsd_zd,
198
+ gen_helper_sve_stdd_zd, },
199
+ };
200
+ gen_helper_gvec_mem_scatter *fn;
201
+
202
+ if (a->esz < a->msz || (a->msz == 0 && a->scale)) {
203
+ return false;
204
+ }
205
+ if (!sve_access_check(s)) {
206
+ return true;
207
+ }
208
+ switch (a->esz) {
209
+ case MO_32:
210
+ fn = fn32[a->xs][a->msz];
211
+ break;
212
+ case MO_64:
213
+ fn = fn64[a->xs][a->msz];
214
+ break;
215
+ default:
216
+ g_assert_not_reached();
217
+ }
218
+ do_mem_zpz(s, a->rd, a->pg, a->rm, a->scale * a->msz,
219
+ cpu_reg_sp(s, a->rn), fn);
220
+ return true;
443
+ return true;
221
+}
444
+}
222
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
223
index XXXXXXX..XXXXXXX 100644
224
--- a/target/arm/sve.decode
225
+++ b/target/arm/sve.decode
226
@@ -XXX,XX +XXX,XX @@
227
&rpri_load rd pg rn imm dtype nreg
228
&rprr_store rd pg rn rm msz esz nreg
229
&rpri_store rd pg rn imm msz esz nreg
230
+&rprr_scatter_store rd pg rn rm esz msz xs scale
231
232
###########################################################################
233
# Named instruction formats. These are generally used to
234
@@ -XXX,XX +XXX,XX @@
235
@rpri_store_msz ....... msz:2 .. . imm:s4 ... pg:3 rn:5 rd:5 &rpri_store
236
@rprr_store_esz_n0 ....... .. esz:2 rm:5 ... pg:3 rn:5 rd:5 \
237
&rprr_store nreg=0
238
+@rprr_scatter_store ....... msz:2 .. rm:5 ... pg:3 rn:5 rd:5 \
239
+ &rprr_scatter_store
240
241
###########################################################################
242
# Instruction patterns. Grouped according to the SVE encodingindex.xhtml.
243
@@ -XXX,XX +XXX,XX @@ ST_zpri 1110010 .. nreg:2 1.... 111 ... ..... ..... \
244
# SVE store multiple structures (scalar plus scalar) (nreg != 0)
245
ST_zprr 1110010 msz:2 nreg:2 ..... 011 ... ..... ..... \
246
@rprr_store esz=%size_23
247
+
248
+# SVE 32-bit scatter store (scalar plus 32-bit scaled offsets)
249
+# Require msz > 0 && msz <= esz.
250
+ST1_zprz 1110010 .. 11 ..... 100 ... ..... ..... \
251
+ @rprr_scatter_store xs=0 esz=2 scale=1
252
+ST1_zprz 1110010 .. 11 ..... 110 ... ..... ..... \
253
+ @rprr_scatter_store xs=1 esz=2 scale=1
254
+
255
+# SVE 32-bit scatter store (scalar plus 32-bit unscaled offsets)
256
+# Require msz <= esz.
257
+ST1_zprz 1110010 .. 10 ..... 100 ... ..... ..... \
258
+ @rprr_scatter_store xs=0 esz=2 scale=0
259
+ST1_zprz 1110010 .. 10 ..... 110 ... ..... ..... \
260
+ @rprr_scatter_store xs=1 esz=2 scale=0
261
+
262
+# SVE 64-bit scatter store (scalar plus 64-bit scaled offset)
263
+# Require msz > 0
264
+ST1_zprz 1110010 .. 01 ..... 101 ... ..... ..... \
265
+ @rprr_scatter_store xs=2 esz=3 scale=1
266
+
267
+# SVE 64-bit scatter store (scalar plus 64-bit unscaled offset)
268
+ST1_zprz 1110010 .. 00 ..... 101 ... ..... ..... \
269
+ @rprr_scatter_store xs=2 esz=3 scale=0
270
+
271
+# SVE 64-bit scatter store (scalar plus unpacked 32-bit scaled offset)
272
+# Require msz > 0
273
+ST1_zprz 1110010 .. 01 ..... 100 ... ..... ..... \
274
+ @rprr_scatter_store xs=0 esz=3 scale=1
275
+ST1_zprz 1110010 .. 01 ..... 110 ... ..... ..... \
276
+ @rprr_scatter_store xs=1 esz=3 scale=1
277
+
278
+# SVE 64-bit scatter store (scalar plus unpacked 32-bit unscaled offset)
279
+ST1_zprz 1110010 .. 00 ..... 100 ... ..... ..... \
280
+ @rprr_scatter_store xs=0 esz=3 scale=0
281
+ST1_zprz 1110010 .. 00 ..... 110 ... ..... ..... \
282
+ @rprr_scatter_store xs=1 esz=3 scale=0
283
--
445
--
284
2.17.1
446
2.25.1
285
286
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We cannot reuse the SVE functions for LD[1-4] and ST[1-4],
4
because those functions accept only a Zreg register number.
5
For SME, we want to pass a pointer into ZA storage.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20220708151540.18136-21-richard.henderson@linaro.org
5
Tested-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 20180627043328.11531-3-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
11
---
9
target/arm/helper-sve.h | 40 ++++++++++
12
target/arm/helper-sme.h | 82 +++++
10
target/arm/sve_helper.c | 157 +++++++++++++++++++++++++++++++++++++
13
target/arm/sme.decode | 9 +
11
target/arm/translate-sve.c | 69 ++++++++++++++++
14
target/arm/sme_helper.c | 595 +++++++++++++++++++++++++++++++++++++
12
target/arm/sve.decode | 6 ++
15
target/arm/translate-sme.c | 70 +++++
13
4 files changed, 272 insertions(+)
16
4 files changed, 756 insertions(+)
14
17
15
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
18
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-sve.h
20
--- a/target/arm/helper-sme.h
18
+++ b/target/arm/helper-sve.h
21
+++ b/target/arm/helper-sme.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_ld1hds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sme_mova_cz_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
20
23
DEF_HELPER_FLAGS_4(sme_mova_zc_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
21
DEF_HELPER_FLAGS_4(sve_ld1sdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
24
DEF_HELPER_FLAGS_4(sme_mova_cz_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
DEF_HELPER_FLAGS_4(sve_ld1sds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
25
DEF_HELPER_FLAGS_4(sme_mova_zc_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
+
26
+
24
+DEF_HELPER_FLAGS_4(sve_ldff1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
27
+DEF_HELPER_FLAGS_5(sme_ld1b_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
25
+DEF_HELPER_FLAGS_4(sve_ldff1bhu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
28
+DEF_HELPER_FLAGS_5(sme_ld1b_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
26
+DEF_HELPER_FLAGS_4(sve_ldff1bsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
29
+DEF_HELPER_FLAGS_5(sme_ld1b_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
27
+DEF_HELPER_FLAGS_4(sve_ldff1bdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
30
+DEF_HELPER_FLAGS_5(sme_ld1b_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
28
+DEF_HELPER_FLAGS_4(sve_ldff1bhs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
31
+
29
+DEF_HELPER_FLAGS_4(sve_ldff1bss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
32
+DEF_HELPER_FLAGS_5(sme_ld1h_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
30
+DEF_HELPER_FLAGS_4(sve_ldff1bds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
33
+DEF_HELPER_FLAGS_5(sme_ld1h_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
31
+
34
+DEF_HELPER_FLAGS_5(sme_ld1h_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
32
+DEF_HELPER_FLAGS_4(sve_ldff1hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
35
+DEF_HELPER_FLAGS_5(sme_ld1h_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
33
+DEF_HELPER_FLAGS_4(sve_ldff1hsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
36
+DEF_HELPER_FLAGS_5(sme_ld1h_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
34
+DEF_HELPER_FLAGS_4(sve_ldff1hdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
37
+DEF_HELPER_FLAGS_5(sme_ld1h_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
35
+DEF_HELPER_FLAGS_4(sve_ldff1hss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
38
+DEF_HELPER_FLAGS_5(sme_ld1h_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
36
+DEF_HELPER_FLAGS_4(sve_ldff1hds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
39
+DEF_HELPER_FLAGS_5(sme_ld1h_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
37
+
40
+
38
+DEF_HELPER_FLAGS_4(sve_ldff1ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
41
+DEF_HELPER_FLAGS_5(sme_ld1s_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
39
+DEF_HELPER_FLAGS_4(sve_ldff1sdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
42
+DEF_HELPER_FLAGS_5(sme_ld1s_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_4(sve_ldff1sds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
43
+DEF_HELPER_FLAGS_5(sme_ld1s_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
41
+
44
+DEF_HELPER_FLAGS_5(sme_ld1s_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
42
+DEF_HELPER_FLAGS_4(sve_ldff1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
45
+DEF_HELPER_FLAGS_5(sme_ld1s_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
43
+
46
+DEF_HELPER_FLAGS_5(sme_ld1s_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
44
+DEF_HELPER_FLAGS_4(sve_ldnf1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
47
+DEF_HELPER_FLAGS_5(sme_ld1s_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
45
+DEF_HELPER_FLAGS_4(sve_ldnf1bhu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
48
+DEF_HELPER_FLAGS_5(sme_ld1s_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
46
+DEF_HELPER_FLAGS_4(sve_ldnf1bsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
49
+
47
+DEF_HELPER_FLAGS_4(sve_ldnf1bdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
50
+DEF_HELPER_FLAGS_5(sme_ld1d_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
48
+DEF_HELPER_FLAGS_4(sve_ldnf1bhs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
51
+DEF_HELPER_FLAGS_5(sme_ld1d_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
49
+DEF_HELPER_FLAGS_4(sve_ldnf1bss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
52
+DEF_HELPER_FLAGS_5(sme_ld1d_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
50
+DEF_HELPER_FLAGS_4(sve_ldnf1bds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_5(sme_ld1d_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
51
+
54
+DEF_HELPER_FLAGS_5(sme_ld1d_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
52
+DEF_HELPER_FLAGS_4(sve_ldnf1hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
55
+DEF_HELPER_FLAGS_5(sme_ld1d_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_4(sve_ldnf1hsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
56
+DEF_HELPER_FLAGS_5(sme_ld1d_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
54
+DEF_HELPER_FLAGS_4(sve_ldnf1hdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
57
+DEF_HELPER_FLAGS_5(sme_ld1d_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
55
+DEF_HELPER_FLAGS_4(sve_ldnf1hss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
58
+
56
+DEF_HELPER_FLAGS_4(sve_ldnf1hds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
59
+DEF_HELPER_FLAGS_5(sme_ld1q_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
57
+
60
+DEF_HELPER_FLAGS_5(sme_ld1q_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
58
+DEF_HELPER_FLAGS_4(sve_ldnf1ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
61
+DEF_HELPER_FLAGS_5(sme_ld1q_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
59
+DEF_HELPER_FLAGS_4(sve_ldnf1sdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
62
+DEF_HELPER_FLAGS_5(sme_ld1q_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_4(sve_ldnf1sds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
63
+DEF_HELPER_FLAGS_5(sme_ld1q_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
61
+
64
+DEF_HELPER_FLAGS_5(sme_ld1q_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
62
+DEF_HELPER_FLAGS_4(sve_ldnf1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
65
+DEF_HELPER_FLAGS_5(sme_ld1q_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
63
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
66
+DEF_HELPER_FLAGS_5(sme_ld1q_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
67
+
68
+DEF_HELPER_FLAGS_5(sme_st1b_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
69
+DEF_HELPER_FLAGS_5(sme_st1b_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
70
+DEF_HELPER_FLAGS_5(sme_st1b_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
71
+DEF_HELPER_FLAGS_5(sme_st1b_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
72
+
73
+DEF_HELPER_FLAGS_5(sme_st1h_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
74
+DEF_HELPER_FLAGS_5(sme_st1h_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
75
+DEF_HELPER_FLAGS_5(sme_st1h_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
76
+DEF_HELPER_FLAGS_5(sme_st1h_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
77
+DEF_HELPER_FLAGS_5(sme_st1h_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
78
+DEF_HELPER_FLAGS_5(sme_st1h_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
79
+DEF_HELPER_FLAGS_5(sme_st1h_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
80
+DEF_HELPER_FLAGS_5(sme_st1h_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
81
+
82
+DEF_HELPER_FLAGS_5(sme_st1s_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
83
+DEF_HELPER_FLAGS_5(sme_st1s_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
84
+DEF_HELPER_FLAGS_5(sme_st1s_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
85
+DEF_HELPER_FLAGS_5(sme_st1s_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
86
+DEF_HELPER_FLAGS_5(sme_st1s_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
87
+DEF_HELPER_FLAGS_5(sme_st1s_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
88
+DEF_HELPER_FLAGS_5(sme_st1s_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
89
+DEF_HELPER_FLAGS_5(sme_st1s_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
90
+
91
+DEF_HELPER_FLAGS_5(sme_st1d_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
92
+DEF_HELPER_FLAGS_5(sme_st1d_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
93
+DEF_HELPER_FLAGS_5(sme_st1d_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
94
+DEF_HELPER_FLAGS_5(sme_st1d_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
95
+DEF_HELPER_FLAGS_5(sme_st1d_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
96
+DEF_HELPER_FLAGS_5(sme_st1d_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
97
+DEF_HELPER_FLAGS_5(sme_st1d_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
98
+DEF_HELPER_FLAGS_5(sme_st1d_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
99
+
100
+DEF_HELPER_FLAGS_5(sme_st1q_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
101
+DEF_HELPER_FLAGS_5(sme_st1q_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
102
+DEF_HELPER_FLAGS_5(sme_st1q_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
103
+DEF_HELPER_FLAGS_5(sme_st1q_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
104
+DEF_HELPER_FLAGS_5(sme_st1q_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
105
+DEF_HELPER_FLAGS_5(sme_st1q_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
106
+DEF_HELPER_FLAGS_5(sme_st1q_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
107
+DEF_HELPER_FLAGS_5(sme_st1q_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
108
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
64
index XXXXXXX..XXXXXXX 100644
109
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/sve_helper.c
110
--- a/target/arm/sme.decode
66
+++ b/target/arm/sve_helper.c
111
+++ b/target/arm/sme.decode
67
@@ -XXX,XX +XXX,XX @@ DO_LD4(sve_ld4dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
112
@@ -XXX,XX +XXX,XX @@ MOVA 11000000 esz:2 00001 0 v:1 .. pg:3 0 za_imm:4 zr:5 \
68
#undef DO_LD2
113
&mova to_vec=1 rs=%mova_rs
69
#undef DO_LD3
114
MOVA 11000000 11 00001 1 v:1 .. pg:3 0 za_imm:4 zr:5 \
70
#undef DO_LD4
115
&mova to_vec=1 rs=%mova_rs esz=4
116
+
117
+### SME Memory
118
+
119
+&ldst esz rs pg rn rm za_imm v:bool st:bool
120
+
121
+LDST1 1110000 0 esz:2 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
122
+ &ldst rs=%mova_rs
123
+LDST1 1110000 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
124
+ &ldst esz=4 rs=%mova_rs
125
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/sme_helper.c
128
+++ b/target/arm/sme_helper.c
129
@@ -XXX,XX +XXX,XX @@
130
131
#include "qemu/osdep.h"
132
#include "cpu.h"
133
+#include "internals.h"
134
#include "tcg/tcg-gvec-desc.h"
135
#include "exec/helper-proto.h"
136
+#include "exec/cpu_ldst.h"
137
+#include "exec/exec-all.h"
138
#include "qemu/int128.h"
139
#include "vec_internal.h"
140
+#include "sve_ldst_internal.h"
141
142
/* ResetSVEState */
143
void arm_reset_sve_state(CPUARMState *env)
144
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_mova_zc_q)(void *vd, void *za, void *vg, uint32_t desc)
145
}
146
147
#undef DO_MOVA_Z
71
+
148
+
72
+/*
149
+/*
73
+ * Load contiguous data, first-fault and no-fault.
150
+ * Clear elements in a tile slice comprising len bytes.
74
+ */
151
+ */
75
+
152
+
153
+typedef void ClearFn(void *ptr, size_t off, size_t len);
154
+
155
+static void clear_horizontal(void *ptr, size_t off, size_t len)
156
+{
157
+ memset(ptr + off, 0, len);
158
+}
159
+
160
+static void clear_vertical_b(void *vptr, size_t off, size_t len)
161
+{
162
+ for (size_t i = 0; i < len; ++i) {
163
+ *(uint8_t *)(vptr + tile_vslice_offset(i + off)) = 0;
164
+ }
165
+}
166
+
167
+static void clear_vertical_h(void *vptr, size_t off, size_t len)
168
+{
169
+ for (size_t i = 0; i < len; i += 2) {
170
+ *(uint16_t *)(vptr + tile_vslice_offset(i + off)) = 0;
171
+ }
172
+}
173
+
174
+static void clear_vertical_s(void *vptr, size_t off, size_t len)
175
+{
176
+ for (size_t i = 0; i < len; i += 4) {
177
+ *(uint32_t *)(vptr + tile_vslice_offset(i + off)) = 0;
178
+ }
179
+}
180
+
181
+static void clear_vertical_d(void *vptr, size_t off, size_t len)
182
+{
183
+ for (size_t i = 0; i < len; i += 8) {
184
+ *(uint64_t *)(vptr + tile_vslice_offset(i + off)) = 0;
185
+ }
186
+}
187
+
188
+static void clear_vertical_q(void *vptr, size_t off, size_t len)
189
+{
190
+ for (size_t i = 0; i < len; i += 16) {
191
+ memset(vptr + tile_vslice_offset(i + off), 0, 16);
192
+ }
193
+}
194
+
195
+/*
196
+ * Copy elements from an array into a tile slice comprising len bytes.
197
+ */
198
+
199
+typedef void CopyFn(void *dst, const void *src, size_t len);
200
+
201
+static void copy_horizontal(void *dst, const void *src, size_t len)
202
+{
203
+ memcpy(dst, src, len);
204
+}
205
+
206
+static void copy_vertical_b(void *vdst, const void *vsrc, size_t len)
207
+{
208
+ const uint8_t *src = vsrc;
209
+ uint8_t *dst = vdst;
210
+ size_t i;
211
+
212
+ for (i = 0; i < len; ++i) {
213
+ dst[tile_vslice_index(i)] = src[i];
214
+ }
215
+}
216
+
217
+static void copy_vertical_h(void *vdst, const void *vsrc, size_t len)
218
+{
219
+ const uint16_t *src = vsrc;
220
+ uint16_t *dst = vdst;
221
+ size_t i;
222
+
223
+ for (i = 0; i < len / 2; ++i) {
224
+ dst[tile_vslice_index(i)] = src[i];
225
+ }
226
+}
227
+
228
+static void copy_vertical_s(void *vdst, const void *vsrc, size_t len)
229
+{
230
+ const uint32_t *src = vsrc;
231
+ uint32_t *dst = vdst;
232
+ size_t i;
233
+
234
+ for (i = 0; i < len / 4; ++i) {
235
+ dst[tile_vslice_index(i)] = src[i];
236
+ }
237
+}
238
+
239
+static void copy_vertical_d(void *vdst, const void *vsrc, size_t len)
240
+{
241
+ const uint64_t *src = vsrc;
242
+ uint64_t *dst = vdst;
243
+ size_t i;
244
+
245
+ for (i = 0; i < len / 8; ++i) {
246
+ dst[tile_vslice_index(i)] = src[i];
247
+ }
248
+}
249
+
250
+static void copy_vertical_q(void *vdst, const void *vsrc, size_t len)
251
+{
252
+ for (size_t i = 0; i < len; i += 16) {
253
+ memcpy(vdst + tile_vslice_offset(i), vsrc + i, 16);
254
+ }
255
+}
256
+
257
+/*
258
+ * Host and TLB primitives for vertical tile slice addressing.
259
+ */
260
+
261
+#define DO_LD(NAME, TYPE, HOST, TLB) \
262
+static inline void sme_##NAME##_v_host(void *za, intptr_t off, void *host) \
263
+{ \
264
+ TYPE val = HOST(host); \
265
+ *(TYPE *)(za + tile_vslice_offset(off)) = val; \
266
+} \
267
+static inline void sme_##NAME##_v_tlb(CPUARMState *env, void *za, \
268
+ intptr_t off, target_ulong addr, uintptr_t ra) \
269
+{ \
270
+ TYPE val = TLB(env, useronly_clean_ptr(addr), ra); \
271
+ *(TYPE *)(za + tile_vslice_offset(off)) = val; \
272
+}
273
+
274
+#define DO_ST(NAME, TYPE, HOST, TLB) \
275
+static inline void sme_##NAME##_v_host(void *za, intptr_t off, void *host) \
276
+{ \
277
+ TYPE val = *(TYPE *)(za + tile_vslice_offset(off)); \
278
+ HOST(host, val); \
279
+} \
280
+static inline void sme_##NAME##_v_tlb(CPUARMState *env, void *za, \
281
+ intptr_t off, target_ulong addr, uintptr_t ra) \
282
+{ \
283
+ TYPE val = *(TYPE *)(za + tile_vslice_offset(off)); \
284
+ TLB(env, useronly_clean_ptr(addr), val, ra); \
285
+}
286
+
287
+/*
288
+ * The ARMVectorReg elements are stored in host-endian 64-bit units.
289
+ * For 128-bit quantities, the sequence defined by the Elem[] pseudocode
290
+ * corresponds to storing the two 64-bit pieces in little-endian order.
291
+ */
292
+#define DO_LDQ(HNAME, VNAME, BE, HOST, TLB) \
293
+static inline void HNAME##_host(void *za, intptr_t off, void *host) \
294
+{ \
295
+ uint64_t val0 = HOST(host), val1 = HOST(host + 8); \
296
+ uint64_t *ptr = za + off; \
297
+ ptr[0] = BE ? val1 : val0, ptr[1] = BE ? val0 : val1; \
298
+} \
299
+static inline void VNAME##_v_host(void *za, intptr_t off, void *host) \
300
+{ \
301
+ HNAME##_host(za, tile_vslice_offset(off), host); \
302
+} \
303
+static inline void HNAME##_tlb(CPUARMState *env, void *za, intptr_t off, \
304
+ target_ulong addr, uintptr_t ra) \
305
+{ \
306
+ uint64_t val0 = TLB(env, useronly_clean_ptr(addr), ra); \
307
+ uint64_t val1 = TLB(env, useronly_clean_ptr(addr + 8), ra); \
308
+ uint64_t *ptr = za + off; \
309
+ ptr[0] = BE ? val1 : val0, ptr[1] = BE ? val0 : val1; \
310
+} \
311
+static inline void VNAME##_v_tlb(CPUARMState *env, void *za, intptr_t off, \
312
+ target_ulong addr, uintptr_t ra) \
313
+{ \
314
+ HNAME##_tlb(env, za, tile_vslice_offset(off), addr, ra); \
315
+}
316
+
317
+#define DO_STQ(HNAME, VNAME, BE, HOST, TLB) \
318
+static inline void HNAME##_host(void *za, intptr_t off, void *host) \
319
+{ \
320
+ uint64_t *ptr = za + off; \
321
+ HOST(host, ptr[BE]); \
322
+ HOST(host + 1, ptr[!BE]); \
323
+} \
324
+static inline void VNAME##_v_host(void *za, intptr_t off, void *host) \
325
+{ \
326
+ HNAME##_host(za, tile_vslice_offset(off), host); \
327
+} \
328
+static inline void HNAME##_tlb(CPUARMState *env, void *za, intptr_t off, \
329
+ target_ulong addr, uintptr_t ra) \
330
+{ \
331
+ uint64_t *ptr = za + off; \
332
+ TLB(env, useronly_clean_ptr(addr), ptr[BE], ra); \
333
+ TLB(env, useronly_clean_ptr(addr + 8), ptr[!BE], ra); \
334
+} \
335
+static inline void VNAME##_v_tlb(CPUARMState *env, void *za, intptr_t off, \
336
+ target_ulong addr, uintptr_t ra) \
337
+{ \
338
+ HNAME##_tlb(env, za, tile_vslice_offset(off), addr, ra); \
339
+}
340
+
341
+DO_LD(ld1b, uint8_t, ldub_p, cpu_ldub_data_ra)
342
+DO_LD(ld1h_be, uint16_t, lduw_be_p, cpu_lduw_be_data_ra)
343
+DO_LD(ld1h_le, uint16_t, lduw_le_p, cpu_lduw_le_data_ra)
344
+DO_LD(ld1s_be, uint32_t, ldl_be_p, cpu_ldl_be_data_ra)
345
+DO_LD(ld1s_le, uint32_t, ldl_le_p, cpu_ldl_le_data_ra)
346
+DO_LD(ld1d_be, uint64_t, ldq_be_p, cpu_ldq_be_data_ra)
347
+DO_LD(ld1d_le, uint64_t, ldq_le_p, cpu_ldq_le_data_ra)
348
+
349
+DO_LDQ(sve_ld1qq_be, sme_ld1q_be, 1, ldq_be_p, cpu_ldq_be_data_ra)
350
+DO_LDQ(sve_ld1qq_le, sme_ld1q_le, 0, ldq_le_p, cpu_ldq_le_data_ra)
351
+
352
+DO_ST(st1b, uint8_t, stb_p, cpu_stb_data_ra)
353
+DO_ST(st1h_be, uint16_t, stw_be_p, cpu_stw_be_data_ra)
354
+DO_ST(st1h_le, uint16_t, stw_le_p, cpu_stw_le_data_ra)
355
+DO_ST(st1s_be, uint32_t, stl_be_p, cpu_stl_be_data_ra)
356
+DO_ST(st1s_le, uint32_t, stl_le_p, cpu_stl_le_data_ra)
357
+DO_ST(st1d_be, uint64_t, stq_be_p, cpu_stq_be_data_ra)
358
+DO_ST(st1d_le, uint64_t, stq_le_p, cpu_stq_le_data_ra)
359
+
360
+DO_STQ(sve_st1qq_be, sme_st1q_be, 1, stq_be_p, cpu_stq_be_data_ra)
361
+DO_STQ(sve_st1qq_le, sme_st1q_le, 0, stq_le_p, cpu_stq_le_data_ra)
362
+
363
+#undef DO_LD
364
+#undef DO_ST
365
+#undef DO_LDQ
366
+#undef DO_STQ
367
+
368
+/*
369
+ * Common helper for all contiguous predicated loads.
370
+ */
371
+
372
+static inline QEMU_ALWAYS_INLINE
373
+void sme_ld1(CPUARMState *env, void *za, uint64_t *vg,
374
+ const target_ulong addr, uint32_t desc, const uintptr_t ra,
375
+ const int esz, uint32_t mtedesc, bool vertical,
376
+ sve_ldst1_host_fn *host_fn,
377
+ sve_ldst1_tlb_fn *tlb_fn,
378
+ ClearFn *clr_fn,
379
+ CopyFn *cpy_fn)
380
+{
381
+ const intptr_t reg_max = simd_oprsz(desc);
382
+ const intptr_t esize = 1 << esz;
383
+ intptr_t reg_off, reg_last;
384
+ SVEContLdSt info;
385
+ void *host;
386
+ int flags;
387
+
388
+ /* Find the active elements. */
389
+ if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, esize)) {
390
+ /* The entire predicate was false; no load occurs. */
391
+ clr_fn(za, 0, reg_max);
392
+ return;
393
+ }
394
+
395
+ /* Probe the page(s). Exit with exception for any invalid page. */
396
+ sve_cont_ldst_pages(&info, FAULT_ALL, env, addr, MMU_DATA_LOAD, ra);
397
+
398
+ /* Handle watchpoints for all active elements. */
399
+ sve_cont_ldst_watchpoints(&info, env, vg, addr, esize, esize,
400
+ BP_MEM_READ, ra);
401
+
402
+ /*
403
+ * Handle mte checks for all active elements.
404
+ * Since TBI must be set for MTE, !mtedesc => !mte_active.
405
+ */
406
+ if (mtedesc) {
407
+ sve_cont_ldst_mte_check(&info, env, vg, addr, esize, esize,
408
+ mtedesc, ra);
409
+ }
410
+
411
+ flags = info.page[0].flags | info.page[1].flags;
412
+ if (unlikely(flags != 0)) {
76
+#ifdef CONFIG_USER_ONLY
413
+#ifdef CONFIG_USER_ONLY
77
+
414
+ g_assert_not_reached();
78
+/* Fault on byte I. All bits in FFR from I are cleared. The vector
415
+#else
79
+ * result from I is CONSTRAINED UNPREDICTABLE; we choose the MERGE
416
+ /*
80
+ * option, which leaves subsequent data unchanged.
417
+ * At least one page includes MMIO.
418
+ * Any bus operation can fail with cpu_transaction_failed,
419
+ * which for ARM will raise SyncExternal. Perform the load
420
+ * into scratch memory to preserve register state until the end.
421
+ */
422
+ ARMVectorReg scratch = { };
423
+
424
+ reg_off = info.reg_off_first[0];
425
+ reg_last = info.reg_off_last[1];
426
+ if (reg_last < 0) {
427
+ reg_last = info.reg_off_split;
428
+ if (reg_last < 0) {
429
+ reg_last = info.reg_off_last[0];
430
+ }
431
+ }
432
+
433
+ do {
434
+ uint64_t pg = vg[reg_off >> 6];
435
+ do {
436
+ if ((pg >> (reg_off & 63)) & 1) {
437
+ tlb_fn(env, &scratch, reg_off, addr + reg_off, ra);
438
+ }
439
+ reg_off += esize;
440
+ } while (reg_off & 63);
441
+ } while (reg_off <= reg_last);
442
+
443
+ cpy_fn(za, &scratch, reg_max);
444
+ return;
445
+#endif
446
+ }
447
+
448
+ /* The entire operation is in RAM, on valid pages. */
449
+
450
+ reg_off = info.reg_off_first[0];
451
+ reg_last = info.reg_off_last[0];
452
+ host = info.page[0].host;
453
+
454
+ if (!vertical) {
455
+ memset(za, 0, reg_max);
456
+ } else if (reg_off) {
457
+ clr_fn(za, 0, reg_off);
458
+ }
459
+
460
+ while (reg_off <= reg_last) {
461
+ uint64_t pg = vg[reg_off >> 6];
462
+ do {
463
+ if ((pg >> (reg_off & 63)) & 1) {
464
+ host_fn(za, reg_off, host + reg_off);
465
+ } else if (vertical) {
466
+ clr_fn(za, reg_off, esize);
467
+ }
468
+ reg_off += esize;
469
+ } while (reg_off <= reg_last && (reg_off & 63));
470
+ }
471
+
472
+ /*
473
+ * Use the slow path to manage the cross-page misalignment.
474
+ * But we know this is RAM and cannot trap.
475
+ */
476
+ reg_off = info.reg_off_split;
477
+ if (unlikely(reg_off >= 0)) {
478
+ tlb_fn(env, za, reg_off, addr + reg_off, ra);
479
+ }
480
+
481
+ reg_off = info.reg_off_first[1];
482
+ if (unlikely(reg_off >= 0)) {
483
+ reg_last = info.reg_off_last[1];
484
+ host = info.page[1].host;
485
+
486
+ do {
487
+ uint64_t pg = vg[reg_off >> 6];
488
+ do {
489
+ if ((pg >> (reg_off & 63)) & 1) {
490
+ host_fn(za, reg_off, host + reg_off);
491
+ } else if (vertical) {
492
+ clr_fn(za, reg_off, esize);
493
+ }
494
+ reg_off += esize;
495
+ } while (reg_off & 63);
496
+ } while (reg_off <= reg_last);
497
+ }
498
+}
499
+
500
+static inline QEMU_ALWAYS_INLINE
501
+void sme_ld1_mte(CPUARMState *env, void *za, uint64_t *vg,
502
+ target_ulong addr, uint32_t desc, uintptr_t ra,
503
+ const int esz, bool vertical,
504
+ sve_ldst1_host_fn *host_fn,
505
+ sve_ldst1_tlb_fn *tlb_fn,
506
+ ClearFn *clr_fn,
507
+ CopyFn *cpy_fn)
508
+{
509
+ uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
510
+ int bit55 = extract64(addr, 55, 1);
511
+
512
+ /* Remove mtedesc from the normal sve descriptor. */
513
+ desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
514
+
515
+ /* Perform gross MTE suppression early. */
516
+ if (!tbi_check(desc, bit55) ||
517
+ tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
518
+ mtedesc = 0;
519
+ }
520
+
521
+ sme_ld1(env, za, vg, addr, desc, ra, esz, mtedesc, vertical,
522
+ host_fn, tlb_fn, clr_fn, cpy_fn);
523
+}
524
+
525
+#define DO_LD(L, END, ESZ) \
526
+void HELPER(sme_ld1##L##END##_h)(CPUARMState *env, void *za, void *vg, \
527
+ target_ulong addr, uint32_t desc) \
528
+{ \
529
+ sme_ld1(env, za, vg, addr, desc, GETPC(), ESZ, 0, false, \
530
+ sve_ld1##L##L##END##_host, sve_ld1##L##L##END##_tlb, \
531
+ clear_horizontal, copy_horizontal); \
532
+} \
533
+void HELPER(sme_ld1##L##END##_v)(CPUARMState *env, void *za, void *vg, \
534
+ target_ulong addr, uint32_t desc) \
535
+{ \
536
+ sme_ld1(env, za, vg, addr, desc, GETPC(), ESZ, 0, true, \
537
+ sme_ld1##L##END##_v_host, sme_ld1##L##END##_v_tlb, \
538
+ clear_vertical_##L, copy_vertical_##L); \
539
+} \
540
+void HELPER(sme_ld1##L##END##_h_mte)(CPUARMState *env, void *za, void *vg, \
541
+ target_ulong addr, uint32_t desc) \
542
+{ \
543
+ sme_ld1_mte(env, za, vg, addr, desc, GETPC(), ESZ, false, \
544
+ sve_ld1##L##L##END##_host, sve_ld1##L##L##END##_tlb, \
545
+ clear_horizontal, copy_horizontal); \
546
+} \
547
+void HELPER(sme_ld1##L##END##_v_mte)(CPUARMState *env, void *za, void *vg, \
548
+ target_ulong addr, uint32_t desc) \
549
+{ \
550
+ sme_ld1_mte(env, za, vg, addr, desc, GETPC(), ESZ, true, \
551
+ sme_ld1##L##END##_v_host, sme_ld1##L##END##_v_tlb, \
552
+ clear_vertical_##L, copy_vertical_##L); \
553
+}
554
+
555
+DO_LD(b, , MO_8)
556
+DO_LD(h, _be, MO_16)
557
+DO_LD(h, _le, MO_16)
558
+DO_LD(s, _be, MO_32)
559
+DO_LD(s, _le, MO_32)
560
+DO_LD(d, _be, MO_64)
561
+DO_LD(d, _le, MO_64)
562
+DO_LD(q, _be, MO_128)
563
+DO_LD(q, _le, MO_128)
564
+
565
+#undef DO_LD
566
+
567
+/*
568
+ * Common helper for all contiguous predicated stores.
81
+ */
569
+ */
82
+static void record_fault(CPUARMState *env, uintptr_t i, uintptr_t oprsz)
570
+
83
+{
571
+static inline QEMU_ALWAYS_INLINE
84
+ uint64_t *ffr = env->vfp.pregs[FFR_PRED_NUM].p;
572
+void sme_st1(CPUARMState *env, void *za, uint64_t *vg,
85
+
573
+ const target_ulong addr, uint32_t desc, const uintptr_t ra,
86
+ if (i & 63) {
574
+ const int esz, uint32_t mtedesc, bool vertical,
87
+ ffr[i / 64] &= MAKE_64BIT_MASK(0, i & 63);
575
+ sve_ldst1_host_fn *host_fn,
88
+ i = ROUND_UP(i, 64);
576
+ sve_ldst1_tlb_fn *tlb_fn)
89
+ }
577
+{
90
+ for (; i < oprsz; i += 64) {
578
+ const intptr_t reg_max = simd_oprsz(desc);
91
+ ffr[i / 64] = 0;
579
+ const intptr_t esize = 1 << esz;
92
+ }
580
+ intptr_t reg_off, reg_last;
93
+}
581
+ SVEContLdSt info;
94
+
582
+ void *host;
95
+/* Hold the mmap lock during the operation so that there is no race
583
+ int flags;
96
+ * between page_check_range and the load operation. We expect the
584
+
97
+ * usual case to have no faults at all, so we check the whole range
585
+ /* Find the active elements. */
98
+ * first and if successful defer to the normal load operation.
586
+ if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, esize)) {
99
+ *
587
+ /* The entire predicate was false; no store occurs. */
100
+ * TODO: Change mmap_lock to a rwlock so that multiple readers
588
+ return;
101
+ * can run simultaneously. This will probably help other uses
589
+ }
102
+ * within QEMU as well.
590
+
103
+ */
591
+ /* Probe the page(s). Exit with exception for any invalid page. */
104
+#define DO_LDFF1(PART, FN, TYPEE, TYPEM, H) \
592
+ sve_cont_ldst_pages(&info, FAULT_ALL, env, addr, MMU_DATA_STORE, ra);
105
+static void do_sve_ldff1##PART(CPUARMState *env, void *vd, void *vg, \
593
+
106
+ target_ulong addr, intptr_t oprsz, \
594
+ /* Handle watchpoints for all active elements. */
107
+ bool first, uintptr_t ra) \
595
+ sve_cont_ldst_watchpoints(&info, env, vg, addr, esize, esize,
108
+{ \
596
+ BP_MEM_WRITE, ra);
109
+ intptr_t i = 0; \
597
+
110
+ do { \
598
+ /*
111
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
599
+ * Handle mte checks for all active elements.
112
+ do { \
600
+ * Since TBI must be set for MTE, !mtedesc => !mte_active.
113
+ TYPEM m = 0; \
601
+ */
114
+ if (pg & 1) { \
602
+ if (mtedesc) {
115
+ if (!first && \
603
+ sve_cont_ldst_mte_check(&info, env, vg, addr, esize, esize,
116
+ unlikely(page_check_range(addr, sizeof(TYPEM), \
604
+ mtedesc, ra);
117
+ PAGE_READ))) { \
605
+ }
118
+ record_fault(env, i, oprsz); \
606
+
119
+ return; \
607
+ flags = info.page[0].flags | info.page[1].flags;
120
+ } \
608
+ if (unlikely(flags != 0)) {
121
+ m = FN(env, addr, ra); \
609
+#ifdef CONFIG_USER_ONLY
122
+ first = false; \
610
+ g_assert_not_reached();
123
+ } \
124
+ *(TYPEE *)(vd + H(i)) = m; \
125
+ i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
126
+ addr += sizeof(TYPEM); \
127
+ } while (i & 15); \
128
+ } while (i < oprsz); \
129
+} \
130
+void HELPER(sve_ldff1##PART)(CPUARMState *env, void *vg, \
131
+ target_ulong addr, uint32_t desc) \
132
+{ \
133
+ intptr_t oprsz = simd_oprsz(desc); \
134
+ unsigned rd = simd_data(desc); \
135
+ void *vd = &env->vfp.zregs[rd]; \
136
+ mmap_lock(); \
137
+ if (likely(page_check_range(addr, oprsz, PAGE_READ) == 0)) { \
138
+ do_sve_ld1##PART(env, vd, vg, addr, oprsz, GETPC()); \
139
+ } else { \
140
+ do_sve_ldff1##PART(env, vd, vg, addr, oprsz, true, GETPC()); \
141
+ } \
142
+ mmap_unlock(); \
143
+}
144
+
145
+/* No-fault loads are like first-fault loads without the
146
+ * first faulting special case.
147
+ */
148
+#define DO_LDNF1(PART) \
149
+void HELPER(sve_ldnf1##PART)(CPUARMState *env, void *vg, \
150
+ target_ulong addr, uint32_t desc) \
151
+{ \
152
+ intptr_t oprsz = simd_oprsz(desc); \
153
+ unsigned rd = simd_data(desc); \
154
+ void *vd = &env->vfp.zregs[rd]; \
155
+ mmap_lock(); \
156
+ if (likely(page_check_range(addr, oprsz, PAGE_READ) == 0)) { \
157
+ do_sve_ld1##PART(env, vd, vg, addr, oprsz, GETPC()); \
158
+ } else { \
159
+ do_sve_ldff1##PART(env, vd, vg, addr, oprsz, false, GETPC()); \
160
+ } \
161
+ mmap_unlock(); \
162
+}
163
+
164
+#else
611
+#else
165
+
612
+ /*
166
+/* TODO: System mode is not yet supported.
613
+ * At least one page includes MMIO.
167
+ * This would probably use tlb_vaddr_to_host.
614
+ * Any bus operation can fail with cpu_transaction_failed,
168
+ */
615
+ * which for ARM will raise SyncExternal. We cannot avoid
169
+#define DO_LDFF1(PART, FN, TYPEE, TYPEM, H) \
616
+ * this fault and will leave with the store incomplete.
170
+void HELPER(sve_ldff1##PART)(CPUARMState *env, void *vg, \
617
+ */
171
+ target_ulong addr, uint32_t desc) \
618
+ reg_off = info.reg_off_first[0];
172
+{ \
619
+ reg_last = info.reg_off_last[1];
173
+ g_assert_not_reached(); \
620
+ if (reg_last < 0) {
174
+}
621
+ reg_last = info.reg_off_split;
175
+
622
+ if (reg_last < 0) {
176
+#define DO_LDNF1(PART) \
623
+ reg_last = info.reg_off_last[0];
177
+void HELPER(sve_ldnf1##PART)(CPUARMState *env, void *vg, \
624
+ }
178
+ target_ulong addr, uint32_t desc) \
625
+ }
179
+{ \
626
+
180
+ g_assert_not_reached(); \
627
+ do {
181
+}
628
+ uint64_t pg = vg[reg_off >> 6];
182
+
629
+ do {
630
+ if ((pg >> (reg_off & 63)) & 1) {
631
+ tlb_fn(env, za, reg_off, addr + reg_off, ra);
632
+ }
633
+ reg_off += esize;
634
+ } while (reg_off & 63);
635
+ } while (reg_off <= reg_last);
636
+ return;
183
+#endif
637
+#endif
184
+
638
+ }
185
+DO_LDFF1(bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
639
+
186
+DO_LDFF1(bhu_r, cpu_ldub_data_ra, uint16_t, uint8_t, H1_2)
640
+ reg_off = info.reg_off_first[0];
187
+DO_LDFF1(bhs_r, cpu_ldsb_data_ra, uint16_t, int8_t, H1_2)
641
+ reg_last = info.reg_off_last[0];
188
+DO_LDFF1(bsu_r, cpu_ldub_data_ra, uint32_t, uint8_t, H1_4)
642
+ host = info.page[0].host;
189
+DO_LDFF1(bss_r, cpu_ldsb_data_ra, uint32_t, int8_t, H1_4)
643
+
190
+DO_LDFF1(bdu_r, cpu_ldub_data_ra, uint64_t, uint8_t, )
644
+ while (reg_off <= reg_last) {
191
+DO_LDFF1(bds_r, cpu_ldsb_data_ra, uint64_t, int8_t, )
645
+ uint64_t pg = vg[reg_off >> 6];
192
+
646
+ do {
193
+DO_LDFF1(hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
647
+ if ((pg >> (reg_off & 63)) & 1) {
194
+DO_LDFF1(hsu_r, cpu_lduw_data_ra, uint32_t, uint16_t, H1_4)
648
+ host_fn(za, reg_off, host + reg_off);
195
+DO_LDFF1(hss_r, cpu_ldsw_data_ra, uint32_t, int8_t, H1_4)
649
+ }
196
+DO_LDFF1(hdu_r, cpu_lduw_data_ra, uint64_t, uint16_t, )
650
+ reg_off += 1 << esz;
197
+DO_LDFF1(hds_r, cpu_ldsw_data_ra, uint64_t, int16_t, )
651
+ } while (reg_off <= reg_last && (reg_off & 63));
198
+
652
+ }
199
+DO_LDFF1(ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
653
+
200
+DO_LDFF1(sdu_r, cpu_ldl_data_ra, uint64_t, uint32_t, )
654
+ /*
201
+DO_LDFF1(sds_r, cpu_ldl_data_ra, uint64_t, int32_t, )
655
+ * Use the slow path to manage the cross-page misalignment.
202
+
656
+ * But we know this is RAM and cannot trap.
203
+DO_LDFF1(dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
657
+ */
204
+
658
+ reg_off = info.reg_off_split;
205
+#undef DO_LDFF1
659
+ if (unlikely(reg_off >= 0)) {
206
+
660
+ tlb_fn(env, za, reg_off, addr + reg_off, ra);
207
+DO_LDNF1(bb_r)
661
+ }
208
+DO_LDNF1(bhu_r)
662
+
209
+DO_LDNF1(bhs_r)
663
+ reg_off = info.reg_off_first[1];
210
+DO_LDNF1(bsu_r)
664
+ if (unlikely(reg_off >= 0)) {
211
+DO_LDNF1(bss_r)
665
+ reg_last = info.reg_off_last[1];
212
+DO_LDNF1(bdu_r)
666
+ host = info.page[1].host;
213
+DO_LDNF1(bds_r)
667
+
214
+
668
+ do {
215
+DO_LDNF1(hh_r)
669
+ uint64_t pg = vg[reg_off >> 6];
216
+DO_LDNF1(hsu_r)
670
+ do {
217
+DO_LDNF1(hss_r)
671
+ if ((pg >> (reg_off & 63)) & 1) {
218
+DO_LDNF1(hdu_r)
672
+ host_fn(za, reg_off, host + reg_off);
219
+DO_LDNF1(hds_r)
673
+ }
220
+
674
+ reg_off += 1 << esz;
221
+DO_LDNF1(ss_r)
675
+ } while (reg_off & 63);
222
+DO_LDNF1(sdu_r)
676
+ } while (reg_off <= reg_last);
223
+DO_LDNF1(sds_r)
677
+ }
224
+
678
+}
225
+DO_LDNF1(dd_r)
679
+
226
+
680
+static inline QEMU_ALWAYS_INLINE
227
+#undef DO_LDNF1
681
+void sme_st1_mte(CPUARMState *env, void *za, uint64_t *vg, target_ulong addr,
228
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
682
+ uint32_t desc, uintptr_t ra, int esz, bool vertical,
683
+ sve_ldst1_host_fn *host_fn,
684
+ sve_ldst1_tlb_fn *tlb_fn)
685
+{
686
+ uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
687
+ int bit55 = extract64(addr, 55, 1);
688
+
689
+ /* Remove mtedesc from the normal sve descriptor. */
690
+ desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
691
+
692
+ /* Perform gross MTE suppression early. */
693
+ if (!tbi_check(desc, bit55) ||
694
+ tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
695
+ mtedesc = 0;
696
+ }
697
+
698
+ sme_st1(env, za, vg, addr, desc, ra, esz, mtedesc,
699
+ vertical, host_fn, tlb_fn);
700
+}
701
+
702
+#define DO_ST(L, END, ESZ) \
703
+void HELPER(sme_st1##L##END##_h)(CPUARMState *env, void *za, void *vg, \
704
+ target_ulong addr, uint32_t desc) \
705
+{ \
706
+ sme_st1(env, za, vg, addr, desc, GETPC(), ESZ, 0, false, \
707
+ sve_st1##L##L##END##_host, sve_st1##L##L##END##_tlb); \
708
+} \
709
+void HELPER(sme_st1##L##END##_v)(CPUARMState *env, void *za, void *vg, \
710
+ target_ulong addr, uint32_t desc) \
711
+{ \
712
+ sme_st1(env, za, vg, addr, desc, GETPC(), ESZ, 0, true, \
713
+ sme_st1##L##END##_v_host, sme_st1##L##END##_v_tlb); \
714
+} \
715
+void HELPER(sme_st1##L##END##_h_mte)(CPUARMState *env, void *za, void *vg, \
716
+ target_ulong addr, uint32_t desc) \
717
+{ \
718
+ sme_st1_mte(env, za, vg, addr, desc, GETPC(), ESZ, false, \
719
+ sve_st1##L##L##END##_host, sve_st1##L##L##END##_tlb); \
720
+} \
721
+void HELPER(sme_st1##L##END##_v_mte)(CPUARMState *env, void *za, void *vg, \
722
+ target_ulong addr, uint32_t desc) \
723
+{ \
724
+ sme_st1_mte(env, za, vg, addr, desc, GETPC(), ESZ, true, \
725
+ sme_st1##L##END##_v_host, sme_st1##L##END##_v_tlb); \
726
+}
727
+
728
+DO_ST(b, , MO_8)
729
+DO_ST(h, _be, MO_16)
730
+DO_ST(h, _le, MO_16)
731
+DO_ST(s, _be, MO_32)
732
+DO_ST(s, _le, MO_32)
733
+DO_ST(d, _be, MO_64)
734
+DO_ST(d, _le, MO_64)
735
+DO_ST(q, _be, MO_128)
736
+DO_ST(q, _le, MO_128)
737
+
738
+#undef DO_ST
739
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
229
index XXXXXXX..XXXXXXX 100644
740
index XXXXXXX..XXXXXXX 100644
230
--- a/target/arm/translate-sve.c
741
--- a/target/arm/translate-sme.c
231
+++ b/target/arm/translate-sve.c
742
+++ b/target/arm/translate-sme.c
232
@@ -XXX,XX +XXX,XX @@ static bool trans_LD_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
743
@@ -XXX,XX +XXX,XX @@ static bool trans_MOVA(DisasContext *s, arg_MOVA *a)
233
}
744
234
return true;
745
return true;
235
}
746
}
236
+
747
+
237
+static bool trans_LDFF1_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn)
748
+static bool trans_LDST1(DisasContext *s, arg_LDST1 *a)
238
+{
749
+{
239
+ static gen_helper_gvec_mem * const fns[16] = {
750
+ typedef void GenLdSt1(TCGv_env, TCGv_ptr, TCGv_ptr, TCGv, TCGv_i32);
240
+ gen_helper_sve_ldff1bb_r,
751
+
241
+ gen_helper_sve_ldff1bhu_r,
752
+ /*
242
+ gen_helper_sve_ldff1bsu_r,
753
+ * Indexed by [esz][be][v][mte][st], which is (except for load/store)
243
+ gen_helper_sve_ldff1bdu_r,
754
+ * also the order in which the elements appear in the function names,
244
+
755
+ * and so how we must concatenate the pieces.
245
+ gen_helper_sve_ldff1sds_r,
756
+ */
246
+ gen_helper_sve_ldff1hh_r,
757
+
247
+ gen_helper_sve_ldff1hsu_r,
758
+#define FN_LS(F) { gen_helper_sme_ld1##F, gen_helper_sme_st1##F }
248
+ gen_helper_sve_ldff1hdu_r,
759
+#define FN_MTE(F) { FN_LS(F), FN_LS(F##_mte) }
249
+
760
+#define FN_HV(F) { FN_MTE(F##_h), FN_MTE(F##_v) }
250
+ gen_helper_sve_ldff1hds_r,
761
+#define FN_END(L, B) { FN_HV(L), FN_HV(B) }
251
+ gen_helper_sve_ldff1hss_r,
762
+
252
+ gen_helper_sve_ldff1ss_r,
763
+ static GenLdSt1 * const fns[5][2][2][2][2] = {
253
+ gen_helper_sve_ldff1sdu_r,
764
+ FN_END(b, b),
254
+
765
+ FN_END(h_le, h_be),
255
+ gen_helper_sve_ldff1bds_r,
766
+ FN_END(s_le, s_be),
256
+ gen_helper_sve_ldff1bss_r,
767
+ FN_END(d_le, d_be),
257
+ gen_helper_sve_ldff1bhs_r,
768
+ FN_END(q_le, q_be),
258
+ gen_helper_sve_ldff1dd_r,
259
+ };
769
+ };
260
+
770
+
261
+ if (sve_access_check(s)) {
771
+#undef FN_LS
262
+ TCGv_i64 addr = new_tmp_a64(s);
772
+#undef FN_MTE
263
+ tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
773
+#undef FN_HV
264
+ tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
774
+#undef FN_END
265
+ do_mem_zpa(s, a->rd, a->pg, addr, fns[a->dtype]);
775
+
266
+ }
776
+ TCGv_ptr t_za, t_pg;
777
+ TCGv_i64 addr;
778
+ int svl, desc = 0;
779
+ bool be = s->be_data == MO_BE;
780
+ bool mte = s->mte_active[0];
781
+
782
+ if (!dc_isar_feature(aa64_sme, s)) {
783
+ return false;
784
+ }
785
+ if (!sme_smza_enabled_check(s)) {
786
+ return true;
787
+ }
788
+
789
+ t_za = get_tile_rowcol(s, a->esz, a->rs, a->za_imm, a->v);
790
+ t_pg = pred_full_reg_ptr(s, a->pg);
791
+ addr = tcg_temp_new_i64();
792
+
793
+ tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), a->esz);
794
+ tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
795
+
796
+ if (mte) {
797
+ desc = FIELD_DP32(desc, MTEDESC, MIDX, get_mem_index(s));
798
+ desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
799
+ desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
800
+ desc = FIELD_DP32(desc, MTEDESC, WRITE, a->st);
801
+ desc = FIELD_DP32(desc, MTEDESC, SIZEM1, (1 << a->esz) - 1);
802
+ desc <<= SVE_MTEDESC_SHIFT;
803
+ } else {
804
+ addr = clean_data_tbi(s, addr);
805
+ }
806
+ svl = streaming_vec_reg_size(s);
807
+ desc = simd_desc(svl, svl, desc);
808
+
809
+ fns[a->esz][be][a->v][mte][a->st](cpu_env, t_za, t_pg, addr,
810
+ tcg_constant_i32(desc));
811
+
812
+ tcg_temp_free_ptr(t_za);
813
+ tcg_temp_free_ptr(t_pg);
814
+ tcg_temp_free_i64(addr);
267
+ return true;
815
+ return true;
268
+}
816
+}
269
+
270
+static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
271
+{
272
+ static gen_helper_gvec_mem * const fns[16] = {
273
+ gen_helper_sve_ldnf1bb_r,
274
+ gen_helper_sve_ldnf1bhu_r,
275
+ gen_helper_sve_ldnf1bsu_r,
276
+ gen_helper_sve_ldnf1bdu_r,
277
+
278
+ gen_helper_sve_ldnf1sds_r,
279
+ gen_helper_sve_ldnf1hh_r,
280
+ gen_helper_sve_ldnf1hsu_r,
281
+ gen_helper_sve_ldnf1hdu_r,
282
+
283
+ gen_helper_sve_ldnf1hds_r,
284
+ gen_helper_sve_ldnf1hss_r,
285
+ gen_helper_sve_ldnf1ss_r,
286
+ gen_helper_sve_ldnf1sdu_r,
287
+
288
+ gen_helper_sve_ldnf1bds_r,
289
+ gen_helper_sve_ldnf1bss_r,
290
+ gen_helper_sve_ldnf1bhs_r,
291
+ gen_helper_sve_ldnf1dd_r,
292
+ };
293
+
294
+ if (sve_access_check(s)) {
295
+ int vsz = vec_full_reg_size(s);
296
+ int elements = vsz >> dtype_esz[a->dtype];
297
+ int off = (a->imm * elements) << dtype_msz(a->dtype);
298
+ TCGv_i64 addr = new_tmp_a64(s);
299
+
300
+ tcg_gen_addi_i64(addr, cpu_reg_sp(s, a->rn), off);
301
+ do_mem_zpa(s, a->rd, a->pg, addr, fns[a->dtype]);
302
+ }
303
+ return true;
304
+}
305
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
306
index XXXXXXX..XXXXXXX 100644
307
--- a/target/arm/sve.decode
308
+++ b/target/arm/sve.decode
309
@@ -XXX,XX +XXX,XX @@ LDR_zri 10000101 10 ...... 010 ... ..... ..... @rd_rn_i9
310
# SVE contiguous load (scalar plus scalar)
311
LD_zprr 1010010 .... ..... 010 ... ..... ..... @rprr_load_dt nreg=0
312
313
+# SVE contiguous first-fault load (scalar plus scalar)
314
+LDFF1_zprr 1010010 .... ..... 011 ... ..... ..... @rprr_load_dt nreg=0
315
+
316
# SVE contiguous load (scalar plus immediate)
317
LD_zpri 1010010 .... 0.... 101 ... ..... ..... @rpri_load_dt nreg=0
318
319
+# SVE contiguous non-fault load (scalar plus immediate)
320
+LDNF1_zpri 1010010 .... 1.... 101 ... ..... ..... @rpri_load_dt nreg=0
321
+
322
# SVE contiguous non-temporal load (scalar plus scalar)
323
# LDNT1B, LDNT1H, LDNT1W, LDNT1D
324
# SVE load multiple structures (scalar plus scalar)
325
--
817
--
326
2.17.1
818
2.25.1
327
328
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Add a TCGv_ptr base argument, which will be cpu_env for SVE.
4
We will reuse this for SME save and restore array insns.
5
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180627043328.11531-2-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-22-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
target/arm/helper-sve.h | 35 +++++++++
11
target/arm/translate-a64.h | 3 +++
10
target/arm/sve_helper.c | 153 +++++++++++++++++++++++++++++++++++++
12
target/arm/translate-sve.c | 48 ++++++++++++++++++++++++++++----------
11
target/arm/translate-sve.c | 121 +++++++++++++++++++++++++++++
13
2 files changed, 39 insertions(+), 12 deletions(-)
12
target/arm/sve.decode | 34 +++++++++
13
4 files changed, 343 insertions(+)
14
14
15
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-sve.h
17
--- a/target/arm/translate-a64.h
18
+++ b/target/arm/helper-sve.h
18
+++ b/target/arm/translate-a64.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_rsqrts_s, TCG_CALL_NO_RWG,
19
@@ -XXX,XX +XXX,XX @@ void gen_gvec_xar(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
20
void, ptr, ptr, ptr, ptr, i32)
20
uint32_t rm_ofs, int64_t shift,
21
DEF_HELPER_FLAGS_5(gvec_rsqrts_d, TCG_CALL_NO_RWG,
21
uint32_t opr_sz, uint32_t max_sz);
22
void, ptr, ptr, ptr, ptr, i32)
22
23
+void gen_sve_ldr(DisasContext *s, TCGv_ptr, int vofs, int len, int rn, int imm);
24
+void gen_sve_str(DisasContext *s, TCGv_ptr, int vofs, int len, int rn, int imm);
23
+
25
+
24
+DEF_HELPER_FLAGS_4(sve_ld1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
26
#endif /* TARGET_ARM_TRANSLATE_A64_H */
25
+DEF_HELPER_FLAGS_4(sve_ld2bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
26
+DEF_HELPER_FLAGS_4(sve_ld3bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
27
+DEF_HELPER_FLAGS_4(sve_ld4bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
28
+
29
+DEF_HELPER_FLAGS_4(sve_ld1hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
30
+DEF_HELPER_FLAGS_4(sve_ld2hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
31
+DEF_HELPER_FLAGS_4(sve_ld3hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
32
+DEF_HELPER_FLAGS_4(sve_ld4hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
33
+
34
+DEF_HELPER_FLAGS_4(sve_ld1ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
35
+DEF_HELPER_FLAGS_4(sve_ld2ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
36
+DEF_HELPER_FLAGS_4(sve_ld3ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
37
+DEF_HELPER_FLAGS_4(sve_ld4ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
38
+
39
+DEF_HELPER_FLAGS_4(sve_ld1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_4(sve_ld2dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
41
+DEF_HELPER_FLAGS_4(sve_ld3dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
42
+DEF_HELPER_FLAGS_4(sve_ld4dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
43
+
44
+DEF_HELPER_FLAGS_4(sve_ld1bhu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
45
+DEF_HELPER_FLAGS_4(sve_ld1bsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
46
+DEF_HELPER_FLAGS_4(sve_ld1bdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
47
+DEF_HELPER_FLAGS_4(sve_ld1bhs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
48
+DEF_HELPER_FLAGS_4(sve_ld1bss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
49
+DEF_HELPER_FLAGS_4(sve_ld1bds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
50
+
51
+DEF_HELPER_FLAGS_4(sve_ld1hsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
52
+DEF_HELPER_FLAGS_4(sve_ld1hdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_4(sve_ld1hss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
54
+DEF_HELPER_FLAGS_4(sve_ld1hds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
55
+
56
+DEF_HELPER_FLAGS_4(sve_ld1sdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
57
+DEF_HELPER_FLAGS_4(sve_ld1sds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
58
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/sve_helper.c
61
+++ b/target/arm/sve_helper.c
62
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_while)(void *vd, uint32_t count, uint32_t pred_desc)
63
64
return predtest_ones(d, oprsz, esz_mask);
65
}
66
+
67
+/*
68
+ * Load contiguous data, protected by a governing predicate.
69
+ */
70
+#define DO_LD1(NAME, FN, TYPEE, TYPEM, H) \
71
+static void do_##NAME(CPUARMState *env, void *vd, void *vg, \
72
+ target_ulong addr, intptr_t oprsz, \
73
+ uintptr_t ra) \
74
+{ \
75
+ intptr_t i = 0; \
76
+ do { \
77
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
78
+ do { \
79
+ TYPEM m = 0; \
80
+ if (pg & 1) { \
81
+ m = FN(env, addr, ra); \
82
+ } \
83
+ *(TYPEE *)(vd + H(i)) = m; \
84
+ i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
85
+ addr += sizeof(TYPEM); \
86
+ } while (i & 15); \
87
+ } while (i < oprsz); \
88
+} \
89
+void HELPER(NAME)(CPUARMState *env, void *vg, \
90
+ target_ulong addr, uint32_t desc) \
91
+{ \
92
+ do_##NAME(env, &env->vfp.zregs[simd_data(desc)], vg, \
93
+ addr, simd_oprsz(desc), GETPC()); \
94
+}
95
+
96
+#define DO_LD2(NAME, FN, TYPEE, TYPEM, H) \
97
+void HELPER(NAME)(CPUARMState *env, void *vg, \
98
+ target_ulong addr, uint32_t desc) \
99
+{ \
100
+ intptr_t i, oprsz = simd_oprsz(desc); \
101
+ intptr_t ra = GETPC(); \
102
+ unsigned rd = simd_data(desc); \
103
+ void *d1 = &env->vfp.zregs[rd]; \
104
+ void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
105
+ for (i = 0; i < oprsz; ) { \
106
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
107
+ do { \
108
+ TYPEM m1 = 0, m2 = 0; \
109
+ if (pg & 1) { \
110
+ m1 = FN(env, addr, ra); \
111
+ m2 = FN(env, addr + sizeof(TYPEM), ra); \
112
+ } \
113
+ *(TYPEE *)(d1 + H(i)) = m1; \
114
+ *(TYPEE *)(d2 + H(i)) = m2; \
115
+ i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
116
+ addr += 2 * sizeof(TYPEM); \
117
+ } while (i & 15); \
118
+ } \
119
+}
120
+
121
+#define DO_LD3(NAME, FN, TYPEE, TYPEM, H) \
122
+void HELPER(NAME)(CPUARMState *env, void *vg, \
123
+ target_ulong addr, uint32_t desc) \
124
+{ \
125
+ intptr_t i, oprsz = simd_oprsz(desc); \
126
+ intptr_t ra = GETPC(); \
127
+ unsigned rd = simd_data(desc); \
128
+ void *d1 = &env->vfp.zregs[rd]; \
129
+ void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
130
+ void *d3 = &env->vfp.zregs[(rd + 2) & 31]; \
131
+ for (i = 0; i < oprsz; ) { \
132
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
133
+ do { \
134
+ TYPEM m1 = 0, m2 = 0, m3 = 0; \
135
+ if (pg & 1) { \
136
+ m1 = FN(env, addr, ra); \
137
+ m2 = FN(env, addr + sizeof(TYPEM), ra); \
138
+ m3 = FN(env, addr + 2 * sizeof(TYPEM), ra); \
139
+ } \
140
+ *(TYPEE *)(d1 + H(i)) = m1; \
141
+ *(TYPEE *)(d2 + H(i)) = m2; \
142
+ *(TYPEE *)(d3 + H(i)) = m3; \
143
+ i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
144
+ addr += 3 * sizeof(TYPEM); \
145
+ } while (i & 15); \
146
+ } \
147
+}
148
+
149
+#define DO_LD4(NAME, FN, TYPEE, TYPEM, H) \
150
+void HELPER(NAME)(CPUARMState *env, void *vg, \
151
+ target_ulong addr, uint32_t desc) \
152
+{ \
153
+ intptr_t i, oprsz = simd_oprsz(desc); \
154
+ intptr_t ra = GETPC(); \
155
+ unsigned rd = simd_data(desc); \
156
+ void *d1 = &env->vfp.zregs[rd]; \
157
+ void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
158
+ void *d3 = &env->vfp.zregs[(rd + 2) & 31]; \
159
+ void *d4 = &env->vfp.zregs[(rd + 3) & 31]; \
160
+ for (i = 0; i < oprsz; ) { \
161
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
162
+ do { \
163
+ TYPEM m1 = 0, m2 = 0, m3 = 0, m4 = 0; \
164
+ if (pg & 1) { \
165
+ m1 = FN(env, addr, ra); \
166
+ m2 = FN(env, addr + sizeof(TYPEM), ra); \
167
+ m3 = FN(env, addr + 2 * sizeof(TYPEM), ra); \
168
+ m4 = FN(env, addr + 3 * sizeof(TYPEM), ra); \
169
+ } \
170
+ *(TYPEE *)(d1 + H(i)) = m1; \
171
+ *(TYPEE *)(d2 + H(i)) = m2; \
172
+ *(TYPEE *)(d3 + H(i)) = m3; \
173
+ *(TYPEE *)(d4 + H(i)) = m4; \
174
+ i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
175
+ addr += 4 * sizeof(TYPEM); \
176
+ } while (i & 15); \
177
+ } \
178
+}
179
+
180
+DO_LD1(sve_ld1bhu_r, cpu_ldub_data_ra, uint16_t, uint8_t, H1_2)
181
+DO_LD1(sve_ld1bhs_r, cpu_ldsb_data_ra, uint16_t, int8_t, H1_2)
182
+DO_LD1(sve_ld1bsu_r, cpu_ldub_data_ra, uint32_t, uint8_t, H1_4)
183
+DO_LD1(sve_ld1bss_r, cpu_ldsb_data_ra, uint32_t, int8_t, H1_4)
184
+DO_LD1(sve_ld1bdu_r, cpu_ldub_data_ra, uint64_t, uint8_t, )
185
+DO_LD1(sve_ld1bds_r, cpu_ldsb_data_ra, uint64_t, int8_t, )
186
+
187
+DO_LD1(sve_ld1hsu_r, cpu_lduw_data_ra, uint32_t, uint16_t, H1_4)
188
+DO_LD1(sve_ld1hss_r, cpu_ldsw_data_ra, uint32_t, int8_t, H1_4)
189
+DO_LD1(sve_ld1hdu_r, cpu_lduw_data_ra, uint64_t, uint16_t, )
190
+DO_LD1(sve_ld1hds_r, cpu_ldsw_data_ra, uint64_t, int16_t, )
191
+
192
+DO_LD1(sve_ld1sdu_r, cpu_ldl_data_ra, uint64_t, uint32_t, )
193
+DO_LD1(sve_ld1sds_r, cpu_ldl_data_ra, uint64_t, int32_t, )
194
+
195
+DO_LD1(sve_ld1bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
196
+DO_LD2(sve_ld2bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
197
+DO_LD3(sve_ld3bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
198
+DO_LD4(sve_ld4bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
199
+
200
+DO_LD1(sve_ld1hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
201
+DO_LD2(sve_ld2hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
202
+DO_LD3(sve_ld3hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
203
+DO_LD4(sve_ld4hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
204
+
205
+DO_LD1(sve_ld1ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
206
+DO_LD2(sve_ld2ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
207
+DO_LD3(sve_ld3ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
208
+DO_LD4(sve_ld4ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
209
+
210
+DO_LD1(sve_ld1dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
211
+DO_LD2(sve_ld2dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
212
+DO_LD3(sve_ld3dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
213
+DO_LD4(sve_ld4dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
214
+
215
+#undef DO_LD1
216
+#undef DO_LD2
217
+#undef DO_LD3
218
+#undef DO_LD4
219
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
27
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
220
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
221
--- a/target/arm/translate-sve.c
29
--- a/target/arm/translate-sve.c
222
+++ b/target/arm/translate-sve.c
30
+++ b/target/arm/translate-sve.c
223
@@ -XXX,XX +XXX,XX @@ typedef void gen_helper_gvec_flags_3(TCGv_i32, TCGv_ptr, TCGv_ptr,
31
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(UCVTF_dd, aa64_sve, gen_gvec_fpst_arg_zpz,
224
typedef void gen_helper_gvec_flags_4(TCGv_i32, TCGv_ptr, TCGv_ptr,
32
* The load should begin at the address Rn + IMM.
225
TCGv_ptr, TCGv_ptr, TCGv_i32);
33
*/
226
34
227
+typedef void gen_helper_gvec_mem(TCGv_env, TCGv_ptr, TCGv_i64, TCGv_i32);
35
-static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
36
+void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
37
+ int len, int rn, int imm)
38
{
39
int len_align = QEMU_ALIGN_DOWN(len, 8);
40
int len_remain = len % 8;
41
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
42
t0 = tcg_temp_new_i64();
43
for (i = 0; i < len_align; i += 8) {
44
tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ);
45
- tcg_gen_st_i64(t0, cpu_env, vofs + i);
46
+ tcg_gen_st_i64(t0, base, vofs + i);
47
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
48
}
49
tcg_temp_free_i64(t0);
50
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
51
clean_addr = new_tmp_a64_local(s);
52
tcg_gen_mov_i64(clean_addr, t0);
53
54
+ if (base != cpu_env) {
55
+ TCGv_ptr b = tcg_temp_local_new_ptr();
56
+ tcg_gen_mov_ptr(b, base);
57
+ base = b;
58
+ }
228
+
59
+
229
/*
60
gen_set_label(loop);
230
* Helpers for extracting complex instruction fields.
61
231
*/
62
t0 = tcg_temp_new_i64();
232
@@ -XXX,XX +XXX,XX @@ static inline int expand_imm_sh8u(int x)
63
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
233
return (uint8_t)x << (x & 0x100 ? 8 : 0);
64
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
65
66
tp = tcg_temp_new_ptr();
67
- tcg_gen_add_ptr(tp, cpu_env, i);
68
+ tcg_gen_add_ptr(tp, base, i);
69
tcg_gen_addi_ptr(i, i, 8);
70
tcg_gen_st_i64(t0, tp, vofs);
71
tcg_temp_free_ptr(tp);
72
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
73
74
tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
75
tcg_temp_free_ptr(i);
76
+
77
+ if (base != cpu_env) {
78
+ tcg_temp_free_ptr(base);
79
+ assert(len_remain == 0);
80
+ }
81
}
82
83
/*
84
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
85
default:
86
g_assert_not_reached();
87
}
88
- tcg_gen_st_i64(t0, cpu_env, vofs + len_align);
89
+ tcg_gen_st_i64(t0, base, vofs + len_align);
90
tcg_temp_free_i64(t0);
91
}
234
}
92
}
235
93
236
+/* Convert a 2-bit memory size (msz) to a 4-bit data type (dtype)
94
/* Similarly for stores. */
237
+ * with unsigned data. C.f. SVE Memory Contiguous Load Group.
95
-static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
238
+ */
96
+void gen_sve_str(DisasContext *s, TCGv_ptr base, int vofs,
239
+static inline int msz_dtype(int msz)
97
+ int len, int rn, int imm)
240
+{
98
{
241
+ static const uint8_t dtype[4] = { 0, 5, 10, 15 };
99
int len_align = QEMU_ALIGN_DOWN(len, 8);
242
+ return dtype[msz];
100
int len_remain = len % 8;
243
+}
101
@@ -XXX,XX +XXX,XX @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
102
103
t0 = tcg_temp_new_i64();
104
for (i = 0; i < len_align; i += 8) {
105
- tcg_gen_ld_i64(t0, cpu_env, vofs + i);
106
+ tcg_gen_ld_i64(t0, base, vofs + i);
107
tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ);
108
tcg_gen_addi_i64(clean_addr, clean_addr, 8);
109
}
110
@@ -XXX,XX +XXX,XX @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
111
clean_addr = new_tmp_a64_local(s);
112
tcg_gen_mov_i64(clean_addr, t0);
113
114
+ if (base != cpu_env) {
115
+ TCGv_ptr b = tcg_temp_local_new_ptr();
116
+ tcg_gen_mov_ptr(b, base);
117
+ base = b;
118
+ }
244
+
119
+
245
/*
120
gen_set_label(loop);
246
* Include the generated decoder.
121
247
*/
122
t0 = tcg_temp_new_i64();
248
@@ -XXX,XX +XXX,XX @@ static bool trans_LDR_pri(DisasContext *s, arg_rri *a, uint32_t insn)
123
tp = tcg_temp_new_ptr();
124
- tcg_gen_add_ptr(tp, cpu_env, i);
125
+ tcg_gen_add_ptr(tp, base, i);
126
tcg_gen_ld_i64(t0, tp, vofs);
127
tcg_gen_addi_ptr(i, i, 8);
128
tcg_temp_free_ptr(tp);
129
@@ -XXX,XX +XXX,XX @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
130
131
tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
132
tcg_temp_free_ptr(i);
133
+
134
+ if (base != cpu_env) {
135
+ tcg_temp_free_ptr(base);
136
+ assert(len_remain == 0);
137
+ }
138
}
139
140
/* Predicate register stores can be any multiple of 2. */
141
if (len_remain) {
142
t0 = tcg_temp_new_i64();
143
- tcg_gen_ld_i64(t0, cpu_env, vofs + len_align);
144
+ tcg_gen_ld_i64(t0, base, vofs + len_align);
145
146
switch (len_remain) {
147
case 2:
148
@@ -XXX,XX +XXX,XX @@ static bool trans_LDR_zri(DisasContext *s, arg_rri *a)
149
if (sve_access_check(s)) {
150
int size = vec_full_reg_size(s);
151
int off = vec_full_reg_offset(s, a->rd);
152
- do_ldr(s, off, size, a->rn, a->imm * size);
153
+ gen_sve_ldr(s, cpu_env, off, size, a->rn, a->imm * size);
249
}
154
}
250
return true;
155
return true;
251
}
156
}
252
+
157
@@ -XXX,XX +XXX,XX @@ static bool trans_LDR_pri(DisasContext *s, arg_rri *a)
253
+/*
158
if (sve_access_check(s)) {
254
+ *** SVE Memory - Contiguous Load Group
159
int size = pred_full_reg_size(s);
255
+ */
160
int off = pred_full_reg_offset(s, a->rd);
256
+
161
- do_ldr(s, off, size, a->rn, a->imm * size);
257
+/* The memory mode of the dtype. */
162
+ gen_sve_ldr(s, cpu_env, off, size, a->rn, a->imm * size);
258
+static const TCGMemOp dtype_mop[16] = {
163
}
259
+ MO_UB, MO_UB, MO_UB, MO_UB,
164
return true;
260
+ MO_SL, MO_UW, MO_UW, MO_UW,
165
}
261
+ MO_SW, MO_SW, MO_UL, MO_UL,
166
@@ -XXX,XX +XXX,XX @@ static bool trans_STR_zri(DisasContext *s, arg_rri *a)
262
+ MO_SB, MO_SB, MO_SB, MO_Q
167
if (sve_access_check(s)) {
263
+};
168
int size = vec_full_reg_size(s);
264
+
169
int off = vec_full_reg_offset(s, a->rd);
265
+#define dtype_msz(x) (dtype_mop[x] & MO_SIZE)
170
- do_str(s, off, size, a->rn, a->imm * size);
266
+
171
+ gen_sve_str(s, cpu_env, off, size, a->rn, a->imm * size);
267
+/* The vector element size of dtype. */
172
}
268
+static const uint8_t dtype_esz[16] = {
173
return true;
269
+ 0, 1, 2, 3,
174
}
270
+ 3, 1, 2, 3,
175
@@ -XXX,XX +XXX,XX @@ static bool trans_STR_pri(DisasContext *s, arg_rri *a)
271
+ 3, 2, 2, 3,
176
if (sve_access_check(s)) {
272
+ 3, 2, 1, 3
177
int size = pred_full_reg_size(s);
273
+};
178
int off = pred_full_reg_offset(s, a->rd);
274
+
179
- do_str(s, off, size, a->rn, a->imm * size);
275
+static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
180
+ gen_sve_str(s, cpu_env, off, size, a->rn, a->imm * size);
276
+ gen_helper_gvec_mem *fn)
181
}
277
+{
182
return true;
278
+ unsigned vsz = vec_full_reg_size(s);
183
}
279
+ TCGv_ptr t_pg;
280
+ TCGv_i32 desc;
281
+
282
+ /* For e.g. LD4, there are not enough arguments to pass all 4
283
+ * registers as pointers, so encode the regno into the data field.
284
+ * For consistency, do this even for LD1.
285
+ */
286
+ desc = tcg_const_i32(simd_desc(vsz, vsz, zt));
287
+ t_pg = tcg_temp_new_ptr();
288
+
289
+ tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
290
+ fn(cpu_env, t_pg, addr, desc);
291
+
292
+ tcg_temp_free_ptr(t_pg);
293
+ tcg_temp_free_i32(desc);
294
+}
295
+
296
+static void do_ld_zpa(DisasContext *s, int zt, int pg,
297
+ TCGv_i64 addr, int dtype, int nreg)
298
+{
299
+ static gen_helper_gvec_mem * const fns[16][4] = {
300
+ { gen_helper_sve_ld1bb_r, gen_helper_sve_ld2bb_r,
301
+ gen_helper_sve_ld3bb_r, gen_helper_sve_ld4bb_r },
302
+ { gen_helper_sve_ld1bhu_r, NULL, NULL, NULL },
303
+ { gen_helper_sve_ld1bsu_r, NULL, NULL, NULL },
304
+ { gen_helper_sve_ld1bdu_r, NULL, NULL, NULL },
305
+
306
+ { gen_helper_sve_ld1sds_r, NULL, NULL, NULL },
307
+ { gen_helper_sve_ld1hh_r, gen_helper_sve_ld2hh_r,
308
+ gen_helper_sve_ld3hh_r, gen_helper_sve_ld4hh_r },
309
+ { gen_helper_sve_ld1hsu_r, NULL, NULL, NULL },
310
+ { gen_helper_sve_ld1hdu_r, NULL, NULL, NULL },
311
+
312
+ { gen_helper_sve_ld1hds_r, NULL, NULL, NULL },
313
+ { gen_helper_sve_ld1hss_r, NULL, NULL, NULL },
314
+ { gen_helper_sve_ld1ss_r, gen_helper_sve_ld2ss_r,
315
+ gen_helper_sve_ld3ss_r, gen_helper_sve_ld4ss_r },
316
+ { gen_helper_sve_ld1sdu_r, NULL, NULL, NULL },
317
+
318
+ { gen_helper_sve_ld1bds_r, NULL, NULL, NULL },
319
+ { gen_helper_sve_ld1bss_r, NULL, NULL, NULL },
320
+ { gen_helper_sve_ld1bhs_r, NULL, NULL, NULL },
321
+ { gen_helper_sve_ld1dd_r, gen_helper_sve_ld2dd_r,
322
+ gen_helper_sve_ld3dd_r, gen_helper_sve_ld4dd_r },
323
+ };
324
+ gen_helper_gvec_mem *fn = fns[dtype][nreg];
325
+
326
+ /* While there are holes in the table, they are not
327
+ * accessible via the instruction encoding.
328
+ */
329
+ assert(fn != NULL);
330
+ do_mem_zpa(s, zt, pg, addr, fn);
331
+}
332
+
333
+static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn)
334
+{
335
+ if (a->rm == 31) {
336
+ return false;
337
+ }
338
+ if (sve_access_check(s)) {
339
+ TCGv_i64 addr = new_tmp_a64(s);
340
+ tcg_gen_muli_i64(addr, cpu_reg(s, a->rm),
341
+ (a->nreg + 1) << dtype_msz(a->dtype));
342
+ tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
343
+ do_ld_zpa(s, a->rd, a->pg, addr, a->dtype, a->nreg);
344
+ }
345
+ return true;
346
+}
347
+
348
+static bool trans_LD_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
349
+{
350
+ if (sve_access_check(s)) {
351
+ int vsz = vec_full_reg_size(s);
352
+ int elements = vsz >> dtype_esz[a->dtype];
353
+ TCGv_i64 addr = new_tmp_a64(s);
354
+
355
+ tcg_gen_addi_i64(addr, cpu_reg_sp(s, a->rn),
356
+ (a->imm * elements * (a->nreg + 1))
357
+ << dtype_msz(a->dtype));
358
+ do_ld_zpa(s, a->rd, a->pg, addr, a->dtype, a->nreg);
359
+ }
360
+ return true;
361
+}
362
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
363
index XXXXXXX..XXXXXXX 100644
364
--- a/target/arm/sve.decode
365
+++ b/target/arm/sve.decode
366
@@ -XXX,XX +XXX,XX @@
367
# Unsigned 8-bit immediate, optionally shifted left by 8.
368
%sh8_i8u 5:9 !function=expand_imm_sh8u
369
370
+# Unsigned load of msz into esz=2, represented as a dtype.
371
+%msz_dtype 23:2 !function=msz_dtype
372
+
373
# Either a copy of rd (at bit 0), or a different source
374
# as propagated via the MOVPRFX instruction.
375
%reg_movprfx 0:5
376
@@ -XXX,XX +XXX,XX @@
377
&incdec2_cnt rd rn pat esz imm d u
378
&incdec_pred rd pg esz d u
379
&incdec2_pred rd rn pg esz d u
380
+&rprr_load rd pg rn rm dtype nreg
381
+&rpri_load rd pg rn imm dtype nreg
382
383
###########################################################################
384
# Named instruction formats. These are generally used to
385
@@ -XXX,XX +XXX,XX @@
386
@incdec2_pred ........ esz:2 .... .. ..... .. pg:4 rd:5 \
387
&incdec2_pred rn=%reg_movprfx
388
389
+# Loads; user must fill in NREG.
390
+@rprr_load_dt ....... dtype:4 rm:5 ... pg:3 rn:5 rd:5 &rprr_load
391
+@rpri_load_dt ....... dtype:4 . imm:s4 ... pg:3 rn:5 rd:5 &rpri_load
392
+
393
+@rprr_load_msz ....... .... rm:5 ... pg:3 rn:5 rd:5 \
394
+ &rprr_load dtype=%msz_dtype
395
+@rpri_load_msz ....... .... . imm:s4 ... pg:3 rn:5 rd:5 \
396
+ &rpri_load dtype=%msz_dtype
397
+
398
###########################################################################
399
# Instruction patterns. Grouped according to the SVE encodingindex.xhtml.
400
401
@@ -XXX,XX +XXX,XX @@ LDR_pri 10000101 10 ...... 000 ... ..... 0 .... @pd_rn_i9
402
403
# SVE load vector register
404
LDR_zri 10000101 10 ...... 010 ... ..... ..... @rd_rn_i9
405
+
406
+### SVE Memory Contiguous Load Group
407
+
408
+# SVE contiguous load (scalar plus scalar)
409
+LD_zprr 1010010 .... ..... 010 ... ..... ..... @rprr_load_dt nreg=0
410
+
411
+# SVE contiguous load (scalar plus immediate)
412
+LD_zpri 1010010 .... 0.... 101 ... ..... ..... @rpri_load_dt nreg=0
413
+
414
+# SVE contiguous non-temporal load (scalar plus scalar)
415
+# LDNT1B, LDNT1H, LDNT1W, LDNT1D
416
+# SVE load multiple structures (scalar plus scalar)
417
+# LD2B, LD2H, LD2W, LD2D; etc.
418
+LD_zprr 1010010 .. nreg:2 ..... 110 ... ..... ..... @rprr_load_msz
419
+
420
+# SVE contiguous non-temporal load (scalar plus immediate)
421
+# LDNT1B, LDNT1H, LDNT1W, LDNT1D
422
+# SVE load multiple structures (scalar plus immediate)
423
+# LD2B, LD2H, LD2W, LD2D; etc.
424
+LD_zpri 1010010 .. nreg:2 0.... 111 ... ..... ..... @rpri_load_msz
425
--
184
--
426
2.17.1
185
2.25.1
427
428
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
We can reuse the SVE functions for LDR and STR, passing in the
4
base of the ZA vector and a zero offset.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-13-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-23-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-sve.c | 21 +++++++++++++++++++++
11
target/arm/sme.decode | 7 +++++++
9
target/arm/sve.decode | 23 +++++++++++++++++++++++
12
target/arm/translate-sme.c | 24 ++++++++++++++++++++++++
10
2 files changed, 44 insertions(+)
13
2 files changed, 31 insertions(+)
11
14
12
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
15
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-sve.c
17
--- a/target/arm/sme.decode
15
+++ b/target/arm/translate-sve.c
18
+++ b/target/arm/sme.decode
16
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
19
@@ -XXX,XX +XXX,XX @@ LDST1 1110000 0 esz:2 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
17
cpu_reg_sp(s, a->rn), fn);
20
&ldst rs=%mova_rs
21
LDST1 1110000 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
22
&ldst esz=4 rs=%mova_rs
23
+
24
+&ldstr rv rn imm
25
+@ldstr ....... ... . ...... .. ... rn:5 . imm:4 \
26
+ &ldstr rv=%mova_rs
27
+
28
+LDR 1110000 100 0 000000 .. 000 ..... 0 .... @ldstr
29
+STR 1110000 100 1 000000 .. 000 ..... 0 .... @ldstr
30
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/translate-sme.c
33
+++ b/target/arm/translate-sme.c
34
@@ -XXX,XX +XXX,XX @@ static bool trans_LDST1(DisasContext *s, arg_LDST1 *a)
35
tcg_temp_free_i64(addr);
18
return true;
36
return true;
19
}
37
}
20
+
38
+
21
+/*
39
+typedef void GenLdStR(DisasContext *, TCGv_ptr, int, int, int, int);
22
+ * Prefetches
23
+ */
24
+
40
+
25
+static bool trans_PRF(DisasContext *s, arg_PRF *a, uint32_t insn)
41
+static bool do_ldst_r(DisasContext *s, arg_ldstr *a, GenLdStR *fn)
26
+{
42
+{
27
+ /* Prefetch is a nop within QEMU. */
43
+ int svl = streaming_vec_reg_size(s);
28
+ sve_access_check(s);
44
+ int imm = a->imm;
45
+ TCGv_ptr base;
46
+
47
+ if (!sme_za_enabled_check(s)) {
48
+ return true;
49
+ }
50
+
51
+ /* ZA[n] equates to ZA0H.B[n]. */
52
+ base = get_tile_rowcol(s, MO_8, a->rv, imm, false);
53
+
54
+ fn(s, base, 0, svl, a->rn, imm * svl);
55
+
56
+ tcg_temp_free_ptr(base);
29
+ return true;
57
+ return true;
30
+}
58
+}
31
+
59
+
32
+static bool trans_PRF_rr(DisasContext *s, arg_PRF_rr *a, uint32_t insn)
60
+TRANS_FEAT(LDR, aa64_sme, do_ldst_r, a, gen_sve_ldr)
33
+{
61
+TRANS_FEAT(STR, aa64_sme, do_ldst_r, a, gen_sve_str)
34
+ if (a->rm == 31) {
35
+ return false;
36
+ }
37
+ /* Prefetch is a nop within QEMU. */
38
+ sve_access_check(s);
39
+ return true;
40
+}
41
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
42
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/sve.decode
44
+++ b/target/arm/sve.decode
45
@@ -XXX,XX +XXX,XX @@ LD1RQ_zprr 1010010 .. 00 ..... 000 ... ..... ..... \
46
LD1RQ_zpri 1010010 .. 00 0.... 001 ... ..... ..... \
47
@rpri_load_msz nreg=0
48
49
+# SVE 32-bit gather prefetch (scalar plus 32-bit scaled offsets)
50
+PRF 1000010 00 -1 ----- 0-- --- ----- 0 ----
51
+
52
+# SVE 32-bit gather prefetch (vector plus immediate)
53
+PRF 1000010 -- 00 ----- 111 --- ----- 0 ----
54
+
55
+# SVE contiguous prefetch (scalar plus immediate)
56
+PRF 1000010 11 1- ----- 0-- --- ----- 0 ----
57
+
58
+# SVE contiguous prefetch (scalar plus scalar)
59
+PRF_rr 1000010 -- 00 rm:5 110 --- ----- 0 ----
60
+
61
+### SVE Memory 64-bit Gather Group
62
+
63
+# SVE 64-bit gather prefetch (scalar plus 64-bit scaled offsets)
64
+PRF 1100010 00 11 ----- 1-- --- ----- 0 ----
65
+
66
+# SVE 64-bit gather prefetch (scalar plus unpacked 32-bit scaled offsets)
67
+PRF 1100010 00 -1 ----- 0-- --- ----- 0 ----
68
+
69
+# SVE 64-bit gather prefetch (vector plus immediate)
70
+PRF 1100010 -- 00 ----- 111 --- ----- 0 ----
71
+
72
### SVE Memory Store Group
73
74
# SVE store predicate register
75
--
62
--
76
2.17.1
63
2.25.1
77
78
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-10-richard.henderson@linaro.org
5
Message-id: 20220708151540.18136-24-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
7
---
8
target/arm/helper-sve.h | 5 +++
8
target/arm/helper-sme.h | 5 +++
9
target/arm/sve_helper.c | 41 +++++++++++++++++++++++++
9
target/arm/sme.decode | 11 +++++
10
target/arm/translate-sve.c | 62 ++++++++++++++++++++++++++++++++++++++
10
target/arm/sme_helper.c | 90 ++++++++++++++++++++++++++++++++++++++
11
target/arm/sve.decode | 5 +++
11
target/arm/translate-sme.c | 31 +++++++++++++
12
4 files changed, 113 insertions(+)
12
4 files changed, 137 insertions(+)
13
13
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
16
--- a/target/arm/helper-sme.h
17
+++ b/target/arm/helper-sve.h
17
+++ b/target/arm/helper-sme.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(sve_clr_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sme_st1q_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i
19
DEF_HELPER_FLAGS_3(sve_clr_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
19
DEF_HELPER_FLAGS_5(sme_st1q_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
20
DEF_HELPER_FLAGS_3(sve_clr_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
20
DEF_HELPER_FLAGS_5(sme_st1q_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
21
21
DEF_HELPER_FLAGS_5(sme_st1q_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
22
+DEF_HELPER_FLAGS_4(sve_movz_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_4(sve_movz_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_4(sve_movz_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_4(sve_movz_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
+
22
+
27
DEF_HELPER_FLAGS_4(sve_asr_zpzi_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_5(sme_addha_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
28
DEF_HELPER_FLAGS_4(sve_asr_zpzi_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
29
DEF_HELPER_FLAGS_4(sve_asr_zpzi_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
30
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
26
+DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
27
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
31
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/sve_helper.c
29
--- a/target/arm/sme.decode
33
+++ b/target/arm/sve_helper.c
30
+++ b/target/arm/sme.decode
34
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_clr_d)(void *vd, void *vg, uint32_t desc)
31
@@ -XXX,XX +XXX,XX @@ LDST1 1110000 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4 \
35
}
32
36
}
33
LDR 1110000 100 0 000000 .. 000 ..... 0 .... @ldstr
37
34
STR 1110000 100 1 000000 .. 000 ..... 0 .... @ldstr
38
+/* Copy Zn into Zd, and store zero into inactive elements. */
35
+
39
+void HELPER(sve_movz_b)(void *vd, void *vn, void *vg, uint32_t desc)
36
+### SME Add Vector to Array
37
+
38
+&adda zad zn pm pn
39
+@adda_32 ........ .. ..... . pm:3 pn:3 zn:5 ... zad:2 &adda
40
+@adda_64 ........ .. ..... . pm:3 pn:3 zn:5 .. zad:3 &adda
41
+
42
+ADDHA_s 11000000 10 01000 0 ... ... ..... 000 .. @adda_32
43
+ADDVA_s 11000000 10 01000 1 ... ... ..... 000 .. @adda_32
44
+ADDHA_d 11000000 11 01000 0 ... ... ..... 00 ... @adda_64
45
+ADDVA_d 11000000 11 01000 1 ... ... ..... 00 ... @adda_64
46
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/sme_helper.c
49
+++ b/target/arm/sme_helper.c
50
@@ -XXX,XX +XXX,XX @@ DO_ST(q, _be, MO_128)
51
DO_ST(q, _le, MO_128)
52
53
#undef DO_ST
54
+
55
+void HELPER(sme_addha_s)(void *vzda, void *vzn, void *vpn,
56
+ void *vpm, uint32_t desc)
40
+{
57
+{
41
+ intptr_t i, opr_sz = simd_oprsz(desc) / 8;
58
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
42
+ uint64_t *d = vd, *n = vn;
59
+ uint64_t *pn = vpn, *pm = vpm;
43
+ uint8_t *pg = vg;
60
+ uint32_t *zda = vzda, *zn = vzn;
44
+ for (i = 0; i < opr_sz; i += 1) {
61
+
45
+ d[i] = n[i] & expand_pred_b(pg[H1(i)]);
62
+ for (row = 0; row < oprsz; ) {
63
+ uint64_t pa = pn[row >> 4];
64
+ do {
65
+ if (pa & 1) {
66
+ for (col = 0; col < oprsz; ) {
67
+ uint64_t pb = pm[col >> 4];
68
+ do {
69
+ if (pb & 1) {
70
+ zda[tile_vslice_index(row) + H4(col)] += zn[H4(col)];
71
+ }
72
+ pb >>= 4;
73
+ } while (++col & 15);
74
+ }
75
+ }
76
+ pa >>= 4;
77
+ } while (++row & 15);
46
+ }
78
+ }
47
+}
79
+}
48
+
80
+
49
+void HELPER(sve_movz_h)(void *vd, void *vn, void *vg, uint32_t desc)
81
+void HELPER(sme_addha_d)(void *vzda, void *vzn, void *vpn,
82
+ void *vpm, uint32_t desc)
50
+{
83
+{
51
+ intptr_t i, opr_sz = simd_oprsz(desc) / 8;
84
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
52
+ uint64_t *d = vd, *n = vn;
85
+ uint8_t *pn = vpn, *pm = vpm;
53
+ uint8_t *pg = vg;
86
+ uint64_t *zda = vzda, *zn = vzn;
54
+ for (i = 0; i < opr_sz; i += 1) {
87
+
55
+ d[i] = n[i] & expand_pred_h(pg[H1(i)]);
88
+ for (row = 0; row < oprsz; ++row) {
89
+ if (pn[H1(row)] & 1) {
90
+ for (col = 0; col < oprsz; ++col) {
91
+ if (pm[H1(col)] & 1) {
92
+ zda[tile_vslice_index(row) + col] += zn[col];
93
+ }
94
+ }
95
+ }
56
+ }
96
+ }
57
+}
97
+}
58
+
98
+
59
+void HELPER(sve_movz_s)(void *vd, void *vn, void *vg, uint32_t desc)
99
+void HELPER(sme_addva_s)(void *vzda, void *vzn, void *vpn,
100
+ void *vpm, uint32_t desc)
60
+{
101
+{
61
+ intptr_t i, opr_sz = simd_oprsz(desc) / 8;
102
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
62
+ uint64_t *d = vd, *n = vn;
103
+ uint64_t *pn = vpn, *pm = vpm;
63
+ uint8_t *pg = vg;
104
+ uint32_t *zda = vzda, *zn = vzn;
64
+ for (i = 0; i < opr_sz; i += 1) {
105
+
65
+ d[i] = n[i] & expand_pred_s(pg[H1(i)]);
106
+ for (row = 0; row < oprsz; ) {
107
+ uint64_t pa = pn[row >> 4];
108
+ do {
109
+ if (pa & 1) {
110
+ uint32_t zn_row = zn[H4(row)];
111
+ for (col = 0; col < oprsz; ) {
112
+ uint64_t pb = pm[col >> 4];
113
+ do {
114
+ if (pb & 1) {
115
+ zda[tile_vslice_index(row) + H4(col)] += zn_row;
116
+ }
117
+ pb >>= 4;
118
+ } while (++col & 15);
119
+ }
120
+ }
121
+ pa >>= 4;
122
+ } while (++row & 15);
66
+ }
123
+ }
67
+}
124
+}
68
+
125
+
69
+void HELPER(sve_movz_d)(void *vd, void *vn, void *vg, uint32_t desc)
126
+void HELPER(sme_addva_d)(void *vzda, void *vzn, void *vpn,
127
+ void *vpm, uint32_t desc)
70
+{
128
+{
71
+ intptr_t i, opr_sz = simd_oprsz(desc) / 8;
129
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
72
+ uint64_t *d = vd, *n = vn;
130
+ uint8_t *pn = vpn, *pm = vpm;
73
+ uint8_t *pg = vg;
131
+ uint64_t *zda = vzda, *zn = vzn;
74
+ for (i = 0; i < opr_sz; i += 1) {
132
+
75
+ d[i] = n[1] & -(uint64_t)(pg[H1(i)] & 1);
133
+ for (row = 0; row < oprsz; ++row) {
134
+ if (pn[H1(row)] & 1) {
135
+ uint64_t zn_row = zn[row];
136
+ for (col = 0; col < oprsz; ++col) {
137
+ if (pm[H1(col)] & 1) {
138
+ zda[tile_vslice_index(row) + col] += zn_row;
139
+ }
140
+ }
141
+ }
76
+ }
142
+ }
77
+}
143
+}
144
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
145
index XXXXXXX..XXXXXXX 100644
146
--- a/target/arm/translate-sme.c
147
+++ b/target/arm/translate-sme.c
148
@@ -XXX,XX +XXX,XX @@ static bool do_ldst_r(DisasContext *s, arg_ldstr *a, GenLdStR *fn)
149
150
TRANS_FEAT(LDR, aa64_sme, do_ldst_r, a, gen_sve_ldr)
151
TRANS_FEAT(STR, aa64_sme, do_ldst_r, a, gen_sve_str)
78
+
152
+
79
/* Three-operand expander, immediate operand, controlled by a predicate.
153
+static bool do_adda(DisasContext *s, arg_adda *a, MemOp esz,
80
*/
154
+ gen_helper_gvec_4 *fn)
81
#define DO_ZPZI(NAME, TYPE, H, OP) \
82
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/target/arm/translate-sve.c
85
+++ b/target/arm/translate-sve.c
86
@@ -XXX,XX +XXX,XX @@ static bool do_clr_zp(DisasContext *s, int rd, int pg, int esz)
87
return true;
88
}
89
90
+/* Copy Zn into Zd, storing zeros into inactive elements. */
91
+static void do_movz_zpz(DisasContext *s, int rd, int rn, int pg, int esz)
92
+{
155
+{
93
+ static gen_helper_gvec_3 * const fns[4] = {
156
+ int svl = streaming_vec_reg_size(s);
94
+ gen_helper_sve_movz_b, gen_helper_sve_movz_h,
157
+ uint32_t desc = simd_desc(svl, svl, 0);
95
+ gen_helper_sve_movz_s, gen_helper_sve_movz_d,
158
+ TCGv_ptr za, zn, pn, pm;
96
+ };
97
+ unsigned vsz = vec_full_reg_size(s);
98
+ tcg_gen_gvec_3_ool(vec_full_reg_offset(s, rd),
99
+ vec_full_reg_offset(s, rn),
100
+ pred_full_reg_offset(s, pg),
101
+ vsz, vsz, 0, fns[esz]);
102
+}
103
+
159
+
104
static bool do_zpzi_ool(DisasContext *s, arg_rpri_esz *a,
160
+ if (!sme_smza_enabled_check(s)) {
105
gen_helper_gvec_3 *fn)
106
{
107
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1RQ_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
108
return true;
109
}
110
111
+/* Load and broadcast element. */
112
+static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
113
+{
114
+ if (!sve_access_check(s)) {
115
+ return true;
161
+ return true;
116
+ }
162
+ }
117
+
163
+
118
+ unsigned vsz = vec_full_reg_size(s);
164
+ /* Sum XZR+zad to find ZAd. */
119
+ unsigned psz = pred_full_reg_size(s);
165
+ za = get_tile_rowcol(s, esz, 31, a->zad, false);
120
+ unsigned esz = dtype_esz[a->dtype];
166
+ zn = vec_full_reg_ptr(s, a->zn);
121
+ TCGLabel *over = gen_new_label();
167
+ pn = pred_full_reg_ptr(s, a->pn);
122
+ TCGv_i64 temp;
168
+ pm = pred_full_reg_ptr(s, a->pm);
123
+
169
+
124
+ /* If the guarding predicate has no bits set, no load occurs. */
170
+ fn(za, zn, pn, pm, tcg_constant_i32(desc));
125
+ if (psz <= 8) {
126
+ /* Reduce the pred_esz_masks value simply to reduce the
127
+ * size of the code generated here.
128
+ */
129
+ uint64_t psz_mask = MAKE_64BIT_MASK(0, psz * 8);
130
+ temp = tcg_temp_new_i64();
131
+ tcg_gen_ld_i64(temp, cpu_env, pred_full_reg_offset(s, a->pg));
132
+ tcg_gen_andi_i64(temp, temp, pred_esz_masks[esz] & psz_mask);
133
+ tcg_gen_brcondi_i64(TCG_COND_EQ, temp, 0, over);
134
+ tcg_temp_free_i64(temp);
135
+ } else {
136
+ TCGv_i32 t32 = tcg_temp_new_i32();
137
+ find_last_active(s, t32, esz, a->pg);
138
+ tcg_gen_brcondi_i32(TCG_COND_LT, t32, 0, over);
139
+ tcg_temp_free_i32(t32);
140
+ }
141
+
171
+
142
+ /* Load the data. */
172
+ tcg_temp_free_ptr(za);
143
+ temp = tcg_temp_new_i64();
173
+ tcg_temp_free_ptr(zn);
144
+ tcg_gen_addi_i64(temp, cpu_reg_sp(s, a->rn), a->imm << esz);
174
+ tcg_temp_free_ptr(pn);
145
+ tcg_gen_qemu_ld_i64(temp, temp, get_mem_index(s),
175
+ tcg_temp_free_ptr(pm);
146
+ s->be_data | dtype_mop[a->dtype]);
147
+
148
+ /* Broadcast to *all* elements. */
149
+ tcg_gen_gvec_dup_i64(esz, vec_full_reg_offset(s, a->rd),
150
+ vsz, vsz, temp);
151
+ tcg_temp_free_i64(temp);
152
+
153
+ /* Zero the inactive elements. */
154
+ gen_set_label(over);
155
+ do_movz_zpz(s, a->rd, a->rd, a->pg, esz);
156
+ return true;
176
+ return true;
157
+}
177
+}
158
+
178
+
159
static void do_st_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
179
+TRANS_FEAT(ADDHA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addha_s)
160
int msz, int esz, int nreg)
180
+TRANS_FEAT(ADDVA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addva_s)
161
{
181
+TRANS_FEAT(ADDHA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addha_d)
162
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
182
+TRANS_FEAT(ADDVA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addva_d)
163
index XXXXXXX..XXXXXXX 100644
164
--- a/target/arm/sve.decode
165
+++ b/target/arm/sve.decode
166
@@ -XXX,XX +XXX,XX @@
167
%imm8_16_10 16:5 10:3
168
%imm9_16_10 16:s6 10:3
169
%size_23 23:2
170
+%dtype_23_13 23:2 13:2
171
172
# A combination of tsz:imm3 -- extract esize.
173
%tszimm_esz 22:2 5:5 !function=tszimm_esz
174
@@ -XXX,XX +XXX,XX @@ LDR_pri 10000101 10 ...... 000 ... ..... 0 .... @pd_rn_i9
175
# SVE load vector register
176
LDR_zri 10000101 10 ...... 010 ... ..... ..... @rd_rn_i9
177
178
+# SVE load and broadcast element
179
+LD1R_zpri 1000010 .. 1 imm:6 1.. pg:3 rn:5 rd:5 \
180
+ &rpri_load dtype=%dtype_23_13 nreg=0
181
+
182
### SVE Memory Contiguous Load Group
183
184
# SVE contiguous load (scalar plus scalar)
185
--
183
--
186
2.17.1
184
2.25.1
187
188
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20220708151540.18136-25-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 20180627043328.11531-8-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
7
---
9
target/arm/helper-sve.h | 16 ++++
8
target/arm/helper-sme.h | 5 +++
10
target/arm/sve_helper.c | 158 +++++++++++++++++++++++++++++++++++++
9
target/arm/sme.decode | 9 +++++
11
target/arm/translate-sve.c | 49 ++++++++++++
10
target/arm/sme_helper.c | 69 ++++++++++++++++++++++++++++++++++++++
12
target/arm/sve.decode | 18 +++++
11
target/arm/translate-sme.c | 32 ++++++++++++++++++
13
4 files changed, 241 insertions(+)
12
4 files changed, 115 insertions(+)
14
13
15
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-sve.h
16
--- a/target/arm/helper-sme.h
18
+++ b/target/arm/helper-sve.h
17
+++ b/target/arm/helper-sme.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_ucvt_ds, TCG_CALL_NO_RWG,
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sme_addha_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
DEF_HELPER_FLAGS_5(sve_ucvt_dd, TCG_CALL_NO_RWG,
19
DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
void, ptr, ptr, ptr, ptr, i32)
20
DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
22
21
DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_3(sve_fmla_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32)
24
+DEF_HELPER_FLAGS_3(sve_fmla_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32)
25
+DEF_HELPER_FLAGS_3(sve_fmla_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32)
26
+
22
+
27
+DEF_HELPER_FLAGS_3(sve_fmls_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32)
23
+DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
28
+DEF_HELPER_FLAGS_3(sve_fmls_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32)
24
+ void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_3(sve_fmls_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32)
25
+DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
26
+ void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
27
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/sme.decode
30
+++ b/target/arm/sme.decode
31
@@ -XXX,XX +XXX,XX @@ ADDHA_s 11000000 10 01000 0 ... ... ..... 000 .. @adda_32
32
ADDVA_s 11000000 10 01000 1 ... ... ..... 000 .. @adda_32
33
ADDHA_d 11000000 11 01000 0 ... ... ..... 00 ... @adda_64
34
ADDVA_d 11000000 11 01000 1 ... ... ..... 00 ... @adda_64
30
+
35
+
31
+DEF_HELPER_FLAGS_3(sve_fnmla_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32)
36
+### SME Outer Product
32
+DEF_HELPER_FLAGS_3(sve_fnmla_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32)
33
+DEF_HELPER_FLAGS_3(sve_fnmla_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32)
34
+
37
+
35
+DEF_HELPER_FLAGS_3(sve_fnmls_zpzzz_h, TCG_CALL_NO_RWG, void, env, ptr, i32)
38
+&op zad zn zm pm pn sub:bool
36
+DEF_HELPER_FLAGS_3(sve_fnmls_zpzzz_s, TCG_CALL_NO_RWG, void, env, ptr, i32)
39
+@op_32 ........ ... zm:5 pm:3 pn:3 zn:5 sub:1 .. zad:2 &op
37
+DEF_HELPER_FLAGS_3(sve_fnmls_zpzzz_d, TCG_CALL_NO_RWG, void, env, ptr, i32)
40
+@op_64 ........ ... zm:5 pm:3 pn:3 zn:5 sub:1 . zad:3 &op
38
+
41
+
39
DEF_HELPER_FLAGS_4(sve_ld1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
42
+FMOPA_s 10000000 100 ..... ... ... ..... . 00 .. @op_32
40
DEF_HELPER_FLAGS_4(sve_ld2bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
43
+FMOPA_d 10000000 110 ..... ... ... ..... . 0 ... @op_64
41
DEF_HELPER_FLAGS_4(sve_ld3bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
44
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
42
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
43
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/sve_helper.c
46
--- a/target/arm/sme_helper.c
45
+++ b/target/arm/sve_helper.c
47
+++ b/target/arm/sme_helper.c
46
@@ -XXX,XX +XXX,XX @@ DO_ZPZ_FP(sve_ucvt_dd, uint64_t, , uint64_to_float64)
48
@@ -XXX,XX +XXX,XX @@
47
49
#include "exec/cpu_ldst.h"
48
#undef DO_ZPZ_FP
50
#include "exec/exec-all.h"
49
51
#include "qemu/int128.h"
50
+/* 4-operand predicated multiply-add. This requires 7 operands to pass
52
+#include "fpu/softfloat.h"
51
+ * "properly", so we need to encode some of the registers into DESC.
53
#include "vec_internal.h"
52
+ */
54
#include "sve_ldst_internal.h"
53
+QEMU_BUILD_BUG_ON(SIMD_DATA_SHIFT + 20 > 32);
55
56
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_addva_d)(void *vzda, void *vzn, void *vpn,
57
}
58
}
59
}
54
+
60
+
55
+static void do_fmla_zpzzz_h(CPUARMState *env, void *vg, uint32_t desc,
61
+void HELPER(sme_fmopa_s)(void *vza, void *vzn, void *vzm, void *vpn,
56
+ uint16_t neg1, uint16_t neg3)
62
+ void *vpm, void *vst, uint32_t desc)
57
+{
63
+{
58
+ intptr_t i = simd_oprsz(desc);
64
+ intptr_t row, col, oprsz = simd_maxsz(desc);
59
+ unsigned rd = extract32(desc, SIMD_DATA_SHIFT, 5);
65
+ uint32_t neg = simd_data(desc) << 31;
60
+ unsigned rn = extract32(desc, SIMD_DATA_SHIFT + 5, 5);
66
+ uint16_t *pn = vpn, *pm = vpm;
61
+ unsigned rm = extract32(desc, SIMD_DATA_SHIFT + 10, 5);
67
+ float_status fpst;
62
+ unsigned ra = extract32(desc, SIMD_DATA_SHIFT + 15, 5);
63
+ void *vd = &env->vfp.zregs[rd];
64
+ void *vn = &env->vfp.zregs[rn];
65
+ void *vm = &env->vfp.zregs[rm];
66
+ void *va = &env->vfp.zregs[ra];
67
+ uint64_t *g = vg;
68
+
68
+
69
+ do {
69
+ /*
70
+ uint64_t pg = g[(i - 1) >> 6];
70
+ * Make a copy of float_status because this operation does not
71
+ * update the cumulative fp exception status. It also produces
72
+ * default nans.
73
+ */
74
+ fpst = *(float_status *)vst;
75
+ set_default_nan_mode(true, &fpst);
76
+
77
+ for (row = 0; row < oprsz; ) {
78
+ uint16_t pa = pn[H2(row >> 4)];
71
+ do {
79
+ do {
72
+ i -= 2;
80
+ if (pa & 1) {
73
+ if (likely((pg >> (i & 63)) & 1)) {
81
+ void *vza_row = vza + tile_vslice_offset(row);
74
+ float16 e1, e2, e3, r;
82
+ uint32_t n = *(uint32_t *)(vzn + H1_4(row)) ^ neg;
75
+
83
+
76
+ e1 = *(uint16_t *)(vn + H1_2(i)) ^ neg1;
84
+ for (col = 0; col < oprsz; ) {
77
+ e2 = *(uint16_t *)(vm + H1_2(i));
85
+ uint16_t pb = pm[H2(col >> 4)];
78
+ e3 = *(uint16_t *)(va + H1_2(i)) ^ neg3;
86
+ do {
79
+ r = float16_muladd(e1, e2, e3, 0, &env->vfp.fp_status);
87
+ if (pb & 1) {
80
+ *(uint16_t *)(vd + H1_2(i)) = r;
88
+ uint32_t *a = vza_row + H1_4(col);
89
+ uint32_t *m = vzm + H1_4(col);
90
+ *a = float32_muladd(n, *m, *a, 0, vst);
91
+ }
92
+ col += 4;
93
+ pb >>= 4;
94
+ } while (col & 15);
95
+ }
81
+ }
96
+ }
82
+ } while (i & 63);
97
+ row += 4;
83
+ } while (i != 0);
98
+ pa >>= 4;
99
+ } while (row & 15);
100
+ }
84
+}
101
+}
85
+
102
+
86
+void HELPER(sve_fmla_zpzzz_h)(CPUARMState *env, void *vg, uint32_t desc)
103
+void HELPER(sme_fmopa_d)(void *vza, void *vzn, void *vzm, void *vpn,
104
+ void *vpm, void *vst, uint32_t desc)
87
+{
105
+{
88
+ do_fmla_zpzzz_h(env, vg, desc, 0, 0);
106
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
107
+ uint64_t neg = (uint64_t)simd_data(desc) << 63;
108
+ uint64_t *za = vza, *zn = vzn, *zm = vzm;
109
+ uint8_t *pn = vpn, *pm = vpm;
110
+ float_status fpst = *(float_status *)vst;
111
+
112
+ set_default_nan_mode(true, &fpst);
113
+
114
+ for (row = 0; row < oprsz; ++row) {
115
+ if (pn[H1(row)] & 1) {
116
+ uint64_t *za_row = &za[tile_vslice_index(row)];
117
+ uint64_t n = zn[row] ^ neg;
118
+
119
+ for (col = 0; col < oprsz; ++col) {
120
+ if (pm[H1(col)] & 1) {
121
+ uint64_t *a = &za_row[col];
122
+ *a = float64_muladd(n, zm[col], *a, 0, &fpst);
123
+ }
124
+ }
125
+ }
126
+ }
89
+}
127
+}
128
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
129
index XXXXXXX..XXXXXXX 100644
130
--- a/target/arm/translate-sme.c
131
+++ b/target/arm/translate-sme.c
132
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(ADDHA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addha_s)
133
TRANS_FEAT(ADDVA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addva_s)
134
TRANS_FEAT(ADDHA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addha_d)
135
TRANS_FEAT(ADDVA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addva_d)
90
+
136
+
91
+void HELPER(sve_fmls_zpzzz_h)(CPUARMState *env, void *vg, uint32_t desc)
137
+static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
138
+ gen_helper_gvec_5_ptr *fn)
92
+{
139
+{
93
+ do_fmla_zpzzz_h(env, vg, desc, 0x8000, 0);
140
+ int svl = streaming_vec_reg_size(s);
94
+}
141
+ uint32_t desc = simd_desc(svl, svl, a->sub);
142
+ TCGv_ptr za, zn, zm, pn, pm, fpst;
95
+
143
+
96
+void HELPER(sve_fnmla_zpzzz_h)(CPUARMState *env, void *vg, uint32_t desc)
144
+ if (!sme_smza_enabled_check(s)) {
97
+{
98
+ do_fmla_zpzzz_h(env, vg, desc, 0x8000, 0x8000);
99
+}
100
+
101
+void HELPER(sve_fnmls_zpzzz_h)(CPUARMState *env, void *vg, uint32_t desc)
102
+{
103
+ do_fmla_zpzzz_h(env, vg, desc, 0, 0x8000);
104
+}
105
+
106
+static void do_fmla_zpzzz_s(CPUARMState *env, void *vg, uint32_t desc,
107
+ uint32_t neg1, uint32_t neg3)
108
+{
109
+ intptr_t i = simd_oprsz(desc);
110
+ unsigned rd = extract32(desc, SIMD_DATA_SHIFT, 5);
111
+ unsigned rn = extract32(desc, SIMD_DATA_SHIFT + 5, 5);
112
+ unsigned rm = extract32(desc, SIMD_DATA_SHIFT + 10, 5);
113
+ unsigned ra = extract32(desc, SIMD_DATA_SHIFT + 15, 5);
114
+ void *vd = &env->vfp.zregs[rd];
115
+ void *vn = &env->vfp.zregs[rn];
116
+ void *vm = &env->vfp.zregs[rm];
117
+ void *va = &env->vfp.zregs[ra];
118
+ uint64_t *g = vg;
119
+
120
+ do {
121
+ uint64_t pg = g[(i - 1) >> 6];
122
+ do {
123
+ i -= 4;
124
+ if (likely((pg >> (i & 63)) & 1)) {
125
+ float32 e1, e2, e3, r;
126
+
127
+ e1 = *(uint32_t *)(vn + H1_4(i)) ^ neg1;
128
+ e2 = *(uint32_t *)(vm + H1_4(i));
129
+ e3 = *(uint32_t *)(va + H1_4(i)) ^ neg3;
130
+ r = float32_muladd(e1, e2, e3, 0, &env->vfp.fp_status);
131
+ *(uint32_t *)(vd + H1_4(i)) = r;
132
+ }
133
+ } while (i & 63);
134
+ } while (i != 0);
135
+}
136
+
137
+void HELPER(sve_fmla_zpzzz_s)(CPUARMState *env, void *vg, uint32_t desc)
138
+{
139
+ do_fmla_zpzzz_s(env, vg, desc, 0, 0);
140
+}
141
+
142
+void HELPER(sve_fmls_zpzzz_s)(CPUARMState *env, void *vg, uint32_t desc)
143
+{
144
+ do_fmla_zpzzz_s(env, vg, desc, 0x80000000, 0);
145
+}
146
+
147
+void HELPER(sve_fnmla_zpzzz_s)(CPUARMState *env, void *vg, uint32_t desc)
148
+{
149
+ do_fmla_zpzzz_s(env, vg, desc, 0x80000000, 0x80000000);
150
+}
151
+
152
+void HELPER(sve_fnmls_zpzzz_s)(CPUARMState *env, void *vg, uint32_t desc)
153
+{
154
+ do_fmla_zpzzz_s(env, vg, desc, 0, 0x80000000);
155
+}
156
+
157
+static void do_fmla_zpzzz_d(CPUARMState *env, void *vg, uint32_t desc,
158
+ uint64_t neg1, uint64_t neg3)
159
+{
160
+ intptr_t i = simd_oprsz(desc);
161
+ unsigned rd = extract32(desc, SIMD_DATA_SHIFT, 5);
162
+ unsigned rn = extract32(desc, SIMD_DATA_SHIFT + 5, 5);
163
+ unsigned rm = extract32(desc, SIMD_DATA_SHIFT + 10, 5);
164
+ unsigned ra = extract32(desc, SIMD_DATA_SHIFT + 15, 5);
165
+ void *vd = &env->vfp.zregs[rd];
166
+ void *vn = &env->vfp.zregs[rn];
167
+ void *vm = &env->vfp.zregs[rm];
168
+ void *va = &env->vfp.zregs[ra];
169
+ uint64_t *g = vg;
170
+
171
+ do {
172
+ uint64_t pg = g[(i - 1) >> 6];
173
+ do {
174
+ i -= 8;
175
+ if (likely((pg >> (i & 63)) & 1)) {
176
+ float64 e1, e2, e3, r;
177
+
178
+ e1 = *(uint64_t *)(vn + i) ^ neg1;
179
+ e2 = *(uint64_t *)(vm + i);
180
+ e3 = *(uint64_t *)(va + i) ^ neg3;
181
+ r = float64_muladd(e1, e2, e3, 0, &env->vfp.fp_status);
182
+ *(uint64_t *)(vd + i) = r;
183
+ }
184
+ } while (i & 63);
185
+ } while (i != 0);
186
+}
187
+
188
+void HELPER(sve_fmla_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc)
189
+{
190
+ do_fmla_zpzzz_d(env, vg, desc, 0, 0);
191
+}
192
+
193
+void HELPER(sve_fmls_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc)
194
+{
195
+ do_fmla_zpzzz_d(env, vg, desc, INT64_MIN, 0);
196
+}
197
+
198
+void HELPER(sve_fnmla_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc)
199
+{
200
+ do_fmla_zpzzz_d(env, vg, desc, INT64_MIN, INT64_MIN);
201
+}
202
+
203
+void HELPER(sve_fnmls_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc)
204
+{
205
+ do_fmla_zpzzz_d(env, vg, desc, 0, INT64_MIN);
206
+}
207
+
208
/*
209
* Load contiguous data, protected by a governing predicate.
210
*/
211
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
212
index XXXXXXX..XXXXXXX 100644
213
--- a/target/arm/translate-sve.c
214
+++ b/target/arm/translate-sve.c
215
@@ -XXX,XX +XXX,XX @@ DO_FP3(FMULX, fmulx)
216
217
#undef DO_FP3
218
219
+typedef void gen_helper_sve_fmla(TCGv_env, TCGv_ptr, TCGv_i32);
220
+
221
+static bool do_fmla(DisasContext *s, arg_rprrr_esz *a, gen_helper_sve_fmla *fn)
222
+{
223
+ if (fn == NULL) {
224
+ return false;
225
+ }
226
+ if (!sve_access_check(s)) {
227
+ return true;
145
+ return true;
228
+ }
146
+ }
229
+
147
+
230
+ unsigned vsz = vec_full_reg_size(s);
148
+ /* Sum XZR+zad to find ZAd. */
231
+ unsigned desc;
149
+ za = get_tile_rowcol(s, esz, 31, a->zad, false);
232
+ TCGv_i32 t_desc;
150
+ zn = vec_full_reg_ptr(s, a->zn);
233
+ TCGv_ptr pg = tcg_temp_new_ptr();
151
+ zm = vec_full_reg_ptr(s, a->zm);
152
+ pn = pred_full_reg_ptr(s, a->pn);
153
+ pm = pred_full_reg_ptr(s, a->pm);
154
+ fpst = fpstatus_ptr(FPST_FPCR);
234
+
155
+
235
+ /* We would need 7 operands to pass these arguments "properly".
156
+ fn(za, zn, zm, pn, pm, fpst, tcg_constant_i32(desc));
236
+ * So we encode all the register numbers into the descriptor.
237
+ */
238
+ desc = deposit32(a->rd, 5, 5, a->rn);
239
+ desc = deposit32(desc, 10, 5, a->rm);
240
+ desc = deposit32(desc, 15, 5, a->ra);
241
+ desc = simd_desc(vsz, vsz, desc);
242
+
157
+
243
+ t_desc = tcg_const_i32(desc);
158
+ tcg_temp_free_ptr(za);
244
+ tcg_gen_addi_ptr(pg, cpu_env, pred_full_reg_offset(s, a->pg));
159
+ tcg_temp_free_ptr(zn);
245
+ fn(cpu_env, pg, t_desc);
160
+ tcg_temp_free_ptr(pn);
246
+ tcg_temp_free_i32(t_desc);
161
+ tcg_temp_free_ptr(pm);
247
+ tcg_temp_free_ptr(pg);
162
+ tcg_temp_free_ptr(fpst);
248
+ return true;
163
+ return true;
249
+}
164
+}
250
+
165
+
251
+#define DO_FMLA(NAME, name) \
166
+TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_s)
252
+static bool trans_##NAME(DisasContext *s, arg_rprrr_esz *a, uint32_t insn) \
167
+TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_fmopa_d)
253
+{ \
254
+ static gen_helper_sve_fmla * const fns[4] = { \
255
+ NULL, gen_helper_sve_##name##_h, \
256
+ gen_helper_sve_##name##_s, gen_helper_sve_##name##_d \
257
+ }; \
258
+ return do_fmla(s, a, fns[a->esz]); \
259
+}
260
+
261
+DO_FMLA(FMLA_zpzzz, fmla_zpzzz)
262
+DO_FMLA(FMLS_zpzzz, fmls_zpzzz)
263
+DO_FMLA(FNMLA_zpzzz, fnmla_zpzzz)
264
+DO_FMLA(FNMLS_zpzzz, fnmls_zpzzz)
265
+
266
+#undef DO_FMLA
267
+
268
/*
269
*** SVE Floating Point Unary Operations Predicated Group
270
*/
271
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
272
index XXXXXXX..XXXXXXX 100644
273
--- a/target/arm/sve.decode
274
+++ b/target/arm/sve.decode
275
@@ -XXX,XX +XXX,XX @@
276
&rprrr_esz ra=%reg_movprfx
277
@rdn_pg_ra_rm ........ esz:2 . rm:5 ... pg:3 ra:5 rd:5 \
278
&rprrr_esz rn=%reg_movprfx
279
+@rdn_pg_rm_ra ........ esz:2 . ra:5 ... pg:3 rm:5 rd:5 \
280
+ &rprrr_esz rn=%reg_movprfx
281
282
# One register operand, with governing predicate, vector element size
283
@rd_pg_rn ........ esz:2 ... ... ... pg:3 rn:5 rd:5 &rpr_esz
284
@@ -XXX,XX +XXX,XX @@ FMULX 01100101 .. 00 1010 100 ... ..... ..... @rdn_pg_rm
285
FDIV 01100101 .. 00 1100 100 ... ..... ..... @rdm_pg_rn # FDIVR
286
FDIV 01100101 .. 00 1101 100 ... ..... ..... @rdn_pg_rm
287
288
+### SVE FP Multiply-Add Group
289
+
290
+# SVE floating-point multiply-accumulate writing addend
291
+FMLA_zpzzz 01100101 .. 1 ..... 000 ... ..... ..... @rda_pg_rn_rm
292
+FMLS_zpzzz 01100101 .. 1 ..... 001 ... ..... ..... @rda_pg_rn_rm
293
+FNMLA_zpzzz 01100101 .. 1 ..... 010 ... ..... ..... @rda_pg_rn_rm
294
+FNMLS_zpzzz 01100101 .. 1 ..... 011 ... ..... ..... @rda_pg_rn_rm
295
+
296
+# SVE floating-point multiply-accumulate writing multiplicand
297
+# Alter the operand extraction order and reuse the helpers from above.
298
+# FMAD, FMSB, FNMAD, FNMS
299
+FMLA_zpzzz 01100101 .. 1 ..... 100 ... ..... ..... @rdn_pg_rm_ra
300
+FMLS_zpzzz 01100101 .. 1 ..... 101 ... ..... ..... @rdn_pg_rm_ra
301
+FNMLA_zpzzz 01100101 .. 1 ..... 110 ... ..... ..... @rdn_pg_rm_ra
302
+FNMLS_zpzzz 01100101 .. 1 ..... 111 ... ..... ..... @rdn_pg_rm_ra
303
+
304
### SVE FP Unary Operations Predicated Group
305
306
# SVE integer convert to floating-point
307
--
168
--
308
2.17.1
169
2.25.1
309
310
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20220708151540.18136-26-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 20180627043328.11531-14-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
7
---
9
target/arm/helper-sve.h | 67 +++++++++++++++++++++++++
8
target/arm/helper-sme.h | 2 ++
10
target/arm/sve_helper.c | 77 ++++++++++++++++++++++++++++
9
target/arm/sme.decode | 2 ++
11
target/arm/translate-sve.c | 100 +++++++++++++++++++++++++++++++++++++
10
target/arm/sme_helper.c | 56 ++++++++++++++++++++++++++++++++++++++
12
target/arm/sve.decode | 57 +++++++++++++++++++++
11
target/arm/translate-sme.c | 30 ++++++++++++++++++++
13
4 files changed, 301 insertions(+)
12
4 files changed, 90 insertions(+)
14
13
15
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-sve.h
16
--- a/target/arm/helper-sme.h
18
+++ b/target/arm/helper-sve.h
17
+++ b/target/arm/helper-sme.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_st1hd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
20
19
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
21
DEF_HELPER_FLAGS_4(sve_st1sd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
20
DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
22
21
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_6(sve_ldbsu_zsu, TCG_CALL_NO_WG,
22
+DEF_HELPER_FLAGS_6(sme_bfmopa, TCG_CALL_NO_RWG,
24
+ void, env, ptr, ptr, ptr, tl, i32)
23
+ void, ptr, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_6(sve_ldhsu_zsu, TCG_CALL_NO_WG,
24
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
26
+ void, env, ptr, ptr, ptr, tl, i32)
25
index XXXXXXX..XXXXXXX 100644
27
+DEF_HELPER_FLAGS_6(sve_ldssu_zsu, TCG_CALL_NO_WG,
26
--- a/target/arm/sme.decode
28
+ void, env, ptr, ptr, ptr, tl, i32)
27
+++ b/target/arm/sme.decode
29
+DEF_HELPER_FLAGS_6(sve_ldbss_zsu, TCG_CALL_NO_WG,
28
@@ -XXX,XX +XXX,XX @@ ADDVA_d 11000000 11 01000 1 ... ... ..... 00 ... @adda_64
30
+ void, env, ptr, ptr, ptr, tl, i32)
29
31
+DEF_HELPER_FLAGS_6(sve_ldhss_zsu, TCG_CALL_NO_WG,
30
FMOPA_s 10000000 100 ..... ... ... ..... . 00 .. @op_32
32
+ void, env, ptr, ptr, ptr, tl, i32)
31
FMOPA_d 10000000 110 ..... ... ... ..... . 0 ... @op_64
33
+
32
+
34
+DEF_HELPER_FLAGS_6(sve_ldbsu_zss, TCG_CALL_NO_WG,
33
+BFMOPA 10000001 100 ..... ... ... ..... . 00 .. @op_32
35
+ void, env, ptr, ptr, ptr, tl, i32)
34
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
36
+DEF_HELPER_FLAGS_6(sve_ldhsu_zss, TCG_CALL_NO_WG,
37
+ void, env, ptr, ptr, ptr, tl, i32)
38
+DEF_HELPER_FLAGS_6(sve_ldssu_zss, TCG_CALL_NO_WG,
39
+ void, env, ptr, ptr, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_6(sve_ldbss_zss, TCG_CALL_NO_WG,
41
+ void, env, ptr, ptr, ptr, tl, i32)
42
+DEF_HELPER_FLAGS_6(sve_ldhss_zss, TCG_CALL_NO_WG,
43
+ void, env, ptr, ptr, ptr, tl, i32)
44
+
45
+DEF_HELPER_FLAGS_6(sve_ldbdu_zsu, TCG_CALL_NO_WG,
46
+ void, env, ptr, ptr, ptr, tl, i32)
47
+DEF_HELPER_FLAGS_6(sve_ldhdu_zsu, TCG_CALL_NO_WG,
48
+ void, env, ptr, ptr, ptr, tl, i32)
49
+DEF_HELPER_FLAGS_6(sve_ldsdu_zsu, TCG_CALL_NO_WG,
50
+ void, env, ptr, ptr, ptr, tl, i32)
51
+DEF_HELPER_FLAGS_6(sve_ldddu_zsu, TCG_CALL_NO_WG,
52
+ void, env, ptr, ptr, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_6(sve_ldbds_zsu, TCG_CALL_NO_WG,
54
+ void, env, ptr, ptr, ptr, tl, i32)
55
+DEF_HELPER_FLAGS_6(sve_ldhds_zsu, TCG_CALL_NO_WG,
56
+ void, env, ptr, ptr, ptr, tl, i32)
57
+DEF_HELPER_FLAGS_6(sve_ldsds_zsu, TCG_CALL_NO_WG,
58
+ void, env, ptr, ptr, ptr, tl, i32)
59
+
60
+DEF_HELPER_FLAGS_6(sve_ldbdu_zss, TCG_CALL_NO_WG,
61
+ void, env, ptr, ptr, ptr, tl, i32)
62
+DEF_HELPER_FLAGS_6(sve_ldhdu_zss, TCG_CALL_NO_WG,
63
+ void, env, ptr, ptr, ptr, tl, i32)
64
+DEF_HELPER_FLAGS_6(sve_ldsdu_zss, TCG_CALL_NO_WG,
65
+ void, env, ptr, ptr, ptr, tl, i32)
66
+DEF_HELPER_FLAGS_6(sve_ldddu_zss, TCG_CALL_NO_WG,
67
+ void, env, ptr, ptr, ptr, tl, i32)
68
+DEF_HELPER_FLAGS_6(sve_ldbds_zss, TCG_CALL_NO_WG,
69
+ void, env, ptr, ptr, ptr, tl, i32)
70
+DEF_HELPER_FLAGS_6(sve_ldhds_zss, TCG_CALL_NO_WG,
71
+ void, env, ptr, ptr, ptr, tl, i32)
72
+DEF_HELPER_FLAGS_6(sve_ldsds_zss, TCG_CALL_NO_WG,
73
+ void, env, ptr, ptr, ptr, tl, i32)
74
+
75
+DEF_HELPER_FLAGS_6(sve_ldbdu_zd, TCG_CALL_NO_WG,
76
+ void, env, ptr, ptr, ptr, tl, i32)
77
+DEF_HELPER_FLAGS_6(sve_ldhdu_zd, TCG_CALL_NO_WG,
78
+ void, env, ptr, ptr, ptr, tl, i32)
79
+DEF_HELPER_FLAGS_6(sve_ldsdu_zd, TCG_CALL_NO_WG,
80
+ void, env, ptr, ptr, ptr, tl, i32)
81
+DEF_HELPER_FLAGS_6(sve_ldddu_zd, TCG_CALL_NO_WG,
82
+ void, env, ptr, ptr, ptr, tl, i32)
83
+DEF_HELPER_FLAGS_6(sve_ldbds_zd, TCG_CALL_NO_WG,
84
+ void, env, ptr, ptr, ptr, tl, i32)
85
+DEF_HELPER_FLAGS_6(sve_ldhds_zd, TCG_CALL_NO_WG,
86
+ void, env, ptr, ptr, ptr, tl, i32)
87
+DEF_HELPER_FLAGS_6(sve_ldsds_zd, TCG_CALL_NO_WG,
88
+ void, env, ptr, ptr, ptr, tl, i32)
89
+
90
DEF_HELPER_FLAGS_6(sve_stbs_zsu, TCG_CALL_NO_WG,
91
void, env, ptr, ptr, ptr, tl, i32)
92
DEF_HELPER_FLAGS_6(sve_sths_zsu, TCG_CALL_NO_WG,
93
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
94
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/sve_helper.c
36
--- a/target/arm/sme_helper.c
96
+++ b/target/arm/sve_helper.c
37
+++ b/target/arm/sme_helper.c
97
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_st4dd_r)(CPUARMState *env, void *vg,
38
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_fmopa_d)(void *vza, void *vzn, void *vzm, void *vpn,
39
}
98
}
40
}
99
}
41
}
100
101
+/* Loads with a vector index. */
102
+
42
+
103
+#define DO_LD1_ZPZ_S(NAME, TYPEI, TYPEM, FN) \
43
+/*
104
+void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
44
+ * Alter PAIR as needed for controlling predicates being false,
105
+ target_ulong base, uint32_t desc) \
45
+ * and for NEG on an enabled row element.
106
+{ \
46
+ */
107
+ intptr_t i, oprsz = simd_oprsz(desc); \
47
+static inline uint32_t f16mop_adj_pair(uint32_t pair, uint32_t pg, uint32_t neg)
108
+ unsigned scale = simd_data(desc); \
48
+{
109
+ uintptr_t ra = GETPC(); \
49
+ /*
110
+ for (i = 0; i < oprsz; i++) { \
50
+ * The pseudocode uses a conditional negate after the conditional zero.
111
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
51
+ * It is simpler here to unconditionally negate before conditional zero.
112
+ do { \
52
+ */
113
+ TYPEM m = 0; \
53
+ pair ^= neg;
114
+ if (pg & 1) { \
54
+ if (!(pg & 1)) {
115
+ target_ulong off = *(TYPEI *)(vm + H1_4(i)); \
55
+ pair &= 0xffff0000u;
116
+ m = FN(env, base + (off << scale), ra); \
56
+ }
117
+ } \
57
+ if (!(pg & 4)) {
118
+ *(uint32_t *)(vd + H1_4(i)) = m; \
58
+ pair &= 0x0000ffffu;
119
+ i += 4, pg >>= 4; \
59
+ }
120
+ } while (i & 15); \
60
+ return pair;
121
+ } \
122
+}
61
+}
123
+
62
+
124
+#define DO_LD1_ZPZ_D(NAME, TYPEI, TYPEM, FN) \
63
+void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
125
+void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
64
+ void *vpm, uint32_t desc)
126
+ target_ulong base, uint32_t desc) \
65
+{
127
+{ \
66
+ intptr_t row, col, oprsz = simd_maxsz(desc);
128
+ intptr_t i, oprsz = simd_oprsz(desc) / 8; \
67
+ uint32_t neg = simd_data(desc) * 0x80008000u;
129
+ unsigned scale = simd_data(desc); \
68
+ uint16_t *pn = vpn, *pm = vpm;
130
+ uintptr_t ra = GETPC(); \
69
+
131
+ uint64_t *d = vd, *m = vm; uint8_t *pg = vg; \
70
+ for (row = 0; row < oprsz; ) {
132
+ for (i = 0; i < oprsz; i++) { \
71
+ uint16_t prow = pn[H2(row >> 4)];
133
+ TYPEM mm = 0; \
72
+ do {
134
+ if (pg[H1(i)] & 1) { \
73
+ void *vza_row = vza + tile_vslice_offset(row);
135
+ target_ulong off = (TYPEI)m[i]; \
74
+ uint32_t n = *(uint32_t *)(vzn + H1_4(row));
136
+ mm = FN(env, base + (off << scale), ra); \
75
+
137
+ } \
76
+ n = f16mop_adj_pair(n, prow, neg);
138
+ d[i] = mm; \
77
+
139
+ } \
78
+ for (col = 0; col < oprsz; ) {
79
+ uint16_t pcol = pm[H2(col >> 4)];
80
+ do {
81
+ if (prow & pcol & 0b0101) {
82
+ uint32_t *a = vza_row + H1_4(col);
83
+ uint32_t m = *(uint32_t *)(vzm + H1_4(col));
84
+
85
+ m = f16mop_adj_pair(m, pcol, 0);
86
+ *a = bfdotadd(*a, n, m);
87
+
88
+ col += 4;
89
+ pcol >>= 4;
90
+ }
91
+ } while (col & 15);
92
+ }
93
+ row += 4;
94
+ prow >>= 4;
95
+ } while (row & 15);
96
+ }
140
+}
97
+}
98
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/target/arm/translate-sme.c
101
+++ b/target/arm/translate-sme.c
102
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(ADDVA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addva_s)
103
TRANS_FEAT(ADDHA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addha_d)
104
TRANS_FEAT(ADDVA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addva_d)
105
106
+static bool do_outprod(DisasContext *s, arg_op *a, MemOp esz,
107
+ gen_helper_gvec_5 *fn)
108
+{
109
+ int svl = streaming_vec_reg_size(s);
110
+ uint32_t desc = simd_desc(svl, svl, a->sub);
111
+ TCGv_ptr za, zn, zm, pn, pm;
141
+
112
+
142
+DO_LD1_ZPZ_S(sve_ldbsu_zsu, uint32_t, uint8_t, cpu_ldub_data_ra)
113
+ if (!sme_smza_enabled_check(s)) {
143
+DO_LD1_ZPZ_S(sve_ldhsu_zsu, uint32_t, uint16_t, cpu_lduw_data_ra)
144
+DO_LD1_ZPZ_S(sve_ldssu_zsu, uint32_t, uint32_t, cpu_ldl_data_ra)
145
+DO_LD1_ZPZ_S(sve_ldbss_zsu, uint32_t, int8_t, cpu_ldub_data_ra)
146
+DO_LD1_ZPZ_S(sve_ldhss_zsu, uint32_t, int16_t, cpu_lduw_data_ra)
147
+
148
+DO_LD1_ZPZ_S(sve_ldbsu_zss, int32_t, uint8_t, cpu_ldub_data_ra)
149
+DO_LD1_ZPZ_S(sve_ldhsu_zss, int32_t, uint16_t, cpu_lduw_data_ra)
150
+DO_LD1_ZPZ_S(sve_ldssu_zss, int32_t, uint32_t, cpu_ldl_data_ra)
151
+DO_LD1_ZPZ_S(sve_ldbss_zss, int32_t, int8_t, cpu_ldub_data_ra)
152
+DO_LD1_ZPZ_S(sve_ldhss_zss, int32_t, int16_t, cpu_lduw_data_ra)
153
+
154
+DO_LD1_ZPZ_D(sve_ldbdu_zsu, uint32_t, uint8_t, cpu_ldub_data_ra)
155
+DO_LD1_ZPZ_D(sve_ldhdu_zsu, uint32_t, uint16_t, cpu_lduw_data_ra)
156
+DO_LD1_ZPZ_D(sve_ldsdu_zsu, uint32_t, uint32_t, cpu_ldl_data_ra)
157
+DO_LD1_ZPZ_D(sve_ldddu_zsu, uint32_t, uint64_t, cpu_ldq_data_ra)
158
+DO_LD1_ZPZ_D(sve_ldbds_zsu, uint32_t, int8_t, cpu_ldub_data_ra)
159
+DO_LD1_ZPZ_D(sve_ldhds_zsu, uint32_t, int16_t, cpu_lduw_data_ra)
160
+DO_LD1_ZPZ_D(sve_ldsds_zsu, uint32_t, int32_t, cpu_ldl_data_ra)
161
+
162
+DO_LD1_ZPZ_D(sve_ldbdu_zss, int32_t, uint8_t, cpu_ldub_data_ra)
163
+DO_LD1_ZPZ_D(sve_ldhdu_zss, int32_t, uint16_t, cpu_lduw_data_ra)
164
+DO_LD1_ZPZ_D(sve_ldsdu_zss, int32_t, uint32_t, cpu_ldl_data_ra)
165
+DO_LD1_ZPZ_D(sve_ldddu_zss, int32_t, uint64_t, cpu_ldq_data_ra)
166
+DO_LD1_ZPZ_D(sve_ldbds_zss, int32_t, int8_t, cpu_ldub_data_ra)
167
+DO_LD1_ZPZ_D(sve_ldhds_zss, int32_t, int16_t, cpu_lduw_data_ra)
168
+DO_LD1_ZPZ_D(sve_ldsds_zss, int32_t, int32_t, cpu_ldl_data_ra)
169
+
170
+DO_LD1_ZPZ_D(sve_ldbdu_zd, uint64_t, uint8_t, cpu_ldub_data_ra)
171
+DO_LD1_ZPZ_D(sve_ldhdu_zd, uint64_t, uint16_t, cpu_lduw_data_ra)
172
+DO_LD1_ZPZ_D(sve_ldsdu_zd, uint64_t, uint32_t, cpu_ldl_data_ra)
173
+DO_LD1_ZPZ_D(sve_ldddu_zd, uint64_t, uint64_t, cpu_ldq_data_ra)
174
+DO_LD1_ZPZ_D(sve_ldbds_zd, uint64_t, int8_t, cpu_ldub_data_ra)
175
+DO_LD1_ZPZ_D(sve_ldhds_zd, uint64_t, int16_t, cpu_lduw_data_ra)
176
+DO_LD1_ZPZ_D(sve_ldsds_zd, uint64_t, int32_t, cpu_ldl_data_ra)
177
+
178
/* Stores with a vector index. */
179
180
#define DO_ST1_ZPZ_S(NAME, TYPEI, FN) \
181
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/target/arm/translate-sve.c
184
+++ b/target/arm/translate-sve.c
185
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm, int scale,
186
tcg_temp_free_i32(desc);
187
}
188
189
+/* Indexed by [ff][xs][u][msz]. */
190
+static gen_helper_gvec_mem_scatter * const gather_load_fn32[2][2][2][3] = {
191
+ { { { gen_helper_sve_ldbss_zsu,
192
+ gen_helper_sve_ldhss_zsu,
193
+ NULL, },
194
+ { gen_helper_sve_ldbsu_zsu,
195
+ gen_helper_sve_ldhsu_zsu,
196
+ gen_helper_sve_ldssu_zsu, } },
197
+ { { gen_helper_sve_ldbss_zss,
198
+ gen_helper_sve_ldhss_zss,
199
+ NULL, },
200
+ { gen_helper_sve_ldbsu_zss,
201
+ gen_helper_sve_ldhsu_zss,
202
+ gen_helper_sve_ldssu_zss, } } },
203
+ /* TODO fill in first-fault handlers */
204
+};
205
+
206
+/* Note that we overload xs=2 to indicate 64-bit offset. */
207
+static gen_helper_gvec_mem_scatter * const gather_load_fn64[2][3][2][4] = {
208
+ { { { gen_helper_sve_ldbds_zsu,
209
+ gen_helper_sve_ldhds_zsu,
210
+ gen_helper_sve_ldsds_zsu,
211
+ NULL, },
212
+ { gen_helper_sve_ldbdu_zsu,
213
+ gen_helper_sve_ldhdu_zsu,
214
+ gen_helper_sve_ldsdu_zsu,
215
+ gen_helper_sve_ldddu_zsu, } },
216
+ { { gen_helper_sve_ldbds_zss,
217
+ gen_helper_sve_ldhds_zss,
218
+ gen_helper_sve_ldsds_zss,
219
+ NULL, },
220
+ { gen_helper_sve_ldbdu_zss,
221
+ gen_helper_sve_ldhdu_zss,
222
+ gen_helper_sve_ldsdu_zss,
223
+ gen_helper_sve_ldddu_zss, } },
224
+ { { gen_helper_sve_ldbds_zd,
225
+ gen_helper_sve_ldhds_zd,
226
+ gen_helper_sve_ldsds_zd,
227
+ NULL, },
228
+ { gen_helper_sve_ldbdu_zd,
229
+ gen_helper_sve_ldhdu_zd,
230
+ gen_helper_sve_ldsdu_zd,
231
+ gen_helper_sve_ldddu_zd, } } },
232
+ /* TODO fill in first-fault handlers */
233
+};
234
+
235
+static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn)
236
+{
237
+ gen_helper_gvec_mem_scatter *fn = NULL;
238
+
239
+ if (!sve_access_check(s)) {
240
+ return true;
114
+ return true;
241
+ }
115
+ }
242
+
116
+
243
+ switch (a->esz) {
117
+ /* Sum XZR+zad to find ZAd. */
244
+ case MO_32:
118
+ za = get_tile_rowcol(s, esz, 31, a->zad, false);
245
+ fn = gather_load_fn32[a->ff][a->xs][a->u][a->msz];
119
+ zn = vec_full_reg_ptr(s, a->zn);
246
+ break;
120
+ zm = vec_full_reg_ptr(s, a->zm);
247
+ case MO_64:
121
+ pn = pred_full_reg_ptr(s, a->pn);
248
+ fn = gather_load_fn64[a->ff][a->xs][a->u][a->msz];
122
+ pm = pred_full_reg_ptr(s, a->pm);
249
+ break;
250
+ }
251
+ assert(fn != NULL);
252
+
123
+
253
+ do_mem_zpz(s, a->rd, a->pg, a->rm, a->scale * a->msz,
124
+ fn(za, zn, zm, pn, pm, tcg_constant_i32(desc));
254
+ cpu_reg_sp(s, a->rn), fn);
125
+
126
+ tcg_temp_free_ptr(za);
127
+ tcg_temp_free_ptr(zn);
128
+ tcg_temp_free_ptr(pn);
129
+ tcg_temp_free_ptr(pm);
255
+ return true;
130
+ return true;
256
+}
131
+}
257
+
132
+
258
+static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a, uint32_t insn)
133
static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
259
+{
134
gen_helper_gvec_5_ptr *fn)
260
+ gen_helper_gvec_mem_scatter *fn = NULL;
135
{
261
+ TCGv_i64 imm;
136
@@ -XXX,XX +XXX,XX @@ static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
137
138
TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_s)
139
TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_fmopa_d)
262
+
140
+
263
+ if (a->esz < a->msz || (a->esz == a->msz && !a->u)) {
141
+/* TODO: FEAT_EBF16 */
264
+ return false;
142
+TRANS_FEAT(BFMOPA, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_bfmopa)
265
+ }
266
+ if (!sve_access_check(s)) {
267
+ return true;
268
+ }
269
+
270
+ switch (a->esz) {
271
+ case MO_32:
272
+ fn = gather_load_fn32[a->ff][0][a->u][a->msz];
273
+ break;
274
+ case MO_64:
275
+ fn = gather_load_fn64[a->ff][2][a->u][a->msz];
276
+ break;
277
+ }
278
+ assert(fn != NULL);
279
+
280
+ /* Treat LD1_zpiz (zn[x] + imm) the same way as LD1_zprz (rn + zm[x])
281
+ * by loading the immediate into the scalar parameter.
282
+ */
283
+ imm = tcg_const_i64(a->imm << a->msz);
284
+ do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, fn);
285
+ tcg_temp_free_i64(imm);
286
+ return true;
287
+}
288
+
289
static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
290
{
291
/* Indexed by [xs][msz]. */
292
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
293
index XXXXXXX..XXXXXXX 100644
294
--- a/target/arm/sve.decode
295
+++ b/target/arm/sve.decode
296
@@ -XXX,XX +XXX,XX @@
297
&rpri_load rd pg rn imm dtype nreg
298
&rprr_store rd pg rn rm msz esz nreg
299
&rpri_store rd pg rn imm msz esz nreg
300
+&rprr_gather_load rd pg rn rm esz msz u ff xs scale
301
+&rpri_gather_load rd pg rn imm esz msz u ff
302
&rprr_scatter_store rd pg rn rm esz msz xs scale
303
304
###########################################################################
305
@@ -XXX,XX +XXX,XX @@
306
@rpri_load_msz ....... .... . imm:s4 ... pg:3 rn:5 rd:5 \
307
&rpri_load dtype=%msz_dtype
308
309
+# Gather Loads.
310
+@rprr_g_load_u ....... .. . . rm:5 . u:1 ff:1 pg:3 rn:5 rd:5 \
311
+ &rprr_gather_load xs=2
312
+@rprr_g_load_xs_u ....... .. xs:1 . rm:5 . u:1 ff:1 pg:3 rn:5 rd:5 \
313
+ &rprr_gather_load
314
+@rprr_g_load_xs_u_sc ....... .. xs:1 scale:1 rm:5 . u:1 ff:1 pg:3 rn:5 rd:5 \
315
+ &rprr_gather_load
316
+@rprr_g_load_xs_sc ....... .. xs:1 scale:1 rm:5 . . ff:1 pg:3 rn:5 rd:5 \
317
+ &rprr_gather_load
318
+@rprr_g_load_u_sc ....... .. . scale:1 rm:5 . u:1 ff:1 pg:3 rn:5 rd:5 \
319
+ &rprr_gather_load xs=2
320
+@rprr_g_load_sc ....... .. . scale:1 rm:5 . . ff:1 pg:3 rn:5 rd:5 \
321
+ &rprr_gather_load xs=2
322
+@rpri_g_load ....... msz:2 .. imm:5 . u:1 ff:1 pg:3 rn:5 rd:5 \
323
+ &rpri_gather_load
324
+
325
# Stores; user must fill in ESZ, MSZ, NREG as needed.
326
@rprr_store ....... .. .. rm:5 ... pg:3 rn:5 rd:5 &rprr_store
327
@rpri_store_msz ....... msz:2 .. . imm:s4 ... pg:3 rn:5 rd:5 &rpri_store
328
@@ -XXX,XX +XXX,XX @@ LDR_zri 10000101 10 ...... 010 ... ..... ..... @rd_rn_i9
329
LD1R_zpri 1000010 .. 1 imm:6 1.. pg:3 rn:5 rd:5 \
330
&rpri_load dtype=%dtype_23_13 nreg=0
331
332
+# SVE 32-bit gather load (scalar plus 32-bit unscaled offsets)
333
+# SVE 32-bit gather load (scalar plus 32-bit scaled offsets)
334
+LD1_zprz 1000010 00 .0 ..... 0.. ... ..... ..... \
335
+ @rprr_g_load_xs_u esz=2 msz=0 scale=0
336
+LD1_zprz 1000010 01 .. ..... 0.. ... ..... ..... \
337
+ @rprr_g_load_xs_u_sc esz=2 msz=1
338
+LD1_zprz 1000010 10 .. ..... 01. ... ..... ..... \
339
+ @rprr_g_load_xs_sc esz=2 msz=2 u=1
340
+
341
+# SVE 32-bit gather load (vector plus immediate)
342
+LD1_zpiz 1000010 .. 01 ..... 1.. ... ..... ..... \
343
+ @rpri_g_load esz=2
344
+
345
### SVE Memory Contiguous Load Group
346
347
# SVE contiguous load (scalar plus scalar)
348
@@ -XXX,XX +XXX,XX @@ PRF_rr 1000010 -- 00 rm:5 110 --- ----- 0 ----
349
350
### SVE Memory 64-bit Gather Group
351
352
+# SVE 64-bit gather load (scalar plus 32-bit unpacked unscaled offsets)
353
+# SVE 64-bit gather load (scalar plus 32-bit unpacked scaled offsets)
354
+LD1_zprz 1100010 00 .0 ..... 0.. ... ..... ..... \
355
+ @rprr_g_load_xs_u esz=3 msz=0 scale=0
356
+LD1_zprz 1100010 01 .. ..... 0.. ... ..... ..... \
357
+ @rprr_g_load_xs_u_sc esz=3 msz=1
358
+LD1_zprz 1100010 10 .. ..... 0.. ... ..... ..... \
359
+ @rprr_g_load_xs_u_sc esz=3 msz=2
360
+LD1_zprz 1100010 11 .. ..... 01. ... ..... ..... \
361
+ @rprr_g_load_xs_sc esz=3 msz=3 u=1
362
+
363
+# SVE 64-bit gather load (scalar plus 64-bit unscaled offsets)
364
+# SVE 64-bit gather load (scalar plus 64-bit scaled offsets)
365
+LD1_zprz 1100010 00 10 ..... 1.. ... ..... ..... \
366
+ @rprr_g_load_u esz=3 msz=0 scale=0
367
+LD1_zprz 1100010 01 1. ..... 1.. ... ..... ..... \
368
+ @rprr_g_load_u_sc esz=3 msz=1
369
+LD1_zprz 1100010 10 1. ..... 1.. ... ..... ..... \
370
+ @rprr_g_load_u_sc esz=3 msz=2
371
+LD1_zprz 1100010 11 1. ..... 11. ... ..... ..... \
372
+ @rprr_g_load_sc esz=3 msz=3 u=1
373
+
374
+# SVE 64-bit gather load (vector plus immediate)
375
+LD1_zpiz 1100010 .. 01 ..... 1.. ... ..... ..... \
376
+ @rpri_g_load esz=3
377
+
378
# SVE 64-bit gather prefetch (scalar plus 64-bit scaled offsets)
379
PRF 1100010 00 11 ----- 1-- --- ----- 0 ----
380
381
--
143
--
382
2.17.1
144
2.25.1
383
384
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20220708151540.18136-27-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-24-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
7
---
8
target/arm/helper-sve.h | 13 +++++++++
8
target/arm/helper-sme.h | 2 ++
9
target/arm/sve_helper.c | 55 ++++++++++++++++++++++++++++++++++++++
9
target/arm/sme.decode | 1 +
10
target/arm/translate-sve.c | 30 +++++++++++++++++++++
10
target/arm/sme_helper.c | 74 ++++++++++++++++++++++++++++++++++++++
11
target/arm/sve.decode | 8 ++++++
11
target/arm/translate-sme.c | 1 +
12
4 files changed, 106 insertions(+)
12
4 files changed, 78 insertions(+)
13
13
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
14
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
16
--- a/target/arm/helper-sme.h
17
+++ b/target/arm/helper-sve.h
17
+++ b/target/arm/helper-sme.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(sve_fmins_s, TCG_CALL_NO_RWG,
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
19
DEF_HELPER_FLAGS_6(sve_fmins_d, TCG_CALL_NO_RWG,
19
DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
20
void, ptr, ptr, ptr, i64, ptr, i32)
20
DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
21
21
22
+DEF_HELPER_FLAGS_5(sve_fcvt_sh, TCG_CALL_NO_RWG,
22
+DEF_HELPER_FLAGS_7(sme_fmopa_h, TCG_CALL_NO_RWG,
23
+ void, ptr, ptr, ptr, ptr, i32)
23
+ void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_5(sve_fcvt_dh, TCG_CALL_NO_RWG,
24
DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
25
+ void, ptr, ptr, ptr, ptr, i32)
25
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_5(sve_fcvt_hs, TCG_CALL_NO_RWG,
26
DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
27
+ void, ptr, ptr, ptr, ptr, i32)
27
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
28
+DEF_HELPER_FLAGS_5(sve_fcvt_ds, TCG_CALL_NO_RWG,
28
index XXXXXXX..XXXXXXX 100644
29
+ void, ptr, ptr, ptr, ptr, i32)
29
--- a/target/arm/sme.decode
30
+DEF_HELPER_FLAGS_5(sve_fcvt_hd, TCG_CALL_NO_RWG,
30
+++ b/target/arm/sme.decode
31
+ void, ptr, ptr, ptr, ptr, i32)
31
@@ -XXX,XX +XXX,XX @@ FMOPA_s 10000000 100 ..... ... ... ..... . 00 .. @op_32
32
+DEF_HELPER_FLAGS_5(sve_fcvt_sd, TCG_CALL_NO_RWG,
32
FMOPA_d 10000000 110 ..... ... ... ..... . 0 ... @op_64
33
+ void, ptr, ptr, ptr, ptr, i32)
33
34
BFMOPA 10000001 100 ..... ... ... ..... . 00 .. @op_32
35
+FMOPA_h 10000001 101 ..... ... ... ..... . 00 .. @op_32
36
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/sme_helper.c
39
+++ b/target/arm/sme_helper.c
40
@@ -XXX,XX +XXX,XX @@ static inline uint32_t f16mop_adj_pair(uint32_t pair, uint32_t pg, uint32_t neg)
41
return pair;
42
}
43
44
+static float32 f16_dotadd(float32 sum, uint32_t e1, uint32_t e2,
45
+ float_status *s_std, float_status *s_odd)
46
+{
47
+ float64 e1r = float16_to_float64(e1 & 0xffff, true, s_std);
48
+ float64 e1c = float16_to_float64(e1 >> 16, true, s_std);
49
+ float64 e2r = float16_to_float64(e2 & 0xffff, true, s_std);
50
+ float64 e2c = float16_to_float64(e2 >> 16, true, s_std);
51
+ float64 t64;
52
+ float32 t32;
34
+
53
+
35
DEF_HELPER_FLAGS_5(sve_scvt_hh, TCG_CALL_NO_RWG,
54
+ /*
36
void, ptr, ptr, ptr, ptr, i32)
55
+ * The ARM pseudocode function FPDot performs both multiplies
37
DEF_HELPER_FLAGS_5(sve_scvt_sh, TCG_CALL_NO_RWG,
56
+ * and the add with a single rounding operation. Emulate this
38
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
57
+ * by performing the first multiply in round-to-odd, then doing
39
index XXXXXXX..XXXXXXX 100644
58
+ * the second multiply as fused multiply-add, and rounding to
40
--- a/target/arm/sve_helper.c
59
+ * float32 all in one step.
41
+++ b/target/arm/sve_helper.c
60
+ */
42
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vg, void *status, uint32_t desc) \
61
+ t64 = float64_mul(e1r, e2r, s_odd);
43
} while (i != 0); \
62
+ t64 = float64r32_muladd(e1c, e2c, t64, 0, s_std);
44
}
45
46
+/* SVE fp16 conversions always use IEEE mode. Like AdvSIMD, they ignore
47
+ * FZ16. When converting from fp16, this affects flushing input denormals;
48
+ * when converting to fp16, this affects flushing output denormals.
49
+ */
50
+static inline float32 sve_f16_to_f32(float16 f, float_status *fpst)
51
+{
52
+ flag save = get_flush_inputs_to_zero(fpst);
53
+ float32 ret;
54
+
63
+
55
+ set_flush_inputs_to_zero(false, fpst);
64
+ /* This conversion is exact, because we've already rounded. */
56
+ ret = float16_to_float32(f, true, fpst);
65
+ t32 = float64_to_float32(t64, s_std);
57
+ set_flush_inputs_to_zero(save, fpst);
66
+
58
+ return ret;
67
+ /* The final accumulation step is not fused. */
68
+ return float32_add(sum, t32, s_std);
59
+}
69
+}
60
+
70
+
61
+static inline float64 sve_f16_to_f64(float16 f, float_status *fpst)
71
+void HELPER(sme_fmopa_h)(void *vza, void *vzn, void *vzm, void *vpn,
72
+ void *vpm, void *vst, uint32_t desc)
62
+{
73
+{
63
+ flag save = get_flush_inputs_to_zero(fpst);
74
+ intptr_t row, col, oprsz = simd_maxsz(desc);
64
+ float64 ret;
75
+ uint32_t neg = simd_data(desc) * 0x80008000u;
76
+ uint16_t *pn = vpn, *pm = vpm;
77
+ float_status fpst_odd, fpst_std;
65
+
78
+
66
+ set_flush_inputs_to_zero(false, fpst);
79
+ /*
67
+ ret = float16_to_float64(f, true, fpst);
80
+ * Make a copy of float_status because this operation does not
68
+ set_flush_inputs_to_zero(save, fpst);
81
+ * update the cumulative fp exception status. It also produces
69
+ return ret;
82
+ * default nans. Make a second copy with round-to-odd -- see above.
83
+ */
84
+ fpst_std = *(float_status *)vst;
85
+ set_default_nan_mode(true, &fpst_std);
86
+ fpst_odd = fpst_std;
87
+ set_float_rounding_mode(float_round_to_odd, &fpst_odd);
88
+
89
+ for (row = 0; row < oprsz; ) {
90
+ uint16_t prow = pn[H2(row >> 4)];
91
+ do {
92
+ void *vza_row = vza + tile_vslice_offset(row);
93
+ uint32_t n = *(uint32_t *)(vzn + H1_4(row));
94
+
95
+ n = f16mop_adj_pair(n, prow, neg);
96
+
97
+ for (col = 0; col < oprsz; ) {
98
+ uint16_t pcol = pm[H2(col >> 4)];
99
+ do {
100
+ if (prow & pcol & 0b0101) {
101
+ uint32_t *a = vza_row + H1_4(col);
102
+ uint32_t m = *(uint32_t *)(vzm + H1_4(col));
103
+
104
+ m = f16mop_adj_pair(m, pcol, 0);
105
+ *a = f16_dotadd(*a, n, m, &fpst_std, &fpst_odd);
106
+
107
+ col += 4;
108
+ pcol >>= 4;
109
+ }
110
+ } while (col & 15);
111
+ }
112
+ row += 4;
113
+ prow >>= 4;
114
+ } while (row & 15);
115
+ }
70
+}
116
+}
71
+
117
+
72
+static inline float16 sve_f32_to_f16(float32 f, float_status *fpst)
118
void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
73
+{
119
void *vpm, uint32_t desc)
74
+ flag save = get_flush_to_zero(fpst);
120
{
75
+ float16 ret;
121
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
76
+
77
+ set_flush_to_zero(false, fpst);
78
+ ret = float32_to_float16(f, true, fpst);
79
+ set_flush_to_zero(save, fpst);
80
+ return ret;
81
+}
82
+
83
+static inline float16 sve_f64_to_f16(float64 f, float_status *fpst)
84
+{
85
+ flag save = get_flush_to_zero(fpst);
86
+ float16 ret;
87
+
88
+ set_flush_to_zero(false, fpst);
89
+ ret = float64_to_float16(f, true, fpst);
90
+ set_flush_to_zero(save, fpst);
91
+ return ret;
92
+}
93
+
94
+DO_ZPZ_FP(sve_fcvt_sh, uint32_t, H1_4, sve_f32_to_f16)
95
+DO_ZPZ_FP(sve_fcvt_hs, uint32_t, H1_4, sve_f16_to_f32)
96
+DO_ZPZ_FP(sve_fcvt_dh, uint64_t, , sve_f64_to_f16)
97
+DO_ZPZ_FP(sve_fcvt_hd, uint64_t, , sve_f16_to_f64)
98
+DO_ZPZ_FP(sve_fcvt_ds, uint64_t, , float64_to_float32)
99
+DO_ZPZ_FP(sve_fcvt_sd, uint64_t, , float32_to_float64)
100
+
101
DO_ZPZ_FP(sve_scvt_hh, uint16_t, H1_2, int16_to_float16)
102
DO_ZPZ_FP(sve_scvt_sh, uint32_t, H1_4, int32_to_float16)
103
DO_ZPZ_FP(sve_scvt_ss, uint32_t, H1_4, int32_to_float32)
104
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
105
index XXXXXXX..XXXXXXX 100644
122
index XXXXXXX..XXXXXXX 100644
106
--- a/target/arm/translate-sve.c
123
--- a/target/arm/translate-sme.c
107
+++ b/target/arm/translate-sve.c
124
+++ b/target/arm/translate-sme.c
108
@@ -XXX,XX +XXX,XX @@ static bool do_zpz_ptr(DisasContext *s, int rd, int rn, int pg,
125
@@ -XXX,XX +XXX,XX @@ static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
109
return true;
126
return true;
110
}
127
}
111
128
112
+static bool trans_FCVT_sh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
129
+TRANS_FEAT(FMOPA_h, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_h)
113
+{
130
TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst, a, MO_32, gen_helper_sme_fmopa_s)
114
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvt_sh);
131
TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_fmopa_d)
115
+}
132
116
+
117
+static bool trans_FCVT_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
118
+{
119
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_hs);
120
+}
121
+
122
+static bool trans_FCVT_dh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
123
+{
124
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvt_dh);
125
+}
126
+
127
+static bool trans_FCVT_hd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
128
+{
129
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_hd);
130
+}
131
+
132
+static bool trans_FCVT_ds(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
133
+{
134
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_ds);
135
+}
136
+
137
+static bool trans_FCVT_sd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
138
+{
139
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_sd);
140
+}
141
+
142
static bool trans_SCVTF_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
143
{
144
return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_scvt_hh);
145
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
146
index XXXXXXX..XXXXXXX 100644
147
--- a/target/arm/sve.decode
148
+++ b/target/arm/sve.decode
149
@@ -XXX,XX +XXX,XX @@ FNMLS_zpzzz 01100101 .. 1 ..... 111 ... ..... ..... @rdn_pg_rm_ra
150
151
### SVE FP Unary Operations Predicated Group
152
153
+# SVE floating-point convert precision
154
+FCVT_sh 01100101 10 0010 00 101 ... ..... ..... @rd_pg_rn_e0
155
+FCVT_hs 01100101 10 0010 01 101 ... ..... ..... @rd_pg_rn_e0
156
+FCVT_dh 01100101 11 0010 00 101 ... ..... ..... @rd_pg_rn_e0
157
+FCVT_hd 01100101 11 0010 01 101 ... ..... ..... @rd_pg_rn_e0
158
+FCVT_ds 01100101 11 0010 10 101 ... ..... ..... @rd_pg_rn_e0
159
+FCVT_sd 01100101 11 0010 11 101 ... ..... ..... @rd_pg_rn_e0
160
+
161
# SVE integer convert to floating-point
162
SCVTF_hh 01100101 01 010 01 0 101 ... ..... ..... @rd_pg_rn_e0
163
SCVTF_sh 01100101 01 010 10 0 101 ... ..... ..... @rd_pg_rn_e0
164
--
133
--
165
2.17.1
134
2.25.1
166
167
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
This is SMOPA, SUMOPA, USMOPA_s, UMOPA, for both Int8 and Int16.
2
4
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-5-richard.henderson@linaro.org
7
Message-id: 20220708151540.18136-28-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
9
---
8
target/arm/translate-sve.c | 52 ++++++++++++++++++++++++++++++++++++++
10
target/arm/helper-sme.h | 16 ++++++++
9
target/arm/sve.decode | 9 +++++++
11
target/arm/sme.decode | 10 +++++
10
2 files changed, 61 insertions(+)
12
target/arm/sme_helper.c | 82 ++++++++++++++++++++++++++++++++++++++
13
target/arm/translate-sme.c | 10 +++++
14
4 files changed, 118 insertions(+)
11
15
12
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
16
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-sve.c
18
--- a/target/arm/helper-sme.h
15
+++ b/target/arm/translate-sve.c
19
+++ b/target/arm/helper-sme.h
16
@@ -XXX,XX +XXX,XX @@ static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
17
return true;
21
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
22
DEF_HELPER_FLAGS_6(sme_bfmopa, TCG_CALL_NO_RWG,
23
void, ptr, ptr, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_6(sme_smopa_s, TCG_CALL_NO_RWG,
25
+ void, ptr, ptr, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_6(sme_umopa_s, TCG_CALL_NO_RWG,
27
+ void, ptr, ptr, ptr, ptr, ptr, i32)
28
+DEF_HELPER_FLAGS_6(sme_sumopa_s, TCG_CALL_NO_RWG,
29
+ void, ptr, ptr, ptr, ptr, ptr, i32)
30
+DEF_HELPER_FLAGS_6(sme_usmopa_s, TCG_CALL_NO_RWG,
31
+ void, ptr, ptr, ptr, ptr, ptr, i32)
32
+DEF_HELPER_FLAGS_6(sme_smopa_d, TCG_CALL_NO_RWG,
33
+ void, ptr, ptr, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_6(sme_umopa_d, TCG_CALL_NO_RWG,
35
+ void, ptr, ptr, ptr, ptr, ptr, i32)
36
+DEF_HELPER_FLAGS_6(sme_sumopa_d, TCG_CALL_NO_RWG,
37
+ void, ptr, ptr, ptr, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_6(sme_usmopa_d, TCG_CALL_NO_RWG,
39
+ void, ptr, ptr, ptr, ptr, ptr, i32)
40
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/sme.decode
43
+++ b/target/arm/sme.decode
44
@@ -XXX,XX +XXX,XX @@ FMOPA_d 10000000 110 ..... ... ... ..... . 0 ... @op_64
45
46
BFMOPA 10000001 100 ..... ... ... ..... . 00 .. @op_32
47
FMOPA_h 10000001 101 ..... ... ... ..... . 00 .. @op_32
48
+
49
+SMOPA_s 1010000 0 10 0 ..... ... ... ..... . 00 .. @op_32
50
+SUMOPA_s 1010000 0 10 1 ..... ... ... ..... . 00 .. @op_32
51
+USMOPA_s 1010000 1 10 0 ..... ... ... ..... . 00 .. @op_32
52
+UMOPA_s 1010000 1 10 1 ..... ... ... ..... . 00 .. @op_32
53
+
54
+SMOPA_d 1010000 0 11 0 ..... ... ... ..... . 0 ... @op_64
55
+SUMOPA_d 1010000 0 11 1 ..... ... ... ..... . 0 ... @op_64
56
+USMOPA_d 1010000 1 11 0 ..... ... ... ..... . 0 ... @op_64
57
+UMOPA_d 1010000 1 11 1 ..... ... ... ..... . 0 ... @op_64
58
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/sme_helper.c
61
+++ b/target/arm/sme_helper.c
62
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
63
} while (row & 15);
64
}
18
}
65
}
19
66
+
20
+static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz)
67
+typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
68
+
69
+static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
70
+ uint8_t *pn, uint8_t *pm,
71
+ uint32_t desc, IMOPFn *fn)
21
+{
72
+{
22
+ static gen_helper_gvec_mem * const fns[4] = {
73
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
23
+ gen_helper_sve_ld1bb_r, gen_helper_sve_ld1hh_r,
74
+ bool neg = simd_data(desc);
24
+ gen_helper_sve_ld1ss_r, gen_helper_sve_ld1dd_r,
25
+ };
26
+ unsigned vsz = vec_full_reg_size(s);
27
+ TCGv_ptr t_pg;
28
+ TCGv_i32 desc;
29
+
75
+
30
+ /* Load the first quadword using the normal predicated load helpers. */
76
+ for (row = 0; row < oprsz; ++row) {
31
+ desc = tcg_const_i32(simd_desc(16, 16, zt));
77
+ uint8_t pa = pn[H1(row)];
32
+ t_pg = tcg_temp_new_ptr();
78
+ uint64_t *za_row = &za[tile_vslice_index(row)];
79
+ uint64_t n = zn[row];
33
+
80
+
34
+ tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
81
+ for (col = 0; col < oprsz; ++col) {
35
+ fns[msz](cpu_env, t_pg, addr, desc);
82
+ uint8_t pb = pm[H1(col)];
83
+ uint64_t *a = &za_row[col];
36
+
84
+
37
+ tcg_temp_free_ptr(t_pg);
85
+ *a = fn(n, zm[col], *a, pa & pb, neg);
38
+ tcg_temp_free_i32(desc);
86
+ }
39
+
40
+ /* Replicate that first quadword. */
41
+ if (vsz > 16) {
42
+ unsigned dofs = vec_full_reg_offset(s, zt);
43
+ tcg_gen_gvec_dup_mem(4, dofs + 16, dofs, vsz - 16, vsz - 16);
44
+ }
87
+ }
45
+}
88
+}
46
+
89
+
47
+static bool trans_LD1RQ_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn)
90
+#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
48
+{
91
+static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
49
+ if (a->rm == 31) {
92
+{ \
50
+ return false;
93
+ uint32_t sum0 = 0, sum1 = 0; \
51
+ }
94
+ /* Apply P to N as a mask, making the inactive elements 0. */ \
52
+ if (sve_access_check(s)) {
95
+ n &= expand_pred_b(p); \
53
+ int msz = dtype_msz(a->dtype);
96
+ sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
54
+ TCGv_i64 addr = new_tmp_a64(s);
97
+ sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
55
+ tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), msz);
98
+ sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
56
+ tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
99
+ sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
57
+ do_ldrq(s, a->rd, a->pg, addr, msz);
100
+ sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
58
+ }
101
+ sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
59
+ return true;
102
+ sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
103
+ sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
104
+ if (neg) { \
105
+ sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1; \
106
+ } else { \
107
+ sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1; \
108
+ } \
109
+ return ((uint64_t)sum1 << 32) | sum0; \
60
+}
110
+}
61
+
111
+
62
+static bool trans_LD1RQ_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
112
+#define DEF_IMOP_64(NAME, NTYPE, MTYPE) \
63
+{
113
+static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
64
+ if (sve_access_check(s)) {
114
+{ \
65
+ TCGv_i64 addr = new_tmp_a64(s);
115
+ uint64_t sum = 0; \
66
+ tcg_gen_addi_i64(addr, cpu_reg_sp(s, a->rn), a->imm * 16);
116
+ /* Apply P to N as a mask, making the inactive elements 0. */ \
67
+ do_ldrq(s, a->rd, a->pg, addr, dtype_msz(a->dtype));
117
+ n &= expand_pred_h(p); \
68
+ }
118
+ sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
69
+ return true;
119
+ sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
120
+ sum += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
121
+ sum += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
122
+ return neg ? a - sum : a + sum; \
70
+}
123
+}
71
+
124
+
72
static void do_st_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
125
+DEF_IMOP_32(smopa_s, int8_t, int8_t)
73
int msz, int esz, int nreg)
126
+DEF_IMOP_32(umopa_s, uint8_t, uint8_t)
74
{
127
+DEF_IMOP_32(sumopa_s, int8_t, uint8_t)
75
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
128
+DEF_IMOP_32(usmopa_s, uint8_t, int8_t)
129
+
130
+DEF_IMOP_64(smopa_d, int16_t, int16_t)
131
+DEF_IMOP_64(umopa_d, uint16_t, uint16_t)
132
+DEF_IMOP_64(sumopa_d, int16_t, uint16_t)
133
+DEF_IMOP_64(usmopa_d, uint16_t, int16_t)
134
+
135
+#define DEF_IMOPH(NAME) \
136
+ void HELPER(sme_##NAME)(void *vza, void *vzn, void *vzm, void *vpn, \
137
+ void *vpm, uint32_t desc) \
138
+ { do_imopa(vza, vzn, vzm, vpn, vpm, desc, NAME); }
139
+
140
+DEF_IMOPH(smopa_s)
141
+DEF_IMOPH(umopa_s)
142
+DEF_IMOPH(sumopa_s)
143
+DEF_IMOPH(usmopa_s)
144
+DEF_IMOPH(smopa_d)
145
+DEF_IMOPH(umopa_d)
146
+DEF_IMOPH(sumopa_d)
147
+DEF_IMOPH(usmopa_d)
148
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
76
index XXXXXXX..XXXXXXX 100644
149
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/sve.decode
150
--- a/target/arm/translate-sme.c
78
+++ b/target/arm/sve.decode
151
+++ b/target/arm/translate-sme.c
79
@@ -XXX,XX +XXX,XX @@ LD_zprr 1010010 .. nreg:2 ..... 110 ... ..... ..... @rprr_load_msz
152
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, MO_64, gen_helper_sme_f
80
# LD2B, LD2H, LD2W, LD2D; etc.
153
81
LD_zpri 1010010 .. nreg:2 0.... 111 ... ..... ..... @rpri_load_msz
154
/* TODO: FEAT_EBF16 */
82
155
TRANS_FEAT(BFMOPA, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_bfmopa)
83
+# SVE load and broadcast quadword (scalar plus scalar)
84
+LD1RQ_zprr 1010010 .. 00 ..... 000 ... ..... ..... \
85
+ @rprr_load_msz nreg=0
86
+
156
+
87
+# SVE load and broadcast quadword (scalar plus immediate)
157
+TRANS_FEAT(SMOPA_s, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_smopa_s)
88
+# LD1RQB, LD1RQH, LD1RQS, LD1RQD
158
+TRANS_FEAT(UMOPA_s, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_umopa_s)
89
+LD1RQ_zpri 1010010 .. 00 0.... 001 ... ..... ..... \
159
+TRANS_FEAT(SUMOPA_s, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_sumopa_s)
90
+ @rpri_load_msz nreg=0
160
+TRANS_FEAT(USMOPA_s, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_usmopa_s)
91
+
161
+
92
### SVE Memory Store Group
162
+TRANS_FEAT(SMOPA_d, aa64_sme_i16i64, do_outprod, a, MO_64, gen_helper_sme_smopa_d)
93
163
+TRANS_FEAT(UMOPA_d, aa64_sme_i16i64, do_outprod, a, MO_64, gen_helper_sme_umopa_d)
94
# SVE contiguous store (scalar plus immediate)
164
+TRANS_FEAT(SUMOPA_d, aa64_sme_i16i64, do_outprod, a, MO_64, gen_helper_sme_sumopa_d)
165
+TRANS_FEAT(USMOPA_d, aa64_sme_i16i64, do_outprod, a, MO_64, gen_helper_sme_usmopa_d)
95
--
166
--
96
2.17.1
167
2.25.1
97
98
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
This is an SVE instruction that operates using the SVE vector
4
length but that it is present only if SME is implemented.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-9-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-29-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 7 +++++
11
target/arm/sve.decode | 20 +++++++++++++
9
target/arm/sve_helper.c | 56 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-sve.c | 57 ++++++++++++++++++++++++++++++++++++++
10
target/arm/translate-sve.c | 45 ++++++++++++++++++++++++++++++
13
2 files changed, 77 insertions(+)
11
target/arm/sve.decode | 5 ++++
12
4 files changed, 113 insertions(+)
13
14
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
17
--- a/target/arm/sve.decode
17
+++ b/target/arm/helper-sve.h
18
+++ b/target/arm/sve.decode
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_rsqrts_s, TCG_CALL_NO_RWG,
19
@@ -XXX,XX +XXX,XX @@ BFMLALT_zzxw 01100100 11 1 ..... 0100.1 ..... ..... @rrxr_3a esz=2
19
DEF_HELPER_FLAGS_5(gvec_rsqrts_d, TCG_CALL_NO_RWG,
20
20
void, ptr, ptr, ptr, ptr, i32)
21
### SVE2 floating-point bfloat16 dot-product (indexed)
21
22
BFDOT_zzxz 01100100 01 1 ..... 010000 ..... ..... @rrxr_2 esz=2
22
+DEF_HELPER_FLAGS_5(sve_fadda_h, TCG_CALL_NO_RWG,
23
+ i64, i64, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_5(sve_fadda_s, TCG_CALL_NO_RWG,
25
+ i64, i64, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_5(sve_fadda_d, TCG_CALL_NO_RWG,
27
+ i64, i64, ptr, ptr, ptr, i32)
28
+
23
+
29
DEF_HELPER_FLAGS_6(sve_fadd_h, TCG_CALL_NO_RWG,
24
+### SVE broadcast predicate element
30
void, ptr, ptr, ptr, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_6(sve_fadd_s, TCG_CALL_NO_RWG,
32
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/sve_helper.c
35
+++ b/target/arm/sve_helper.c
36
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_while)(void *vd, uint32_t count, uint32_t pred_desc)
37
return predtest_ones(d, oprsz, esz_mask);
38
}
39
40
+uint64_t HELPER(sve_fadda_h)(uint64_t nn, void *vm, void *vg,
41
+ void *status, uint32_t desc)
42
+{
43
+ intptr_t i = 0, opr_sz = simd_oprsz(desc);
44
+ float16 result = nn;
45
+
25
+
46
+ do {
26
+&psel esz pd pn pm rv imm
47
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
27
+%psel_rv 16:2 !function=plus_12
48
+ do {
28
+%psel_imm_b 22:2 19:2
49
+ if (pg & 1) {
29
+%psel_imm_h 22:2 20:1
50
+ float16 mm = *(float16 *)(vm + H1_2(i));
30
+%psel_imm_s 22:2
51
+ result = float16_add(result, mm, status);
31
+%psel_imm_d 23:1
52
+ }
32
+@psel ........ .. . ... .. .. pn:4 . pm:4 . pd:4 \
53
+ i += sizeof(float16), pg >>= sizeof(float16);
33
+ &psel rv=%psel_rv
54
+ } while (i & 15);
55
+ } while (i < opr_sz);
56
+
34
+
57
+ return result;
35
+PSEL 00100101 .. 1 ..1 .. 01 .... 0 .... 0 .... \
58
+}
36
+ @psel esz=0 imm=%psel_imm_b
59
+
37
+PSEL 00100101 .. 1 .10 .. 01 .... 0 .... 0 .... \
60
+uint64_t HELPER(sve_fadda_s)(uint64_t nn, void *vm, void *vg,
38
+ @psel esz=1 imm=%psel_imm_h
61
+ void *status, uint32_t desc)
39
+PSEL 00100101 .. 1 100 .. 01 .... 0 .... 0 .... \
62
+{
40
+ @psel esz=2 imm=%psel_imm_s
63
+ intptr_t i = 0, opr_sz = simd_oprsz(desc);
41
+PSEL 00100101 .1 1 000 .. 01 .... 0 .... 0 .... \
64
+ float32 result = nn;
42
+ @psel esz=3 imm=%psel_imm_d
65
+
66
+ do {
67
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
68
+ do {
69
+ if (pg & 1) {
70
+ float32 mm = *(float32 *)(vm + H1_2(i));
71
+ result = float32_add(result, mm, status);
72
+ }
73
+ i += sizeof(float32), pg >>= sizeof(float32);
74
+ } while (i & 15);
75
+ } while (i < opr_sz);
76
+
77
+ return result;
78
+}
79
+
80
+uint64_t HELPER(sve_fadda_d)(uint64_t nn, void *vm, void *vg,
81
+ void *status, uint32_t desc)
82
+{
83
+ intptr_t i = 0, opr_sz = simd_oprsz(desc) / 8;
84
+ uint64_t *m = vm;
85
+ uint8_t *pg = vg;
86
+
87
+ for (i = 0; i < opr_sz; i++) {
88
+ if (pg[H1(i)] & 1) {
89
+ nn = float64_add(nn, m[i], status);
90
+ }
91
+ }
92
+
93
+ return nn;
94
+}
95
+
96
/* Fully general three-operand expander, controlled by a predicate,
97
* With the extra float_status parameter.
98
*/
99
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
43
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
100
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
101
--- a/target/arm/translate-sve.c
45
--- a/target/arm/translate-sve.c
102
+++ b/target/arm/translate-sve.c
46
+++ b/target/arm/translate-sve.c
103
@@ -XXX,XX +XXX,XX @@ DO_ZZI(UMIN, umin)
47
@@ -XXX,XX +XXX,XX @@ static bool do_BFMLAL_zzxw(DisasContext *s, arg_rrxr_esz *a, bool sel)
104
48
105
#undef DO_ZZI
49
TRANS_FEAT(BFMLALB_zzxw, aa64_sve_bf16, do_BFMLAL_zzxw, a, false)
106
50
TRANS_FEAT(BFMLALT_zzxw, aa64_sve_bf16, do_BFMLAL_zzxw, a, true)
107
+/*
108
+ *** SVE Floating Point Accumulating Reduction Group
109
+ */
110
+
51
+
111
+static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a, uint32_t insn)
52
+static bool trans_PSEL(DisasContext *s, arg_psel *a)
112
+{
53
+{
113
+ typedef void fadda_fn(TCGv_i64, TCGv_i64, TCGv_ptr,
54
+ int vl = vec_full_reg_size(s);
114
+ TCGv_ptr, TCGv_ptr, TCGv_i32);
55
+ int pl = pred_gvec_reg_size(s);
115
+ static fadda_fn * const fns[3] = {
56
+ int elements = vl >> a->esz;
116
+ gen_helper_sve_fadda_h,
57
+ TCGv_i64 tmp, didx, dbit;
117
+ gen_helper_sve_fadda_s,
58
+ TCGv_ptr ptr;
118
+ gen_helper_sve_fadda_d,
119
+ };
120
+ unsigned vsz = vec_full_reg_size(s);
121
+ TCGv_ptr t_rm, t_pg, t_fpst;
122
+ TCGv_i64 t_val;
123
+ TCGv_i32 t_desc;
124
+
59
+
125
+ if (a->esz == 0) {
60
+ if (!dc_isar_feature(aa64_sme, s)) {
126
+ return false;
61
+ return false;
127
+ }
62
+ }
128
+ if (!sve_access_check(s)) {
63
+ if (!sve_access_check(s)) {
129
+ return true;
64
+ return true;
130
+ }
65
+ }
131
+
66
+
132
+ t_val = load_esz(cpu_env, vec_reg_offset(s, a->rn, 0, a->esz), a->esz);
67
+ tmp = tcg_temp_new_i64();
133
+ t_rm = tcg_temp_new_ptr();
68
+ dbit = tcg_temp_new_i64();
134
+ t_pg = tcg_temp_new_ptr();
69
+ didx = tcg_temp_new_i64();
135
+ tcg_gen_addi_ptr(t_rm, cpu_env, vec_full_reg_offset(s, a->rm));
70
+ ptr = tcg_temp_new_ptr();
136
+ tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, a->pg));
137
+ t_fpst = get_fpstatus_ptr(a->esz == MO_16);
138
+ t_desc = tcg_const_i32(simd_desc(vsz, vsz, 0));
139
+
71
+
140
+ fns[a->esz - 1](t_val, t_val, t_rm, t_pg, t_fpst, t_desc);
72
+ /* Compute the predicate element. */
73
+ tcg_gen_addi_i64(tmp, cpu_reg(s, a->rv), a->imm);
74
+ if (is_power_of_2(elements)) {
75
+ tcg_gen_andi_i64(tmp, tmp, elements - 1);
76
+ } else {
77
+ tcg_gen_remu_i64(tmp, tmp, tcg_constant_i64(elements));
78
+ }
141
+
79
+
142
+ tcg_temp_free_i32(t_desc);
80
+ /* Extract the predicate byte and bit indices. */
143
+ tcg_temp_free_ptr(t_fpst);
81
+ tcg_gen_shli_i64(tmp, tmp, a->esz);
144
+ tcg_temp_free_ptr(t_pg);
82
+ tcg_gen_andi_i64(dbit, tmp, 7);
145
+ tcg_temp_free_ptr(t_rm);
83
+ tcg_gen_shri_i64(didx, tmp, 3);
84
+ if (HOST_BIG_ENDIAN) {
85
+ tcg_gen_xori_i64(didx, didx, 7);
86
+ }
146
+
87
+
147
+ write_fp_dreg(s, a->rd, t_val);
88
+ /* Load the predicate word. */
148
+ tcg_temp_free_i64(t_val);
89
+ tcg_gen_trunc_i64_ptr(ptr, didx);
90
+ tcg_gen_add_ptr(ptr, ptr, cpu_env);
91
+ tcg_gen_ld8u_i64(tmp, ptr, pred_full_reg_offset(s, a->pm));
92
+
93
+ /* Extract the predicate bit and replicate to MO_64. */
94
+ tcg_gen_shr_i64(tmp, tmp, dbit);
95
+ tcg_gen_andi_i64(tmp, tmp, 1);
96
+ tcg_gen_neg_i64(tmp, tmp);
97
+
98
+ /* Apply to either copy the source, or write zeros. */
99
+ tcg_gen_gvec_ands(MO_64, pred_full_reg_offset(s, a->pd),
100
+ pred_full_reg_offset(s, a->pn), tmp, pl, pl);
101
+
102
+ tcg_temp_free_i64(tmp);
103
+ tcg_temp_free_i64(dbit);
104
+ tcg_temp_free_i64(didx);
105
+ tcg_temp_free_ptr(ptr);
149
+ return true;
106
+ return true;
150
+}
107
+}
151
+
152
/*
153
*** SVE Floating Point Arithmetic - Unpredicated Group
154
*/
155
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
156
index XXXXXXX..XXXXXXX 100644
157
--- a/target/arm/sve.decode
158
+++ b/target/arm/sve.decode
159
@@ -XXX,XX +XXX,XX @@ UMIN_zzi 00100101 .. 101 011 110 ........ ..... @rdn_i8u
160
# SVE integer multiply immediate (unpredicated)
161
MUL_zzi 00100101 .. 110 000 110 ........ ..... @rdn_i8s
162
163
+### SVE FP Accumulating Reduction Group
164
+
165
+# SVE floating-point serial reduction (predicated)
166
+FADDA 01100101 .. 011 000 001 ... ..... ..... @rdn_pg_rm
167
+
168
### SVE Floating Point Arithmetic - Unpredicated Group
169
170
# SVE floating-point arithmetic (unpredicated)
171
--
108
--
172
2.17.1
109
2.25.1
173
174
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
This is an SVE instruction that operates using the SVE vector
4
length but that it is present only if SME is implemented.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-4-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-30-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 29 +++++
11
target/arm/helper-sve.h | 2 ++
9
target/arm/sve_helper.c | 211 +++++++++++++++++++++++++++++++++++++
12
target/arm/sve.decode | 1 +
10
target/arm/translate-sve.c | 65 ++++++++++++
13
target/arm/sve_helper.c | 16 ++++++++++++++++
11
target/arm/sve.decode | 38 +++++++
14
target/arm/translate-sve.c | 2 ++
12
4 files changed, 343 insertions(+)
15
4 files changed, 21 insertions(+)
13
16
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
19
--- a/target/arm/helper-sve.h
17
+++ b/target/arm/helper-sve.h
20
+++ b/target/arm/helper-sve.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_ldnf1sdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_revh_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
19
DEF_HELPER_FLAGS_4(sve_ldnf1sds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
22
20
23
DEF_HELPER_FLAGS_4(sve_revw_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
21
DEF_HELPER_FLAGS_4(sve_ldnf1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
24
25
+DEF_HELPER_FLAGS_4(sme_revd_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
+
26
+
23
+DEF_HELPER_FLAGS_4(sve_st1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
27
DEF_HELPER_FLAGS_4(sve_rbit_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_4(sve_st2bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
28
DEF_HELPER_FLAGS_4(sve_rbit_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_4(sve_st3bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
29
DEF_HELPER_FLAGS_4(sve_rbit_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_4(sve_st4bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
30
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
27
+
31
index XXXXXXX..XXXXXXX 100644
28
+DEF_HELPER_FLAGS_4(sve_st1hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
32
--- a/target/arm/sve.decode
29
+DEF_HELPER_FLAGS_4(sve_st2hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
33
+++ b/target/arm/sve.decode
30
+DEF_HELPER_FLAGS_4(sve_st3hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
34
@@ -XXX,XX +XXX,XX @@ REVB 00000101 .. 1001 00 100 ... ..... ..... @rd_pg_rn
31
+DEF_HELPER_FLAGS_4(sve_st4hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
35
REVH 00000101 .. 1001 01 100 ... ..... ..... @rd_pg_rn
32
+
36
REVW 00000101 .. 1001 10 100 ... ..... ..... @rd_pg_rn
33
+DEF_HELPER_FLAGS_4(sve_st1ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
37
RBIT 00000101 .. 1001 11 100 ... ..... ..... @rd_pg_rn
34
+DEF_HELPER_FLAGS_4(sve_st2ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
38
+REVD 00000101 00 1011 10 100 ... ..... ..... @rd_pg_rn_e0
35
+DEF_HELPER_FLAGS_4(sve_st3ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
39
36
+DEF_HELPER_FLAGS_4(sve_st4ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
40
# SVE vector splice (predicated, destructive)
37
+
41
SPLICE 00000101 .. 101 100 100 ... ..... ..... @rdn_pg_rm
38
+DEF_HELPER_FLAGS_4(sve_st1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
39
+DEF_HELPER_FLAGS_4(sve_st2dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_4(sve_st3dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
41
+DEF_HELPER_FLAGS_4(sve_st4dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
42
+
43
+DEF_HELPER_FLAGS_4(sve_st1bh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
44
+DEF_HELPER_FLAGS_4(sve_st1bs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
45
+DEF_HELPER_FLAGS_4(sve_st1bd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
46
+
47
+DEF_HELPER_FLAGS_4(sve_st1hs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
48
+DEF_HELPER_FLAGS_4(sve_st1hd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
49
+
50
+DEF_HELPER_FLAGS_4(sve_st1sd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
51
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
42
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
52
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/sve_helper.c
44
--- a/target/arm/sve_helper.c
54
+++ b/target/arm/sve_helper.c
45
+++ b/target/arm/sve_helper.c
55
@@ -XXX,XX +XXX,XX @@ DO_LDNF1(sds_r)
46
@@ -XXX,XX +XXX,XX @@ DO_ZPZ_D(sve_revh_d, uint64_t, hswap64)
56
DO_LDNF1(dd_r)
47
57
48
DO_ZPZ_D(sve_revw_d, uint64_t, wswap64)
58
#undef DO_LDNF1
49
59
+
50
+void HELPER(sme_revd_q)(void *vd, void *vn, void *vg, uint32_t desc)
60
+/*
61
+ * Store contiguous data, protected by a governing predicate.
62
+ */
63
+#define DO_ST1(NAME, FN, TYPEE, TYPEM, H) \
64
+void HELPER(NAME)(CPUARMState *env, void *vg, \
65
+ target_ulong addr, uint32_t desc) \
66
+{ \
67
+ intptr_t i, oprsz = simd_oprsz(desc); \
68
+ intptr_t ra = GETPC(); \
69
+ unsigned rd = simd_data(desc); \
70
+ void *vd = &env->vfp.zregs[rd]; \
71
+ for (i = 0; i < oprsz; ) { \
72
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
73
+ do { \
74
+ if (pg & 1) { \
75
+ TYPEM m = *(TYPEE *)(vd + H(i)); \
76
+ FN(env, addr, m, ra); \
77
+ } \
78
+ i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
79
+ addr += sizeof(TYPEM); \
80
+ } while (i & 15); \
81
+ } \
82
+}
83
+
84
+#define DO_ST1_D(NAME, FN, TYPEM) \
85
+void HELPER(NAME)(CPUARMState *env, void *vg, \
86
+ target_ulong addr, uint32_t desc) \
87
+{ \
88
+ intptr_t i, oprsz = simd_oprsz(desc) / 8; \
89
+ intptr_t ra = GETPC(); \
90
+ unsigned rd = simd_data(desc); \
91
+ uint64_t *d = &env->vfp.zregs[rd].d[0]; \
92
+ uint8_t *pg = vg; \
93
+ for (i = 0; i < oprsz; i += 1) { \
94
+ if (pg[H1(i)] & 1) { \
95
+ FN(env, addr, d[i], ra); \
96
+ } \
97
+ addr += sizeof(TYPEM); \
98
+ } \
99
+}
100
+
101
+#define DO_ST2(NAME, FN, TYPEE, TYPEM, H) \
102
+void HELPER(NAME)(CPUARMState *env, void *vg, \
103
+ target_ulong addr, uint32_t desc) \
104
+{ \
105
+ intptr_t i, oprsz = simd_oprsz(desc); \
106
+ intptr_t ra = GETPC(); \
107
+ unsigned rd = simd_data(desc); \
108
+ void *d1 = &env->vfp.zregs[rd]; \
109
+ void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
110
+ for (i = 0; i < oprsz; ) { \
111
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
112
+ do { \
113
+ if (pg & 1) { \
114
+ TYPEM m1 = *(TYPEE *)(d1 + H(i)); \
115
+ TYPEM m2 = *(TYPEE *)(d2 + H(i)); \
116
+ FN(env, addr, m1, ra); \
117
+ FN(env, addr + sizeof(TYPEM), m2, ra); \
118
+ } \
119
+ i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
120
+ addr += 2 * sizeof(TYPEM); \
121
+ } while (i & 15); \
122
+ } \
123
+}
124
+
125
+#define DO_ST3(NAME, FN, TYPEE, TYPEM, H) \
126
+void HELPER(NAME)(CPUARMState *env, void *vg, \
127
+ target_ulong addr, uint32_t desc) \
128
+{ \
129
+ intptr_t i, oprsz = simd_oprsz(desc); \
130
+ intptr_t ra = GETPC(); \
131
+ unsigned rd = simd_data(desc); \
132
+ void *d1 = &env->vfp.zregs[rd]; \
133
+ void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
134
+ void *d3 = &env->vfp.zregs[(rd + 2) & 31]; \
135
+ for (i = 0; i < oprsz; ) { \
136
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
137
+ do { \
138
+ if (pg & 1) { \
139
+ TYPEM m1 = *(TYPEE *)(d1 + H(i)); \
140
+ TYPEM m2 = *(TYPEE *)(d2 + H(i)); \
141
+ TYPEM m3 = *(TYPEE *)(d3 + H(i)); \
142
+ FN(env, addr, m1, ra); \
143
+ FN(env, addr + sizeof(TYPEM), m2, ra); \
144
+ FN(env, addr + 2 * sizeof(TYPEM), m3, ra); \
145
+ } \
146
+ i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
147
+ addr += 3 * sizeof(TYPEM); \
148
+ } while (i & 15); \
149
+ } \
150
+}
151
+
152
+#define DO_ST4(NAME, FN, TYPEE, TYPEM, H) \
153
+void HELPER(NAME)(CPUARMState *env, void *vg, \
154
+ target_ulong addr, uint32_t desc) \
155
+{ \
156
+ intptr_t i, oprsz = simd_oprsz(desc); \
157
+ intptr_t ra = GETPC(); \
158
+ unsigned rd = simd_data(desc); \
159
+ void *d1 = &env->vfp.zregs[rd]; \
160
+ void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
161
+ void *d3 = &env->vfp.zregs[(rd + 2) & 31]; \
162
+ void *d4 = &env->vfp.zregs[(rd + 3) & 31]; \
163
+ for (i = 0; i < oprsz; ) { \
164
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
165
+ do { \
166
+ if (pg & 1) { \
167
+ TYPEM m1 = *(TYPEE *)(d1 + H(i)); \
168
+ TYPEM m2 = *(TYPEE *)(d2 + H(i)); \
169
+ TYPEM m3 = *(TYPEE *)(d3 + H(i)); \
170
+ TYPEM m4 = *(TYPEE *)(d4 + H(i)); \
171
+ FN(env, addr, m1, ra); \
172
+ FN(env, addr + sizeof(TYPEM), m2, ra); \
173
+ FN(env, addr + 2 * sizeof(TYPEM), m3, ra); \
174
+ FN(env, addr + 3 * sizeof(TYPEM), m4, ra); \
175
+ } \
176
+ i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
177
+ addr += 4 * sizeof(TYPEM); \
178
+ } while (i & 15); \
179
+ } \
180
+}
181
+
182
+DO_ST1(sve_st1bh_r, cpu_stb_data_ra, uint16_t, uint8_t, H1_2)
183
+DO_ST1(sve_st1bs_r, cpu_stb_data_ra, uint32_t, uint8_t, H1_4)
184
+DO_ST1_D(sve_st1bd_r, cpu_stb_data_ra, uint8_t)
185
+
186
+DO_ST1(sve_st1hs_r, cpu_stw_data_ra, uint32_t, uint16_t, H1_4)
187
+DO_ST1_D(sve_st1hd_r, cpu_stw_data_ra, uint16_t)
188
+
189
+DO_ST1_D(sve_st1sd_r, cpu_stl_data_ra, uint32_t)
190
+
191
+DO_ST1(sve_st1bb_r, cpu_stb_data_ra, uint8_t, uint8_t, H1)
192
+DO_ST2(sve_st2bb_r, cpu_stb_data_ra, uint8_t, uint8_t, H1)
193
+DO_ST3(sve_st3bb_r, cpu_stb_data_ra, uint8_t, uint8_t, H1)
194
+DO_ST4(sve_st4bb_r, cpu_stb_data_ra, uint8_t, uint8_t, H1)
195
+
196
+DO_ST1(sve_st1hh_r, cpu_stw_data_ra, uint16_t, uint16_t, H1_2)
197
+DO_ST2(sve_st2hh_r, cpu_stw_data_ra, uint16_t, uint16_t, H1_2)
198
+DO_ST3(sve_st3hh_r, cpu_stw_data_ra, uint16_t, uint16_t, H1_2)
199
+DO_ST4(sve_st4hh_r, cpu_stw_data_ra, uint16_t, uint16_t, H1_2)
200
+
201
+DO_ST1(sve_st1ss_r, cpu_stl_data_ra, uint32_t, uint32_t, H1_4)
202
+DO_ST2(sve_st2ss_r, cpu_stl_data_ra, uint32_t, uint32_t, H1_4)
203
+DO_ST3(sve_st3ss_r, cpu_stl_data_ra, uint32_t, uint32_t, H1_4)
204
+DO_ST4(sve_st4ss_r, cpu_stl_data_ra, uint32_t, uint32_t, H1_4)
205
+
206
+DO_ST1_D(sve_st1dd_r, cpu_stq_data_ra, uint64_t)
207
+
208
+void HELPER(sve_st2dd_r)(CPUARMState *env, void *vg,
209
+ target_ulong addr, uint32_t desc)
210
+{
51
+{
211
+ intptr_t i, oprsz = simd_oprsz(desc) / 8;
52
+ intptr_t i, opr_sz = simd_oprsz(desc) / 8;
212
+ intptr_t ra = GETPC();
53
+ uint64_t *d = vd, *n = vn;
213
+ unsigned rd = simd_data(desc);
214
+ uint64_t *d1 = &env->vfp.zregs[rd].d[0];
215
+ uint64_t *d2 = &env->vfp.zregs[(rd + 1) & 31].d[0];
216
+ uint8_t *pg = vg;
54
+ uint8_t *pg = vg;
217
+
55
+
218
+ for (i = 0; i < oprsz; i += 1) {
56
+ for (i = 0; i < opr_sz; i += 2) {
219
+ if (pg[H1(i)] & 1) {
57
+ if (pg[H1(i)] & 1) {
220
+ cpu_stq_data_ra(env, addr, d1[i], ra);
58
+ uint64_t n0 = n[i + 0];
221
+ cpu_stq_data_ra(env, addr + 8, d2[i], ra);
59
+ uint64_t n1 = n[i + 1];
60
+ d[i + 0] = n1;
61
+ d[i + 1] = n0;
222
+ }
62
+ }
223
+ addr += 2 * 8;
224
+ }
63
+ }
225
+}
64
+}
226
+
65
+
227
+void HELPER(sve_st3dd_r)(CPUARMState *env, void *vg,
66
DO_ZPZ(sve_rbit_b, uint8_t, H1, revbit8)
228
+ target_ulong addr, uint32_t desc)
67
DO_ZPZ(sve_rbit_h, uint16_t, H1_2, revbit16)
229
+{
68
DO_ZPZ(sve_rbit_s, uint32_t, H1_4, revbit32)
230
+ intptr_t i, oprsz = simd_oprsz(desc) / 8;
231
+ intptr_t ra = GETPC();
232
+ unsigned rd = simd_data(desc);
233
+ uint64_t *d1 = &env->vfp.zregs[rd].d[0];
234
+ uint64_t *d2 = &env->vfp.zregs[(rd + 1) & 31].d[0];
235
+ uint64_t *d3 = &env->vfp.zregs[(rd + 2) & 31].d[0];
236
+ uint8_t *pg = vg;
237
+
238
+ for (i = 0; i < oprsz; i += 1) {
239
+ if (pg[H1(i)] & 1) {
240
+ cpu_stq_data_ra(env, addr, d1[i], ra);
241
+ cpu_stq_data_ra(env, addr + 8, d2[i], ra);
242
+ cpu_stq_data_ra(env, addr + 16, d3[i], ra);
243
+ }
244
+ addr += 3 * 8;
245
+ }
246
+}
247
+
248
+void HELPER(sve_st4dd_r)(CPUARMState *env, void *vg,
249
+ target_ulong addr, uint32_t desc)
250
+{
251
+ intptr_t i, oprsz = simd_oprsz(desc) / 8;
252
+ intptr_t ra = GETPC();
253
+ unsigned rd = simd_data(desc);
254
+ uint64_t *d1 = &env->vfp.zregs[rd].d[0];
255
+ uint64_t *d2 = &env->vfp.zregs[(rd + 1) & 31].d[0];
256
+ uint64_t *d3 = &env->vfp.zregs[(rd + 2) & 31].d[0];
257
+ uint64_t *d4 = &env->vfp.zregs[(rd + 3) & 31].d[0];
258
+ uint8_t *pg = vg;
259
+
260
+ for (i = 0; i < oprsz; i += 1) {
261
+ if (pg[H1(i)] & 1) {
262
+ cpu_stq_data_ra(env, addr, d1[i], ra);
263
+ cpu_stq_data_ra(env, addr + 8, d2[i], ra);
264
+ cpu_stq_data_ra(env, addr + 16, d3[i], ra);
265
+ cpu_stq_data_ra(env, addr + 24, d4[i], ra);
266
+ }
267
+ addr += 4 * 8;
268
+ }
269
+}
270
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
69
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
271
index XXXXXXX..XXXXXXX 100644
70
index XXXXXXX..XXXXXXX 100644
272
--- a/target/arm/translate-sve.c
71
--- a/target/arm/translate-sve.c
273
+++ b/target/arm/translate-sve.c
72
+++ b/target/arm/translate-sve.c
274
@@ -XXX,XX +XXX,XX @@ static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
73
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(REVH, aa64_sve, gen_gvec_ool_arg_zpz, revh_fns[a->esz], a, 0)
275
}
74
TRANS_FEAT(REVW, aa64_sve, gen_gvec_ool_arg_zpz,
276
return true;
75
a->esz == 3 ? gen_helper_sve_revw_d : NULL, a, 0)
277
}
76
77
+TRANS_FEAT(REVD, aa64_sme, gen_gvec_ool_arg_zpz, gen_helper_sme_revd_q, a, 0)
278
+
78
+
279
+static void do_st_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
79
TRANS_FEAT(SPLICE, aa64_sve, gen_gvec_ool_arg_zpzz,
280
+ int msz, int esz, int nreg)
80
gen_helper_sve_splice, a, a->esz)
281
+{
81
282
+ static gen_helper_gvec_mem * const fn_single[4][4] = {
283
+ { gen_helper_sve_st1bb_r, gen_helper_sve_st1bh_r,
284
+ gen_helper_sve_st1bs_r, gen_helper_sve_st1bd_r },
285
+ { NULL, gen_helper_sve_st1hh_r,
286
+ gen_helper_sve_st1hs_r, gen_helper_sve_st1hd_r },
287
+ { NULL, NULL,
288
+ gen_helper_sve_st1ss_r, gen_helper_sve_st1sd_r },
289
+ { NULL, NULL, NULL, gen_helper_sve_st1dd_r },
290
+ };
291
+ static gen_helper_gvec_mem * const fn_multiple[3][4] = {
292
+ { gen_helper_sve_st2bb_r, gen_helper_sve_st2hh_r,
293
+ gen_helper_sve_st2ss_r, gen_helper_sve_st2dd_r },
294
+ { gen_helper_sve_st3bb_r, gen_helper_sve_st3hh_r,
295
+ gen_helper_sve_st3ss_r, gen_helper_sve_st3dd_r },
296
+ { gen_helper_sve_st4bb_r, gen_helper_sve_st4hh_r,
297
+ gen_helper_sve_st4ss_r, gen_helper_sve_st4dd_r },
298
+ };
299
+ gen_helper_gvec_mem *fn;
300
+
301
+ if (nreg == 0) {
302
+ /* ST1 */
303
+ fn = fn_single[msz][esz];
304
+ } else {
305
+ /* ST2, ST3, ST4 -- msz == esz, enforced by encoding */
306
+ assert(msz == esz);
307
+ fn = fn_multiple[nreg - 1][msz];
308
+ }
309
+ assert(fn != NULL);
310
+ do_mem_zpa(s, zt, pg, addr, fn);
311
+}
312
+
313
+static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a, uint32_t insn)
314
+{
315
+ if (a->rm == 31 || a->msz > a->esz) {
316
+ return false;
317
+ }
318
+ if (sve_access_check(s)) {
319
+ TCGv_i64 addr = new_tmp_a64(s);
320
+ tcg_gen_muli_i64(addr, cpu_reg(s, a->rm), (a->nreg + 1) << a->msz);
321
+ tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
322
+ do_st_zpa(s, a->rd, a->pg, addr, a->msz, a->esz, a->nreg);
323
+ }
324
+ return true;
325
+}
326
+
327
+static bool trans_ST_zpri(DisasContext *s, arg_rpri_store *a, uint32_t insn)
328
+{
329
+ if (a->msz > a->esz) {
330
+ return false;
331
+ }
332
+ if (sve_access_check(s)) {
333
+ int vsz = vec_full_reg_size(s);
334
+ int elements = vsz >> a->esz;
335
+ TCGv_i64 addr = new_tmp_a64(s);
336
+
337
+ tcg_gen_addi_i64(addr, cpu_reg_sp(s, a->rn),
338
+ (a->imm * elements * (a->nreg + 1)) << a->msz);
339
+ do_st_zpa(s, a->rd, a->pg, addr, a->msz, a->esz, a->nreg);
340
+ }
341
+ return true;
342
+}
343
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
344
index XXXXXXX..XXXXXXX 100644
345
--- a/target/arm/sve.decode
346
+++ b/target/arm/sve.decode
347
@@ -XXX,XX +XXX,XX @@
348
%imm7_22_16 22:2 16:5
349
%imm8_16_10 16:5 10:3
350
%imm9_16_10 16:s6 10:3
351
+%size_23 23:2
352
353
# A combination of tsz:imm3 -- extract esize.
354
%tszimm_esz 22:2 5:5 !function=tszimm_esz
355
@@ -XXX,XX +XXX,XX @@
356
&incdec2_pred rd rn pg esz d u
357
&rprr_load rd pg rn rm dtype nreg
358
&rpri_load rd pg rn imm dtype nreg
359
+&rprr_store rd pg rn rm msz esz nreg
360
+&rpri_store rd pg rn imm msz esz nreg
361
362
###########################################################################
363
# Named instruction formats. These are generally used to
364
@@ -XXX,XX +XXX,XX @@
365
@rpri_load_msz ....... .... . imm:s4 ... pg:3 rn:5 rd:5 \
366
&rpri_load dtype=%msz_dtype
367
368
+# Stores; user must fill in ESZ, MSZ, NREG as needed.
369
+@rprr_store ....... .. .. rm:5 ... pg:3 rn:5 rd:5 &rprr_store
370
+@rpri_store_msz ....... msz:2 .. . imm:s4 ... pg:3 rn:5 rd:5 &rpri_store
371
+@rprr_store_esz_n0 ....... .. esz:2 rm:5 ... pg:3 rn:5 rd:5 \
372
+ &rprr_store nreg=0
373
+
374
###########################################################################
375
# Instruction patterns. Grouped according to the SVE encodingindex.xhtml.
376
377
@@ -XXX,XX +XXX,XX @@ LD_zprr 1010010 .. nreg:2 ..... 110 ... ..... ..... @rprr_load_msz
378
# SVE load multiple structures (scalar plus immediate)
379
# LD2B, LD2H, LD2W, LD2D; etc.
380
LD_zpri 1010010 .. nreg:2 0.... 111 ... ..... ..... @rpri_load_msz
381
+
382
+### SVE Memory Store Group
383
+
384
+# SVE contiguous store (scalar plus immediate)
385
+# ST1B, ST1H, ST1W, ST1D; require msz <= esz
386
+ST_zpri 1110010 .. esz:2 0.... 111 ... ..... ..... \
387
+ @rpri_store_msz nreg=0
388
+
389
+# SVE contiguous store (scalar plus scalar)
390
+# ST1B, ST1H, ST1W, ST1D; require msz <= esz
391
+# Enumerate msz lest we conflict with STR_zri.
392
+ST_zprr 1110010 00 .. ..... 010 ... ..... ..... \
393
+ @rprr_store_esz_n0 msz=0
394
+ST_zprr 1110010 01 .. ..... 010 ... ..... ..... \
395
+ @rprr_store_esz_n0 msz=1
396
+ST_zprr 1110010 10 .. ..... 010 ... ..... ..... \
397
+ @rprr_store_esz_n0 msz=2
398
+ST_zprr 1110010 11 11 ..... 010 ... ..... ..... \
399
+ @rprr_store msz=3 esz=3 nreg=0
400
+
401
+# SVE contiguous non-temporal store (scalar plus immediate) (nreg == 0)
402
+# SVE store multiple structures (scalar plus immediate) (nreg != 0)
403
+ST_zpri 1110010 .. nreg:2 1.... 111 ... ..... ..... \
404
+ @rpri_store_msz esz=%size_23
405
+
406
+# SVE contiguous non-temporal store (scalar plus scalar) (nreg == 0)
407
+# SVE store multiple structures (scalar plus scalar) (nreg != 0)
408
+ST_zprr 1110010 msz:2 nreg:2 ..... 011 ... ..... ..... \
409
+ @rprr_store esz=%size_23
410
--
82
--
411
2.17.1
83
2.25.1
412
413
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
This is an SVE instruction that operates using the SVE vector
4
length but that it is present only if SME is implemented.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-19-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-31-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper.h | 14 +++++++++++
11
target/arm/helper.h | 18 +++++++
9
target/arm/translate-sve.c | 50 ++++++++++++++++++++++++++++++++++++++
12
target/arm/sve.decode | 5 ++
10
target/arm/vec_helper.c | 48 ++++++++++++++++++++++++++++++++++++
13
target/arm/translate-sve.c | 102 +++++++++++++++++++++++++++++++++++++
11
target/arm/sve.decode | 19 +++++++++++++++
14
target/arm/vec_helper.c | 24 +++++++++
12
4 files changed, 131 insertions(+)
15
4 files changed, 149 insertions(+)
13
16
14
diff --git a/target/arm/helper.h b/target/arm/helper.h
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.h
19
--- a/target/arm/helper.h
17
+++ b/target/arm/helper.h
20
+++ b/target/arm/helper.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(gvec_bfmlal, TCG_CALL_NO_RWG,
19
DEF_HELPER_FLAGS_5(gvec_ftsmul_d, TCG_CALL_NO_RWG,
22
DEF_HELPER_FLAGS_6(gvec_bfmlal_idx, TCG_CALL_NO_RWG,
20
void, ptr, ptr, ptr, ptr, i32)
23
void, ptr, ptr, ptr, ptr, ptr, i32)
21
24
22
+DEF_HELPER_FLAGS_5(gvec_fmul_idx_h, TCG_CALL_NO_RWG,
25
+DEF_HELPER_FLAGS_5(gvec_sclamp_b, TCG_CALL_NO_RWG,
23
+ void, ptr, ptr, ptr, ptr, i32)
26
+ void, ptr, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_5(gvec_fmul_idx_s, TCG_CALL_NO_RWG,
27
+DEF_HELPER_FLAGS_5(gvec_sclamp_h, TCG_CALL_NO_RWG,
25
+ void, ptr, ptr, ptr, ptr, i32)
28
+ void, ptr, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_5(gvec_fmul_idx_d, TCG_CALL_NO_RWG,
29
+DEF_HELPER_FLAGS_5(gvec_sclamp_s, TCG_CALL_NO_RWG,
27
+ void, ptr, ptr, ptr, ptr, i32)
30
+ void, ptr, ptr, ptr, ptr, i32)
28
+
31
+DEF_HELPER_FLAGS_5(gvec_sclamp_d, TCG_CALL_NO_RWG,
29
+DEF_HELPER_FLAGS_6(gvec_fmla_idx_h, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, i32)
30
+ void, ptr, ptr, ptr, ptr, ptr, i32)
33
+
31
+DEF_HELPER_FLAGS_6(gvec_fmla_idx_s, TCG_CALL_NO_RWG,
34
+DEF_HELPER_FLAGS_5(gvec_uclamp_b, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, ptr, i32)
35
+ void, ptr, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_6(gvec_fmla_idx_d, TCG_CALL_NO_RWG,
36
+DEF_HELPER_FLAGS_5(gvec_uclamp_h, TCG_CALL_NO_RWG,
34
+ void, ptr, ptr, ptr, ptr, ptr, i32)
37
+ void, ptr, ptr, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_5(gvec_uclamp_s, TCG_CALL_NO_RWG,
39
+ void, ptr, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_5(gvec_uclamp_d, TCG_CALL_NO_RWG,
41
+ void, ptr, ptr, ptr, ptr, i32)
35
+
42
+
36
#ifdef TARGET_AARCH64
43
#ifdef TARGET_AARCH64
37
#include "helper-a64.h"
44
#include "helper-a64.h"
38
#include "helper-sve.h"
45
#include "helper-sve.h"
46
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/sve.decode
49
+++ b/target/arm/sve.decode
50
@@ -XXX,XX +XXX,XX @@ PSEL 00100101 .. 1 100 .. 01 .... 0 .... 0 .... \
51
@psel esz=2 imm=%psel_imm_s
52
PSEL 00100101 .1 1 000 .. 01 .... 0 .... 0 .... \
53
@psel esz=3 imm=%psel_imm_d
54
+
55
+### SVE clamp
56
+
57
+SCLAMP 01000100 .. 0 ..... 110000 ..... ..... @rda_rn_rm
58
+UCLAMP 01000100 .. 0 ..... 110001 ..... ..... @rda_rn_rm
39
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
59
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
40
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/translate-sve.c
61
--- a/target/arm/translate-sve.c
42
+++ b/target/arm/translate-sve.c
62
+++ b/target/arm/translate-sve.c
43
@@ -XXX,XX +XXX,XX @@ DO_ZZI(UMIN, umin)
63
@@ -XXX,XX +XXX,XX @@ static bool trans_PSEL(DisasContext *s, arg_psel *a)
44
64
tcg_temp_free_ptr(ptr);
45
#undef DO_ZZI
65
return true;
46
66
}
47
+/*
67
+
48
+ *** SVE Floating Point Multiply-Add Indexed Group
68
+static void gen_sclamp_i32(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m, TCGv_i32 a)
49
+ */
69
+{
50
+
70
+ tcg_gen_smax_i32(d, a, n);
51
+static bool trans_FMLA_zzxz(DisasContext *s, arg_FMLA_zzxz *a, uint32_t insn)
71
+ tcg_gen_smin_i32(d, d, m);
52
+{
72
+}
53
+ static gen_helper_gvec_4_ptr * const fns[3] = {
73
+
54
+ gen_helper_gvec_fmla_idx_h,
74
+static void gen_sclamp_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 a)
55
+ gen_helper_gvec_fmla_idx_s,
75
+{
56
+ gen_helper_gvec_fmla_idx_d,
76
+ tcg_gen_smax_i64(d, a, n);
57
+ };
77
+ tcg_gen_smin_i64(d, d, m);
58
+
78
+}
59
+ if (sve_access_check(s)) {
79
+
60
+ unsigned vsz = vec_full_reg_size(s);
80
+static void gen_sclamp_vec(unsigned vece, TCGv_vec d, TCGv_vec n,
61
+ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
81
+ TCGv_vec m, TCGv_vec a)
62
+ tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, a->rd),
82
+{
63
+ vec_full_reg_offset(s, a->rn),
83
+ tcg_gen_smax_vec(vece, d, a, n);
64
+ vec_full_reg_offset(s, a->rm),
84
+ tcg_gen_smin_vec(vece, d, d, m);
65
+ vec_full_reg_offset(s, a->ra),
85
+}
66
+ status, vsz, vsz, (a->index << 1) | a->sub,
86
+
67
+ fns[a->esz - 1]);
87
+static void gen_sclamp(unsigned vece, uint32_t d, uint32_t n, uint32_t m,
68
+ tcg_temp_free_ptr(status);
88
+ uint32_t a, uint32_t oprsz, uint32_t maxsz)
69
+ }
89
+{
70
+ return true;
90
+ static const TCGOpcode vecop[] = {
71
+}
91
+ INDEX_op_smin_vec, INDEX_op_smax_vec, 0
72
+
92
+ };
73
+/*
93
+ static const GVecGen4 ops[4] = {
74
+ *** SVE Floating Point Multiply Indexed Group
94
+ { .fniv = gen_sclamp_vec,
75
+ */
95
+ .fno = gen_helper_gvec_sclamp_b,
76
+
96
+ .opt_opc = vecop,
77
+static bool trans_FMUL_zzx(DisasContext *s, arg_FMUL_zzx *a, uint32_t insn)
97
+ .vece = MO_8 },
78
+{
98
+ { .fniv = gen_sclamp_vec,
79
+ static gen_helper_gvec_3_ptr * const fns[3] = {
99
+ .fno = gen_helper_gvec_sclamp_h,
80
+ gen_helper_gvec_fmul_idx_h,
100
+ .opt_opc = vecop,
81
+ gen_helper_gvec_fmul_idx_s,
101
+ .vece = MO_16 },
82
+ gen_helper_gvec_fmul_idx_d,
102
+ { .fni4 = gen_sclamp_i32,
83
+ };
103
+ .fniv = gen_sclamp_vec,
84
+
104
+ .fno = gen_helper_gvec_sclamp_s,
85
+ if (sve_access_check(s)) {
105
+ .opt_opc = vecop,
86
+ unsigned vsz = vec_full_reg_size(s);
106
+ .vece = MO_32 },
87
+ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
107
+ { .fni8 = gen_sclamp_i64,
88
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
108
+ .fniv = gen_sclamp_vec,
89
+ vec_full_reg_offset(s, a->rn),
109
+ .fno = gen_helper_gvec_sclamp_d,
90
+ vec_full_reg_offset(s, a->rm),
110
+ .opt_opc = vecop,
91
+ status, vsz, vsz, a->index, fns[a->esz - 1]);
111
+ .vece = MO_64,
92
+ tcg_temp_free_ptr(status);
112
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64 }
93
+ }
113
+ };
94
+ return true;
114
+ tcg_gen_gvec_4(d, n, m, a, oprsz, maxsz, &ops[vece]);
95
+}
115
+}
96
+
116
+
97
/*
117
+TRANS_FEAT(SCLAMP, aa64_sme, gen_gvec_fn_arg_zzzz, gen_sclamp, a)
98
*** SVE Floating Point Accumulating Reduction Group
118
+
99
*/
119
+static void gen_uclamp_i32(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m, TCGv_i32 a)
120
+{
121
+ tcg_gen_umax_i32(d, a, n);
122
+ tcg_gen_umin_i32(d, d, m);
123
+}
124
+
125
+static void gen_uclamp_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 a)
126
+{
127
+ tcg_gen_umax_i64(d, a, n);
128
+ tcg_gen_umin_i64(d, d, m);
129
+}
130
+
131
+static void gen_uclamp_vec(unsigned vece, TCGv_vec d, TCGv_vec n,
132
+ TCGv_vec m, TCGv_vec a)
133
+{
134
+ tcg_gen_umax_vec(vece, d, a, n);
135
+ tcg_gen_umin_vec(vece, d, d, m);
136
+}
137
+
138
+static void gen_uclamp(unsigned vece, uint32_t d, uint32_t n, uint32_t m,
139
+ uint32_t a, uint32_t oprsz, uint32_t maxsz)
140
+{
141
+ static const TCGOpcode vecop[] = {
142
+ INDEX_op_umin_vec, INDEX_op_umax_vec, 0
143
+ };
144
+ static const GVecGen4 ops[4] = {
145
+ { .fniv = gen_uclamp_vec,
146
+ .fno = gen_helper_gvec_uclamp_b,
147
+ .opt_opc = vecop,
148
+ .vece = MO_8 },
149
+ { .fniv = gen_uclamp_vec,
150
+ .fno = gen_helper_gvec_uclamp_h,
151
+ .opt_opc = vecop,
152
+ .vece = MO_16 },
153
+ { .fni4 = gen_uclamp_i32,
154
+ .fniv = gen_uclamp_vec,
155
+ .fno = gen_helper_gvec_uclamp_s,
156
+ .opt_opc = vecop,
157
+ .vece = MO_32 },
158
+ { .fni8 = gen_uclamp_i64,
159
+ .fniv = gen_uclamp_vec,
160
+ .fno = gen_helper_gvec_uclamp_d,
161
+ .opt_opc = vecop,
162
+ .vece = MO_64,
163
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64 }
164
+ };
165
+ tcg_gen_gvec_4(d, n, m, a, oprsz, maxsz, &ops[vece]);
166
+}
167
+
168
+TRANS_FEAT(UCLAMP, aa64_sme, gen_gvec_fn_arg_zzzz, gen_uclamp, a)
100
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
169
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
101
index XXXXXXX..XXXXXXX 100644
170
index XXXXXXX..XXXXXXX 100644
102
--- a/target/arm/vec_helper.c
171
--- a/target/arm/vec_helper.c
103
+++ b/target/arm/vec_helper.c
172
+++ b/target/arm/vec_helper.c
104
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_rsqrts_d, helper_rsqrtsf_f64, float64)
173
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_bfmlal_idx)(void *vd, void *vn, void *vm,
105
174
}
106
#endif
175
clear_tail(d, opr_sz, simd_maxsz(desc));
107
#undef DO_3OP
176
}
108
+
177
+
109
+/* For the indexed ops, SVE applies the index per 128-bit vector segment.
178
+#define DO_CLAMP(NAME, TYPE) \
110
+ * For AdvSIMD, there is of course only one such vector segment.
179
+void HELPER(NAME)(void *d, void *n, void *m, void *a, uint32_t desc) \
111
+ */
180
+{ \
112
+
181
+ intptr_t i, opr_sz = simd_oprsz(desc); \
113
+#define DO_MUL_IDX(NAME, TYPE, H) \
182
+ for (i = 0; i < opr_sz; i += sizeof(TYPE)) { \
114
+void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
183
+ TYPE aa = *(TYPE *)(a + i); \
115
+{ \
184
+ TYPE nn = *(TYPE *)(n + i); \
116
+ intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \
185
+ TYPE mm = *(TYPE *)(m + i); \
117
+ intptr_t idx = simd_data(desc); \
186
+ TYPE dd = MIN(MAX(aa, nn), mm); \
118
+ TYPE *d = vd, *n = vn, *m = vm; \
187
+ *(TYPE *)(d + i) = dd; \
119
+ for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \
188
+ } \
120
+ TYPE mm = m[H(i + idx)]; \
189
+ clear_tail(d, opr_sz, simd_maxsz(desc)); \
121
+ for (j = 0; j < segment; j++) { \
190
+}
122
+ d[i + j] = TYPE##_mul(n[i + j], mm, stat); \
191
+
123
+ } \
192
+DO_CLAMP(gvec_sclamp_b, int8_t)
124
+ } \
193
+DO_CLAMP(gvec_sclamp_h, int16_t)
125
+}
194
+DO_CLAMP(gvec_sclamp_s, int32_t)
126
+
195
+DO_CLAMP(gvec_sclamp_d, int64_t)
127
+DO_MUL_IDX(gvec_fmul_idx_h, float16, H2)
196
+
128
+DO_MUL_IDX(gvec_fmul_idx_s, float32, H4)
197
+DO_CLAMP(gvec_uclamp_b, uint8_t)
129
+DO_MUL_IDX(gvec_fmul_idx_d, float64, )
198
+DO_CLAMP(gvec_uclamp_h, uint16_t)
130
+
199
+DO_CLAMP(gvec_uclamp_s, uint32_t)
131
+#undef DO_MUL_IDX
200
+DO_CLAMP(gvec_uclamp_d, uint64_t)
132
+
133
+#define DO_FMLA_IDX(NAME, TYPE, H) \
134
+void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, \
135
+ void *stat, uint32_t desc) \
136
+{ \
137
+ intptr_t i, j, oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE); \
138
+ TYPE op1_neg = extract32(desc, SIMD_DATA_SHIFT, 1); \
139
+ intptr_t idx = desc >> (SIMD_DATA_SHIFT + 1); \
140
+ TYPE *d = vd, *n = vn, *m = vm, *a = va; \
141
+ op1_neg <<= (8 * sizeof(TYPE) - 1); \
142
+ for (i = 0; i < oprsz / sizeof(TYPE); i += segment) { \
143
+ TYPE mm = m[H(i + idx)]; \
144
+ for (j = 0; j < segment; j++) { \
145
+ d[i + j] = TYPE##_muladd(n[i + j] ^ op1_neg, \
146
+ mm, a[i + j], 0, stat); \
147
+ } \
148
+ } \
149
+}
150
+
151
+DO_FMLA_IDX(gvec_fmla_idx_h, float16, H2)
152
+DO_FMLA_IDX(gvec_fmla_idx_s, float32, H4)
153
+DO_FMLA_IDX(gvec_fmla_idx_d, float64, )
154
+
155
+#undef DO_FMLA_IDX
156
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
157
index XXXXXXX..XXXXXXX 100644
158
--- a/target/arm/sve.decode
159
+++ b/target/arm/sve.decode
160
@@ -XXX,XX +XXX,XX @@
161
%imm9_16_10 16:s6 10:3
162
%size_23 23:2
163
%dtype_23_13 23:2 13:2
164
+%index3_22_19 22:1 19:2
165
166
# A combination of tsz:imm3 -- extract esize.
167
%tszimm_esz 22:2 5:5 !function=tszimm_esz
168
@@ -XXX,XX +XXX,XX @@ UMIN_zzi 00100101 .. 101 011 110 ........ ..... @rdn_i8u
169
# SVE integer multiply immediate (unpredicated)
170
MUL_zzi 00100101 .. 110 000 110 ........ ..... @rdn_i8s
171
172
+### SVE FP Multiply-Add Indexed Group
173
+
174
+# SVE floating-point multiply-add (indexed)
175
+FMLA_zzxz 01100100 0.1 .. rm:3 00000 sub:1 rn:5 rd:5 \
176
+ ra=%reg_movprfx index=%index3_22_19 esz=1
177
+FMLA_zzxz 01100100 101 index:2 rm:3 00000 sub:1 rn:5 rd:5 \
178
+ ra=%reg_movprfx esz=2
179
+FMLA_zzxz 01100100 111 index:1 rm:4 00000 sub:1 rn:5 rd:5 \
180
+ ra=%reg_movprfx esz=3
181
+
182
+### SVE FP Multiply Indexed Group
183
+
184
+# SVE floating-point multiply (indexed)
185
+FMUL_zzx 01100100 0.1 .. rm:3 001000 rn:5 rd:5 \
186
+ index=%index3_22_19 esz=1
187
+FMUL_zzx 01100100 101 index:2 rm:3 001000 rn:5 rd:5 esz=2
188
+FMUL_zzx 01100100 111 index:1 rm:4 001000 rn:5 rd:5 esz=3
189
+
190
### SVE FP Accumulating Reduction Group
191
192
# SVE floating-point serial reduction (predicated)
193
--
201
--
194
2.17.1
202
2.25.1
195
196
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
Since kernel commit a86bd139f2 (arm64: arch_timer: Enable CNTVCT_EL0
3
We can handle both exception entry and exception return by
4
trap..), released in kernel version v4.12, user-space has been able
4
hooking into aarch64_sve_change_el.
5
to read these system registers. As we can't use QEMUTimer's in
6
linux-user mode we just directly call cpu_get_clock().
7
5
8
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180625160009.17437-2-alex.bennee@linaro.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-32-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
target/arm/helper.c | 27 ++++++++++++++++++++++++---
11
target/arm/helper.c | 15 +++++++++++++--
15
1 file changed, 24 insertions(+), 3 deletions(-)
12
1 file changed, 13 insertions(+), 2 deletions(-)
16
13
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
16
--- a/target/arm/helper.c
20
+++ b/target/arm/helper.c
17
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
18
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
22
};
19
return;
23
20
}
24
#else
21
25
-/* In user-mode none of the generic timer registers are accessible,
22
+ old_a64 = old_el ? arm_el_is_aa64(env, old_el) : el0_a64;
26
- * and their implementation depends on QEMU_CLOCK_VIRTUAL and qdev gpio outputs,
23
+ new_a64 = new_el ? arm_el_is_aa64(env, new_el) : el0_a64;
27
- * so instead just don't register any of them.
28
+
24
+
29
+/* In user-mode most of the generic timer registers are inaccessible
25
+ /*
30
+ * however modern kernels (4.12+) allow access to cntvct_el0
26
+ * Both AArch64.TakeException and AArch64.ExceptionReturn
31
*/
27
+ * invoke ResetSVEState when taking an exception from, or
28
+ * returning to, AArch32 state when PSTATE.SM is enabled.
29
+ */
30
+ if (old_a64 != new_a64 && FIELD_EX64(env->svcr, SVCR, SM)) {
31
+ arm_reset_sve_state(env);
32
+ return;
33
+ }
32
+
34
+
33
+static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
35
/*
34
+{
36
* DDI0584A.d sec 3.2: "If SVE instructions are disabled or trapped
35
+ /* Currently we have no support for QEMUTimer in linux-user so we
37
* at ELx, or not available because the EL is in AArch32 state, then
36
+ * can't call gt_get_countervalue(env), instead we directly
38
@@ -XXX,XX +XXX,XX @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
37
+ * call the lower level functions.
39
* we already have the correct register contents when encountering the
38
+ */
40
* vq0->vq0 transition between EL0->EL1.
39
+ return cpu_get_clock() / GTIMER_SCALE;
41
*/
40
+}
42
- old_a64 = old_el ? arm_el_is_aa64(env, old_el) : el0_a64;
41
+
43
old_len = (old_a64 && !sve_exception_el(env, old_el)
42
static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
44
? sve_vqm1_for_el(env, old_el) : 0);
43
+ { .name = "CNTFRQ_EL0", .state = ARM_CP_STATE_AA64,
45
- new_a64 = new_el ? arm_el_is_aa64(env, new_el) : el0_a64;
44
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
46
new_len = (new_a64 && !sve_exception_el(env, new_el)
45
+ .type = ARM_CP_CONST, .access = PL0_R /* no PL1_RW in linux-user */,
47
? sve_vqm1_for_el(env, new_el) : 0);
46
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
47
+ .resetvalue = NANOSECONDS_PER_SECOND / GTIMER_SCALE,
48
+ },
49
+ { .name = "CNTVCT_EL0", .state = ARM_CP_STATE_AA64,
50
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 2,
51
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
52
+ .readfn = gt_virt_cnt_read,
53
+ },
54
REGINFO_SENTINEL
55
};
56
48
57
--
49
--
58
2.17.1
50
2.25.1
59
60
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
There is no need to re-set these 9 features already
3
Note that SME remains effectively disabled for user-only,
4
implied by the call to aarch64_a57_initfn.
4
because we do not yet set CPACR_EL1.SMEN. This needs to
5
wait until the kernel ABI is implemented.
5
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20220708151540.18136-33-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20180629001538.11415-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/cpu64.c | 9 ---------
12
docs/system/arm/emulation.rst | 4 ++++
13
1 file changed, 9 deletions(-)
13
target/arm/cpu64.c | 11 +++++++++++
14
2 files changed, 15 insertions(+)
14
15
16
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
17
index XXXXXXX..XXXXXXX 100644
18
--- a/docs/system/arm/emulation.rst
19
+++ b/docs/system/arm/emulation.rst
20
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
21
- FEAT_SHA512 (Advanced SIMD SHA512 instructions)
22
- FEAT_SM3 (Advanced SIMD SM3 instructions)
23
- FEAT_SM4 (Advanced SIMD SM4 instructions)
24
+- FEAT_SME (Scalable Matrix Extension)
25
+- FEAT_SME_FA64 (Full A64 instruction set in Streaming SVE mode)
26
+- FEAT_SME_F64F64 (Double-precision floating-point outer product instructions)
27
+- FEAT_SME_I16I64 (16-bit to 64-bit integer widening outer product instructions)
28
- FEAT_SPECRES (Speculation restriction instructions)
29
- FEAT_SSBS (Speculative Store Bypass Safe)
30
- FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
15
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
31
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
16
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu64.c
33
--- a/target/arm/cpu64.c
18
+++ b/target/arm/cpu64.c
34
+++ b/target/arm/cpu64.c
19
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
35
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
20
* whereas the architecture requires them to be present in both if
36
*/
21
* present in either.
37
t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); /* FEAT_MTE3 */
22
*/
38
t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0); /* FEAT_RASv1p1 + FEAT_DoubleFault */
23
- set_feature(&cpu->env, ARM_FEATURE_V8);
39
+ t = FIELD_DP64(t, ID_AA64PFR1, SME, 1); /* FEAT_SME */
24
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
40
t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
25
- set_feature(&cpu->env, ARM_FEATURE_NEON);
41
cpu->isar.id_aa64pfr1 = t;
26
- set_feature(&cpu->env, ARM_FEATURE_AARCH64);
42
27
- set_feature(&cpu->env, ARM_FEATURE_V8_AES);
43
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
28
- set_feature(&cpu->env, ARM_FEATURE_V8_SHA1);
44
t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* FEAT_PMUv3p4 */
29
- set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
45
cpu->isar.id_aa64dfr0 = t;
30
set_feature(&cpu->env, ARM_FEATURE_V8_SHA512);
46
31
set_feature(&cpu->env, ARM_FEATURE_V8_SHA3);
47
+ t = cpu->isar.id_aa64smfr0;
32
set_feature(&cpu->env, ARM_FEATURE_V8_SM3);
48
+ t = FIELD_DP64(t, ID_AA64SMFR0, F32F32, 1); /* FEAT_SME */
33
set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
49
+ t = FIELD_DP64(t, ID_AA64SMFR0, B16F32, 1); /* FEAT_SME */
34
- set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
50
+ t = FIELD_DP64(t, ID_AA64SMFR0, F16F32, 1); /* FEAT_SME */
35
- set_feature(&cpu->env, ARM_FEATURE_CRC);
51
+ t = FIELD_DP64(t, ID_AA64SMFR0, I8I32, 0xf); /* FEAT_SME */
36
set_feature(&cpu->env, ARM_FEATURE_V8_ATOMICS);
52
+ t = FIELD_DP64(t, ID_AA64SMFR0, F64F64, 1); /* FEAT_SME_F64F64 */
37
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
53
+ t = FIELD_DP64(t, ID_AA64SMFR0, I16I64, 0xf); /* FEAT_SME_I16I64 */
38
set_feature(&cpu->env, ARM_FEATURE_V8_DOTPROD);
54
+ t = FIELD_DP64(t, ID_AA64SMFR0, FA64, 1); /* FEAT_SME_FA64 */
55
+ cpu->isar.id_aa64smfr0 = t;
56
+
57
/* Replicate the same data to the 32-bit id registers. */
58
aa32_max_features(cpu);
59
39
--
60
--
40
2.17.1
61
2.25.1
41
42
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-25-richard.henderson@linaro.org
5
Message-id: 20220708151540.18136-34-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
7
---
8
target/arm/helper-sve.h | 30 +++++++++++++
8
linux-user/aarch64/target_cpu.h | 5 ++++-
9
target/arm/helper.h | 12 +++---
9
1 file changed, 4 insertions(+), 1 deletion(-)
10
target/arm/helper.c | 2 +-
11
target/arm/sve_helper.c | 88 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-sve.c | 70 ++++++++++++++++++++++++++++++
13
target/arm/sve.decode | 16 +++++++
14
6 files changed, 211 insertions(+), 7 deletions(-)
15
10
16
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
11
diff --git a/linux-user/aarch64/target_cpu.h b/linux-user/aarch64/target_cpu.h
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper-sve.h
13
--- a/linux-user/aarch64/target_cpu.h
19
+++ b/target/arm/helper-sve.h
14
+++ b/linux-user/aarch64/target_cpu.h
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_fcvt_hd, TCG_CALL_NO_RWG,
15
@@ -XXX,XX +XXX,XX @@ static inline void cpu_clone_regs_parent(CPUARMState *env, unsigned flags)
21
DEF_HELPER_FLAGS_5(sve_fcvt_sd, TCG_CALL_NO_RWG,
16
22
void, ptr, ptr, ptr, ptr, i32)
17
static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
23
18
{
24
+DEF_HELPER_FLAGS_5(sve_fcvtzs_hh, TCG_CALL_NO_RWG,
19
- /* Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is
25
+ void, ptr, ptr, ptr, ptr, i32)
20
+ /*
26
+DEF_HELPER_FLAGS_5(sve_fcvtzs_hs, TCG_CALL_NO_RWG,
21
+ * Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is
27
+ void, ptr, ptr, ptr, ptr, i32)
22
* different from AArch32 Linux, which uses TPIDRRO.
28
+DEF_HELPER_FLAGS_5(sve_fcvtzs_ss, TCG_CALL_NO_RWG,
23
*/
29
+ void, ptr, ptr, ptr, ptr, i32)
24
env->cp15.tpidr_el[0] = newtls;
30
+DEF_HELPER_FLAGS_5(sve_fcvtzs_ds, TCG_CALL_NO_RWG,
25
+ /* TPIDR2_EL0 is cleared with CLONE_SETTLS. */
31
+ void, ptr, ptr, ptr, ptr, i32)
26
+ env->cp15.tpidr2_el0 = 0;
32
+DEF_HELPER_FLAGS_5(sve_fcvtzs_hd, TCG_CALL_NO_RWG,
33
+ void, ptr, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_5(sve_fcvtzs_sd, TCG_CALL_NO_RWG,
35
+ void, ptr, ptr, ptr, ptr, i32)
36
+DEF_HELPER_FLAGS_5(sve_fcvtzs_dd, TCG_CALL_NO_RWG,
37
+ void, ptr, ptr, ptr, ptr, i32)
38
+
39
+DEF_HELPER_FLAGS_5(sve_fcvtzu_hh, TCG_CALL_NO_RWG,
40
+ void, ptr, ptr, ptr, ptr, i32)
41
+DEF_HELPER_FLAGS_5(sve_fcvtzu_hs, TCG_CALL_NO_RWG,
42
+ void, ptr, ptr, ptr, ptr, i32)
43
+DEF_HELPER_FLAGS_5(sve_fcvtzu_ss, TCG_CALL_NO_RWG,
44
+ void, ptr, ptr, ptr, ptr, i32)
45
+DEF_HELPER_FLAGS_5(sve_fcvtzu_ds, TCG_CALL_NO_RWG,
46
+ void, ptr, ptr, ptr, ptr, i32)
47
+DEF_HELPER_FLAGS_5(sve_fcvtzu_hd, TCG_CALL_NO_RWG,
48
+ void, ptr, ptr, ptr, ptr, i32)
49
+DEF_HELPER_FLAGS_5(sve_fcvtzu_sd, TCG_CALL_NO_RWG,
50
+ void, ptr, ptr, ptr, ptr, i32)
51
+DEF_HELPER_FLAGS_5(sve_fcvtzu_dd, TCG_CALL_NO_RWG,
52
+ void, ptr, ptr, ptr, ptr, i32)
53
+
54
DEF_HELPER_FLAGS_5(sve_scvt_hh, TCG_CALL_NO_RWG,
55
void, ptr, ptr, ptr, ptr, i32)
56
DEF_HELPER_FLAGS_5(sve_scvt_sh, TCG_CALL_NO_RWG,
57
diff --git a/target/arm/helper.h b/target/arm/helper.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/helper.h
60
+++ b/target/arm/helper.h
61
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(vfp_touid, i32, f64, ptr)
62
DEF_HELPER_2(vfp_touizh, i32, f16, ptr)
63
DEF_HELPER_2(vfp_touizs, i32, f32, ptr)
64
DEF_HELPER_2(vfp_touizd, i32, f64, ptr)
65
-DEF_HELPER_2(vfp_tosih, i32, f16, ptr)
66
-DEF_HELPER_2(vfp_tosis, i32, f32, ptr)
67
-DEF_HELPER_2(vfp_tosid, i32, f64, ptr)
68
-DEF_HELPER_2(vfp_tosizh, i32, f16, ptr)
69
-DEF_HELPER_2(vfp_tosizs, i32, f32, ptr)
70
-DEF_HELPER_2(vfp_tosizd, i32, f64, ptr)
71
+DEF_HELPER_2(vfp_tosih, s32, f16, ptr)
72
+DEF_HELPER_2(vfp_tosis, s32, f32, ptr)
73
+DEF_HELPER_2(vfp_tosid, s32, f64, ptr)
74
+DEF_HELPER_2(vfp_tosizh, s32, f16, ptr)
75
+DEF_HELPER_2(vfp_tosizs, s32, f32, ptr)
76
+DEF_HELPER_2(vfp_tosizd, s32, f64, ptr)
77
78
DEF_HELPER_3(vfp_toshs_round_to_zero, i32, f32, i32, ptr)
79
DEF_HELPER_3(vfp_tosls_round_to_zero, i32, f32, i32, ptr)
80
diff --git a/target/arm/helper.c b/target/arm/helper.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/helper.c
83
+++ b/target/arm/helper.c
84
@@ -XXX,XX +XXX,XX @@ ftype HELPER(name)(uint32_t x, void *fpstp) \
85
}
27
}
86
28
87
#define CONV_FTOI(name, ftype, fsz, sign, round) \
29
static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
88
-uint32_t HELPER(name)(ftype x, void *fpstp) \
89
+sign##int32_t HELPER(name)(ftype x, void *fpstp) \
90
{ \
91
float_status *fpst = fpstp; \
92
if (float##fsz##_is_any_nan(x)) { \
93
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/sve_helper.c
96
+++ b/target/arm/sve_helper.c
97
@@ -XXX,XX +XXX,XX @@ static inline float16 sve_f64_to_f16(float64 f, float_status *fpst)
98
return ret;
99
}
100
101
+static inline int16_t vfp_float16_to_int16_rtz(float16 f, float_status *s)
102
+{
103
+ if (float16_is_any_nan(f)) {
104
+ float_raise(float_flag_invalid, s);
105
+ return 0;
106
+ }
107
+ return float16_to_int16_round_to_zero(f, s);
108
+}
109
+
110
+static inline int64_t vfp_float16_to_int64_rtz(float16 f, float_status *s)
111
+{
112
+ if (float16_is_any_nan(f)) {
113
+ float_raise(float_flag_invalid, s);
114
+ return 0;
115
+ }
116
+ return float16_to_int64_round_to_zero(f, s);
117
+}
118
+
119
+static inline int64_t vfp_float32_to_int64_rtz(float32 f, float_status *s)
120
+{
121
+ if (float32_is_any_nan(f)) {
122
+ float_raise(float_flag_invalid, s);
123
+ return 0;
124
+ }
125
+ return float32_to_int64_round_to_zero(f, s);
126
+}
127
+
128
+static inline int64_t vfp_float64_to_int64_rtz(float64 f, float_status *s)
129
+{
130
+ if (float64_is_any_nan(f)) {
131
+ float_raise(float_flag_invalid, s);
132
+ return 0;
133
+ }
134
+ return float64_to_int64_round_to_zero(f, s);
135
+}
136
+
137
+static inline uint16_t vfp_float16_to_uint16_rtz(float16 f, float_status *s)
138
+{
139
+ if (float16_is_any_nan(f)) {
140
+ float_raise(float_flag_invalid, s);
141
+ return 0;
142
+ }
143
+ return float16_to_uint16_round_to_zero(f, s);
144
+}
145
+
146
+static inline uint64_t vfp_float16_to_uint64_rtz(float16 f, float_status *s)
147
+{
148
+ if (float16_is_any_nan(f)) {
149
+ float_raise(float_flag_invalid, s);
150
+ return 0;
151
+ }
152
+ return float16_to_uint64_round_to_zero(f, s);
153
+}
154
+
155
+static inline uint64_t vfp_float32_to_uint64_rtz(float32 f, float_status *s)
156
+{
157
+ if (float32_is_any_nan(f)) {
158
+ float_raise(float_flag_invalid, s);
159
+ return 0;
160
+ }
161
+ return float32_to_uint64_round_to_zero(f, s);
162
+}
163
+
164
+static inline uint64_t vfp_float64_to_uint64_rtz(float64 f, float_status *s)
165
+{
166
+ if (float64_is_any_nan(f)) {
167
+ float_raise(float_flag_invalid, s);
168
+ return 0;
169
+ }
170
+ return float64_to_uint64_round_to_zero(f, s);
171
+}
172
+
173
DO_ZPZ_FP(sve_fcvt_sh, uint32_t, H1_4, sve_f32_to_f16)
174
DO_ZPZ_FP(sve_fcvt_hs, uint32_t, H1_4, sve_f16_to_f32)
175
DO_ZPZ_FP(sve_fcvt_dh, uint64_t, , sve_f64_to_f16)
176
@@ -XXX,XX +XXX,XX @@ DO_ZPZ_FP(sve_fcvt_hd, uint64_t, , sve_f16_to_f64)
177
DO_ZPZ_FP(sve_fcvt_ds, uint64_t, , float64_to_float32)
178
DO_ZPZ_FP(sve_fcvt_sd, uint64_t, , float32_to_float64)
179
180
+DO_ZPZ_FP(sve_fcvtzs_hh, uint16_t, H1_2, vfp_float16_to_int16_rtz)
181
+DO_ZPZ_FP(sve_fcvtzs_hs, uint32_t, H1_4, helper_vfp_tosizh)
182
+DO_ZPZ_FP(sve_fcvtzs_ss, uint32_t, H1_4, helper_vfp_tosizs)
183
+DO_ZPZ_FP(sve_fcvtzs_hd, uint64_t, , vfp_float16_to_int64_rtz)
184
+DO_ZPZ_FP(sve_fcvtzs_sd, uint64_t, , vfp_float32_to_int64_rtz)
185
+DO_ZPZ_FP(sve_fcvtzs_ds, uint64_t, , helper_vfp_tosizd)
186
+DO_ZPZ_FP(sve_fcvtzs_dd, uint64_t, , vfp_float64_to_int64_rtz)
187
+
188
+DO_ZPZ_FP(sve_fcvtzu_hh, uint16_t, H1_2, vfp_float16_to_uint16_rtz)
189
+DO_ZPZ_FP(sve_fcvtzu_hs, uint32_t, H1_4, helper_vfp_touizh)
190
+DO_ZPZ_FP(sve_fcvtzu_ss, uint32_t, H1_4, helper_vfp_touizs)
191
+DO_ZPZ_FP(sve_fcvtzu_hd, uint64_t, , vfp_float16_to_uint64_rtz)
192
+DO_ZPZ_FP(sve_fcvtzu_sd, uint64_t, , vfp_float32_to_uint64_rtz)
193
+DO_ZPZ_FP(sve_fcvtzu_ds, uint64_t, , helper_vfp_touizd)
194
+DO_ZPZ_FP(sve_fcvtzu_dd, uint64_t, , vfp_float64_to_uint64_rtz)
195
+
196
DO_ZPZ_FP(sve_scvt_hh, uint16_t, H1_2, int16_to_float16)
197
DO_ZPZ_FP(sve_scvt_sh, uint32_t, H1_4, int32_to_float16)
198
DO_ZPZ_FP(sve_scvt_ss, uint32_t, H1_4, int32_to_float32)
199
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/target/arm/translate-sve.c
202
+++ b/target/arm/translate-sve.c
203
@@ -XXX,XX +XXX,XX @@ static bool trans_FCVT_sd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
204
return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_sd);
205
}
206
207
+static bool trans_FCVTZS_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
208
+{
209
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvtzs_hh);
210
+}
211
+
212
+static bool trans_FCVTZU_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
213
+{
214
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvtzu_hh);
215
+}
216
+
217
+static bool trans_FCVTZS_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
218
+{
219
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvtzs_hs);
220
+}
221
+
222
+static bool trans_FCVTZU_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
223
+{
224
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvtzu_hs);
225
+}
226
+
227
+static bool trans_FCVTZS_hd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
228
+{
229
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvtzs_hd);
230
+}
231
+
232
+static bool trans_FCVTZU_hd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
233
+{
234
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvtzu_hd);
235
+}
236
+
237
+static bool trans_FCVTZS_ss(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
238
+{
239
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzs_ss);
240
+}
241
+
242
+static bool trans_FCVTZU_ss(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
243
+{
244
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzu_ss);
245
+}
246
+
247
+static bool trans_FCVTZS_sd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
248
+{
249
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzs_sd);
250
+}
251
+
252
+static bool trans_FCVTZU_sd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
253
+{
254
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzu_sd);
255
+}
256
+
257
+static bool trans_FCVTZS_ds(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
258
+{
259
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzs_ds);
260
+}
261
+
262
+static bool trans_FCVTZU_ds(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
263
+{
264
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzu_ds);
265
+}
266
+
267
+static bool trans_FCVTZS_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
268
+{
269
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzs_dd);
270
+}
271
+
272
+static bool trans_FCVTZU_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
273
+{
274
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzu_dd);
275
+}
276
+
277
static bool trans_SCVTF_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
278
{
279
return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_scvt_hh);
280
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
281
index XXXXXXX..XXXXXXX 100644
282
--- a/target/arm/sve.decode
283
+++ b/target/arm/sve.decode
284
@@ -XXX,XX +XXX,XX @@ FCVT_hd 01100101 11 0010 01 101 ... ..... ..... @rd_pg_rn_e0
285
FCVT_ds 01100101 11 0010 10 101 ... ..... ..... @rd_pg_rn_e0
286
FCVT_sd 01100101 11 0010 11 101 ... ..... ..... @rd_pg_rn_e0
287
288
+# SVE floating-point convert to integer
289
+FCVTZS_hh 01100101 01 011 01 0 101 ... ..... ..... @rd_pg_rn_e0
290
+FCVTZU_hh 01100101 01 011 01 1 101 ... ..... ..... @rd_pg_rn_e0
291
+FCVTZS_hs 01100101 01 011 10 0 101 ... ..... ..... @rd_pg_rn_e0
292
+FCVTZU_hs 01100101 01 011 10 1 101 ... ..... ..... @rd_pg_rn_e0
293
+FCVTZS_hd 01100101 01 011 11 0 101 ... ..... ..... @rd_pg_rn_e0
294
+FCVTZU_hd 01100101 01 011 11 1 101 ... ..... ..... @rd_pg_rn_e0
295
+FCVTZS_ss 01100101 10 011 10 0 101 ... ..... ..... @rd_pg_rn_e0
296
+FCVTZU_ss 01100101 10 011 10 1 101 ... ..... ..... @rd_pg_rn_e0
297
+FCVTZS_ds 01100101 11 011 00 0 101 ... ..... ..... @rd_pg_rn_e0
298
+FCVTZU_ds 01100101 11 011 00 1 101 ... ..... ..... @rd_pg_rn_e0
299
+FCVTZS_sd 01100101 11 011 10 0 101 ... ..... ..... @rd_pg_rn_e0
300
+FCVTZU_sd 01100101 11 011 10 1 101 ... ..... ..... @rd_pg_rn_e0
301
+FCVTZS_dd 01100101 11 011 11 0 101 ... ..... ..... @rd_pg_rn_e0
302
+FCVTZU_dd 01100101 11 011 11 1 101 ... ..... ..... @rd_pg_rn_e0
303
+
304
# SVE integer convert to floating-point
305
SCVTF_hh 01100101 01 010 01 0 101 ... ..... ..... @rd_pg_rn_e0
306
SCVTF_sh 01100101 01 010 10 0 101 ... ..... ..... @rd_pg_rn_e0
307
--
30
--
308
2.17.1
31
2.25.1
309
310
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-15-richard.henderson@linaro.org
5
Message-id: 20220708151540.18136-35-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
7
---
8
target/arm/helper-sve.h | 67 +++++++++++++++++++++++++++++
8
linux-user/aarch64/cpu_loop.c | 9 +++++++++
9
target/arm/sve_helper.c | 88 ++++++++++++++++++++++++++++++++++++++
9
1 file changed, 9 insertions(+)
10
target/arm/translate-sve.c | 40 ++++++++++++++++-
11
3 files changed, 193 insertions(+), 2 deletions(-)
12
10
13
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
11
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-sve.h
13
--- a/linux-user/aarch64/cpu_loop.c
16
+++ b/target/arm/helper-sve.h
14
+++ b/linux-user/aarch64/cpu_loop.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(sve_ldhds_zd, TCG_CALL_NO_WG,
15
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
18
DEF_HELPER_FLAGS_6(sve_ldsds_zd, TCG_CALL_NO_WG,
16
19
void, env, ptr, ptr, ptr, tl, i32)
17
switch (trapnr) {
20
18
case EXCP_SWI:
21
+DEF_HELPER_FLAGS_6(sve_ldffbsu_zsu, TCG_CALL_NO_WG,
19
+ /*
22
+ void, env, ptr, ptr, ptr, tl, i32)
20
+ * On syscall, PSTATE.ZA is preserved, along with the ZA matrix.
23
+DEF_HELPER_FLAGS_6(sve_ldffhsu_zsu, TCG_CALL_NO_WG,
21
+ * PSTATE.SM is cleared, per SMSTOP, which does ResetSVEState.
24
+ void, env, ptr, ptr, ptr, tl, i32)
22
+ */
25
+DEF_HELPER_FLAGS_6(sve_ldffssu_zsu, TCG_CALL_NO_WG,
23
+ if (FIELD_EX64(env->svcr, SVCR, SM)) {
26
+ void, env, ptr, ptr, ptr, tl, i32)
24
+ env->svcr = FIELD_DP64(env->svcr, SVCR, SM, 0);
27
+DEF_HELPER_FLAGS_6(sve_ldffbss_zsu, TCG_CALL_NO_WG,
25
+ arm_rebuild_hflags(env);
28
+ void, env, ptr, ptr, ptr, tl, i32)
26
+ arm_reset_sve_state(env);
29
+DEF_HELPER_FLAGS_6(sve_ldffhss_zsu, TCG_CALL_NO_WG,
27
+ }
30
+ void, env, ptr, ptr, ptr, tl, i32)
28
ret = do_syscall(env,
31
+
29
env->xregs[8],
32
+DEF_HELPER_FLAGS_6(sve_ldffbsu_zss, TCG_CALL_NO_WG,
30
env->xregs[0],
33
+ void, env, ptr, ptr, ptr, tl, i32)
34
+DEF_HELPER_FLAGS_6(sve_ldffhsu_zss, TCG_CALL_NO_WG,
35
+ void, env, ptr, ptr, ptr, tl, i32)
36
+DEF_HELPER_FLAGS_6(sve_ldffssu_zss, TCG_CALL_NO_WG,
37
+ void, env, ptr, ptr, ptr, tl, i32)
38
+DEF_HELPER_FLAGS_6(sve_ldffbss_zss, TCG_CALL_NO_WG,
39
+ void, env, ptr, ptr, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_6(sve_ldffhss_zss, TCG_CALL_NO_WG,
41
+ void, env, ptr, ptr, ptr, tl, i32)
42
+
43
+DEF_HELPER_FLAGS_6(sve_ldffbdu_zsu, TCG_CALL_NO_WG,
44
+ void, env, ptr, ptr, ptr, tl, i32)
45
+DEF_HELPER_FLAGS_6(sve_ldffhdu_zsu, TCG_CALL_NO_WG,
46
+ void, env, ptr, ptr, ptr, tl, i32)
47
+DEF_HELPER_FLAGS_6(sve_ldffsdu_zsu, TCG_CALL_NO_WG,
48
+ void, env, ptr, ptr, ptr, tl, i32)
49
+DEF_HELPER_FLAGS_6(sve_ldffddu_zsu, TCG_CALL_NO_WG,
50
+ void, env, ptr, ptr, ptr, tl, i32)
51
+DEF_HELPER_FLAGS_6(sve_ldffbds_zsu, TCG_CALL_NO_WG,
52
+ void, env, ptr, ptr, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_6(sve_ldffhds_zsu, TCG_CALL_NO_WG,
54
+ void, env, ptr, ptr, ptr, tl, i32)
55
+DEF_HELPER_FLAGS_6(sve_ldffsds_zsu, TCG_CALL_NO_WG,
56
+ void, env, ptr, ptr, ptr, tl, i32)
57
+
58
+DEF_HELPER_FLAGS_6(sve_ldffbdu_zss, TCG_CALL_NO_WG,
59
+ void, env, ptr, ptr, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_6(sve_ldffhdu_zss, TCG_CALL_NO_WG,
61
+ void, env, ptr, ptr, ptr, tl, i32)
62
+DEF_HELPER_FLAGS_6(sve_ldffsdu_zss, TCG_CALL_NO_WG,
63
+ void, env, ptr, ptr, ptr, tl, i32)
64
+DEF_HELPER_FLAGS_6(sve_ldffddu_zss, TCG_CALL_NO_WG,
65
+ void, env, ptr, ptr, ptr, tl, i32)
66
+DEF_HELPER_FLAGS_6(sve_ldffbds_zss, TCG_CALL_NO_WG,
67
+ void, env, ptr, ptr, ptr, tl, i32)
68
+DEF_HELPER_FLAGS_6(sve_ldffhds_zss, TCG_CALL_NO_WG,
69
+ void, env, ptr, ptr, ptr, tl, i32)
70
+DEF_HELPER_FLAGS_6(sve_ldffsds_zss, TCG_CALL_NO_WG,
71
+ void, env, ptr, ptr, ptr, tl, i32)
72
+
73
+DEF_HELPER_FLAGS_6(sve_ldffbdu_zd, TCG_CALL_NO_WG,
74
+ void, env, ptr, ptr, ptr, tl, i32)
75
+DEF_HELPER_FLAGS_6(sve_ldffhdu_zd, TCG_CALL_NO_WG,
76
+ void, env, ptr, ptr, ptr, tl, i32)
77
+DEF_HELPER_FLAGS_6(sve_ldffsdu_zd, TCG_CALL_NO_WG,
78
+ void, env, ptr, ptr, ptr, tl, i32)
79
+DEF_HELPER_FLAGS_6(sve_ldffddu_zd, TCG_CALL_NO_WG,
80
+ void, env, ptr, ptr, ptr, tl, i32)
81
+DEF_HELPER_FLAGS_6(sve_ldffbds_zd, TCG_CALL_NO_WG,
82
+ void, env, ptr, ptr, ptr, tl, i32)
83
+DEF_HELPER_FLAGS_6(sve_ldffhds_zd, TCG_CALL_NO_WG,
84
+ void, env, ptr, ptr, ptr, tl, i32)
85
+DEF_HELPER_FLAGS_6(sve_ldffsds_zd, TCG_CALL_NO_WG,
86
+ void, env, ptr, ptr, ptr, tl, i32)
87
+
88
DEF_HELPER_FLAGS_6(sve_stbs_zsu, TCG_CALL_NO_WG,
89
void, env, ptr, ptr, ptr, tl, i32)
90
DEF_HELPER_FLAGS_6(sve_sths_zsu, TCG_CALL_NO_WG,
91
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/target/arm/sve_helper.c
94
+++ b/target/arm/sve_helper.c
95
@@ -XXX,XX +XXX,XX @@ DO_LD1_ZPZ_D(sve_ldbds_zd, uint64_t, int8_t, cpu_ldub_data_ra)
96
DO_LD1_ZPZ_D(sve_ldhds_zd, uint64_t, int16_t, cpu_lduw_data_ra)
97
DO_LD1_ZPZ_D(sve_ldsds_zd, uint64_t, int32_t, cpu_ldl_data_ra)
98
99
+/* First fault loads with a vector index. */
100
+
101
+#ifdef CONFIG_USER_ONLY
102
+
103
+#define DO_LDFF1_ZPZ(NAME, TYPEE, TYPEI, TYPEM, FN, H) \
104
+void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
105
+ target_ulong base, uint32_t desc) \
106
+{ \
107
+ intptr_t i, oprsz = simd_oprsz(desc); \
108
+ unsigned scale = simd_data(desc); \
109
+ uintptr_t ra = GETPC(); \
110
+ bool first = true; \
111
+ mmap_lock(); \
112
+ for (i = 0; i < oprsz; i++) { \
113
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
114
+ do { \
115
+ TYPEM m = 0; \
116
+ if (pg & 1) { \
117
+ target_ulong off = *(TYPEI *)(vm + H(i)); \
118
+ target_ulong addr = base + (off << scale); \
119
+ if (!first && \
120
+ page_check_range(addr, sizeof(TYPEM), PAGE_READ)) { \
121
+ record_fault(env, i, oprsz); \
122
+ goto exit; \
123
+ } \
124
+ m = FN(env, addr, ra); \
125
+ first = false; \
126
+ } \
127
+ *(TYPEE *)(vd + H(i)) = m; \
128
+ i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
129
+ } while (i & 15); \
130
+ } \
131
+ exit: \
132
+ mmap_unlock(); \
133
+}
134
+
135
+#else
136
+
137
+#define DO_LDFF1_ZPZ(NAME, TYPEE, TYPEI, TYPEM, FN, H) \
138
+void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
139
+ target_ulong base, uint32_t desc) \
140
+{ \
141
+ g_assert_not_reached(); \
142
+}
143
+
144
+#endif
145
+
146
+#define DO_LDFF1_ZPZ_S(NAME, TYPEI, TYPEM, FN) \
147
+ DO_LDFF1_ZPZ(NAME, uint32_t, TYPEI, TYPEM, FN, H1_4)
148
+#define DO_LDFF1_ZPZ_D(NAME, TYPEI, TYPEM, FN) \
149
+ DO_LDFF1_ZPZ(NAME, uint64_t, TYPEI, TYPEM, FN, )
150
+
151
+DO_LDFF1_ZPZ_S(sve_ldffbsu_zsu, uint32_t, uint8_t, cpu_ldub_data_ra)
152
+DO_LDFF1_ZPZ_S(sve_ldffhsu_zsu, uint32_t, uint16_t, cpu_lduw_data_ra)
153
+DO_LDFF1_ZPZ_S(sve_ldffssu_zsu, uint32_t, uint32_t, cpu_ldl_data_ra)
154
+DO_LDFF1_ZPZ_S(sve_ldffbss_zsu, uint32_t, int8_t, cpu_ldub_data_ra)
155
+DO_LDFF1_ZPZ_S(sve_ldffhss_zsu, uint32_t, int16_t, cpu_lduw_data_ra)
156
+
157
+DO_LDFF1_ZPZ_S(sve_ldffbsu_zss, int32_t, uint8_t, cpu_ldub_data_ra)
158
+DO_LDFF1_ZPZ_S(sve_ldffhsu_zss, int32_t, uint16_t, cpu_lduw_data_ra)
159
+DO_LDFF1_ZPZ_S(sve_ldffssu_zss, int32_t, uint32_t, cpu_ldl_data_ra)
160
+DO_LDFF1_ZPZ_S(sve_ldffbss_zss, int32_t, int8_t, cpu_ldub_data_ra)
161
+DO_LDFF1_ZPZ_S(sve_ldffhss_zss, int32_t, int16_t, cpu_lduw_data_ra)
162
+
163
+DO_LDFF1_ZPZ_D(sve_ldffbdu_zsu, uint32_t, uint8_t, cpu_ldub_data_ra)
164
+DO_LDFF1_ZPZ_D(sve_ldffhdu_zsu, uint32_t, uint16_t, cpu_lduw_data_ra)
165
+DO_LDFF1_ZPZ_D(sve_ldffsdu_zsu, uint32_t, uint32_t, cpu_ldl_data_ra)
166
+DO_LDFF1_ZPZ_D(sve_ldffddu_zsu, uint32_t, uint64_t, cpu_ldq_data_ra)
167
+DO_LDFF1_ZPZ_D(sve_ldffbds_zsu, uint32_t, int8_t, cpu_ldub_data_ra)
168
+DO_LDFF1_ZPZ_D(sve_ldffhds_zsu, uint32_t, int16_t, cpu_lduw_data_ra)
169
+DO_LDFF1_ZPZ_D(sve_ldffsds_zsu, uint32_t, int32_t, cpu_ldl_data_ra)
170
+
171
+DO_LDFF1_ZPZ_D(sve_ldffbdu_zss, int32_t, uint8_t, cpu_ldub_data_ra)
172
+DO_LDFF1_ZPZ_D(sve_ldffhdu_zss, int32_t, uint16_t, cpu_lduw_data_ra)
173
+DO_LDFF1_ZPZ_D(sve_ldffsdu_zss, int32_t, uint32_t, cpu_ldl_data_ra)
174
+DO_LDFF1_ZPZ_D(sve_ldffddu_zss, int32_t, uint64_t, cpu_ldq_data_ra)
175
+DO_LDFF1_ZPZ_D(sve_ldffbds_zss, int32_t, int8_t, cpu_ldub_data_ra)
176
+DO_LDFF1_ZPZ_D(sve_ldffhds_zss, int32_t, int16_t, cpu_lduw_data_ra)
177
+DO_LDFF1_ZPZ_D(sve_ldffsds_zss, int32_t, int32_t, cpu_ldl_data_ra)
178
+
179
+DO_LDFF1_ZPZ_D(sve_ldffbdu_zd, uint64_t, uint8_t, cpu_ldub_data_ra)
180
+DO_LDFF1_ZPZ_D(sve_ldffhdu_zd, uint64_t, uint16_t, cpu_lduw_data_ra)
181
+DO_LDFF1_ZPZ_D(sve_ldffsdu_zd, uint64_t, uint32_t, cpu_ldl_data_ra)
182
+DO_LDFF1_ZPZ_D(sve_ldffddu_zd, uint64_t, uint64_t, cpu_ldq_data_ra)
183
+DO_LDFF1_ZPZ_D(sve_ldffbds_zd, uint64_t, int8_t, cpu_ldub_data_ra)
184
+DO_LDFF1_ZPZ_D(sve_ldffhds_zd, uint64_t, int16_t, cpu_lduw_data_ra)
185
+DO_LDFF1_ZPZ_D(sve_ldffsds_zd, uint64_t, int32_t, cpu_ldl_data_ra)
186
+
187
/* Stores with a vector index. */
188
189
#define DO_ST1_ZPZ_S(NAME, TYPEI, FN) \
190
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/target/arm/translate-sve.c
193
+++ b/target/arm/translate-sve.c
194
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_mem_scatter * const gather_load_fn32[2][2][2][3] = {
195
{ gen_helper_sve_ldbsu_zss,
196
gen_helper_sve_ldhsu_zss,
197
gen_helper_sve_ldssu_zss, } } },
198
- /* TODO fill in first-fault handlers */
199
+
200
+ { { { gen_helper_sve_ldffbss_zsu,
201
+ gen_helper_sve_ldffhss_zsu,
202
+ NULL, },
203
+ { gen_helper_sve_ldffbsu_zsu,
204
+ gen_helper_sve_ldffhsu_zsu,
205
+ gen_helper_sve_ldffssu_zsu, } },
206
+ { { gen_helper_sve_ldffbss_zss,
207
+ gen_helper_sve_ldffhss_zss,
208
+ NULL, },
209
+ { gen_helper_sve_ldffbsu_zss,
210
+ gen_helper_sve_ldffhsu_zss,
211
+ gen_helper_sve_ldffssu_zss, } } }
212
};
213
214
/* Note that we overload xs=2 to indicate 64-bit offset. */
215
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_mem_scatter * const gather_load_fn64[2][3][2][4] = {
216
gen_helper_sve_ldhdu_zd,
217
gen_helper_sve_ldsdu_zd,
218
gen_helper_sve_ldddu_zd, } } },
219
- /* TODO fill in first-fault handlers */
220
+
221
+ { { { gen_helper_sve_ldffbds_zsu,
222
+ gen_helper_sve_ldffhds_zsu,
223
+ gen_helper_sve_ldffsds_zsu,
224
+ NULL, },
225
+ { gen_helper_sve_ldffbdu_zsu,
226
+ gen_helper_sve_ldffhdu_zsu,
227
+ gen_helper_sve_ldffsdu_zsu,
228
+ gen_helper_sve_ldffddu_zsu, } },
229
+ { { gen_helper_sve_ldffbds_zss,
230
+ gen_helper_sve_ldffhds_zss,
231
+ gen_helper_sve_ldffsds_zss,
232
+ NULL, },
233
+ { gen_helper_sve_ldffbdu_zss,
234
+ gen_helper_sve_ldffhdu_zss,
235
+ gen_helper_sve_ldffsdu_zss,
236
+ gen_helper_sve_ldffddu_zss, } },
237
+ { { gen_helper_sve_ldffbds_zd,
238
+ gen_helper_sve_ldffhds_zd,
239
+ gen_helper_sve_ldffsds_zd,
240
+ NULL, },
241
+ { gen_helper_sve_ldffbdu_zd,
242
+ gen_helper_sve_ldffhdu_zd,
243
+ gen_helper_sve_ldffsdu_zd,
244
+ gen_helper_sve_ldffddu_zd, } } }
245
};
246
247
static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn)
248
--
31
--
249
2.17.1
32
2.25.1
250
251
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The load/store API will ease further code movement.
3
Make sure to zero the currently reserved fields.
4
4
5
Per the Physical Layer Simplified Spec. "3.6 Bus Protocol":
6
7
"In the CMD line the Most Significant Bit (MSB) is transmitted
8
first, the Least Significant Bit (LSB) is the last."
9
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220708151540.18136-36-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
9
---
14
hw/sd/bcm2835_sdhost.c | 13 +++++--------
10
linux-user/aarch64/signal.c | 9 ++++++++-
15
hw/sd/milkymist-memcard.c | 3 +--
11
1 file changed, 8 insertions(+), 1 deletion(-)
16
hw/sd/omap_mmc.c | 6 ++----
17
hw/sd/pl181.c | 11 ++++-------
18
hw/sd/sdhci.c | 15 +++++----------
19
hw/sd/ssi-sd.c | 6 ++----
20
6 files changed, 19 insertions(+), 35 deletions(-)
21
12
22
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
23
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/sd/bcm2835_sdhost.c
15
--- a/linux-user/aarch64/signal.c
25
+++ b/hw/sd/bcm2835_sdhost.c
16
+++ b/linux-user/aarch64/signal.c
26
@@ -XXX,XX +XXX,XX @@ static void bcm2835_sdhost_send_command(BCM2835SDHostState *s)
17
@@ -XXX,XX +XXX,XX @@ struct target_extra_context {
27
goto error;
18
struct target_sve_context {
28
}
19
struct target_aarch64_ctx head;
29
if (!(s->cmd & SDCMD_NO_RESPONSE)) {
20
uint16_t vl;
30
-#define RWORD(n) (((uint32_t)rsp[n] << 24) | (rsp[n + 1] << 16) \
21
- uint16_t reserved[3];
31
- | (rsp[n + 2] << 8) | rsp[n + 3])
22
+ uint16_t flags;
32
if (rlen == 0 || (rlen == 4 && (s->cmd & SDCMD_LONG_RESPONSE))) {
23
+ uint16_t reserved[2];
33
goto error;
24
/* The actual SVE data immediately follows. It is laid out
34
}
25
* according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of
35
@@ -XXX,XX +XXX,XX @@ static void bcm2835_sdhost_send_command(BCM2835SDHostState *s)
26
* the original struct pointer.
36
goto error;
27
@@ -XXX,XX +XXX,XX @@ struct target_sve_context {
37
}
28
#define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \
38
if (rlen == 4) {
29
(TARGET_SVE_SIG_PREG_OFFSET(VQ, 17))
39
- s->rsp[0] = RWORD(0);
30
40
+ s->rsp[0] = ldl_be_p(&rsp[0]);
31
+#define TARGET_SVE_SIG_FLAG_SM 1
41
s->rsp[1] = s->rsp[2] = s->rsp[3] = 0;
32
+
42
} else {
33
struct target_rt_sigframe {
43
- s->rsp[0] = RWORD(12);
34
struct target_siginfo info;
44
- s->rsp[1] = RWORD(8);
35
struct target_ucontext uc;
45
- s->rsp[2] = RWORD(4);
36
@@ -XXX,XX +XXX,XX @@ static void target_setup_sve_record(struct target_sve_context *sve,
46
- s->rsp[3] = RWORD(0);
37
{
47
+ s->rsp[0] = ldl_be_p(&rsp[12]);
38
int i, j;
48
+ s->rsp[1] = ldl_be_p(&rsp[8]);
39
49
+ s->rsp[2] = ldl_be_p(&rsp[4]);
40
+ memset(sve, 0, sizeof(*sve));
50
+ s->rsp[3] = ldl_be_p(&rsp[0]);
41
__put_user(TARGET_SVE_MAGIC, &sve->head.magic);
51
}
42
__put_user(size, &sve->head.size);
52
-#undef RWORD
43
__put_user(vq * TARGET_SVE_VQ_BYTES, &sve->vl);
53
}
44
+ if (FIELD_EX64(env->svcr, SVCR, SM)) {
54
/* We never really delay commands, so if this was a 'busywait' command
45
+ __put_user(TARGET_SVE_SIG_FLAG_SM, &sve->flags);
55
* then we've completed it now and can raise the interrupt.
46
+ }
56
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
47
57
index XXXXXXX..XXXXXXX 100644
48
/* Note that SVE regs are stored as a byte stream, with each byte element
58
--- a/hw/sd/milkymist-memcard.c
49
* at a subsequent address. This corresponds to a little-endian store
59
+++ b/hw/sd/milkymist-memcard.c
60
@@ -XXX,XX +XXX,XX @@ static void memcard_sd_command(MilkymistMemcardState *s)
61
SDRequest req;
62
63
req.cmd = s->command[0] & 0x3f;
64
- req.arg = (s->command[1] << 24) | (s->command[2] << 16)
65
- | (s->command[3] << 8) | s->command[4];
66
+ req.arg = ldl_be_p(s->command + 1);
67
req.crc = s->command[5];
68
69
s->response[0] = req.cmd;
70
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/hw/sd/omap_mmc.c
73
+++ b/hw/sd/omap_mmc.c
74
@@ -XXX,XX +XXX,XX @@ static void omap_mmc_command(struct omap_mmc_s *host, int cmd, int dir,
75
CID_CSD_OVERWRITE;
76
if (host->sdio & (1 << 13))
77
mask |= AKE_SEQ_ERROR;
78
- rspstatus = (response[0] << 24) | (response[1] << 16) |
79
- (response[2] << 8) | (response[3] << 0);
80
+ rspstatus = ldl_be_p(response);
81
break;
82
83
case sd_r2:
84
@@ -XXX,XX +XXX,XX @@ static void omap_mmc_command(struct omap_mmc_s *host, int cmd, int dir,
85
}
86
rsplen = 4;
87
88
- rspstatus = (response[0] << 24) | (response[1] << 16) |
89
- (response[2] << 8) | (response[3] << 0);
90
+ rspstatus = ldl_be_p(response);
91
if (rspstatus & 0x80000000)
92
host->status &= 0xe000;
93
else
94
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/hw/sd/pl181.c
97
+++ b/hw/sd/pl181.c
98
@@ -XXX,XX +XXX,XX @@ static void pl181_send_command(PL181State *s)
99
if (rlen < 0)
100
goto error;
101
if (s->cmd & PL181_CMD_RESPONSE) {
102
-#define RWORD(n) (((uint32_t)response[n] << 24) | (response[n + 1] << 16) \
103
- | (response[n + 2] << 8) | response[n + 3])
104
if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP)))
105
goto error;
106
if (rlen != 4 && rlen != 16)
107
goto error;
108
- s->response[0] = RWORD(0);
109
+ s->response[0] = ldl_be_p(&response[0]);
110
if (rlen == 4) {
111
s->response[1] = s->response[2] = s->response[3] = 0;
112
} else {
113
- s->response[1] = RWORD(4);
114
- s->response[2] = RWORD(8);
115
- s->response[3] = RWORD(12) & ~1;
116
+ s->response[1] = ldl_be_p(&response[4]);
117
+ s->response[2] = ldl_be_p(&response[8]);
118
+ s->response[3] = ldl_be_p(&response[12]) & ~1;
119
}
120
DPRINTF("Response received\n");
121
s->status |= PL181_STATUS_CMDRESPEND;
122
-#undef RWORD
123
} else {
124
DPRINTF("Command sent\n");
125
s->status |= PL181_STATUS_CMDSENT;
126
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
127
index XXXXXXX..XXXXXXX 100644
128
--- a/hw/sd/sdhci.c
129
+++ b/hw/sd/sdhci.c
130
@@ -XXX,XX +XXX,XX @@ static void sdhci_send_command(SDHCIState *s)
131
132
if (s->cmdreg & SDHC_CMD_RESPONSE) {
133
if (rlen == 4) {
134
- s->rspreg[0] = (response[0] << 24) | (response[1] << 16) |
135
- (response[2] << 8) | response[3];
136
+ s->rspreg[0] = ldl_be_p(response);
137
s->rspreg[1] = s->rspreg[2] = s->rspreg[3] = 0;
138
trace_sdhci_response4(s->rspreg[0]);
139
} else if (rlen == 16) {
140
- s->rspreg[0] = (response[11] << 24) | (response[12] << 16) |
141
- (response[13] << 8) | response[14];
142
- s->rspreg[1] = (response[7] << 24) | (response[8] << 16) |
143
- (response[9] << 8) | response[10];
144
- s->rspreg[2] = (response[3] << 24) | (response[4] << 16) |
145
- (response[5] << 8) | response[6];
146
+ s->rspreg[0] = ldl_be_p(&response[11]);
147
+ s->rspreg[1] = ldl_be_p(&response[7]);
148
+ s->rspreg[2] = ldl_be_p(&response[3]);
149
s->rspreg[3] = (response[0] << 16) | (response[1] << 8) |
150
response[2];
151
trace_sdhci_response16(s->rspreg[3], s->rspreg[2],
152
@@ -XXX,XX +XXX,XX @@ static void sdhci_end_transfer(SDHCIState *s)
153
trace_sdhci_end_transfer(request.cmd, request.arg);
154
sdbus_do_command(&s->sdbus, &request, response);
155
/* Auto CMD12 response goes to the upper Response register */
156
- s->rspreg[3] = (response[0] << 24) | (response[1] << 16) |
157
- (response[2] << 8) | response[3];
158
+ s->rspreg[3] = ldl_be_p(response);
159
}
160
161
s->prnsts &= ~(SDHC_DOING_READ | SDHC_DOING_WRITE |
162
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/hw/sd/ssi-sd.c
165
+++ b/hw/sd/ssi-sd.c
166
@@ -XXX,XX +XXX,XX @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
167
uint8_t longresp[16];
168
/* FIXME: Check CRC. */
169
request.cmd = s->cmd;
170
- request.arg = (s->cmdarg[0] << 24) | (s->cmdarg[1] << 16)
171
- | (s->cmdarg[2] << 8) | s->cmdarg[3];
172
+ request.arg = ldl_be_p(s->cmdarg);
173
DPRINTF("CMD%d arg 0x%08x\n", s->cmd, request.arg);
174
s->arglen = sdbus_do_command(&s->sdbus, &request, longresp);
175
if (s->arglen <= 0) {
176
@@ -XXX,XX +XXX,XX @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
177
/* CMD13 returns a 2-byte statuse work. Other commands
178
only return the first byte. */
179
s->arglen = (s->cmd == 13) ? 2 : 1;
180
- cardstatus = (longresp[0] << 24) | (longresp[1] << 16)
181
- | (longresp[2] << 8) | longresp[3];
182
+ cardstatus = ldl_be_p(longresp);
183
status = 0;
184
if (((cardstatus >> 9) & 0xf) < 4)
185
status |= SSI_SDR_IDLE;
186
--
50
--
187
2.17.1
51
2.25.1
188
189
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Fold the return value setting into the goto, so each
4
point of failure need not do both.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-20-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-37-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper-sve.h | 35 ++++++++++++++++++++++
11
linux-user/aarch64/signal.c | 26 +++++++++++---------------
9
target/arm/sve_helper.c | 61 ++++++++++++++++++++++++++++++++++++++
12
1 file changed, 11 insertions(+), 15 deletions(-)
10
target/arm/translate-sve.c | 57 +++++++++++++++++++++++++++++++++++
11
target/arm/sve.decode | 8 +++++
12
4 files changed, 161 insertions(+)
13
13
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
14
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
16
--- a/linux-user/aarch64/signal.c
17
+++ b/target/arm/helper-sve.h
17
+++ b/linux-user/aarch64/signal.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_rsqrts_s, TCG_CALL_NO_RWG,
18
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
19
DEF_HELPER_FLAGS_5(gvec_rsqrts_d, TCG_CALL_NO_RWG,
19
struct target_sve_context *sve = NULL;
20
void, ptr, ptr, ptr, ptr, i32)
20
uint64_t extra_datap = 0;
21
21
bool used_extra = false;
22
+DEF_HELPER_FLAGS_4(sve_faddv_h, TCG_CALL_NO_RWG,
22
- bool err = false;
23
+ i64, ptr, ptr, ptr, i32)
23
int vq = 0, sve_size = 0;
24
+DEF_HELPER_FLAGS_4(sve_faddv_s, TCG_CALL_NO_RWG,
24
25
+ i64, ptr, ptr, ptr, i32)
25
target_restore_general_frame(env, sf);
26
+DEF_HELPER_FLAGS_4(sve_faddv_d, TCG_CALL_NO_RWG,
26
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
27
+ i64, ptr, ptr, ptr, i32)
27
switch (magic) {
28
case 0:
29
if (size != 0) {
30
- err = true;
31
- goto exit;
32
+ goto err;
33
}
34
if (used_extra) {
35
ctx = NULL;
36
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
37
38
case TARGET_FPSIMD_MAGIC:
39
if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
40
- err = true;
41
- goto exit;
42
+ goto err;
43
}
44
fpsimd = (struct target_fpsimd_context *)ctx;
45
break;
46
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
47
break;
48
}
49
}
50
- err = true;
51
- goto exit;
52
+ goto err;
53
54
case TARGET_EXTRA_MAGIC:
55
if (extra || size != sizeof(struct target_extra_context)) {
56
- err = true;
57
- goto exit;
58
+ goto err;
59
}
60
__get_user(extra_datap,
61
&((struct target_extra_context *)ctx)->datap);
62
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
63
/* Unknown record -- we certainly didn't generate it.
64
* Did we in fact get out of sync?
65
*/
66
- err = true;
67
- goto exit;
68
+ goto err;
69
}
70
ctx = (void *)ctx + size;
71
}
72
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
73
if (fpsimd) {
74
target_restore_fpsimd_record(env, fpsimd);
75
} else {
76
- err = true;
77
+ goto err;
78
}
79
80
/* SVE data, if present, overwrites FPSIMD data. */
81
if (sve) {
82
target_restore_sve_record(env, sve, vq);
83
}
84
-
85
- exit:
86
unlock_user(extra, extra_datap, 0);
87
- return err;
88
+ return 0;
28
+
89
+
29
+DEF_HELPER_FLAGS_4(sve_fmaxnmv_h, TCG_CALL_NO_RWG,
90
+ err:
30
+ i64, ptr, ptr, ptr, i32)
91
+ unlock_user(extra, extra_datap, 0);
31
+DEF_HELPER_FLAGS_4(sve_fmaxnmv_s, TCG_CALL_NO_RWG,
92
+ return 1;
32
+ i64, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_4(sve_fmaxnmv_d, TCG_CALL_NO_RWG,
34
+ i64, ptr, ptr, ptr, i32)
35
+
36
+DEF_HELPER_FLAGS_4(sve_fminnmv_h, TCG_CALL_NO_RWG,
37
+ i64, ptr, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_4(sve_fminnmv_s, TCG_CALL_NO_RWG,
39
+ i64, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_4(sve_fminnmv_d, TCG_CALL_NO_RWG,
41
+ i64, ptr, ptr, ptr, i32)
42
+
43
+DEF_HELPER_FLAGS_4(sve_fmaxv_h, TCG_CALL_NO_RWG,
44
+ i64, ptr, ptr, ptr, i32)
45
+DEF_HELPER_FLAGS_4(sve_fmaxv_s, TCG_CALL_NO_RWG,
46
+ i64, ptr, ptr, ptr, i32)
47
+DEF_HELPER_FLAGS_4(sve_fmaxv_d, TCG_CALL_NO_RWG,
48
+ i64, ptr, ptr, ptr, i32)
49
+
50
+DEF_HELPER_FLAGS_4(sve_fminv_h, TCG_CALL_NO_RWG,
51
+ i64, ptr, ptr, ptr, i32)
52
+DEF_HELPER_FLAGS_4(sve_fminv_s, TCG_CALL_NO_RWG,
53
+ i64, ptr, ptr, ptr, i32)
54
+DEF_HELPER_FLAGS_4(sve_fminv_d, TCG_CALL_NO_RWG,
55
+ i64, ptr, ptr, ptr, i32)
56
+
57
DEF_HELPER_FLAGS_5(sve_fadda_h, TCG_CALL_NO_RWG,
58
i64, i64, ptr, ptr, ptr, i32)
59
DEF_HELPER_FLAGS_5(sve_fadda_s, TCG_CALL_NO_RWG,
60
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/sve_helper.c
63
+++ b/target/arm/sve_helper.c
64
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sve_while)(void *vd, uint32_t count, uint32_t pred_desc)
65
return predtest_ones(d, oprsz, esz_mask);
66
}
93
}
67
94
68
+/* Recursive reduction on a function;
95
static abi_ulong get_sigframe(struct target_sigaction *ka,
69
+ * C.f. the ARM ARM function ReducePredicated.
70
+ *
71
+ * While it would be possible to write this without the DATA temporary,
72
+ * it is much simpler to process the predicate register this way.
73
+ * The recursion is bounded to depth 7 (128 fp16 elements), so there's
74
+ * little to gain with a more complex non-recursive form.
75
+ */
76
+#define DO_REDUCE(NAME, TYPE, H, FUNC, IDENT) \
77
+static TYPE NAME##_reduce(TYPE *data, float_status *status, uintptr_t n) \
78
+{ \
79
+ if (n == 1) { \
80
+ return *data; \
81
+ } else { \
82
+ uintptr_t half = n / 2; \
83
+ TYPE lo = NAME##_reduce(data, status, half); \
84
+ TYPE hi = NAME##_reduce(data + half, status, half); \
85
+ return TYPE##_##FUNC(lo, hi, status); \
86
+ } \
87
+} \
88
+uint64_t HELPER(NAME)(void *vn, void *vg, void *vs, uint32_t desc) \
89
+{ \
90
+ uintptr_t i, oprsz = simd_oprsz(desc), maxsz = simd_maxsz(desc); \
91
+ TYPE data[sizeof(ARMVectorReg) / sizeof(TYPE)]; \
92
+ for (i = 0; i < oprsz; ) { \
93
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
94
+ do { \
95
+ TYPE nn = *(TYPE *)(vn + H(i)); \
96
+ *(TYPE *)((void *)data + i) = (pg & 1 ? nn : IDENT); \
97
+ i += sizeof(TYPE), pg >>= sizeof(TYPE); \
98
+ } while (i & 15); \
99
+ } \
100
+ for (; i < maxsz; i += sizeof(TYPE)) { \
101
+ *(TYPE *)((void *)data + i) = IDENT; \
102
+ } \
103
+ return NAME##_reduce(data, vs, maxsz / sizeof(TYPE)); \
104
+}
105
+
106
+DO_REDUCE(sve_faddv_h, float16, H1_2, add, float16_zero)
107
+DO_REDUCE(sve_faddv_s, float32, H1_4, add, float32_zero)
108
+DO_REDUCE(sve_faddv_d, float64, , add, float64_zero)
109
+
110
+/* Identity is floatN_default_nan, without the function call. */
111
+DO_REDUCE(sve_fminnmv_h, float16, H1_2, minnum, 0x7E00)
112
+DO_REDUCE(sve_fminnmv_s, float32, H1_4, minnum, 0x7FC00000)
113
+DO_REDUCE(sve_fminnmv_d, float64, , minnum, 0x7FF8000000000000ULL)
114
+
115
+DO_REDUCE(sve_fmaxnmv_h, float16, H1_2, maxnum, 0x7E00)
116
+DO_REDUCE(sve_fmaxnmv_s, float32, H1_4, maxnum, 0x7FC00000)
117
+DO_REDUCE(sve_fmaxnmv_d, float64, , maxnum, 0x7FF8000000000000ULL)
118
+
119
+DO_REDUCE(sve_fminv_h, float16, H1_2, min, float16_infinity)
120
+DO_REDUCE(sve_fminv_s, float32, H1_4, min, float32_infinity)
121
+DO_REDUCE(sve_fminv_d, float64, , min, float64_infinity)
122
+
123
+DO_REDUCE(sve_fmaxv_h, float16, H1_2, max, float16_chs(float16_infinity))
124
+DO_REDUCE(sve_fmaxv_s, float32, H1_4, max, float32_chs(float32_infinity))
125
+DO_REDUCE(sve_fmaxv_d, float64, , max, float64_chs(float64_infinity))
126
+
127
+#undef DO_REDUCE
128
+
129
uint64_t HELPER(sve_fadda_h)(uint64_t nn, void *vm, void *vg,
130
void *status, uint32_t desc)
131
{
132
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/target/arm/translate-sve.c
135
+++ b/target/arm/translate-sve.c
136
@@ -XXX,XX +XXX,XX @@ static bool trans_FMUL_zzx(DisasContext *s, arg_FMUL_zzx *a, uint32_t insn)
137
return true;
138
}
139
140
+/*
141
+ *** SVE Floating Point Fast Reduction Group
142
+ */
143
+
144
+typedef void gen_helper_fp_reduce(TCGv_i64, TCGv_ptr, TCGv_ptr,
145
+ TCGv_ptr, TCGv_i32);
146
+
147
+static void do_reduce(DisasContext *s, arg_rpr_esz *a,
148
+ gen_helper_fp_reduce *fn)
149
+{
150
+ unsigned vsz = vec_full_reg_size(s);
151
+ unsigned p2vsz = pow2ceil(vsz);
152
+ TCGv_i32 t_desc = tcg_const_i32(simd_desc(vsz, p2vsz, 0));
153
+ TCGv_ptr t_zn, t_pg, status;
154
+ TCGv_i64 temp;
155
+
156
+ temp = tcg_temp_new_i64();
157
+ t_zn = tcg_temp_new_ptr();
158
+ t_pg = tcg_temp_new_ptr();
159
+
160
+ tcg_gen_addi_ptr(t_zn, cpu_env, vec_full_reg_offset(s, a->rn));
161
+ tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, a->pg));
162
+ status = get_fpstatus_ptr(a->esz == MO_16);
163
+
164
+ fn(temp, t_zn, t_pg, status, t_desc);
165
+ tcg_temp_free_ptr(t_zn);
166
+ tcg_temp_free_ptr(t_pg);
167
+ tcg_temp_free_ptr(status);
168
+ tcg_temp_free_i32(t_desc);
169
+
170
+ write_fp_dreg(s, a->rd, temp);
171
+ tcg_temp_free_i64(temp);
172
+}
173
+
174
+#define DO_VPZ(NAME, name) \
175
+static bool trans_##NAME(DisasContext *s, arg_rpr_esz *a, uint32_t insn) \
176
+{ \
177
+ static gen_helper_fp_reduce * const fns[3] = { \
178
+ gen_helper_sve_##name##_h, \
179
+ gen_helper_sve_##name##_s, \
180
+ gen_helper_sve_##name##_d, \
181
+ }; \
182
+ if (a->esz == 0) { \
183
+ return false; \
184
+ } \
185
+ if (sve_access_check(s)) { \
186
+ do_reduce(s, a, fns[a->esz - 1]); \
187
+ } \
188
+ return true; \
189
+}
190
+
191
+DO_VPZ(FADDV, faddv)
192
+DO_VPZ(FMINNMV, fminnmv)
193
+DO_VPZ(FMAXNMV, fmaxnmv)
194
+DO_VPZ(FMINV, fminv)
195
+DO_VPZ(FMAXV, fmaxv)
196
+
197
/*
198
*** SVE Floating Point Accumulating Reduction Group
199
*/
200
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
201
index XXXXXXX..XXXXXXX 100644
202
--- a/target/arm/sve.decode
203
+++ b/target/arm/sve.decode
204
@@ -XXX,XX +XXX,XX @@ FMUL_zzx 01100100 0.1 .. rm:3 001000 rn:5 rd:5 \
205
FMUL_zzx 01100100 101 index:2 rm:3 001000 rn:5 rd:5 esz=2
206
FMUL_zzx 01100100 111 index:1 rm:4 001000 rn:5 rd:5 esz=3
207
208
+### SVE FP Fast Reduction Group
209
+
210
+FADDV 01100101 .. 000 000 001 ... ..... ..... @rd_pg_rn
211
+FMAXNMV 01100101 .. 000 100 001 ... ..... ..... @rd_pg_rn
212
+FMINNMV 01100101 .. 000 101 001 ... ..... ..... @rd_pg_rn
213
+FMAXV 01100101 .. 000 110 001 ... ..... ..... @rd_pg_rn
214
+FMINV 01100101 .. 000 111 001 ... ..... ..... @rd_pg_rn
215
+
216
### SVE FP Accumulating Reduction Group
217
218
# SVE floating-point serial reduction (predicated)
219
--
96
--
220
2.17.1
97
2.25.1
221
222
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We already check for the same condition within the normal integer
3
In parse_user_sigframe, the kernel rejects duplicate sve records,
4
sdiv and sdiv64 helpers. Use a slightly different formation that
4
or records that are smaller than the header. We were silently
5
does not require deducing the expression type.
5
allowing these cases to pass, dropping the record.
6
6
7
Fixes: f97cfd596ed
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20220708151540.18136-38-richard.henderson@linaro.org
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20180629001538.11415-2-richard.henderson@linaro.org
12
[PMM: reworded a comment]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
11
---
15
target/arm/sve_helper.c | 20 +++++++++++++++-----
12
linux-user/aarch64/signal.c | 5 ++++-
16
1 file changed, 15 insertions(+), 5 deletions(-)
13
1 file changed, 4 insertions(+), 1 deletion(-)
17
14
18
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
15
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/sve_helper.c
17
--- a/linux-user/aarch64/signal.c
21
+++ b/target/arm/sve_helper.c
18
+++ b/linux-user/aarch64/signal.c
22
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \
19
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
23
#define DO_MIN(N, M) ((N) >= (M) ? (M) : (N))
20
break;
24
#define DO_ABD(N, M) ((N) >= (M) ? (N) - (M) : (M) - (N))
21
25
#define DO_MUL(N, M) (N * M)
22
case TARGET_SVE_MAGIC:
26
-#define DO_DIV(N, M) (M ? N / M : 0)
23
+ if (sve || size < sizeof(struct target_sve_context)) {
27
+
24
+ goto err;
28
+
25
+ }
29
+/*
26
if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
30
+ * We must avoid the C undefined behaviour cases: division by
27
vq = sve_vq(env);
31
+ * zero and signed division of INT_MIN by -1. Both of these
28
sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
32
+ * have architecturally defined required results for Arm.
29
- if (!sve && size == sve_size) {
33
+ * We special case all signed divisions by -1 to avoid having
30
+ if (size == sve_size) {
34
+ * to deduce the minimum integer for the type involved.
31
sve = (struct target_sve_context *)ctx;
35
+ */
32
break;
36
+#define DO_SDIV(N, M) (unlikely(M == 0) ? 0 : unlikely(M == -1) ? -N : N / M)
33
}
37
+#define DO_UDIV(N, M) (unlikely(M == 0) ? 0 : N / M)
38
39
DO_ZPZZ(sve_and_zpzz_b, uint8_t, H1, DO_AND)
40
DO_ZPZZ(sve_and_zpzz_h, uint16_t, H1_2, DO_AND)
41
@@ -XXX,XX +XXX,XX @@ DO_ZPZZ(sve_umulh_zpzz_h, uint16_t, H1_2, do_mulh_h)
42
DO_ZPZZ(sve_umulh_zpzz_s, uint32_t, H1_4, do_mulh_s)
43
DO_ZPZZ_D(sve_umulh_zpzz_d, uint64_t, do_umulh_d)
44
45
-DO_ZPZZ(sve_sdiv_zpzz_s, int32_t, H1_4, DO_DIV)
46
-DO_ZPZZ_D(sve_sdiv_zpzz_d, int64_t, DO_DIV)
47
+DO_ZPZZ(sve_sdiv_zpzz_s, int32_t, H1_4, DO_SDIV)
48
+DO_ZPZZ_D(sve_sdiv_zpzz_d, int64_t, DO_SDIV)
49
50
-DO_ZPZZ(sve_udiv_zpzz_s, uint32_t, H1_4, DO_DIV)
51
-DO_ZPZZ_D(sve_udiv_zpzz_d, uint64_t, DO_DIV)
52
+DO_ZPZZ(sve_udiv_zpzz_s, uint32_t, H1_4, DO_UDIV)
53
+DO_ZPZZ_D(sve_udiv_zpzz_d, uint64_t, DO_UDIV)
54
55
/* Note that all bits of the shift are significant
56
and not modulo the element size. */
57
--
34
--
58
2.17.1
35
2.25.1
59
60
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-18-richard.henderson@linaro.org
5
Message-id: 20220708151540.18136-39-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
7
---
8
target/arm/helper-sve.h | 56 ++++++++++++++++++++++++++++
8
linux-user/aarch64/signal.c | 3 +++
9
target/arm/sve_helper.c | 69 +++++++++++++++++++++++++++++++++++
9
1 file changed, 3 insertions(+)
10
target/arm/translate-sve.c | 75 ++++++++++++++++++++++++++++++++++++++
11
target/arm/sve.decode | 14 +++++++
12
4 files changed, 214 insertions(+)
13
10
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
11
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
13
--- a/linux-user/aarch64/signal.c
17
+++ b/target/arm/helper-sve.h
14
+++ b/linux-user/aarch64/signal.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(sve_fmulx_s, TCG_CALL_NO_RWG,
15
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
19
DEF_HELPER_FLAGS_6(sve_fmulx_d, TCG_CALL_NO_RWG,
16
__get_user(extra_size,
20
void, ptr, ptr, ptr, ptr, ptr, i32)
17
&((struct target_extra_context *)ctx)->size);
21
18
extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
22
+DEF_HELPER_FLAGS_6(sve_fadds_h, TCG_CALL_NO_RWG,
19
+ if (!extra) {
23
+ void, ptr, ptr, ptr, i64, ptr, i32)
20
+ return 1;
24
+DEF_HELPER_FLAGS_6(sve_fadds_s, TCG_CALL_NO_RWG,
21
+ }
25
+ void, ptr, ptr, ptr, i64, ptr, i32)
22
break;
26
+DEF_HELPER_FLAGS_6(sve_fadds_d, TCG_CALL_NO_RWG,
23
27
+ void, ptr, ptr, ptr, i64, ptr, i32)
24
default:
28
+
29
+DEF_HELPER_FLAGS_6(sve_fsubs_h, TCG_CALL_NO_RWG,
30
+ void, ptr, ptr, ptr, i64, ptr, i32)
31
+DEF_HELPER_FLAGS_6(sve_fsubs_s, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, i64, ptr, i32)
33
+DEF_HELPER_FLAGS_6(sve_fsubs_d, TCG_CALL_NO_RWG,
34
+ void, ptr, ptr, ptr, i64, ptr, i32)
35
+
36
+DEF_HELPER_FLAGS_6(sve_fmuls_h, TCG_CALL_NO_RWG,
37
+ void, ptr, ptr, ptr, i64, ptr, i32)
38
+DEF_HELPER_FLAGS_6(sve_fmuls_s, TCG_CALL_NO_RWG,
39
+ void, ptr, ptr, ptr, i64, ptr, i32)
40
+DEF_HELPER_FLAGS_6(sve_fmuls_d, TCG_CALL_NO_RWG,
41
+ void, ptr, ptr, ptr, i64, ptr, i32)
42
+
43
+DEF_HELPER_FLAGS_6(sve_fsubrs_h, TCG_CALL_NO_RWG,
44
+ void, ptr, ptr, ptr, i64, ptr, i32)
45
+DEF_HELPER_FLAGS_6(sve_fsubrs_s, TCG_CALL_NO_RWG,
46
+ void, ptr, ptr, ptr, i64, ptr, i32)
47
+DEF_HELPER_FLAGS_6(sve_fsubrs_d, TCG_CALL_NO_RWG,
48
+ void, ptr, ptr, ptr, i64, ptr, i32)
49
+
50
+DEF_HELPER_FLAGS_6(sve_fmaxnms_h, TCG_CALL_NO_RWG,
51
+ void, ptr, ptr, ptr, i64, ptr, i32)
52
+DEF_HELPER_FLAGS_6(sve_fmaxnms_s, TCG_CALL_NO_RWG,
53
+ void, ptr, ptr, ptr, i64, ptr, i32)
54
+DEF_HELPER_FLAGS_6(sve_fmaxnms_d, TCG_CALL_NO_RWG,
55
+ void, ptr, ptr, ptr, i64, ptr, i32)
56
+
57
+DEF_HELPER_FLAGS_6(sve_fminnms_h, TCG_CALL_NO_RWG,
58
+ void, ptr, ptr, ptr, i64, ptr, i32)
59
+DEF_HELPER_FLAGS_6(sve_fminnms_s, TCG_CALL_NO_RWG,
60
+ void, ptr, ptr, ptr, i64, ptr, i32)
61
+DEF_HELPER_FLAGS_6(sve_fminnms_d, TCG_CALL_NO_RWG,
62
+ void, ptr, ptr, ptr, i64, ptr, i32)
63
+
64
+DEF_HELPER_FLAGS_6(sve_fmaxs_h, TCG_CALL_NO_RWG,
65
+ void, ptr, ptr, ptr, i64, ptr, i32)
66
+DEF_HELPER_FLAGS_6(sve_fmaxs_s, TCG_CALL_NO_RWG,
67
+ void, ptr, ptr, ptr, i64, ptr, i32)
68
+DEF_HELPER_FLAGS_6(sve_fmaxs_d, TCG_CALL_NO_RWG,
69
+ void, ptr, ptr, ptr, i64, ptr, i32)
70
+
71
+DEF_HELPER_FLAGS_6(sve_fmins_h, TCG_CALL_NO_RWG,
72
+ void, ptr, ptr, ptr, i64, ptr, i32)
73
+DEF_HELPER_FLAGS_6(sve_fmins_s, TCG_CALL_NO_RWG,
74
+ void, ptr, ptr, ptr, i64, ptr, i32)
75
+DEF_HELPER_FLAGS_6(sve_fmins_d, TCG_CALL_NO_RWG,
76
+ void, ptr, ptr, ptr, i64, ptr, i32)
77
+
78
DEF_HELPER_FLAGS_5(sve_scvt_hh, TCG_CALL_NO_RWG,
79
void, ptr, ptr, ptr, ptr, i32)
80
DEF_HELPER_FLAGS_5(sve_scvt_sh, TCG_CALL_NO_RWG,
81
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/target/arm/sve_helper.c
84
+++ b/target/arm/sve_helper.c
85
@@ -XXX,XX +XXX,XX @@ DO_ZPZZ_FP(sve_fmulx_d, uint64_t, , helper_vfp_mulxd)
86
87
#undef DO_ZPZZ_FP
88
89
+/* Three-operand expander, with one scalar operand, controlled by
90
+ * a predicate, with the extra float_status parameter.
91
+ */
92
+#define DO_ZPZS_FP(NAME, TYPE, H, OP) \
93
+void HELPER(NAME)(void *vd, void *vn, void *vg, uint64_t scalar, \
94
+ void *status, uint32_t desc) \
95
+{ \
96
+ intptr_t i = simd_oprsz(desc); \
97
+ uint64_t *g = vg; \
98
+ TYPE mm = scalar; \
99
+ do { \
100
+ uint64_t pg = g[(i - 1) >> 6]; \
101
+ do { \
102
+ i -= sizeof(TYPE); \
103
+ if (likely((pg >> (i & 63)) & 1)) { \
104
+ TYPE nn = *(TYPE *)(vn + H(i)); \
105
+ *(TYPE *)(vd + H(i)) = OP(nn, mm, status); \
106
+ } \
107
+ } while (i & 63); \
108
+ } while (i != 0); \
109
+}
110
+
111
+DO_ZPZS_FP(sve_fadds_h, float16, H1_2, float16_add)
112
+DO_ZPZS_FP(sve_fadds_s, float32, H1_4, float32_add)
113
+DO_ZPZS_FP(sve_fadds_d, float64, , float64_add)
114
+
115
+DO_ZPZS_FP(sve_fsubs_h, float16, H1_2, float16_sub)
116
+DO_ZPZS_FP(sve_fsubs_s, float32, H1_4, float32_sub)
117
+DO_ZPZS_FP(sve_fsubs_d, float64, , float64_sub)
118
+
119
+DO_ZPZS_FP(sve_fmuls_h, float16, H1_2, float16_mul)
120
+DO_ZPZS_FP(sve_fmuls_s, float32, H1_4, float32_mul)
121
+DO_ZPZS_FP(sve_fmuls_d, float64, , float64_mul)
122
+
123
+static inline float16 subr_h(float16 a, float16 b, float_status *s)
124
+{
125
+ return float16_sub(b, a, s);
126
+}
127
+
128
+static inline float32 subr_s(float32 a, float32 b, float_status *s)
129
+{
130
+ return float32_sub(b, a, s);
131
+}
132
+
133
+static inline float64 subr_d(float64 a, float64 b, float_status *s)
134
+{
135
+ return float64_sub(b, a, s);
136
+}
137
+
138
+DO_ZPZS_FP(sve_fsubrs_h, float16, H1_2, subr_h)
139
+DO_ZPZS_FP(sve_fsubrs_s, float32, H1_4, subr_s)
140
+DO_ZPZS_FP(sve_fsubrs_d, float64, , subr_d)
141
+
142
+DO_ZPZS_FP(sve_fmaxnms_h, float16, H1_2, float16_maxnum)
143
+DO_ZPZS_FP(sve_fmaxnms_s, float32, H1_4, float32_maxnum)
144
+DO_ZPZS_FP(sve_fmaxnms_d, float64, , float64_maxnum)
145
+
146
+DO_ZPZS_FP(sve_fminnms_h, float16, H1_2, float16_minnum)
147
+DO_ZPZS_FP(sve_fminnms_s, float32, H1_4, float32_minnum)
148
+DO_ZPZS_FP(sve_fminnms_d, float64, , float64_minnum)
149
+
150
+DO_ZPZS_FP(sve_fmaxs_h, float16, H1_2, float16_max)
151
+DO_ZPZS_FP(sve_fmaxs_s, float32, H1_4, float32_max)
152
+DO_ZPZS_FP(sve_fmaxs_d, float64, , float64_max)
153
+
154
+DO_ZPZS_FP(sve_fmins_h, float16, H1_2, float16_min)
155
+DO_ZPZS_FP(sve_fmins_s, float32, H1_4, float32_min)
156
+DO_ZPZS_FP(sve_fmins_d, float64, , float64_min)
157
+
158
/* Fully general two-operand expander, controlled by a predicate,
159
* With the extra float_status parameter.
160
*/
161
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/target/arm/translate-sve.c
164
+++ b/target/arm/translate-sve.c
165
@@ -XXX,XX +XXX,XX @@
166
#include "exec/log.h"
167
#include "trace-tcg.h"
168
#include "translate-a64.h"
169
+#include "fpu/softfloat.h"
170
171
172
typedef void GVecGen2sFn(unsigned, uint32_t, uint32_t,
173
@@ -XXX,XX +XXX,XX @@ DO_FP3(FMULX, fmulx)
174
175
#undef DO_FP3
176
177
+typedef void gen_helper_sve_fp2scalar(TCGv_ptr, TCGv_ptr, TCGv_ptr,
178
+ TCGv_i64, TCGv_ptr, TCGv_i32);
179
+
180
+static void do_fp_scalar(DisasContext *s, int zd, int zn, int pg, bool is_fp16,
181
+ TCGv_i64 scalar, gen_helper_sve_fp2scalar *fn)
182
+{
183
+ unsigned vsz = vec_full_reg_size(s);
184
+ TCGv_ptr t_zd, t_zn, t_pg, status;
185
+ TCGv_i32 desc;
186
+
187
+ t_zd = tcg_temp_new_ptr();
188
+ t_zn = tcg_temp_new_ptr();
189
+ t_pg = tcg_temp_new_ptr();
190
+ tcg_gen_addi_ptr(t_zd, cpu_env, vec_full_reg_offset(s, zd));
191
+ tcg_gen_addi_ptr(t_zn, cpu_env, vec_full_reg_offset(s, zn));
192
+ tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
193
+
194
+ status = get_fpstatus_ptr(is_fp16);
195
+ desc = tcg_const_i32(simd_desc(vsz, vsz, 0));
196
+ fn(t_zd, t_zn, t_pg, scalar, status, desc);
197
+
198
+ tcg_temp_free_i32(desc);
199
+ tcg_temp_free_ptr(status);
200
+ tcg_temp_free_ptr(t_pg);
201
+ tcg_temp_free_ptr(t_zn);
202
+ tcg_temp_free_ptr(t_zd);
203
+}
204
+
205
+static void do_fp_imm(DisasContext *s, arg_rpri_esz *a, uint64_t imm,
206
+ gen_helper_sve_fp2scalar *fn)
207
+{
208
+ TCGv_i64 temp = tcg_const_i64(imm);
209
+ do_fp_scalar(s, a->rd, a->rn, a->pg, a->esz == MO_16, temp, fn);
210
+ tcg_temp_free_i64(temp);
211
+}
212
+
213
+#define DO_FP_IMM(NAME, name, const0, const1) \
214
+static bool trans_##NAME##_zpzi(DisasContext *s, arg_rpri_esz *a, \
215
+ uint32_t insn) \
216
+{ \
217
+ static gen_helper_sve_fp2scalar * const fns[3] = { \
218
+ gen_helper_sve_##name##_h, \
219
+ gen_helper_sve_##name##_s, \
220
+ gen_helper_sve_##name##_d \
221
+ }; \
222
+ static uint64_t const val[3][2] = { \
223
+ { float16_##const0, float16_##const1 }, \
224
+ { float32_##const0, float32_##const1 }, \
225
+ { float64_##const0, float64_##const1 }, \
226
+ }; \
227
+ if (a->esz == 0) { \
228
+ return false; \
229
+ } \
230
+ if (sve_access_check(s)) { \
231
+ do_fp_imm(s, a, val[a->esz - 1][a->imm], fns[a->esz - 1]); \
232
+ } \
233
+ return true; \
234
+}
235
+
236
+#define float16_two make_float16(0x4000)
237
+#define float32_two make_float32(0x40000000)
238
+#define float64_two make_float64(0x4000000000000000ULL)
239
+
240
+DO_FP_IMM(FADD, fadds, half, one)
241
+DO_FP_IMM(FSUB, fsubs, half, one)
242
+DO_FP_IMM(FMUL, fmuls, half, two)
243
+DO_FP_IMM(FSUBR, fsubrs, half, one)
244
+DO_FP_IMM(FMAXNM, fmaxnms, zero, one)
245
+DO_FP_IMM(FMINNM, fminnms, zero, one)
246
+DO_FP_IMM(FMAX, fmaxs, zero, one)
247
+DO_FP_IMM(FMIN, fmins, zero, one)
248
+
249
+#undef DO_FP_IMM
250
+
251
static bool do_fp_cmp(DisasContext *s, arg_rprr_esz *a,
252
gen_helper_gvec_4_ptr *fn)
253
{
254
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
255
index XXXXXXX..XXXXXXX 100644
256
--- a/target/arm/sve.decode
257
+++ b/target/arm/sve.decode
258
@@ -XXX,XX +XXX,XX @@
259
@rdn_pg4 ........ esz:2 .. pg:4 ... ........ rd:5 \
260
&rpri_esz rn=%reg_movprfx
261
262
+# Two register operand, one one-bit floating-point operand.
263
+@rdn_i1 ........ esz:2 ......... pg:3 .... imm:1 rd:5 \
264
+ &rpri_esz rn=%reg_movprfx
265
+
266
# Two register operand, one encoded bitmask.
267
@rdn_dbm ........ .. .... dbm:13 rd:5 \
268
&rr_dbm rn=%reg_movprfx
269
@@ -XXX,XX +XXX,XX @@ FMULX 01100101 .. 00 1010 100 ... ..... ..... @rdn_pg_rm
270
FDIV 01100101 .. 00 1100 100 ... ..... ..... @rdm_pg_rn # FDIVR
271
FDIV 01100101 .. 00 1101 100 ... ..... ..... @rdn_pg_rm
272
273
+# SVE floating-point arithmetic with immediate (predicated)
274
+FADD_zpzi 01100101 .. 011 000 100 ... 0000 . ..... @rdn_i1
275
+FSUB_zpzi 01100101 .. 011 001 100 ... 0000 . ..... @rdn_i1
276
+FMUL_zpzi 01100101 .. 011 010 100 ... 0000 . ..... @rdn_i1
277
+FSUBR_zpzi 01100101 .. 011 011 100 ... 0000 . ..... @rdn_i1
278
+FMAXNM_zpzi 01100101 .. 011 100 100 ... 0000 . ..... @rdn_i1
279
+FMINNM_zpzi 01100101 .. 011 101 100 ... 0000 . ..... @rdn_i1
280
+FMAX_zpzi 01100101 .. 011 110 100 ... 0000 . ..... @rdn_i1
281
+FMIN_zpzi 01100101 .. 011 111 100 ... 0000 . ..... @rdn_i1
282
+
283
### SVE FP Multiply-Add Group
284
285
# SVE floating-point multiply-accumulate writing addend
286
--
25
--
287
2.17.1
26
2.25.1
288
289
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Move the checks out of the parsing loop and into the
4
restore function. This more closely mirrors the code
5
structure in the kernel, and is slightly clearer.
6
7
Reject rather than silently skip incorrect VL and SVE record sizes,
8
bringing our checks in to line with those the kernel does.
2
9
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-26-richard.henderson@linaro.org
12
Message-id: 20220708151540.18136-40-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
14
---
8
target/arm/helper-sve.h | 14 +++++++
15
linux-user/aarch64/signal.c | 51 +++++++++++++++++++++++++------------
9
target/arm/sve_helper.c | 8 ++++
16
1 file changed, 35 insertions(+), 16 deletions(-)
10
target/arm/translate-sve.c | 77 ++++++++++++++++++++++++++++++++++++++
11
target/arm/sve.decode | 9 +++++
12
4 files changed, 108 insertions(+)
13
17
14
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
18
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-sve.h
20
--- a/linux-user/aarch64/signal.c
17
+++ b/target/arm/helper-sve.h
21
+++ b/linux-user/aarch64/signal.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(sve_fcvtzu_sd, TCG_CALL_NO_RWG,
22
@@ -XXX,XX +XXX,XX @@ static void target_restore_fpsimd_record(CPUARMState *env,
19
DEF_HELPER_FLAGS_5(sve_fcvtzu_dd, TCG_CALL_NO_RWG,
23
}
20
void, ptr, ptr, ptr, ptr, i32)
21
22
+DEF_HELPER_FLAGS_5(sve_frint_h, TCG_CALL_NO_RWG,
23
+ void, ptr, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_5(sve_frint_s, TCG_CALL_NO_RWG,
25
+ void, ptr, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_5(sve_frint_d, TCG_CALL_NO_RWG,
27
+ void, ptr, ptr, ptr, ptr, i32)
28
+
29
+DEF_HELPER_FLAGS_5(sve_frintx_h, TCG_CALL_NO_RWG,
30
+ void, ptr, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_5(sve_frintx_s, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_5(sve_frintx_d, TCG_CALL_NO_RWG,
34
+ void, ptr, ptr, ptr, ptr, i32)
35
+
36
DEF_HELPER_FLAGS_5(sve_scvt_hh, TCG_CALL_NO_RWG,
37
void, ptr, ptr, ptr, ptr, i32)
38
DEF_HELPER_FLAGS_5(sve_scvt_sh, TCG_CALL_NO_RWG,
39
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/sve_helper.c
42
+++ b/target/arm/sve_helper.c
43
@@ -XXX,XX +XXX,XX @@ DO_ZPZ_FP(sve_fcvtzu_sd, uint64_t, , vfp_float32_to_uint64_rtz)
44
DO_ZPZ_FP(sve_fcvtzu_ds, uint64_t, , helper_vfp_touizd)
45
DO_ZPZ_FP(sve_fcvtzu_dd, uint64_t, , vfp_float64_to_uint64_rtz)
46
47
+DO_ZPZ_FP(sve_frint_h, uint16_t, H1_2, helper_advsimd_rinth)
48
+DO_ZPZ_FP(sve_frint_s, uint32_t, H1_4, helper_rints)
49
+DO_ZPZ_FP(sve_frint_d, uint64_t, , helper_rintd)
50
+
51
+DO_ZPZ_FP(sve_frintx_h, uint16_t, H1_2, float16_round_to_int)
52
+DO_ZPZ_FP(sve_frintx_s, uint32_t, H1_4, float32_round_to_int)
53
+DO_ZPZ_FP(sve_frintx_d, uint64_t, , float64_round_to_int)
54
+
55
DO_ZPZ_FP(sve_scvt_hh, uint16_t, H1_2, int16_to_float16)
56
DO_ZPZ_FP(sve_scvt_sh, uint32_t, H1_4, int32_to_float16)
57
DO_ZPZ_FP(sve_scvt_ss, uint32_t, H1_4, int32_to_float32)
58
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/translate-sve.c
61
+++ b/target/arm/translate-sve.c
62
@@ -XXX,XX +XXX,XX @@ static bool trans_FCVTZU_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
63
return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzu_dd);
64
}
24
}
65
25
66
+static gen_helper_gvec_3_ptr * const frint_fns[3] = {
26
-static void target_restore_sve_record(CPUARMState *env,
67
+ gen_helper_sve_frint_h,
27
- struct target_sve_context *sve, int vq)
68
+ gen_helper_sve_frint_s,
28
+static bool target_restore_sve_record(CPUARMState *env,
69
+ gen_helper_sve_frint_d
29
+ struct target_sve_context *sve,
70
+};
30
+ int size)
71
+
31
{
72
+static bool trans_FRINTI(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
32
- int i, j;
73
+{
33
+ int i, j, vl, vq;
74
+ if (a->esz == 0) {
34
35
- /* Note that SVE regs are stored as a byte stream, with each byte element
36
+ if (!cpu_isar_feature(aa64_sve, env_archcpu(env))) {
75
+ return false;
37
+ return false;
76
+ }
38
+ }
77
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, a->esz == MO_16,
78
+ frint_fns[a->esz - 1]);
79
+}
80
+
39
+
81
+static bool trans_FRINTX(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
40
+ __get_user(vl, &sve->vl);
82
+{
41
+ vq = sve_vq(env);
83
+ static gen_helper_gvec_3_ptr * const fns[3] = {
42
+
84
+ gen_helper_sve_frintx_h,
43
+ /* Reject mismatched VL. */
85
+ gen_helper_sve_frintx_s,
44
+ if (vl != vq * TARGET_SVE_VQ_BYTES) {
86
+ gen_helper_sve_frintx_d
87
+ };
88
+ if (a->esz == 0) {
89
+ return false;
45
+ return false;
90
+ }
46
+ }
91
+ return do_zpz_ptr(s, a->rd, a->rn, a->pg, a->esz == MO_16, fns[a->esz - 1]);
92
+}
93
+
47
+
94
+static bool do_frint_mode(DisasContext *s, arg_rpr_esz *a, int mode)
48
+ /* Accept empty record -- used to clear PSTATE.SM. */
95
+{
49
+ if (size <= sizeof(*sve)) {
96
+ if (a->esz == 0) {
50
+ return true;
51
+ }
52
+
53
+ /* Reject non-empty but incomplete record. */
54
+ if (size < TARGET_SVE_SIG_CONTEXT_SIZE(vq)) {
97
+ return false;
55
+ return false;
98
+ }
56
+ }
99
+ if (sve_access_check(s)) {
100
+ unsigned vsz = vec_full_reg_size(s);
101
+ TCGv_i32 tmode = tcg_const_i32(mode);
102
+ TCGv_ptr status = get_fpstatus_ptr(a->esz == MO_16);
103
+
57
+
104
+ gen_helper_set_rmode(tmode, tmode, status);
58
+ /*
105
+
59
+ * Note that SVE regs are stored as a byte stream, with each byte element
106
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
60
* at a subsequent address. This corresponds to a little-endian load
107
+ vec_full_reg_offset(s, a->rn),
61
* of our 64-bit hunks.
108
+ pred_full_reg_offset(s, a->pg),
62
*/
109
+ status, vsz, vsz, 0, frint_fns[a->esz - 1]);
63
@@ -XXX,XX +XXX,XX @@ static void target_restore_sve_record(CPUARMState *env,
110
+
64
}
111
+ gen_helper_set_rmode(tmode, tmode, status);
65
}
112
+ tcg_temp_free_i32(tmode);
66
}
113
+ tcg_temp_free_ptr(status);
114
+ }
115
+ return true;
67
+ return true;
116
+}
68
}
117
+
69
118
+static bool trans_FRINTN(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
70
static int target_restore_sigframe(CPUARMState *env,
119
+{
71
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
120
+ return do_frint_mode(s, a, float_round_nearest_even);
72
struct target_sve_context *sve = NULL;
121
+}
73
uint64_t extra_datap = 0;
122
+
74
bool used_extra = false;
123
+static bool trans_FRINTP(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
75
- int vq = 0, sve_size = 0;
124
+{
76
+ int sve_size = 0;
125
+ return do_frint_mode(s, a, float_round_up);
77
126
+}
78
target_restore_general_frame(env, sf);
127
+
79
128
+static bool trans_FRINTM(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
80
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
129
+{
81
if (sve || size < sizeof(struct target_sve_context)) {
130
+ return do_frint_mode(s, a, float_round_down);
82
goto err;
131
+}
83
}
132
+
84
- if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
133
+static bool trans_FRINTZ(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
85
- vq = sve_vq(env);
134
+{
86
- sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
135
+ return do_frint_mode(s, a, float_round_to_zero);
87
- if (size == sve_size) {
136
+}
88
- sve = (struct target_sve_context *)ctx;
137
+
89
- break;
138
+static bool trans_FRINTA(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
90
- }
139
+{
91
- }
140
+ return do_frint_mode(s, a, float_round_ties_away);
92
- goto err;
141
+}
93
+ sve = (struct target_sve_context *)ctx;
142
+
94
+ sve_size = size;
143
static bool trans_SCVTF_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
95
+ break;
144
{
96
145
return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_scvt_hh);
97
case TARGET_EXTRA_MAGIC:
146
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
98
if (extra || size != sizeof(struct target_extra_context)) {
147
index XXXXXXX..XXXXXXX 100644
99
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
148
--- a/target/arm/sve.decode
100
}
149
+++ b/target/arm/sve.decode
101
150
@@ -XXX,XX +XXX,XX @@ FCVTZU_sd 01100101 11 011 10 1 101 ... ..... ..... @rd_pg_rn_e0
102
/* SVE data, if present, overwrites FPSIMD data. */
151
FCVTZS_dd 01100101 11 011 11 0 101 ... ..... ..... @rd_pg_rn_e0
103
- if (sve) {
152
FCVTZU_dd 01100101 11 011 11 1 101 ... ..... ..... @rd_pg_rn_e0
104
- target_restore_sve_record(env, sve, vq);
153
105
+ if (sve && !target_restore_sve_record(env, sve, sve_size)) {
154
+# SVE floating-point round to integral value
106
+ goto err;
155
+FRINTN 01100101 .. 000 000 101 ... ..... ..... @rd_pg_rn
107
}
156
+FRINTP 01100101 .. 000 001 101 ... ..... ..... @rd_pg_rn
108
unlock_user(extra, extra_datap, 0);
157
+FRINTM 01100101 .. 000 010 101 ... ..... ..... @rd_pg_rn
109
return 0;
158
+FRINTZ 01100101 .. 000 011 101 ... ..... ..... @rd_pg_rn
159
+FRINTA 01100101 .. 000 100 101 ... ..... ..... @rd_pg_rn
160
+FRINTX 01100101 .. 000 110 101 ... ..... ..... @rd_pg_rn
161
+FRINTI 01100101 .. 000 111 101 ... ..... ..... @rd_pg_rn
162
+
163
# SVE integer convert to floating-point
164
SCVTF_hh 01100101 01 010 01 0 101 ... ..... ..... @rd_pg_rn_e0
165
SCVTF_sh 01100101 01 010 10 0 101 ... ..... ..... @rd_pg_rn_e0
166
--
110
--
167
2.17.1
111
2.25.1
168
169
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Set the SM bit in the SVE record on signal delivery, create the ZA record.
4
Restore SM and ZA state according to the records present on return.
2
5
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180627043328.11531-11-richard.henderson@linaro.org
8
Message-id: 20220708151540.18136-41-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-sve.c | 103 +++++++++++++++++++++++++++++++++++++
11
linux-user/aarch64/signal.c | 167 +++++++++++++++++++++++++++++++++---
9
target/arm/sve.decode | 6 +++
12
1 file changed, 154 insertions(+), 13 deletions(-)
10
2 files changed, 109 insertions(+)
11
13
12
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
14
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-sve.c
16
--- a/linux-user/aarch64/signal.c
15
+++ b/target/arm/translate-sve.c
17
+++ b/linux-user/aarch64/signal.c
16
@@ -XXX,XX +XXX,XX @@ static void do_ldr(DisasContext *s, uint32_t vofs, uint32_t len,
18
@@ -XXX,XX +XXX,XX @@ struct target_sve_context {
17
tcg_temp_free_i64(t0);
19
20
#define TARGET_SVE_SIG_FLAG_SM 1
21
22
+#define TARGET_ZA_MAGIC 0x54366345
23
+
24
+struct target_za_context {
25
+ struct target_aarch64_ctx head;
26
+ uint16_t vl;
27
+ uint16_t reserved[3];
28
+ /* The actual ZA data immediately follows. */
29
+};
30
+
31
+#define TARGET_ZA_SIG_REGS_OFFSET \
32
+ QEMU_ALIGN_UP(sizeof(struct target_za_context), TARGET_SVE_VQ_BYTES)
33
+#define TARGET_ZA_SIG_ZAV_OFFSET(VQ, N) \
34
+ (TARGET_ZA_SIG_REGS_OFFSET + (VQ) * TARGET_SVE_VQ_BYTES * (N))
35
+#define TARGET_ZA_SIG_CONTEXT_SIZE(VQ) \
36
+ TARGET_ZA_SIG_ZAV_OFFSET(VQ, VQ * TARGET_SVE_VQ_BYTES)
37
+
38
struct target_rt_sigframe {
39
struct target_siginfo info;
40
struct target_ucontext uc;
41
@@ -XXX,XX +XXX,XX @@ static void target_setup_end_record(struct target_aarch64_ctx *end)
18
}
42
}
19
43
20
+/* Similarly for stores. */
44
static void target_setup_sve_record(struct target_sve_context *sve,
21
+static void do_str(DisasContext *s, uint32_t vofs, uint32_t len,
45
- CPUARMState *env, int vq, int size)
22
+ int rn, int imm)
46
+ CPUARMState *env, int size)
47
{
48
- int i, j;
49
+ int i, j, vq = sve_vq(env);
50
51
memset(sve, 0, sizeof(*sve));
52
__put_user(TARGET_SVE_MAGIC, &sve->head.magic);
53
@@ -XXX,XX +XXX,XX @@ static void target_setup_sve_record(struct target_sve_context *sve,
54
}
55
}
56
57
+static void target_setup_za_record(struct target_za_context *za,
58
+ CPUARMState *env, int size)
23
+{
59
+{
24
+ uint32_t len_align = QEMU_ALIGN_DOWN(len, 8);
60
+ int vq = sme_vq(env);
25
+ uint32_t len_remain = len % 8;
61
+ int vl = vq * TARGET_SVE_VQ_BYTES;
26
+ uint32_t nparts = len / 8 + ctpop8(len_remain);
62
+ int i, j;
27
+ int midx = get_mem_index(s);
63
+
28
+ TCGv_i64 addr, t0;
64
+ memset(za, 0, sizeof(*za));
29
+
65
+ __put_user(TARGET_ZA_MAGIC, &za->head.magic);
30
+ addr = tcg_temp_new_i64();
66
+ __put_user(size, &za->head.size);
31
+ t0 = tcg_temp_new_i64();
67
+ __put_user(vl, &za->vl);
32
+
68
+
33
+ /* Note that unpredicated load/store of vector/predicate registers
69
+ if (size == TARGET_ZA_SIG_CONTEXT_SIZE(0)) {
34
+ * are defined as a stream of bytes, which equates to little-endian
70
+ return;
35
+ * operations on larger quantities. There is no nice way to force
71
+ }
36
+ * a little-endian store for aarch64_be-linux-user out of line.
72
+ assert(size == TARGET_ZA_SIG_CONTEXT_SIZE(vq));
37
+ *
73
+
38
+ * Attempt to keep code expansion to a minimum by limiting the
74
+ /*
39
+ * amount of unrolling done.
75
+ * Note that ZA vectors are stored as a byte stream,
76
+ * with each byte element at a subsequent address.
40
+ */
77
+ */
41
+ if (nparts <= 4) {
78
+ for (i = 0; i < vl; ++i) {
42
+ int i;
79
+ uint64_t *z = (void *)za + TARGET_ZA_SIG_ZAV_OFFSET(vq, i);
43
+
80
+ for (j = 0; j < vq * 2; ++j) {
44
+ for (i = 0; i < len_align; i += 8) {
81
+ __put_user_e(env->zarray[i].d[j], z + j, le);
45
+ tcg_gen_ld_i64(t0, cpu_env, vofs + i);
46
+ tcg_gen_addi_i64(addr, cpu_reg_sp(s, rn), imm + i);
47
+ tcg_gen_qemu_st_i64(t0, addr, midx, MO_LEQ);
48
+ }
82
+ }
49
+ } else {
83
+ }
50
+ TCGLabel *loop = gen_new_label();
51
+ TCGv_ptr t2, i = tcg_const_local_ptr(0);
52
+
53
+ gen_set_label(loop);
54
+
55
+ t2 = tcg_temp_new_ptr();
56
+ tcg_gen_add_ptr(t2, cpu_env, i);
57
+ tcg_gen_ld_i64(t0, t2, vofs);
58
+
59
+ /* Minimize the number of local temps that must be re-read from
60
+ * the stack each iteration. Instead, re-compute values other
61
+ * than the loop counter.
62
+ */
63
+ tcg_gen_addi_ptr(t2, i, imm);
64
+ tcg_gen_extu_ptr_i64(addr, t2);
65
+ tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, rn));
66
+ tcg_temp_free_ptr(t2);
67
+
68
+ tcg_gen_qemu_st_i64(t0, addr, midx, MO_LEQ);
69
+
70
+ tcg_gen_addi_ptr(i, i, 8);
71
+
72
+ tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
73
+ tcg_temp_free_ptr(i);
74
+ }
75
+
76
+ /* Predicate register stores can be any multiple of 2. */
77
+ if (len_remain) {
78
+ tcg_gen_ld_i64(t0, cpu_env, vofs + len_align);
79
+ tcg_gen_addi_i64(addr, cpu_reg_sp(s, rn), imm + len_align);
80
+
81
+ switch (len_remain) {
82
+ case 2:
83
+ case 4:
84
+ case 8:
85
+ tcg_gen_qemu_st_i64(t0, addr, midx, MO_LE | ctz32(len_remain));
86
+ break;
87
+
88
+ case 6:
89
+ tcg_gen_qemu_st_i64(t0, addr, midx, MO_LEUL);
90
+ tcg_gen_addi_i64(addr, addr, 4);
91
+ tcg_gen_shri_i64(t0, t0, 32);
92
+ tcg_gen_qemu_st_i64(t0, addr, midx, MO_LEUW);
93
+ break;
94
+
95
+ default:
96
+ g_assert_not_reached();
97
+ }
98
+ }
99
+ tcg_temp_free_i64(addr);
100
+ tcg_temp_free_i64(t0);
101
+}
84
+}
102
+
85
+
103
static bool trans_LDR_zri(DisasContext *s, arg_rri *a, uint32_t insn)
86
static void target_restore_general_frame(CPUARMState *env,
104
{
87
struct target_rt_sigframe *sf)
105
if (sve_access_check(s)) {
88
{
106
@@ -XXX,XX +XXX,XX @@ static bool trans_LDR_pri(DisasContext *s, arg_rri *a, uint32_t insn)
89
@@ -XXX,XX +XXX,XX @@ static void target_restore_fpsimd_record(CPUARMState *env,
90
91
static bool target_restore_sve_record(CPUARMState *env,
92
struct target_sve_context *sve,
93
- int size)
94
+ int size, int *svcr)
95
{
96
- int i, j, vl, vq;
97
+ int i, j, vl, vq, flags;
98
+ bool sm;
99
100
- if (!cpu_isar_feature(aa64_sve, env_archcpu(env))) {
101
+ __get_user(vl, &sve->vl);
102
+ __get_user(flags, &sve->flags);
103
+
104
+ sm = flags & TARGET_SVE_SIG_FLAG_SM;
105
+
106
+ /* The cpu must support Streaming or Non-streaming SVE. */
107
+ if (sm
108
+ ? !cpu_isar_feature(aa64_sme, env_archcpu(env))
109
+ : !cpu_isar_feature(aa64_sve, env_archcpu(env))) {
110
return false;
111
}
112
113
- __get_user(vl, &sve->vl);
114
- vq = sve_vq(env);
115
+ /*
116
+ * Note that we cannot use sve_vq() because that depends on the
117
+ * current setting of PSTATE.SM, not the state to be restored.
118
+ */
119
+ vq = sve_vqm1_for_el_sm(env, 0, sm) + 1;
120
121
/* Reject mismatched VL. */
122
if (vl != vq * TARGET_SVE_VQ_BYTES) {
123
@@ -XXX,XX +XXX,XX @@ static bool target_restore_sve_record(CPUARMState *env,
124
return false;
125
}
126
127
+ *svcr = FIELD_DP64(*svcr, SVCR, SM, sm);
128
+
129
/*
130
* Note that SVE regs are stored as a byte stream, with each byte element
131
* at a subsequent address. This corresponds to a little-endian load
132
@@ -XXX,XX +XXX,XX @@ static bool target_restore_sve_record(CPUARMState *env,
107
return true;
133
return true;
108
}
134
}
109
135
110
+static bool trans_STR_zri(DisasContext *s, arg_rri *a, uint32_t insn)
136
+static bool target_restore_za_record(CPUARMState *env,
137
+ struct target_za_context *za,
138
+ int size, int *svcr)
111
+{
139
+{
112
+ if (sve_access_check(s)) {
140
+ int i, j, vl, vq;
113
+ int size = vec_full_reg_size(s);
141
+
114
+ int off = vec_full_reg_offset(s, a->rd);
142
+ if (!cpu_isar_feature(aa64_sme, env_archcpu(env))) {
115
+ do_str(s, off, size, a->rn, a->imm * size);
143
+ return false;
144
+ }
145
+
146
+ __get_user(vl, &za->vl);
147
+ vq = sme_vq(env);
148
+
149
+ /* Reject mismatched VL. */
150
+ if (vl != vq * TARGET_SVE_VQ_BYTES) {
151
+ return false;
152
+ }
153
+
154
+ /* Accept empty record -- used to clear PSTATE.ZA. */
155
+ if (size <= TARGET_ZA_SIG_CONTEXT_SIZE(0)) {
156
+ return true;
157
+ }
158
+
159
+ /* Reject non-empty but incomplete record. */
160
+ if (size < TARGET_ZA_SIG_CONTEXT_SIZE(vq)) {
161
+ return false;
162
+ }
163
+
164
+ *svcr = FIELD_DP64(*svcr, SVCR, ZA, 1);
165
+
166
+ for (i = 0; i < vl; ++i) {
167
+ uint64_t *z = (void *)za + TARGET_ZA_SIG_ZAV_OFFSET(vq, i);
168
+ for (j = 0; j < vq * 2; ++j) {
169
+ __get_user_e(env->zarray[i].d[j], z + j, le);
170
+ }
116
+ }
171
+ }
117
+ return true;
172
+ return true;
118
+}
173
+}
119
+
174
+
120
+static bool trans_STR_pri(DisasContext *s, arg_rri *a, uint32_t insn)
175
static int target_restore_sigframe(CPUARMState *env,
121
+{
176
struct target_rt_sigframe *sf)
122
+ if (sve_access_check(s)) {
177
{
123
+ int size = pred_full_reg_size(s);
178
struct target_aarch64_ctx *ctx, *extra = NULL;
124
+ int off = pred_full_reg_offset(s, a->rd);
179
struct target_fpsimd_context *fpsimd = NULL;
125
+ do_str(s, off, size, a->rn, a->imm * size);
180
struct target_sve_context *sve = NULL;
126
+ }
181
+ struct target_za_context *za = NULL;
127
+ return true;
182
uint64_t extra_datap = 0;
128
+}
183
bool used_extra = false;
129
+
184
int sve_size = 0;
130
/*
185
+ int za_size = 0;
131
*** SVE Memory - Contiguous Load Group
186
+ int svcr = 0;
132
*/
187
133
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
188
target_restore_general_frame(env, sf);
134
index XXXXXXX..XXXXXXX 100644
189
135
--- a/target/arm/sve.decode
190
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
136
+++ b/target/arm/sve.decode
191
sve_size = size;
137
@@ -XXX,XX +XXX,XX @@ LD1RQ_zpri 1010010 .. 00 0.... 001 ... ..... ..... \
192
break;
138
193
139
### SVE Memory Store Group
194
+ case TARGET_ZA_MAGIC:
140
195
+ if (za || size < sizeof(struct target_za_context)) {
141
+# SVE store predicate register
196
+ goto err;
142
+STR_pri 1110010 11 0. ..... 000 ... ..... 0 .... @pd_rn_i9
197
+ }
143
+
198
+ za = (struct target_za_context *)ctx;
144
+# SVE store vector register
199
+ za_size = size;
145
+STR_zri 1110010 11 0. ..... 010 ... ..... ..... @rd_rn_i9
200
+ break;
146
+
201
+
147
# SVE contiguous store (scalar plus immediate)
202
case TARGET_EXTRA_MAGIC:
148
# ST1B, ST1H, ST1W, ST1D; require msz <= esz
203
if (extra || size != sizeof(struct target_extra_context)) {
149
ST_zpri 1110010 .. esz:2 0.... 111 ... ..... ..... \
204
goto err;
205
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
206
}
207
208
/* SVE data, if present, overwrites FPSIMD data. */
209
- if (sve && !target_restore_sve_record(env, sve, sve_size)) {
210
+ if (sve && !target_restore_sve_record(env, sve, sve_size, &svcr)) {
211
goto err;
212
}
213
+ if (za && !target_restore_za_record(env, za, za_size, &svcr)) {
214
+ goto err;
215
+ }
216
+ if (env->svcr != svcr) {
217
+ env->svcr = svcr;
218
+ arm_rebuild_hflags(env);
219
+ }
220
unlock_user(extra, extra_datap, 0);
221
return 0;
222
223
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
224
.total_size = offsetof(struct target_rt_sigframe,
225
uc.tuc_mcontext.__reserved),
226
};
227
- int fpsimd_ofs, fr_ofs, sve_ofs = 0, vq = 0, sve_size = 0;
228
+ int fpsimd_ofs, fr_ofs, sve_ofs = 0, za_ofs = 0;
229
+ int sve_size = 0, za_size = 0;
230
struct target_rt_sigframe *frame;
231
struct target_rt_frame_record *fr;
232
abi_ulong frame_addr, return_addr;
233
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
234
&layout);
235
236
/* SVE state needs saving only if it exists. */
237
- if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
238
- vq = sve_vq(env);
239
- sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
240
+ if (cpu_isar_feature(aa64_sve, env_archcpu(env)) ||
241
+ cpu_isar_feature(aa64_sme, env_archcpu(env))) {
242
+ sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(sve_vq(env)), 16);
243
sve_ofs = alloc_sigframe_space(sve_size, &layout);
244
}
245
+ if (cpu_isar_feature(aa64_sme, env_archcpu(env))) {
246
+ /* ZA state needs saving only if it is enabled. */
247
+ if (FIELD_EX64(env->svcr, SVCR, ZA)) {
248
+ za_size = TARGET_ZA_SIG_CONTEXT_SIZE(sme_vq(env));
249
+ } else {
250
+ za_size = TARGET_ZA_SIG_CONTEXT_SIZE(0);
251
+ }
252
+ za_ofs = alloc_sigframe_space(za_size, &layout);
253
+ }
254
255
if (layout.extra_ofs) {
256
/* Reserve space for the extra end marker. The standard end marker
257
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
258
target_setup_end_record((void *)frame + layout.extra_end_ofs);
259
}
260
if (sve_ofs) {
261
- target_setup_sve_record((void *)frame + sve_ofs, env, vq, sve_size);
262
+ target_setup_sve_record((void *)frame + sve_ofs, env, sve_size);
263
+ }
264
+ if (za_ofs) {
265
+ target_setup_za_record((void *)frame + za_ofs, env, za_size);
266
}
267
268
/* Set up the stack frame for unwinding. */
269
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
270
env->btype = 2;
271
}
272
273
+ /*
274
+ * Invoke the signal handler with both SM and ZA disabled.
275
+ * When clearing SM, ResetSVEState, per SMSTOP.
276
+ */
277
+ if (FIELD_EX64(env->svcr, SVCR, SM)) {
278
+ arm_reset_sve_state(env);
279
+ }
280
+ if (env->svcr) {
281
+ env->svcr = 0;
282
+ arm_rebuild_hflags(env);
283
+ }
284
+
285
if (info) {
286
tswap_siginfo(&frame->info, info);
287
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
150
--
288
--
151
2.17.1
289
2.25.1
152
153
diff view generated by jsdifflib
1
From: Aaron Lindsay <alindsay@codeaurora.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This makes it match its AArch64 equivalent, PMINTENSET_EL1
3
Add "sve" to the sve prctl functions, to distinguish
4
them from the coming "sme" prctls with similar names.
4
5
5
Signed-off-by: Aaron Lindsay <alindsay@codeaurora.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 1529699547-17044-13-git-send-email-alindsay@codeaurora.org
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-42-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
target/arm/helper.c | 2 +-
11
linux-user/aarch64/target_prctl.h | 8 ++++----
10
1 file changed, 1 insertion(+), 1 deletion(-)
12
linux-user/syscall.c | 12 ++++++------
13
2 files changed, 10 insertions(+), 10 deletions(-)
11
14
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
17
--- a/linux-user/aarch64/target_prctl.h
15
+++ b/target/arm/helper.c
18
+++ b/linux-user/aarch64/target_prctl.h
16
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
19
@@ -XXX,XX +XXX,XX @@
17
.writefn = pmuserenr_write, .raw_writefn = raw_write },
20
#ifndef AARCH64_TARGET_PRCTL_H
18
{ .name = "PMINTENSET", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 1,
21
#define AARCH64_TARGET_PRCTL_H
19
.access = PL1_RW, .accessfn = access_tpm,
22
20
- .type = ARM_CP_ALIAS,
23
-static abi_long do_prctl_get_vl(CPUArchState *env)
21
+ .type = ARM_CP_ALIAS | ARM_CP_IO,
24
+static abi_long do_prctl_sve_get_vl(CPUArchState *env)
22
.fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pminten),
25
{
23
.resetvalue = 0,
26
ARMCPU *cpu = env_archcpu(env);
24
.writefn = pmintenset_write, .raw_writefn = raw_write },
27
if (cpu_isar_feature(aa64_sve, cpu)) {
28
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_get_vl(CPUArchState *env)
29
}
30
return -TARGET_EINVAL;
31
}
32
-#define do_prctl_get_vl do_prctl_get_vl
33
+#define do_prctl_sve_get_vl do_prctl_sve_get_vl
34
35
-static abi_long do_prctl_set_vl(CPUArchState *env, abi_long arg2)
36
+static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
37
{
38
/*
39
* We cannot support either PR_SVE_SET_VL_ONEXEC or PR_SVE_VL_INHERIT.
40
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_set_vl(CPUArchState *env, abi_long arg2)
41
}
42
return -TARGET_EINVAL;
43
}
44
-#define do_prctl_set_vl do_prctl_set_vl
45
+#define do_prctl_sve_set_vl do_prctl_sve_set_vl
46
47
static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2)
48
{
49
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/linux-user/syscall.c
52
+++ b/linux-user/syscall.c
53
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
54
#ifndef do_prctl_set_fp_mode
55
#define do_prctl_set_fp_mode do_prctl_inval1
56
#endif
57
-#ifndef do_prctl_get_vl
58
-#define do_prctl_get_vl do_prctl_inval0
59
+#ifndef do_prctl_sve_get_vl
60
+#define do_prctl_sve_get_vl do_prctl_inval0
61
#endif
62
-#ifndef do_prctl_set_vl
63
-#define do_prctl_set_vl do_prctl_inval1
64
+#ifndef do_prctl_sve_set_vl
65
+#define do_prctl_sve_set_vl do_prctl_inval1
66
#endif
67
#ifndef do_prctl_reset_keys
68
#define do_prctl_reset_keys do_prctl_inval1
69
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
70
case PR_SET_FP_MODE:
71
return do_prctl_set_fp_mode(env, arg2);
72
case PR_SVE_GET_VL:
73
- return do_prctl_get_vl(env);
74
+ return do_prctl_sve_get_vl(env);
75
case PR_SVE_SET_VL:
76
- return do_prctl_set_vl(env, arg2);
77
+ return do_prctl_sve_set_vl(env, arg2);
78
case PR_PAC_RESET_KEYS:
79
if (arg3 || arg4 || arg5) {
80
return -TARGET_EINVAL;
25
--
81
--
26
2.17.1
82
2.25.1
27
28
diff view generated by jsdifflib
1
From: Aaron Lindsay <alindsay@codeaurora.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
KVM implies V7VE, which implies ARM_DIV and THUMB_DIV. The conditional
3
These prctl set the Streaming SVE vector length, which may
4
detection here is therefore unnecessary. Because V7VE is already
4
be completely different from the Normal SVE vector length.
5
unconditionally specified for all KVM hosts, ARM_DIV and THUMB_DIV are
6
already indirectly specified and do not need to be included here at all.
7
5
8
Signed-off-by: Aaron Lindsay <alindsay@codeaurora.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 1529699547-17044-6-git-send-email-alindsay@codeaurora.org
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220708151540.18136-43-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/kvm32.c | 19 +------------------
11
linux-user/aarch64/target_prctl.h | 54 +++++++++++++++++++++++++++++++
13
1 file changed, 1 insertion(+), 18 deletions(-)
12
linux-user/syscall.c | 16 +++++++++
13
2 files changed, 70 insertions(+)
14
14
15
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
15
diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/kvm32.c
17
--- a/linux-user/aarch64/target_prctl.h
18
+++ b/target/arm/kvm32.c
18
+++ b/linux-user/aarch64/target_prctl.h
19
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
19
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_sve_get_vl(CPUArchState *env)
20
* and then query that CPU for the relevant ID registers.
20
{
21
*/
21
ARMCPU *cpu = env_archcpu(env);
22
int i, ret, fdarray[3];
22
if (cpu_isar_feature(aa64_sve, cpu)) {
23
- uint32_t midr, id_pfr0, id_isar0, mvfr1;
23
+ /* PSTATE.SM is always unset on syscall entry. */
24
+ uint32_t midr, id_pfr0, mvfr1;
24
return sve_vq(env) * 16;
25
uint64_t features = 0;
26
/* Old kernels may not know about the PREFERRED_TARGET ioctl: however
27
* we know these will only support creating one kind of guest CPU,
28
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
29
| ENCODE_CP_REG(15, 0, 0, 0, 1, 0, 0),
30
.addr = (uintptr_t)&id_pfr0,
31
},
32
- {
33
- .id = KVM_REG_ARM | KVM_REG_SIZE_U32
34
- | ENCODE_CP_REG(15, 0, 0, 0, 2, 0, 0),
35
- .addr = (uintptr_t)&id_isar0,
36
- },
37
{
38
.id = KVM_REG_ARM | KVM_REG_SIZE_U32
39
| KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR1,
40
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
41
set_feature(&features, ARM_FEATURE_VFP3);
42
set_feature(&features, ARM_FEATURE_GENERIC_TIMER);
43
44
- switch (extract32(id_isar0, 24, 4)) {
45
- case 1:
46
- set_feature(&features, ARM_FEATURE_THUMB_DIV);
47
- break;
48
- case 2:
49
- set_feature(&features, ARM_FEATURE_ARM_DIV);
50
- set_feature(&features, ARM_FEATURE_THUMB_DIV);
51
- break;
52
- default:
53
- break;
54
- }
55
-
56
if (extract32(id_pfr0, 12, 4) == 1) {
57
set_feature(&features, ARM_FEATURE_THUMB2EE);
58
}
25
}
26
return -TARGET_EINVAL;
27
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
28
&& arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
29
uint32_t vq, old_vq;
30
31
+ /* PSTATE.SM is always unset on syscall entry. */
32
old_vq = sve_vq(env);
33
34
/*
35
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
36
}
37
#define do_prctl_sve_set_vl do_prctl_sve_set_vl
38
39
+static abi_long do_prctl_sme_get_vl(CPUArchState *env)
40
+{
41
+ ARMCPU *cpu = env_archcpu(env);
42
+ if (cpu_isar_feature(aa64_sme, cpu)) {
43
+ return sme_vq(env) * 16;
44
+ }
45
+ return -TARGET_EINVAL;
46
+}
47
+#define do_prctl_sme_get_vl do_prctl_sme_get_vl
48
+
49
+static abi_long do_prctl_sme_set_vl(CPUArchState *env, abi_long arg2)
50
+{
51
+ /*
52
+ * We cannot support either PR_SME_SET_VL_ONEXEC or PR_SME_VL_INHERIT.
53
+ * Note the kernel definition of sve_vl_valid allows for VQ=512,
54
+ * i.e. VL=8192, even though the architectural maximum is VQ=16.
55
+ */
56
+ if (cpu_isar_feature(aa64_sme, env_archcpu(env))
57
+ && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
58
+ int vq, old_vq;
59
+
60
+ old_vq = sme_vq(env);
61
+
62
+ /*
63
+ * Bound the value of vq, so that we know that it fits into
64
+ * the 4-bit field in SMCR_EL1. Because PSTATE.SM is cleared
65
+ * on syscall entry, we are not modifying the current SVE
66
+ * vector length.
67
+ */
68
+ vq = MAX(arg2 / 16, 1);
69
+ vq = MIN(vq, 16);
70
+ env->vfp.smcr_el[1] =
71
+ FIELD_DP64(env->vfp.smcr_el[1], SMCR, LEN, vq - 1);
72
+
73
+ /* Delay rebuilding hflags until we know if ZA must change. */
74
+ vq = sve_vqm1_for_el_sm(env, 0, true) + 1;
75
+
76
+ if (vq != old_vq) {
77
+ /*
78
+ * PSTATE.ZA state is cleared on any change to SVL.
79
+ * We need not call arm_rebuild_hflags because PSTATE.SM was
80
+ * cleared on syscall entry, so this hasn't changed VL.
81
+ */
82
+ env->svcr = FIELD_DP64(env->svcr, SVCR, ZA, 0);
83
+ arm_rebuild_hflags(env);
84
+ }
85
+ return vq * 16;
86
+ }
87
+ return -TARGET_EINVAL;
88
+}
89
+#define do_prctl_sme_set_vl do_prctl_sme_set_vl
90
+
91
static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2)
92
{
93
ARMCPU *cpu = env_archcpu(env);
94
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/linux-user/syscall.c
97
+++ b/linux-user/syscall.c
98
@@ -XXX,XX +XXX,XX @@ abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
99
#ifndef PR_SET_SYSCALL_USER_DISPATCH
100
# define PR_SET_SYSCALL_USER_DISPATCH 59
101
#endif
102
+#ifndef PR_SME_SET_VL
103
+# define PR_SME_SET_VL 63
104
+# define PR_SME_GET_VL 64
105
+# define PR_SME_VL_LEN_MASK 0xffff
106
+# define PR_SME_VL_INHERIT (1 << 17)
107
+#endif
108
109
#include "target_prctl.h"
110
111
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
112
#ifndef do_prctl_set_unalign
113
#define do_prctl_set_unalign do_prctl_inval1
114
#endif
115
+#ifndef do_prctl_sme_get_vl
116
+#define do_prctl_sme_get_vl do_prctl_inval0
117
+#endif
118
+#ifndef do_prctl_sme_set_vl
119
+#define do_prctl_sme_set_vl do_prctl_inval1
120
+#endif
121
122
static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
123
abi_long arg3, abi_long arg4, abi_long arg5)
124
@@ -XXX,XX +XXX,XX @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
125
return do_prctl_sve_get_vl(env);
126
case PR_SVE_SET_VL:
127
return do_prctl_sve_set_vl(env, arg2);
128
+ case PR_SME_GET_VL:
129
+ return do_prctl_sme_get_vl(env);
130
+ case PR_SME_SET_VL:
131
+ return do_prctl_sme_set_vl(env, arg2);
132
case PR_PAC_RESET_KEYS:
133
if (arg3 || arg4 || arg5) {
134
return -TARGET_EINVAL;
59
--
135
--
60
2.17.1
136
2.25.1
61
62
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This register was added to aa32 state by ARMv8.2.
3
There's no reason to set CPACR_EL1.ZEN if SVE disabled.
4
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20220708151540.18136-44-richard.henderson@linaro.org
7
Message-id: 20180629001538.11415-6-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
9
---
10
target/arm/cpu.h | 1 +
10
target/arm/cpu.c | 7 +++----
11
target/arm/cpu.c | 4 ++++
11
1 file changed, 3 insertions(+), 4 deletions(-)
12
target/arm/cpu64.c | 2 ++
13
target/arm/helper.c | 5 ++---
14
4 files changed, 9 insertions(+), 3 deletions(-)
15
12
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
uint32_t id_isar3;
22
uint32_t id_isar4;
23
uint32_t id_isar5;
24
+ uint32_t id_isar6;
25
uint64_t id_aa64pfr0;
26
uint64_t id_aa64pfr1;
27
uint64_t id_aa64dfr0;
28
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
29
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.c
15
--- a/target/arm/cpu.c
31
+++ b/target/arm/cpu.c
16
+++ b/target/arm/cpu.c
32
@@ -XXX,XX +XXX,XX @@ static void cortex_m3_initfn(Object *obj)
17
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
33
cpu->id_isar3 = 0x01111110;
18
/* and to the FP/Neon instructions */
34
cpu->id_isar4 = 0x01310102;
19
env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
35
cpu->id_isar5 = 0x00000000;
20
CPACR_EL1, FPEN, 3);
36
+ cpu->id_isar6 = 0x00000000;
21
- /* and to the SVE instructions */
37
}
22
- env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
38
23
- CPACR_EL1, ZEN, 3);
39
static void cortex_m4_initfn(Object *obj)
24
- /* with reasonable vector length */
40
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
25
+ /* and to the SVE instructions, with default vector length */
41
cpu->id_isar3 = 0x01111110;
26
if (cpu_isar_feature(aa64_sve, cpu)) {
42
cpu->id_isar4 = 0x01310102;
27
+ env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
43
cpu->id_isar5 = 0x00000000;
28
+ CPACR_EL1, ZEN, 3);
44
+ cpu->id_isar6 = 0x00000000;
29
env->vfp.zcr_el[1] = cpu->sve_default_vq - 1;
45
}
30
}
46
31
/*
47
static void cortex_m33_initfn(Object *obj)
48
@@ -XXX,XX +XXX,XX @@ static void cortex_m33_initfn(Object *obj)
49
cpu->id_isar3 = 0x01111131;
50
cpu->id_isar4 = 0x01310132;
51
cpu->id_isar5 = 0x00000000;
52
+ cpu->id_isar6 = 0x00000000;
53
cpu->clidr = 0x00000000;
54
cpu->ctr = 0x8000c000;
55
}
56
@@ -XXX,XX +XXX,XX @@ static void cortex_r5_initfn(Object *obj)
57
cpu->id_isar3 = 0x01112131;
58
cpu->id_isar4 = 0x0010142;
59
cpu->id_isar5 = 0x0;
60
+ cpu->id_isar6 = 0x0;
61
cpu->mp_is_up = true;
62
cpu->pmsav7_dregion = 16;
63
define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
64
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/cpu64.c
67
+++ b/target/arm/cpu64.c
68
@@ -XXX,XX +XXX,XX @@ static void aarch64_a57_initfn(Object *obj)
69
cpu->id_isar3 = 0x01112131;
70
cpu->id_isar4 = 0x00011142;
71
cpu->id_isar5 = 0x00011121;
72
+ cpu->id_isar6 = 0;
73
cpu->id_aa64pfr0 = 0x00002222;
74
cpu->id_aa64dfr0 = 0x10305106;
75
cpu->pmceid0 = 0x00000000;
76
@@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj)
77
cpu->id_isar3 = 0x01112131;
78
cpu->id_isar4 = 0x00011142;
79
cpu->id_isar5 = 0x00011121;
80
+ cpu->id_isar6 = 0;
81
cpu->id_aa64pfr0 = 0x00002222;
82
cpu->id_aa64dfr0 = 0x10305106;
83
cpu->id_aa64isar0 = 0x00011120;
84
diff --git a/target/arm/helper.c b/target/arm/helper.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/helper.c
87
+++ b/target/arm/helper.c
88
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
89
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6,
90
.access = PL1_R, .type = ARM_CP_CONST,
91
.resetvalue = cpu->id_mmfr4 },
92
- /* 7 is as yet unallocated and must RAZ */
93
- { .name = "ID_ISAR7_RESERVED", .state = ARM_CP_STATE_BOTH,
94
+ { .name = "ID_ISAR6", .state = ARM_CP_STATE_BOTH,
95
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7,
96
.access = PL1_R, .type = ARM_CP_CONST,
97
- .resetvalue = 0 },
98
+ .resetvalue = cpu->id_isar6 },
99
REGINFO_SENTINEL
100
};
101
define_arm_cp_regs(cpu, v6_idregs);
102
--
32
--
103
2.17.1
33
2.25.1
104
105
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
There is no need to re-set these 3 features already
3
Enable SME, TPIDR2_EL0, and FA64 if supported by the cpu.
4
implied by the call to aarch64_a15_initfn.
5
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20220708151540.18136-45-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20180629001538.11415-5-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
target/arm/cpu.c | 3 ---
10
target/arm/cpu.c | 11 +++++++++++
13
1 file changed, 3 deletions(-)
11
1 file changed, 11 insertions(+)
14
12
15
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.c
15
--- a/target/arm/cpu.c
18
+++ b/target/arm/cpu.c
16
+++ b/target/arm/cpu.c
19
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
17
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
20
* since we don't correctly set the ID registers to advertise them,
18
CPACR_EL1, ZEN, 3);
21
*/
19
env->vfp.zcr_el[1] = cpu->sve_default_vq - 1;
22
set_feature(&cpu->env, ARM_FEATURE_V8);
20
}
23
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
21
+ /* and for SME instructions, with default vector length, and TPIDR2 */
24
- set_feature(&cpu->env, ARM_FEATURE_NEON);
22
+ if (cpu_isar_feature(aa64_sme, cpu)) {
25
- set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
23
+ env->cp15.sctlr_el[1] |= SCTLR_EnTP2;
26
set_feature(&cpu->env, ARM_FEATURE_V8_AES);
24
+ env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
27
set_feature(&cpu->env, ARM_FEATURE_V8_SHA1);
25
+ CPACR_EL1, SMEN, 3);
28
set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
26
+ env->vfp.smcr_el[1] = cpu->sme_default_vq - 1;
27
+ if (cpu_isar_feature(aa64_sme_fa64, cpu)) {
28
+ env->vfp.smcr_el[1] = FIELD_DP64(env->vfp.smcr_el[1],
29
+ SMCR, FA64, 1);
30
+ }
31
+ }
32
/*
33
* Enable 48-bit address space (TODO: take reserved_va into account).
34
* Enable TBI0 but not TBI1.
29
--
35
--
30
2.17.1
36
2.25.1
31
32
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Enable ARM_FEATURE_SVE for the generic "max" cpu.
4
5
Tested-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180627043328.11531-35-richard.henderson@linaro.org
5
Message-id: 20220708151540.18136-46-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
7
---
11
linux-user/elfload.c | 1 +
8
linux-user/elfload.c | 20 ++++++++++++++++++++
12
target/arm/cpu.c | 7 +++++++
9
1 file changed, 20 insertions(+)
13
target/arm/cpu64.c | 1 +
14
3 files changed, 9 insertions(+)
15
10
16
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
11
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
18
--- a/linux-user/elfload.c
13
--- a/linux-user/elfload.c
19
+++ b/linux-user/elfload.c
14
+++ b/linux-user/elfload.c
20
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
15
@@ -XXX,XX +XXX,XX @@ enum {
21
GET_FEATURE(ARM_FEATURE_V8_ATOMICS, ARM_HWCAP_A64_ATOMICS);
16
ARM_HWCAP2_A64_RNG = 1 << 16,
22
GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
17
ARM_HWCAP2_A64_BTI = 1 << 17,
23
GET_FEATURE(ARM_FEATURE_V8_FCMA, ARM_HWCAP_A64_FCMA);
18
ARM_HWCAP2_A64_MTE = 1 << 18,
24
+ GET_FEATURE(ARM_FEATURE_SVE, ARM_HWCAP_A64_SVE);
19
+ ARM_HWCAP2_A64_ECV = 1 << 19,
25
#undef GET_FEATURE
20
+ ARM_HWCAP2_A64_AFP = 1 << 20,
21
+ ARM_HWCAP2_A64_RPRES = 1 << 21,
22
+ ARM_HWCAP2_A64_MTE3 = 1 << 22,
23
+ ARM_HWCAP2_A64_SME = 1 << 23,
24
+ ARM_HWCAP2_A64_SME_I16I64 = 1 << 24,
25
+ ARM_HWCAP2_A64_SME_F64F64 = 1 << 25,
26
+ ARM_HWCAP2_A64_SME_I8I32 = 1 << 26,
27
+ ARM_HWCAP2_A64_SME_F16F32 = 1 << 27,
28
+ ARM_HWCAP2_A64_SME_B16F32 = 1 << 28,
29
+ ARM_HWCAP2_A64_SME_F32F32 = 1 << 29,
30
+ ARM_HWCAP2_A64_SME_FA64 = 1 << 30,
31
};
32
33
#define ELF_HWCAP get_elf_hwcap()
34
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap2(void)
35
GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG);
36
GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI);
37
GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE);
38
+ GET_FEATURE_ID(aa64_sme, (ARM_HWCAP2_A64_SME |
39
+ ARM_HWCAP2_A64_SME_F32F32 |
40
+ ARM_HWCAP2_A64_SME_B16F32 |
41
+ ARM_HWCAP2_A64_SME_F16F32 |
42
+ ARM_HWCAP2_A64_SME_I8I32));
43
+ GET_FEATURE_ID(aa64_sme_f64f64, ARM_HWCAP2_A64_SME_F64F64);
44
+ GET_FEATURE_ID(aa64_sme_i16i64, ARM_HWCAP2_A64_SME_I16I64);
45
+ GET_FEATURE_ID(aa64_sme_fa64, ARM_HWCAP2_A64_SME_FA64);
26
46
27
return hwcaps;
47
return hwcaps;
28
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
48
}
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.c
31
+++ b/target/arm/cpu.c
32
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
33
env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE;
34
/* and to the FP/Neon instructions */
35
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 2, 3);
36
+ /* and to the SVE instructions */
37
+ env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3);
38
+ env->cp15.cptr_el[3] |= CPTR_EZ;
39
+ /* with maximum vector length */
40
+ env->vfp.zcr_el[1] = ARM_MAX_VQ - 1;
41
+ env->vfp.zcr_el[2] = ARM_MAX_VQ - 1;
42
+ env->vfp.zcr_el[3] = ARM_MAX_VQ - 1;
43
#else
44
/* Reset into the highest available EL */
45
if (arm_feature(env, ARM_FEATURE_EL3)) {
46
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu64.c
49
+++ b/target/arm/cpu64.c
50
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
51
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
52
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
53
set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
54
+ set_feature(&cpu->env, ARM_FEATURE_SVE);
55
/* For usermode -cpu max we can use a larger and more efficient DCZ
56
* blocksize since we don't have to follow what the hardware does.
57
*/
58
--
49
--
59
2.17.1
50
2.25.1
60
61
diff view generated by jsdifflib
Deleted patch
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
1
3
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
---
7
hw/arm/mcimx7d-sabre.c | 2 --
8
1 file changed, 2 deletions(-)
9
10
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/arm/mcimx7d-sabre.c
13
+++ b/hw/arm/mcimx7d-sabre.c
14
@@ -XXX,XX +XXX,XX @@
15
#include "hw/arm/fsl-imx7.h"
16
#include "hw/boards.h"
17
#include "sysemu/sysemu.h"
18
-#include "sysemu/device_tree.h"
19
#include "qemu/error-report.h"
20
#include "sysemu/qtest.h"
21
-#include "net/net.h"
22
23
typedef struct {
24
FslIMX7State soc;
25
--
26
2.17.1
27
28
diff view generated by jsdifflib
Deleted patch
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
1
3
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
---
7
hw/arm/fsl-imx7.c | 2 +-
8
1 file changed, 1 insertion(+), 1 deletion(-)
9
10
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/arm/fsl-imx7.c
13
+++ b/hw/arm/fsl-imx7.c
14
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
15
/*
16
* SRC
17
*/
18
- create_unimplemented_device("sdma", FSL_IMX7_SRC_ADDR, FSL_IMX7_SRC_SIZE);
19
+ create_unimplemented_device("src", FSL_IMX7_SRC_ADDR, FSL_IMX7_SRC_SIZE);
20
21
/*
22
* Watchdog
23
--
24
2.17.1
25
26
diff view generated by jsdifflib
Deleted patch
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
1
3
The qdev_get_gpio_in() function accept an int as second parameter.
4
5
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/arm/fsl-imx7.c | 6 +++---
11
1 file changed, 3 insertions(+), 3 deletions(-)
12
13
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/fsl-imx7.c
16
+++ b/hw/arm/fsl-imx7.c
17
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
18
FSL_IMX7_ECSPI4_ADDR,
19
};
20
21
- static const hwaddr FSL_IMX7_SPIn_IRQ[FSL_IMX7_NUM_ECSPIS] = {
22
+ static const int FSL_IMX7_SPIn_IRQ[FSL_IMX7_NUM_ECSPIS] = {
23
FSL_IMX7_ECSPI1_IRQ,
24
FSL_IMX7_ECSPI2_IRQ,
25
FSL_IMX7_ECSPI3_IRQ,
26
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
27
FSL_IMX7_I2C4_ADDR,
28
};
29
30
- static const hwaddr FSL_IMX7_I2Cn_IRQ[FSL_IMX7_NUM_I2CS] = {
31
+ static const int FSL_IMX7_I2Cn_IRQ[FSL_IMX7_NUM_I2CS] = {
32
FSL_IMX7_I2C1_IRQ,
33
FSL_IMX7_I2C2_IRQ,
34
FSL_IMX7_I2C3_IRQ,
35
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
36
FSL_IMX7_USB3_ADDR,
37
};
38
39
- static const hwaddr FSL_IMX7_USBn_IRQ[FSL_IMX7_NUM_USBS] = {
40
+ static const int FSL_IMX7_USBn_IRQ[FSL_IMX7_NUM_USBS] = {
41
FSL_IMX7_USB1_IRQ,
42
FSL_IMX7_USB2_IRQ,
43
FSL_IMX7_USB3_IRQ,
44
--
45
2.17.1
46
47
diff view generated by jsdifflib
Deleted patch
1
We don't actually implement SD command CRC checking, because
2
for almost all of our SD controllers the CRC generation is
3
done in hardware, and so modelling CRC generation and checking
4
would be a bit pointless. (The exception is that milkymist-memcard
5
makes the guest software compute the CRC.)
6
1
7
As a result almost all of our SD controller models don't bother
8
to set the SDRequest crc field, and the SD card model doesn't
9
check it. So the tracing of it in sdbus_do_command() provokes
10
Coverity warnings about use of uninitialized data.
11
12
Drop the CRC field from the trace; we can always add it back
13
if and when we do anything useful with the CRC.
14
15
Fixes Coverity issues 1386072, 1386074, 1386076, 1390571.
16
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Message-id: 20180626180324.5537-1-peter.maydell@linaro.org
20
---
21
hw/sd/core.c | 2 +-
22
hw/sd/trace-events | 2 +-
23
2 files changed, 2 insertions(+), 2 deletions(-)
24
25
diff --git a/hw/sd/core.c b/hw/sd/core.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/sd/core.c
28
+++ b/hw/sd/core.c
29
@@ -XXX,XX +XXX,XX @@ int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
30
{
31
SDState *card = get_card(sdbus);
32
33
- trace_sdbus_command(sdbus_name(sdbus), req->cmd, req->arg, req->crc);
34
+ trace_sdbus_command(sdbus_name(sdbus), req->cmd, req->arg);
35
if (card) {
36
SDCardClass *sc = SD_CARD_GET_CLASS(card);
37
38
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/sd/trace-events
41
+++ b/hw/sd/trace-events
42
@@ -XXX,XX +XXX,XX @@ bcm2835_sdhost_edm_change(const char *why, uint32_t edm) "(%s) EDM now 0x%x"
43
bcm2835_sdhost_update_irq(uint32_t irq) "IRQ bits 0x%x\n"
44
45
# hw/sd/core.c
46
-sdbus_command(const char *bus_name, uint8_t cmd, uint32_t arg, uint8_t crc) "@%s CMD%02d arg 0x%08x crc 0x%02x"
47
+sdbus_command(const char *bus_name, uint8_t cmd, uint32_t arg) "@%s CMD%02d arg 0x%08x"
48
sdbus_read(const char *bus_name, uint8_t value) "@%s value 0x%02x"
49
sdbus_write(const char *bus_name, uint8_t value) "@%s value 0x%02x"
50
sdbus_set_voltage(const char *bus_name, uint16_t millivolts) "@%s %u (mV)"
51
--
52
2.17.1
53
54
diff view generated by jsdifflib