1
The following changes since commit e5cd695266c5709308aa95b1baae499e4b5d4544:
1
Respin to fix some accidental wrong Author lines, no content
2
changes.
2
3
3
Merge remote-tracking branch 'remotes/cody/tags/block-pull-request' into staging (2018-05-08 17:05:58 +0100)
4
-- PMM
5
6
The following changes since commit 0bbba1665ca2e7f1c80d4797077fe57bad58898e:
7
8
Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-october-2018-part-4' into staging (2018-10-30 10:45:49 +0000)
4
9
5
are available in the Git repository at:
10
are available in the Git repository at:
6
11
7
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180510
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20181030
8
13
9
for you to fetch changes up to 9a9f1f59521f46e8ff4527d9a2b52f83577e2aa3:
14
for you to fetch changes up to 1f5a65a188210509bfb0c025fc91635c8436b98a:
10
15
11
target/arm: Clear SVE high bits for FMOV (2018-05-10 18:10:58 +0100)
16
tests/boot-serial-test: Add microbit board testcase (2018-10-30 13:20:18 +0000)
12
17
13
----------------------------------------------------------------
18
----------------------------------------------------------------
14
target-arm queue:
19
target-arm queue:
15
* hw/arm/iotkit.c: fix minor memory leak
20
* microbit: Add the UART to our nRF51 SoC model
16
* softfloat: fix wrong-exception-flags bug for multiply-add corner case
21
* Add a virtual Xilinx Versal board "xlnx-versal-virt"
17
* arm: isolate and clean up DTB generation
22
* hw/arm/virt: Set VIRT_COMPAT_3_0 compat
18
* implement Arm v8.1-Atomics extension
19
* Fix some bugs and missing instructions in the v8.2-FP16 extension
20
23
21
----------------------------------------------------------------
24
----------------------------------------------------------------
22
Igor Mammedov (4):
25
Edgar E. Iglesias (2):
23
pc: simplify MachineClass::get_hotplug_handler handling
26
hw/arm: versal: Add a model of Xilinx Versal SoC
24
platform-bus-device: use device plug callback instead of machine_done notifier
27
hw/arm: versal: Add a virtual Xilinx Versal board
25
arm/boot: split load_dtb() from arm_load_kernel()
26
make sure that we aren't overwriting mc->get_hotplug_handler by accident
27
28
28
Peter Maydell (3):
29
Eric Auger (1):
29
hw/arm/iotkit.c: fix minor memory leak
30
hw/arm/virt: Set VIRT_COMPAT_3_0 compat
30
softfloat: Handle default NaN mode after pickNaNMulAdd, not before
31
atomic.h: Work around gcc spurious "unused value" warning
32
31
33
Richard Henderson (14):
32
Julia Suvorova (3):
34
tcg: Introduce helpers for integer min/max
33
hw/char: Implement nRF51 SoC UART
35
target/arm: Use new min/max expanders
34
hw/arm/nrf51_soc: Connect UART to nRF51 SoC
36
target/xtensa: Use new min/max expanders
35
tests/boot-serial-test: Add microbit board testcase
37
tcg: Introduce atomic helpers for integer min/max
38
tcg: Use GEN_ATOMIC_HELPER_FN for opposite endian atomic add
39
target/riscv: Use new atomic min/max expanders
40
target/arm: Introduce ARM_FEATURE_V8_ATOMICS and initial decode
41
target/arm: Fill in disas_ldst_atomic
42
target/arm: Implement CAS and CASP
43
target/arm: Enable ARM_FEATURE_V8_ATOMICS for user-only
44
target/arm: Implement vector shifted SCVF/UCVF for fp16
45
target/arm: Implement vector shifted FCVT for fp16
46
target/arm: Fix float16 to/from int16
47
target/arm: Clear SVE high bits for FMOV
48
36
49
accel/tcg/atomic_template.h | 112 ++++++----
37
hw/arm/Makefile.objs | 1 +
50
accel/tcg/tcg-runtime.h | 8 +
38
hw/char/Makefile.objs | 1 +
51
hw/ppc/e500.h | 5 +
39
include/hw/arm/nrf51_soc.h | 3 +
52
include/hw/arm/arm.h | 45 +++-
40
include/hw/arm/xlnx-versal.h | 122 +++++++++
53
include/hw/arm/sysbus-fdt.h | 37 +---
41
include/hw/char/nrf51_uart.h | 78 ++++++
54
include/hw/arm/virt.h | 1 +
42
hw/arm/microbit.c | 2 +
55
include/hw/i386/pc.h | 8 -
43
hw/arm/nrf51_soc.c | 20 ++
56
include/hw/platform-bus.h | 4 +-
44
hw/arm/virt.c | 4 +
57
include/qemu/atomic.h | 2 +-
45
hw/arm/xlnx-versal-virt.c | 493 ++++++++++++++++++++++++++++++++++++
58
target/arm/cpu.h | 1 +
46
hw/arm/xlnx-versal.c | 323 +++++++++++++++++++++++
59
target/arm/helper-a64.h | 2 +
47
hw/char/nrf51_uart.c | 330 ++++++++++++++++++++++++
60
target/arm/helper.h | 4 +-
48
tests/boot-serial-test.c | 19 ++
61
tcg/tcg-op.h | 50 +++++
49
default-configs/aarch64-softmmu.mak | 1 +
62
tcg/tcg.h | 8 +
50
hw/char/trace-events | 4 +
63
fpu/softfloat.c | 52 +++--
51
14 files changed, 1401 insertions(+)
64
hw/arm/boot.c | 72 ++-----
52
create mode 100644 include/hw/arm/xlnx-versal.h
65
hw/arm/iotkit.c | 1 +
53
create mode 100644 include/hw/char/nrf51_uart.h
66
hw/arm/sysbus-fdt.c | 64 +-----
54
create mode 100644 hw/arm/xlnx-versal-virt.c
67
hw/arm/virt.c | 96 ++++++---
55
create mode 100644 hw/arm/xlnx-versal.c
68
hw/core/platform-bus.c | 29 +--
56
create mode 100644 hw/char/nrf51_uart.c
69
hw/i386/pc.c | 7 +-
70
hw/ppc/e500.c | 38 ++--
71
hw/ppc/e500plat.c | 32 +++
72
hw/ppc/spapr.c | 1 +
73
hw/s390x/s390-virtio-ccw.c | 1 +
74
linux-user/elfload.c | 1 +
75
target/arm/cpu64.c | 1 +
76
target/arm/helper-a64.c | 43 ++++
77
target/arm/helper.c | 53 ++++-
78
target/arm/translate-a64.c | 490 +++++++++++++++++++++++++++++++++-----------
79
target/riscv/translate.c | 72 ++-----
80
target/xtensa/translate.c | 50 +++--
81
tcg/tcg-op.c | 48 +++++
82
33 files changed, 934 insertions(+), 504 deletions(-)
83
57
diff view generated by jsdifflib
Deleted patch
1
Coverity (CID1390573) spots that we forgot to free the
2
gpioname strings in a loop in the iotkit realize function.
3
Correct the error.
4
1
5
This isn't a significant leak, because this function
6
only ever runs once.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Peter Xu <peterx@redhat.com>
11
Message-id: 20180427110137.19304-1-peter.maydell@linaro.org
12
---
13
hw/arm/iotkit.c | 1 +
14
1 file changed, 1 insertion(+)
15
16
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/iotkit.c
19
+++ b/hw/arm/iotkit.c
20
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
21
qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
22
qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
23
qdev_get_gpio_in(devs, 0));
24
+ g_free(gpioname);
25
}
26
27
iotkit_forward_sec_resp_cfg(s);
28
--
29
2.17.0
30
31
diff view generated by jsdifflib
Deleted patch
1
It is implementation defined whether a multiply-add of
2
(0,inf,qnan) or (inf,0,qnan) raises InvalidaOperation or
3
not, so we let the target-specific pickNaNMulAdd function
4
handle this. This means that we must do the "return the
5
default NaN in default NaN mode" check after the call,
6
not before. Correct the ordering, and restore the comment
7
from the old propagateFloat64MulAddNaN() that warned about
8
this corner case.
9
1
10
This fixes a regression from 2.11 for Arm guests where we would
11
incorrectly fail to set the Invalid flag for these cases.
12
13
Cc: qemu-stable@nongnu.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
Tested-by: Alex Bennée <alex.bennee@linaro.org>
18
Message-id: 20180504100547.14621-1-peter.maydell@linaro.org
19
---
20
fpu/softfloat.c | 52 ++++++++++++++++++++++++++++---------------------
21
1 file changed, 30 insertions(+), 22 deletions(-)
22
23
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/fpu/softfloat.c
26
+++ b/fpu/softfloat.c
27
@@ -XXX,XX +XXX,XX @@ static FloatParts pick_nan(FloatParts a, FloatParts b, float_status *s)
28
static FloatParts pick_nan_muladd(FloatParts a, FloatParts b, FloatParts c,
29
bool inf_zero, float_status *s)
30
{
31
+ int which;
32
+
33
if (is_snan(a.cls) || is_snan(b.cls) || is_snan(c.cls)) {
34
s->float_exception_flags |= float_flag_invalid;
35
}
36
37
- if (s->default_nan_mode) {
38
- a.cls = float_class_dnan;
39
- } else {
40
- switch (pickNaNMulAdd(is_qnan(a.cls), is_snan(a.cls),
41
- is_qnan(b.cls), is_snan(b.cls),
42
- is_qnan(c.cls), is_snan(c.cls),
43
- inf_zero, s)) {
44
- case 0:
45
- break;
46
- case 1:
47
- a = b;
48
- break;
49
- case 2:
50
- a = c;
51
- break;
52
- case 3:
53
- a.cls = float_class_dnan;
54
- return a;
55
- default:
56
- g_assert_not_reached();
57
- }
58
+ which = pickNaNMulAdd(is_qnan(a.cls), is_snan(a.cls),
59
+ is_qnan(b.cls), is_snan(b.cls),
60
+ is_qnan(c.cls), is_snan(c.cls),
61
+ inf_zero, s);
62
63
- a.cls = float_class_msnan;
64
+ if (s->default_nan_mode) {
65
+ /* Note that this check is after pickNaNMulAdd so that function
66
+ * has an opportunity to set the Invalid flag.
67
+ */
68
+ a.cls = float_class_dnan;
69
+ return a;
70
}
71
+
72
+ switch (which) {
73
+ case 0:
74
+ break;
75
+ case 1:
76
+ a = b;
77
+ break;
78
+ case 2:
79
+ a = c;
80
+ break;
81
+ case 3:
82
+ a.cls = float_class_dnan;
83
+ return a;
84
+ default:
85
+ g_assert_not_reached();
86
+ }
87
+ a.cls = float_class_msnan;
88
+
89
return a;
90
}
91
92
--
93
2.17.0
94
95
diff view generated by jsdifflib
Deleted patch
1
From: Igor Mammedov <imammedo@redhat.com>
2
1
3
By default MachineClass::get_hotplug_handler is NULL and concrete board
4
should set it to it's own handler.
5
Considering there isn't any default handler, drop saving empty
6
MachineClass::get_hotplug_handler in child class and make PC code
7
consistent with spapr/s390x boards.
8
9
We can bring this back when actual usecase surfaces and do it
10
consistently across boards that use get_hotplug_handler().
11
12
Suggested-by: David Gibson <david@gibson.dropbear.id.au>
13
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
16
Message-id: 1525691524-32265-2-git-send-email-imammedo@redhat.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
include/hw/i386/pc.h | 8 --------
20
hw/i386/pc.c | 6 +-----
21
2 files changed, 1 insertion(+), 13 deletions(-)
22
23
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/i386/pc.h
26
+++ b/include/hw/i386/pc.h
27
@@ -XXX,XX +XXX,XX @@ struct PCMachineState {
28
/**
29
* PCMachineClass:
30
*
31
- * Methods:
32
- *
33
- * @get_hotplug_handler: pointer to parent class callback @get_hotplug_handler
34
- *
35
* Compat fields:
36
*
37
* @enforce_aligned_dimm: check that DIMM's address/size is aligned by
38
@@ -XXX,XX +XXX,XX @@ struct PCMachineClass {
39
40
/*< public >*/
41
42
- /* Methods: */
43
- HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
44
- DeviceState *dev);
45
-
46
/* Device configuration: */
47
bool pci_enabled;
48
bool kvmclock_enabled;
49
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/i386/pc.c
52
+++ b/hw/i386/pc.c
53
@@ -XXX,XX +XXX,XX @@ static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
54
static HotplugHandler *pc_get_hotpug_handler(MachineState *machine,
55
DeviceState *dev)
56
{
57
- PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(machine);
58
-
59
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
60
object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
61
return HOTPLUG_HANDLER(machine);
62
}
63
64
- return pcmc->get_hotplug_handler ?
65
- pcmc->get_hotplug_handler(machine, dev) : NULL;
66
+ return NULL;
67
}
68
69
static void
70
@@ -XXX,XX +XXX,XX @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
71
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
72
NMIClass *nc = NMI_CLASS(oc);
73
74
- pcmc->get_hotplug_handler = mc->get_hotplug_handler;
75
pcmc->pci_enabled = true;
76
pcmc->has_acpi_build = true;
77
pcmc->rsdp_in_ram = true;
78
--
79
2.17.0
80
81
diff view generated by jsdifflib
Deleted patch
1
From: Igor Mammedov <imammedo@redhat.com>
2
1
3
platform-bus were using machine_done notifier to get and map
4
(assign irq/mmio resources) dynamically added sysbus devices
5
after all '-device' options had been processed.
6
That however creates non obvious dependencies on ordering of
7
machine_done notifiers and requires carefull line juggling
8
to keep it working. For example see comment above
9
create_platform_bus() and 'straitforward' arm_load_kernel()
10
had to converted to machine_done notifier and that lead to
11
yet another machine_done notifier to keep it working
12
arm_register_platform_bus_fdt_creator().
13
14
Instead of hiding resource assignment in platform-bus-device
15
to magically initialize sysbus devices, use device plug
16
callback and assign resources explicitly at board level
17
at the moment each -device option is being processed.
18
19
That adds a bunch of machine declaration boiler plate to
20
e500plat board, similar to ARM/x86 but gets rid of hidden
21
machine_done notifier and would allow to remove the dependent
22
notifiers in ARM code simplifying it and making code flow
23
easier to follow.
24
25
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
26
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
27
Acked-by: David Gibson <david@gibson.dropbear.id.au>
28
Message-id: 1525691524-32265-3-git-send-email-imammedo@redhat.com
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
---
31
hw/ppc/e500.h | 5 +++++
32
include/hw/arm/virt.h | 1 +
33
include/hw/platform-bus.h | 4 ++--
34
hw/arm/sysbus-fdt.c | 3 ---
35
hw/arm/virt.c | 31 +++++++++++++++++++++++++++++++
36
hw/core/platform-bus.c | 29 +++++------------------------
37
hw/ppc/e500.c | 38 +++++++++++++++++---------------------
38
hw/ppc/e500plat.c | 31 +++++++++++++++++++++++++++++++
39
8 files changed, 92 insertions(+), 50 deletions(-)
40
41
diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/ppc/e500.h
44
+++ b/hw/ppc/e500.h
45
@@ -XXX,XX +XXX,XX @@
46
#define PPCE500_H
47
48
#include "hw/boards.h"
49
+#include "hw/platform-bus.h"
50
51
typedef struct PPCE500MachineState {
52
/*< private >*/
53
MachineState parent_obj;
54
55
+ /* points to instance of TYPE_PLATFORM_BUS_DEVICE if
56
+ * board supports dynamic sysbus devices
57
+ */
58
+ PlatformBusDevice *pbus_dev;
59
} PPCE500MachineState;
60
61
typedef struct PPCE500MachineClass {
62
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
63
index XXXXXXX..XXXXXXX 100644
64
--- a/include/hw/arm/virt.h
65
+++ b/include/hw/arm/virt.h
66
@@ -XXX,XX +XXX,XX @@ typedef struct {
67
typedef struct {
68
MachineState parent;
69
Notifier machine_done;
70
+ DeviceState *platform_bus_dev;
71
FWCfgState *fw_cfg;
72
bool secure;
73
bool highmem;
74
diff --git a/include/hw/platform-bus.h b/include/hw/platform-bus.h
75
index XXXXXXX..XXXXXXX 100644
76
--- a/include/hw/platform-bus.h
77
+++ b/include/hw/platform-bus.h
78
@@ -XXX,XX +XXX,XX @@ typedef struct PlatformBusDevice PlatformBusDevice;
79
struct PlatformBusDevice {
80
/*< private >*/
81
SysBusDevice parent_obj;
82
- Notifier notifier;
83
- bool done_gathering;
84
85
/*< public >*/
86
uint32_t mmio_size;
87
@@ -XXX,XX +XXX,XX @@ int platform_bus_get_irqn(PlatformBusDevice *platform_bus, SysBusDevice *sbdev,
88
hwaddr platform_bus_get_mmio_addr(PlatformBusDevice *pbus, SysBusDevice *sbdev,
89
int n);
90
91
+void platform_bus_link_device(PlatformBusDevice *pbus, SysBusDevice *sbdev);
92
+
93
#endif /* HW_PLATFORM_BUS_H */
94
diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/hw/arm/sysbus-fdt.c
97
+++ b/hw/arm/sysbus-fdt.c
98
@@ -XXX,XX +XXX,XX @@ static void add_all_platform_bus_fdt_nodes(ARMPlatformBusFDTParams *fdt_params)
99
dev = qdev_find_recursive(sysbus_get_default(), TYPE_PLATFORM_BUS_DEVICE);
100
pbus = PLATFORM_BUS_DEVICE(dev);
101
102
- /* We can only create dt nodes for dynamic devices when they're ready */
103
- assert(pbus->done_gathering);
104
-
105
PlatformBusFDTData data = {
106
.fdt = fdt,
107
.irq_start = irq_start,
108
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/hw/arm/virt.c
111
+++ b/hw/arm/virt.c
112
@@ -XXX,XX +XXX,XX @@ static void create_platform_bus(VirtMachineState *vms, qemu_irq *pic)
113
qdev_prop_set_uint32(dev, "mmio_size",
114
platform_bus_params.platform_bus_size);
115
qdev_init_nofail(dev);
116
+ vms->platform_bus_dev = dev;
117
s = SYS_BUS_DEVICE(dev);
118
119
for (i = 0; i < platform_bus_params.platform_bus_num_irqs; i++) {
120
@@ -XXX,XX +XXX,XX @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
121
return ms->possible_cpus;
122
}
123
124
+static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
125
+ DeviceState *dev, Error **errp)
126
+{
127
+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
128
+
129
+ if (vms->platform_bus_dev) {
130
+ if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)) {
131
+ platform_bus_link_device(PLATFORM_BUS_DEVICE(vms->platform_bus_dev),
132
+ SYS_BUS_DEVICE(dev));
133
+ }
134
+ }
135
+}
136
+
137
+static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
138
+ DeviceState *dev)
139
+{
140
+ if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)) {
141
+ return HOTPLUG_HANDLER(machine);
142
+ }
143
+
144
+ return NULL;
145
+}
146
+
147
static void virt_machine_class_init(ObjectClass *oc, void *data)
148
{
149
MachineClass *mc = MACHINE_CLASS(oc);
150
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
151
152
mc->init = machvirt_init;
153
/* Start max_cpus at the maximum QEMU supports. We'll further restrict
154
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
155
mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
156
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
157
mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
158
+ mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
159
+ hc->plug = virt_machine_device_plug_cb;
160
}
161
162
static const TypeInfo virt_machine_info = {
163
@@ -XXX,XX +XXX,XX @@ static const TypeInfo virt_machine_info = {
164
.instance_size = sizeof(VirtMachineState),
165
.class_size = sizeof(VirtMachineClass),
166
.class_init = virt_machine_class_init,
167
+ .interfaces = (InterfaceInfo[]) {
168
+ { TYPE_HOTPLUG_HANDLER },
169
+ { }
170
+ },
171
};
172
173
static void machvirt_machine_init(void)
174
diff --git a/hw/core/platform-bus.c b/hw/core/platform-bus.c
175
index XXXXXXX..XXXXXXX 100644
176
--- a/hw/core/platform-bus.c
177
+++ b/hw/core/platform-bus.c
178
@@ -XXX,XX +XXX,XX @@ static void plaform_bus_refresh_irqs(PlatformBusDevice *pbus)
179
{
180
bitmap_zero(pbus->used_irqs, pbus->num_irqs);
181
foreach_dynamic_sysbus_device(platform_bus_count_irqs, pbus);
182
- pbus->done_gathering = true;
183
}
184
185
static void platform_bus_map_irq(PlatformBusDevice *pbus, SysBusDevice *sbdev,
186
@@ -XXX,XX +XXX,XX @@ static void platform_bus_map_mmio(PlatformBusDevice *pbus, SysBusDevice *sbdev,
187
}
188
189
/*
190
- * For each sysbus device, look for unassigned IRQ lines as well as
191
- * unassociated MMIO regions. Connect them to the platform bus if available.
192
+ * Look for unassigned IRQ lines as well as unassociated MMIO regions.
193
+ * Connect them to the platform bus if available.
194
*/
195
-static void link_sysbus_device(SysBusDevice *sbdev, void *opaque)
196
+void platform_bus_link_device(PlatformBusDevice *pbus, SysBusDevice *sbdev)
197
{
198
- PlatformBusDevice *pbus = opaque;
199
int i;
200
201
for (i = 0; sysbus_has_irq(sbdev, i); i++) {
202
@@ -XXX,XX +XXX,XX @@ static void link_sysbus_device(SysBusDevice *sbdev, void *opaque)
203
}
204
}
205
206
-static void platform_bus_init_notify(Notifier *notifier, void *data)
207
-{
208
- PlatformBusDevice *pb = container_of(notifier, PlatformBusDevice, notifier);
209
-
210
- /*
211
- * Generate a bitmap of used IRQ lines, as the user might have specified
212
- * them on the command line.
213
- */
214
- plaform_bus_refresh_irqs(pb);
215
-
216
- foreach_dynamic_sysbus_device(link_sysbus_device, pb);
217
-}
218
-
219
static void platform_bus_realize(DeviceState *dev, Error **errp)
220
{
221
PlatformBusDevice *pbus;
222
@@ -XXX,XX +XXX,XX @@ static void platform_bus_realize(DeviceState *dev, Error **errp)
223
sysbus_init_irq(d, &pbus->irqs[i]);
224
}
225
226
- /*
227
- * Register notifier that allows us to gather dangling devices once the
228
- * machine is completely assembled
229
- */
230
- pbus->notifier.notify = platform_bus_init_notify;
231
- qemu_add_machine_init_done_notifier(&pbus->notifier);
232
+ /* some devices might be initialized before so update used IRQs map */
233
+ plaform_bus_refresh_irqs(pbus);
234
}
235
236
static Property platform_bus_properties[] = {
237
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/hw/ppc/e500.c
240
+++ b/hw/ppc/e500.c
241
@@ -XXX,XX +XXX,XX @@ static void sysbus_device_create_devtree(SysBusDevice *sbdev, void *opaque)
242
}
243
}
244
245
-static void platform_bus_create_devtree(const PPCE500MachineClass *pmc,
246
+static void platform_bus_create_devtree(PPCE500MachineState *pms,
247
void *fdt, const char *mpic)
248
{
249
+ const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
250
gchar *node = g_strdup_printf("/platform@%"PRIx64, pmc->platform_bus_base);
251
const char platcomp[] = "qemu,platform\0simple-bus";
252
uint64_t addr = pmc->platform_bus_base;
253
uint64_t size = pmc->platform_bus_size;
254
int irq_start = pmc->platform_bus_first_irq;
255
- PlatformBusDevice *pbus;
256
- DeviceState *dev;
257
258
/* Create a /platform node that we can put all devices into */
259
260
@@ -XXX,XX +XXX,XX @@ static void platform_bus_create_devtree(const PPCE500MachineClass *pmc,
261
262
qemu_fdt_setprop_phandle(fdt, node, "interrupt-parent", mpic);
263
264
- dev = qdev_find_recursive(sysbus_get_default(), TYPE_PLATFORM_BUS_DEVICE);
265
- pbus = PLATFORM_BUS_DEVICE(dev);
266
+ /* Create dt nodes for dynamic devices */
267
+ PlatformDevtreeData data = {
268
+ .fdt = fdt,
269
+ .mpic = mpic,
270
+ .irq_start = irq_start,
271
+ .node = node,
272
+ .pbus = pms->pbus_dev,
273
+ };
274
275
- /* We can only create dt nodes for dynamic devices when they're ready */
276
- if (pbus->done_gathering) {
277
- PlatformDevtreeData data = {
278
- .fdt = fdt,
279
- .mpic = mpic,
280
- .irq_start = irq_start,
281
- .node = node,
282
- .pbus = pbus,
283
- };
284
-
285
- /* Loop through all dynamic sysbus devices and create nodes for them */
286
- foreach_dynamic_sysbus_device(sysbus_device_create_devtree, &data);
287
- }
288
+ /* Loop through all dynamic sysbus devices and create nodes for them */
289
+ foreach_dynamic_sysbus_device(sysbus_device_create_devtree, &data);
290
291
g_free(node);
292
}
293
@@ -XXX,XX +XXX,XX @@ static int ppce500_load_device_tree(PPCE500MachineState *pms,
294
}
295
g_free(soc);
296
297
- if (pmc->has_platform_bus) {
298
- platform_bus_create_devtree(pmc, fdt, mpic);
299
+ if (pms->pbus_dev) {
300
+ platform_bus_create_devtree(pms, fdt, mpic);
301
}
302
g_free(mpic);
303
304
@@ -XXX,XX +XXX,XX @@ void ppce500_init(MachineState *machine)
305
qdev_prop_set_uint32(dev, "num_irqs", pmc->platform_bus_num_irqs);
306
qdev_prop_set_uint32(dev, "mmio_size", pmc->platform_bus_size);
307
qdev_init_nofail(dev);
308
- s = SYS_BUS_DEVICE(dev);
309
+ pms->pbus_dev = PLATFORM_BUS_DEVICE(dev);
310
311
+ s = SYS_BUS_DEVICE(pms->pbus_dev);
312
for (i = 0; i < pmc->platform_bus_num_irqs; i++) {
313
int irqn = pmc->platform_bus_first_irq + i;
314
sysbus_connect_irq(s, i, qdev_get_gpio_in(mpicdev, irqn));
315
@@ -XXX,XX +XXX,XX @@ static const TypeInfo ppce500_info = {
316
.name = TYPE_PPCE500_MACHINE,
317
.parent = TYPE_MACHINE,
318
.abstract = true,
319
+ .instance_size = sizeof(PPCE500MachineState),
320
.class_size = sizeof(PPCE500MachineClass),
321
};
322
323
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
324
index XXXXXXX..XXXXXXX 100644
325
--- a/hw/ppc/e500plat.c
326
+++ b/hw/ppc/e500plat.c
327
@@ -XXX,XX +XXX,XX @@ static void e500plat_init(MachineState *machine)
328
ppce500_init(machine);
329
}
330
331
+static void e500plat_machine_device_plug_cb(HotplugHandler *hotplug_dev,
332
+ DeviceState *dev, Error **errp)
333
+{
334
+ PPCE500MachineState *pms = PPCE500_MACHINE(hotplug_dev);
335
+
336
+ if (pms->pbus_dev) {
337
+ if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)) {
338
+ platform_bus_link_device(pms->pbus_dev, SYS_BUS_DEVICE(dev));
339
+ }
340
+ }
341
+}
342
+
343
+static
344
+HotplugHandler *e500plat_machine_get_hotpug_handler(MachineState *machine,
345
+ DeviceState *dev)
346
+{
347
+ if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)) {
348
+ return HOTPLUG_HANDLER(machine);
349
+ }
350
+
351
+ return NULL;
352
+}
353
+
354
#define TYPE_E500PLAT_MACHINE MACHINE_TYPE_NAME("ppce500")
355
356
static void e500plat_machine_class_init(ObjectClass *oc, void *data)
357
{
358
PPCE500MachineClass *pmc = PPCE500_MACHINE_CLASS(oc);
359
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
360
MachineClass *mc = MACHINE_CLASS(oc);
361
362
+ mc->get_hotplug_handler = e500plat_machine_get_hotpug_handler;
363
+ hc->plug = e500plat_machine_device_plug_cb;
364
+
365
pmc->pci_first_slot = 0x1;
366
pmc->pci_nr_slots = PCI_SLOT_MAX - 1;
367
pmc->fixup_devtree = e500plat_fixup_devtree;
368
@@ -XXX,XX +XXX,XX @@ static const TypeInfo e500plat_info = {
369
.name = TYPE_E500PLAT_MACHINE,
370
.parent = TYPE_PPCE500_MACHINE,
371
.class_init = e500plat_machine_class_init,
372
+ .interfaces = (InterfaceInfo[]) {
373
+ { TYPE_HOTPLUG_HANDLER },
374
+ { }
375
+ }
376
};
377
378
static void e500plat_register_types(void)
379
--
380
2.17.0
381
382
diff view generated by jsdifflib
Deleted patch
1
From: Igor Mammedov <imammedo@redhat.com>
2
1
3
load_dtb() depends on arm_load_kernel() to figure out place
4
in RAM where it should be loaded, but it's not required for
5
arm_load_kernel() to work. Sometimes it's neccesary for
6
devices added with -device/device_add to be enumerated in
7
DTB as well, which's lead to [1] and surrounding commits to
8
add 2 more machine_done notifiers with non obvious ordering
9
to make dynamic sysbus devices initialization happen in
10
the right order.
11
12
However instead of moving whole arm_load_kernel() in to
13
machine_done, it's sufficient to move only load_dtb() into
14
virt_machine_done() notifier and remove ArmLoadKernelNotifier/
15
/PlatformBusFDTNotifierParams notifiers, which saves us ~90LOC
16
and simplifies code flow quite a bit.
17
Later would allow to consolidate DTB generation within one
18
function for 'mach-virt' board and make it reentrant so it
19
could generate updated DTB in device hotplug secenarios.
20
21
While at it rename load_dtb() to arm_load_dtb() since it's
22
public now.
23
24
Add additional field skip_dtb_autoload to struct arm_boot_info
25
to allow manual DTB load later in mach-virt and to avoid touching
26
all other boards to explicitly call arm_load_dtb().
27
28
1) (ac9d32e hw/arm/boot: arm_load_kernel implemented as a machine init done notifier)
29
30
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
31
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
32
Reviewed-by: Andrew Jones <drjones@redhat.com>
33
Message-id: 1525691524-32265-4-git-send-email-imammedo@redhat.com
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
---
36
include/hw/arm/arm.h | 45 +++++++++++++++++------
37
include/hw/arm/sysbus-fdt.h | 37 ++++---------------
38
hw/arm/boot.c | 72 ++++++++++---------------------------
39
hw/arm/sysbus-fdt.c | 61 +++----------------------------
40
hw/arm/virt.c | 64 ++++++++++++++++-----------------
41
5 files changed, 94 insertions(+), 185 deletions(-)
42
43
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
44
index XXXXXXX..XXXXXXX 100644
45
--- a/include/hw/arm/arm.h
46
+++ b/include/hw/arm/arm.h
47
@@ -XXX,XX +XXX,XX @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
48
*/
49
void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size);
50
51
-/*
52
- * struct used as a parameter of the arm_load_kernel machine init
53
- * done notifier
54
- */
55
-typedef struct {
56
- Notifier notifier; /* actual notifier */
57
- ARMCPU *cpu; /* handle to the first cpu object */
58
-} ArmLoadKernelNotifier;
59
-
60
/* arm_boot.c */
61
struct arm_boot_info {
62
uint64_t ram_size;
63
@@ -XXX,XX +XXX,XX @@ struct arm_boot_info {
64
const char *initrd_filename;
65
const char *dtb_filename;
66
hwaddr loader_start;
67
+ hwaddr dtb_start;
68
+ hwaddr dtb_limit;
69
+ /* If set to True, arm_load_kernel() will not load DTB.
70
+ * It allows board to load DTB manually later.
71
+ * (default: False)
72
+ */
73
+ bool skip_dtb_autoload;
74
/* multicore boards that use the default secondary core boot functions
75
* need to put the address of the secondary boot code, the boot reg,
76
* and the GIC address in the next 3 values, respectively. boards that
77
@@ -XXX,XX +XXX,XX @@ struct arm_boot_info {
78
* the user it should implement this hook.
79
*/
80
void (*modify_dtb)(const struct arm_boot_info *info, void *fdt);
81
- /* machine init done notifier executing arm_load_dtb */
82
- ArmLoadKernelNotifier load_kernel_notifier;
83
/* Used internally by arm_boot.c */
84
int is_linux;
85
hwaddr initrd_start;
86
@@ -XXX,XX +XXX,XX @@ struct arm_boot_info {
87
*/
88
void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info);
89
90
+AddressSpace *arm_boot_address_space(ARMCPU *cpu,
91
+ const struct arm_boot_info *info);
92
+
93
+/**
94
+ * arm_load_dtb() - load a device tree binary image into memory
95
+ * @addr: the address to load the image at
96
+ * @binfo: struct describing the boot environment
97
+ * @addr_limit: upper limit of the available memory area at @addr
98
+ * @as: address space to load image to
99
+ *
100
+ * Load a device tree supplied by the machine or by the user with the
101
+ * '-dtb' command line option, and put it at offset @addr in target
102
+ * memory.
103
+ *
104
+ * If @addr_limit contains a meaningful value (i.e., it is strictly greater
105
+ * than @addr), the device tree is only loaded if its size does not exceed
106
+ * the limit.
107
+ *
108
+ * Returns: the size of the device tree image on success,
109
+ * 0 if the image size exceeds the limit,
110
+ * -1 on errors.
111
+ *
112
+ * Note: Must not be called unless have_dtb(binfo) is true.
113
+ */
114
+int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
115
+ hwaddr addr_limit, AddressSpace *as);
116
+
117
/* Write a secure board setup routine with a dummy handler for SMCs */
118
void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
119
const struct arm_boot_info *info,
120
diff --git a/include/hw/arm/sysbus-fdt.h b/include/hw/arm/sysbus-fdt.h
121
index XXXXXXX..XXXXXXX 100644
122
--- a/include/hw/arm/sysbus-fdt.h
123
+++ b/include/hw/arm/sysbus-fdt.h
124
@@ -XXX,XX +XXX,XX @@
125
#ifndef HW_ARM_SYSBUS_FDT_H
126
#define HW_ARM_SYSBUS_FDT_H
127
128
-#include "hw/arm/arm.h"
129
-#include "qemu-common.h"
130
-#include "hw/sysbus.h"
131
-
132
-/*
133
- * struct that contains dimensioning parameters of the platform bus
134
- */
135
-typedef struct {
136
- hwaddr platform_bus_base; /* start address of the bus */
137
- hwaddr platform_bus_size; /* size of the bus */
138
- int platform_bus_first_irq; /* first hwirq assigned to the bus */
139
- int platform_bus_num_irqs; /* number of hwirq assigned to the bus */
140
-} ARMPlatformBusSystemParams;
141
-
142
-/*
143
- * struct that contains all relevant info to build the fdt nodes of
144
- * platform bus and attached dynamic sysbus devices
145
- * in the future might be augmented with additional info
146
- * such as PHY, CLK handles ...
147
- */
148
-typedef struct {
149
- const ARMPlatformBusSystemParams *system_params;
150
- struct arm_boot_info *binfo;
151
- const char *intc; /* parent interrupt controller name */
152
-} ARMPlatformBusFDTParams;
153
+#include "exec/hwaddr.h"
154
155
/**
156
- * arm_register_platform_bus_fdt_creator - register a machine init done
157
- * notifier that creates the device tree nodes of the platform bus and
158
- * associated dynamic sysbus devices
159
+ * platform_bus_add_all_fdt_nodes - create all the platform bus nodes
160
+ *
161
+ * builds the parent platform bus node and all the nodes of dynamic
162
+ * sysbus devices attached to it.
163
*/
164
-void arm_register_platform_bus_fdt_creator(ARMPlatformBusFDTParams *fdt_params);
165
-
166
+void platform_bus_add_all_fdt_nodes(void *fdt, const char *intc, hwaddr addr,
167
+ hwaddr bus_size, int irq_start);
168
#endif
169
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
170
index XXXXXXX..XXXXXXX 100644
171
--- a/hw/arm/boot.c
172
+++ b/hw/arm/boot.c
173
@@ -XXX,XX +XXX,XX @@
174
#define ARM64_TEXT_OFFSET_OFFSET 8
175
#define ARM64_MAGIC_OFFSET 56
176
177
-static AddressSpace *arm_boot_address_space(ARMCPU *cpu,
178
- const struct arm_boot_info *info)
179
+AddressSpace *arm_boot_address_space(ARMCPU *cpu,
180
+ const struct arm_boot_info *info)
181
{
182
/* Return the address space to use for bootloader reads and writes.
183
* We prefer the secure address space if the CPU has it and we're
184
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
185
qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
186
}
187
188
-/**
189
- * load_dtb() - load a device tree binary image into memory
190
- * @addr: the address to load the image at
191
- * @binfo: struct describing the boot environment
192
- * @addr_limit: upper limit of the available memory area at @addr
193
- * @as: address space to load image to
194
- *
195
- * Load a device tree supplied by the machine or by the user with the
196
- * '-dtb' command line option, and put it at offset @addr in target
197
- * memory.
198
- *
199
- * If @addr_limit contains a meaningful value (i.e., it is strictly greater
200
- * than @addr), the device tree is only loaded if its size does not exceed
201
- * the limit.
202
- *
203
- * Returns: the size of the device tree image on success,
204
- * 0 if the image size exceeds the limit,
205
- * -1 on errors.
206
- *
207
- * Note: Must not be called unless have_dtb(binfo) is true.
208
- */
209
-static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
210
- hwaddr addr_limit, AddressSpace *as)
211
+int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
212
+ hwaddr addr_limit, AddressSpace *as)
213
{
214
void *fdt = NULL;
215
int size, rc;
216
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
217
return size;
218
}
219
220
-static void arm_load_kernel_notify(Notifier *notifier, void *data)
221
+void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
222
{
223
CPUState *cs;
224
int kernel_size;
225
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
226
int elf_machine;
227
hwaddr entry;
228
static const ARMInsnFixup *primary_loader;
229
- ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
230
- notifier, notifier);
231
- ARMCPU *cpu = n->cpu;
232
- struct arm_boot_info *info =
233
- container_of(n, struct arm_boot_info, load_kernel_notifier);
234
AddressSpace *as = arm_boot_address_space(cpu, info);
235
236
/* The board code is not supposed to set secure_board_setup unless
237
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
238
assert(!(info->secure_board_setup && kvm_enabled()));
239
240
info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
241
+ info->dtb_limit = 0;
242
243
/* Load the kernel. */
244
if (!info->kernel_filename || info->firmware_loaded) {
245
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
246
* the kernel is supposed to be loaded by the bootloader), copy the
247
* DTB to the base of RAM for the bootloader to pick up.
248
*/
249
- if (load_dtb(info->loader_start, info, 0, as) < 0) {
250
- exit(1);
251
- }
252
+ info->dtb_start = info->loader_start;
253
}
254
255
if (info->kernel_filename) {
256
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
257
*/
258
if (elf_low_addr > info->loader_start
259
|| elf_high_addr < info->loader_start) {
260
- /* Pass elf_low_addr as address limit to load_dtb if it may be
261
+ /* Set elf_low_addr as address limit for arm_load_dtb if it may be
262
* pointing into RAM, otherwise pass '0' (no limit)
263
*/
264
if (elf_low_addr < info->loader_start) {
265
elf_low_addr = 0;
266
}
267
- if (load_dtb(info->loader_start, info, elf_low_addr, as) < 0) {
268
- exit(1);
269
- }
270
+ info->dtb_start = info->loader_start;
271
+ info->dtb_limit = elf_low_addr;
272
}
273
}
274
entry = elf_entry;
275
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
276
*/
277
if (have_dtb(info)) {
278
hwaddr align;
279
- hwaddr dtb_start;
280
281
if (elf_machine == EM_AARCH64) {
282
/*
283
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
284
}
285
286
/* Place the DTB after the initrd in memory with alignment. */
287
- dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size, align);
288
- if (load_dtb(dtb_start, info, 0, as) < 0) {
289
- exit(1);
290
- }
291
- fixupcontext[FIXUP_ARGPTR] = dtb_start;
292
+ info->dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size,
293
+ align);
294
+ fixupcontext[FIXUP_ARGPTR] = info->dtb_start;
295
} else {
296
fixupcontext[FIXUP_ARGPTR] = info->loader_start + KERNEL_ARGS_ADDR;
297
if (info->ram_size >= (1ULL << 32)) {
298
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
299
for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
300
ARM_CPU(cs)->env.boot_info = info;
301
}
302
-}
303
-
304
-void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
305
-{
306
- CPUState *cs;
307
-
308
- info->load_kernel_notifier.cpu = cpu;
309
- info->load_kernel_notifier.notifier.notify = arm_load_kernel_notify;
310
- qemu_add_machine_init_done_notifier(&info->load_kernel_notifier.notifier);
311
312
/* CPU objects (unlike devices) are not automatically reset on system
313
* reset, so we must always register a handler to do so. If we're
314
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
315
for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
316
qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
317
}
318
+
319
+ if (!info->skip_dtb_autoload && have_dtb(info)) {
320
+ if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as) < 0) {
321
+ exit(1);
322
+ }
323
+ }
324
}
325
326
static const TypeInfo arm_linux_boot_if_info = {
327
diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
328
index XXXXXXX..XXXXXXX 100644
329
--- a/hw/arm/sysbus-fdt.c
330
+++ b/hw/arm/sysbus-fdt.c
331
@@ -XXX,XX +XXX,XX @@ typedef struct PlatformBusFDTData {
332
PlatformBusDevice *pbus;
333
} PlatformBusFDTData;
334
335
-/*
336
- * struct used when calling the machine init done notifier
337
- * that constructs the fdt nodes of platform bus devices
338
- */
339
-typedef struct PlatformBusFDTNotifierParams {
340
- Notifier notifier;
341
- ARMPlatformBusFDTParams *fdt_params;
342
-} PlatformBusFDTNotifierParams;
343
-
344
/* struct that associates a device type name and a node creation function */
345
typedef struct NodeCreationPair {
346
const char *typename;
347
@@ -XXX,XX +XXX,XX @@ static void add_fdt_node(SysBusDevice *sbdev, void *opaque)
348
exit(1);
349
}
350
351
-/**
352
- * add_all_platform_bus_fdt_nodes - create all the platform bus nodes
353
- *
354
- * builds the parent platform bus node and all the nodes of dynamic
355
- * sysbus devices attached to it.
356
- */
357
-static void add_all_platform_bus_fdt_nodes(ARMPlatformBusFDTParams *fdt_params)
358
+void platform_bus_add_all_fdt_nodes(void *fdt, const char *intc, hwaddr addr,
359
+ hwaddr bus_size, int irq_start)
360
{
361
const char platcomp[] = "qemu,platform\0simple-bus";
362
PlatformBusDevice *pbus;
363
DeviceState *dev;
364
gchar *node;
365
- uint64_t addr, size;
366
- int irq_start, dtb_size;
367
- struct arm_boot_info *info = fdt_params->binfo;
368
- const ARMPlatformBusSystemParams *params = fdt_params->system_params;
369
- const char *intc = fdt_params->intc;
370
- void *fdt = info->get_dtb(info, &dtb_size);
371
-
372
- /*
373
- * If the user provided a dtb, we assume the dynamic sysbus nodes
374
- * already are integrated there. This corresponds to a use case where
375
- * the dynamic sysbus nodes are complex and their generation is not yet
376
- * supported. In that case the user can take charge of the guest dt
377
- * while qemu takes charge of the qom stuff.
378
- */
379
- if (info->dtb_filename) {
380
- return;
381
- }
382
383
assert(fdt);
384
385
- node = g_strdup_printf("/platform@%"PRIx64, params->platform_bus_base);
386
- addr = params->platform_bus_base;
387
- size = params->platform_bus_size;
388
- irq_start = params->platform_bus_first_irq;
389
+ node = g_strdup_printf("/platform@%"PRIx64, addr);
390
391
/* Create a /platform node that we can put all devices into */
392
qemu_fdt_add_subnode(fdt, node);
393
@@ -XXX,XX +XXX,XX @@ static void add_all_platform_bus_fdt_nodes(ARMPlatformBusFDTParams *fdt_params)
394
*/
395
qemu_fdt_setprop_cells(fdt, node, "#size-cells", 1);
396
qemu_fdt_setprop_cells(fdt, node, "#address-cells", 1);
397
- qemu_fdt_setprop_cells(fdt, node, "ranges", 0, addr >> 32, addr, size);
398
+ qemu_fdt_setprop_cells(fdt, node, "ranges", 0, addr >> 32, addr, bus_size);
399
400
qemu_fdt_setprop_phandle(fdt, node, "interrupt-parent", intc);
401
402
@@ -XXX,XX +XXX,XX @@ static void add_all_platform_bus_fdt_nodes(ARMPlatformBusFDTParams *fdt_params)
403
404
g_free(node);
405
}
406
-
407
-static void platform_bus_fdt_notify(Notifier *notifier, void *data)
408
-{
409
- PlatformBusFDTNotifierParams *p = DO_UPCAST(PlatformBusFDTNotifierParams,
410
- notifier, notifier);
411
-
412
- add_all_platform_bus_fdt_nodes(p->fdt_params);
413
- g_free(p->fdt_params);
414
- g_free(p);
415
-}
416
-
417
-void arm_register_platform_bus_fdt_creator(ARMPlatformBusFDTParams *fdt_params)
418
-{
419
- PlatformBusFDTNotifierParams *p = g_new(PlatformBusFDTNotifierParams, 1);
420
-
421
- p->fdt_params = fdt_params;
422
- p->notifier.notify = platform_bus_fdt_notify;
423
- qemu_add_machine_init_done_notifier(&p->notifier);
424
-}
425
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
426
index XXXXXXX..XXXXXXX 100644
427
--- a/hw/arm/virt.c
428
+++ b/hw/arm/virt.c
429
@@ -XXX,XX +XXX,XX @@
430
431
#define PLATFORM_BUS_NUM_IRQS 64
432
433
-static ARMPlatformBusSystemParams platform_bus_params;
434
-
435
/* RAM limit in GB. Since VIRT_MEM starts at the 1GB mark, this means
436
* RAM can go up to the 256GB mark, leaving 256GB of the physical
437
* address space unallocated and free for future use between 256G and 512G.
438
@@ -XXX,XX +XXX,XX @@ static void create_platform_bus(VirtMachineState *vms, qemu_irq *pic)
439
DeviceState *dev;
440
SysBusDevice *s;
441
int i;
442
- ARMPlatformBusFDTParams *fdt_params = g_new(ARMPlatformBusFDTParams, 1);
443
MemoryRegion *sysmem = get_system_memory();
444
445
- platform_bus_params.platform_bus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
446
- platform_bus_params.platform_bus_size = vms->memmap[VIRT_PLATFORM_BUS].size;
447
- platform_bus_params.platform_bus_first_irq = vms->irqmap[VIRT_PLATFORM_BUS];
448
- platform_bus_params.platform_bus_num_irqs = PLATFORM_BUS_NUM_IRQS;
449
-
450
- fdt_params->system_params = &platform_bus_params;
451
- fdt_params->binfo = &vms->bootinfo;
452
- fdt_params->intc = "/intc";
453
- /*
454
- * register a machine init done notifier that creates the device tree
455
- * nodes of the platform bus and its children dynamic sysbus devices
456
- */
457
- arm_register_platform_bus_fdt_creator(fdt_params);
458
-
459
dev = qdev_create(NULL, TYPE_PLATFORM_BUS_DEVICE);
460
dev->id = TYPE_PLATFORM_BUS_DEVICE;
461
- qdev_prop_set_uint32(dev, "num_irqs",
462
- platform_bus_params.platform_bus_num_irqs);
463
- qdev_prop_set_uint32(dev, "mmio_size",
464
- platform_bus_params.platform_bus_size);
465
+ qdev_prop_set_uint32(dev, "num_irqs", PLATFORM_BUS_NUM_IRQS);
466
+ qdev_prop_set_uint32(dev, "mmio_size", vms->memmap[VIRT_PLATFORM_BUS].size);
467
qdev_init_nofail(dev);
468
vms->platform_bus_dev = dev;
469
- s = SYS_BUS_DEVICE(dev);
470
471
- for (i = 0; i < platform_bus_params.platform_bus_num_irqs; i++) {
472
- int irqn = platform_bus_params.platform_bus_first_irq + i;
473
+ s = SYS_BUS_DEVICE(dev);
474
+ for (i = 0; i < PLATFORM_BUS_NUM_IRQS; i++) {
475
+ int irqn = vms->irqmap[VIRT_PLATFORM_BUS] + i;
476
sysbus_connect_irq(s, i, pic[irqn]);
477
}
478
479
memory_region_add_subregion(sysmem,
480
- platform_bus_params.platform_bus_base,
481
+ vms->memmap[VIRT_PLATFORM_BUS].base,
482
sysbus_mmio_get_region(s, 0));
483
}
484
485
@@ -XXX,XX +XXX,XX @@ void virt_machine_done(Notifier *notifier, void *data)
486
{
487
VirtMachineState *vms = container_of(notifier, VirtMachineState,
488
machine_done);
489
+ ARMCPU *cpu = ARM_CPU(first_cpu);
490
+ struct arm_boot_info *info = &vms->bootinfo;
491
+ AddressSpace *as = arm_boot_address_space(cpu, info);
492
+
493
+ /*
494
+ * If the user provided a dtb, we assume the dynamic sysbus nodes
495
+ * already are integrated there. This corresponds to a use case where
496
+ * the dynamic sysbus nodes are complex and their generation is not yet
497
+ * supported. In that case the user can take charge of the guest dt
498
+ * while qemu takes charge of the qom stuff.
499
+ */
500
+ if (info->dtb_filename == NULL) {
501
+ platform_bus_add_all_fdt_nodes(vms->fdt, "/intc",
502
+ vms->memmap[VIRT_PLATFORM_BUS].base,
503
+ vms->memmap[VIRT_PLATFORM_BUS].size,
504
+ vms->irqmap[VIRT_PLATFORM_BUS]);
505
+ }
506
+ if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as) < 0) {
507
+ exit(1);
508
+ }
509
510
virt_acpi_setup(vms);
511
virt_build_smbios(vms);
512
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
513
vms->fw_cfg = create_fw_cfg(vms, &address_space_memory);
514
rom_set_fw(vms->fw_cfg);
515
516
- vms->machine_done.notify = virt_machine_done;
517
- qemu_add_machine_init_done_notifier(&vms->machine_done);
518
+ create_platform_bus(vms, pic);
519
520
vms->bootinfo.ram_size = machine->ram_size;
521
vms->bootinfo.kernel_filename = machine->kernel_filename;
522
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
523
vms->bootinfo.board_id = -1;
524
vms->bootinfo.loader_start = vms->memmap[VIRT_MEM].base;
525
vms->bootinfo.get_dtb = machvirt_dtb;
526
+ vms->bootinfo.skip_dtb_autoload = true;
527
vms->bootinfo.firmware_loaded = firmware_loaded;
528
arm_load_kernel(ARM_CPU(first_cpu), &vms->bootinfo);
529
530
- /*
531
- * arm_load_kernel machine init done notifier registration must
532
- * happen before the platform_bus_create call. In this latter,
533
- * another notifier is registered which adds platform bus nodes.
534
- * Notifiers are executed in registration reverse order.
535
- */
536
- create_platform_bus(vms, pic);
537
+ vms->machine_done.notify = virt_machine_done;
538
+ qemu_add_machine_init_done_notifier(&vms->machine_done);
539
}
540
541
static bool virt_get_secure(Object *obj, Error **errp)
542
--
543
2.17.0
544
545
diff view generated by jsdifflib
Deleted patch
1
From: Igor Mammedov <imammedo@redhat.com>
2
1
3
Suggested-by: Eduardo Habkost <ehabkost@redhat.com>
4
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 1525691524-32265-5-git-send-email-imammedo@redhat.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
hw/arm/virt.c | 1 +
10
hw/i386/pc.c | 1 +
11
hw/ppc/e500plat.c | 1 +
12
hw/ppc/spapr.c | 1 +
13
hw/s390x/s390-virtio-ccw.c | 1 +
14
5 files changed, 5 insertions(+)
15
16
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/virt.c
19
+++ b/hw/arm/virt.c
20
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
21
mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
22
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
23
mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
24
+ assert(!mc->get_hotplug_handler);
25
mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
26
hc->plug = virt_machine_device_plug_cb;
27
}
28
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/i386/pc.c
31
+++ b/hw/i386/pc.c
32
@@ -XXX,XX +XXX,XX @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
33
pcmc->acpi_data_size = 0x20000 + 0x8000;
34
pcmc->save_tsc_khz = true;
35
pcmc->linuxboot_dma_enabled = true;
36
+ assert(!mc->get_hotplug_handler);
37
mc->get_hotplug_handler = pc_get_hotpug_handler;
38
mc->cpu_index_to_instance_props = pc_cpu_index_to_props;
39
mc->get_default_cpu_node_id = pc_get_default_cpu_node_id;
40
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/ppc/e500plat.c
43
+++ b/hw/ppc/e500plat.c
44
@@ -XXX,XX +XXX,XX @@ static void e500plat_machine_class_init(ObjectClass *oc, void *data)
45
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
46
MachineClass *mc = MACHINE_CLASS(oc);
47
48
+ assert(!mc->get_hotplug_handler);
49
mc->get_hotplug_handler = e500plat_machine_get_hotpug_handler;
50
hc->plug = e500plat_machine_device_plug_cb;
51
52
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/ppc/spapr.c
55
+++ b/hw/ppc/spapr.c
56
@@ -XXX,XX +XXX,XX @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
57
mc->kvm_type = spapr_kvm_type;
58
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_SPAPR_PCI_HOST_BRIDGE);
59
mc->pci_allow_0_address = true;
60
+ assert(!mc->get_hotplug_handler);
61
mc->get_hotplug_handler = spapr_get_hotplug_handler;
62
hc->pre_plug = spapr_machine_device_pre_plug;
63
hc->plug = spapr_machine_device_plug;
64
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/hw/s390x/s390-virtio-ccw.c
67
+++ b/hw/s390x/s390-virtio-ccw.c
68
@@ -XXX,XX +XXX,XX @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
69
mc->no_sdcard = 1;
70
mc->max_cpus = S390_MAX_CPUS;
71
mc->has_hotpluggable_cpus = true;
72
+ assert(!mc->get_hotplug_handler);
73
mc->get_hotplug_handler = s390_get_hotplug_handler;
74
mc->cpu_index_to_instance_props = s390_cpu_index_to_props;
75
mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids;
76
--
77
2.17.0
78
79
diff view generated by jsdifflib
Deleted patch
1
Some versions of gcc produce a spurious warning if the result of
2
__atomic_compare_echange_n() is not used and the type involved
3
is a signed 8 bit value:
4
error: value computed is not used [-Werror=unused-value]
5
This has been seen on at least
6
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
7
1
8
Work around this by using an explicit cast to void to indicate
9
that we don't care about the return value.
10
11
We don't currently use our atomic_cmpxchg() macro on any signed
12
8 bit types, but the upcoming support for the Arm v8.1-Atomics
13
will require it.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
---
19
include/qemu/atomic.h | 2 +-
20
1 file changed, 1 insertion(+), 1 deletion(-)
21
22
diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/qemu/atomic.h
25
+++ b/include/qemu/atomic.h
26
@@ -XXX,XX +XXX,XX @@
27
/* Returns the eventual value, failed or not */
28
#define atomic_cmpxchg__nocheck(ptr, old, new) ({ \
29
typeof_strip_qual(*ptr) _old = (old); \
30
- __atomic_compare_exchange_n(ptr, &_old, new, false, \
31
+ (void)__atomic_compare_exchange_n(ptr, &_old, new, false, \
32
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \
33
_old; \
34
})
35
--
36
2.17.0
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
These operations are re-invented by several targets so far.
4
Several supported hosts have insns for these, so place the
5
expanders out-of-line for a future introduction of tcg opcodes.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180508151437.4232-2-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
tcg/tcg-op.h | 16 ++++++++++++++++
13
tcg/tcg-op.c | 40 ++++++++++++++++++++++++++++++++++++++++
14
2 files changed, 56 insertions(+)
15
16
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tcg/tcg-op.h
19
+++ b/tcg/tcg-op.h
20
@@ -XXX,XX +XXX,XX @@ void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg);
21
void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg);
22
void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg);
23
void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg);
24
+void tcg_gen_smin_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
25
+void tcg_gen_smax_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
26
+void tcg_gen_umin_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
27
+void tcg_gen_umax_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
28
29
static inline void tcg_gen_discard_i32(TCGv_i32 arg)
30
{
31
@@ -XXX,XX +XXX,XX @@ void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg);
32
void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg);
33
void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg);
34
void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg);
35
+void tcg_gen_smin_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
36
+void tcg_gen_smax_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
37
+void tcg_gen_umin_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
38
+void tcg_gen_umax_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
39
40
#if TCG_TARGET_REG_BITS == 64
41
static inline void tcg_gen_discard_i64(TCGv_i64 arg)
42
@@ -XXX,XX +XXX,XX @@ void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t);
43
#define tcg_gen_mulu2_tl tcg_gen_mulu2_i64
44
#define tcg_gen_muls2_tl tcg_gen_muls2_i64
45
#define tcg_gen_mulsu2_tl tcg_gen_mulsu2_i64
46
+#define tcg_gen_smin_tl tcg_gen_smin_i64
47
+#define tcg_gen_umin_tl tcg_gen_umin_i64
48
+#define tcg_gen_smax_tl tcg_gen_smax_i64
49
+#define tcg_gen_umax_tl tcg_gen_umax_i64
50
#define tcg_gen_atomic_cmpxchg_tl tcg_gen_atomic_cmpxchg_i64
51
#define tcg_gen_atomic_xchg_tl tcg_gen_atomic_xchg_i64
52
#define tcg_gen_atomic_fetch_add_tl tcg_gen_atomic_fetch_add_i64
53
@@ -XXX,XX +XXX,XX @@ void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t);
54
#define tcg_gen_mulu2_tl tcg_gen_mulu2_i32
55
#define tcg_gen_muls2_tl tcg_gen_muls2_i32
56
#define tcg_gen_mulsu2_tl tcg_gen_mulsu2_i32
57
+#define tcg_gen_smin_tl tcg_gen_smin_i32
58
+#define tcg_gen_umin_tl tcg_gen_umin_i32
59
+#define tcg_gen_smax_tl tcg_gen_smax_i32
60
+#define tcg_gen_umax_tl tcg_gen_umax_i32
61
#define tcg_gen_atomic_cmpxchg_tl tcg_gen_atomic_cmpxchg_i32
62
#define tcg_gen_atomic_xchg_tl tcg_gen_atomic_xchg_i32
63
#define tcg_gen_atomic_fetch_add_tl tcg_gen_atomic_fetch_add_i32
64
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/tcg/tcg-op.c
67
+++ b/tcg/tcg-op.c
68
@@ -XXX,XX +XXX,XX @@ void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
69
}
70
}
71
72
+void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
73
+{
74
+ tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b);
75
+}
76
+
77
+void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
78
+{
79
+ tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b);
80
+}
81
+
82
+void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
83
+{
84
+ tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a);
85
+}
86
+
87
+void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
88
+{
89
+ tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a);
90
+}
91
+
92
/* 64-bit ops */
93
94
#if TCG_TARGET_REG_BITS == 32
95
@@ -XXX,XX +XXX,XX @@ void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2)
96
tcg_temp_free_i64(t2);
97
}
98
99
+void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
100
+{
101
+ tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b);
102
+}
103
+
104
+void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
105
+{
106
+ tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b);
107
+}
108
+
109
+void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
110
+{
111
+ tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a);
112
+}
113
+
114
+void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b)
115
+{
116
+ tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a);
117
+}
118
+
119
/* Size changing operations. */
120
121
void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
122
--
123
2.17.0
124
125
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The generic expanders replace nearly identical code in the translator.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180508151437.4232-3-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/translate-a64.c | 46 ++++++++++++--------------------------
11
1 file changed, 14 insertions(+), 32 deletions(-)
12
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
16
+++ b/target/arm/translate-a64.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
18
tcg_gen_add_i64(tcg_res, tcg_res, tcg_elt);
19
break;
20
case 0x0a: /* SMAXV / UMAXV */
21
- tcg_gen_movcond_i64(is_u ? TCG_COND_GEU : TCG_COND_GE,
22
- tcg_res,
23
- tcg_res, tcg_elt, tcg_res, tcg_elt);
24
+ if (is_u) {
25
+ tcg_gen_umax_i64(tcg_res, tcg_res, tcg_elt);
26
+ } else {
27
+ tcg_gen_smax_i64(tcg_res, tcg_res, tcg_elt);
28
+ }
29
break;
30
case 0x1a: /* SMINV / UMINV */
31
- tcg_gen_movcond_i64(is_u ? TCG_COND_LEU : TCG_COND_LE,
32
- tcg_res,
33
- tcg_res, tcg_elt, tcg_res, tcg_elt);
34
- break;
35
+ if (is_u) {
36
+ tcg_gen_umin_i64(tcg_res, tcg_res, tcg_elt);
37
+ } else {
38
+ tcg_gen_smin_i64(tcg_res, tcg_res, tcg_elt);
39
+ }
40
break;
41
default:
42
g_assert_not_reached();
43
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_logic(DisasContext *s, uint32_t insn)
44
}
45
}
46
47
-/* Helper functions for 32 bit comparisons */
48
-static void gen_max_s32(TCGv_i32 res, TCGv_i32 op1, TCGv_i32 op2)
49
-{
50
- tcg_gen_movcond_i32(TCG_COND_GE, res, op1, op2, op1, op2);
51
-}
52
-
53
-static void gen_max_u32(TCGv_i32 res, TCGv_i32 op1, TCGv_i32 op2)
54
-{
55
- tcg_gen_movcond_i32(TCG_COND_GEU, res, op1, op2, op1, op2);
56
-}
57
-
58
-static void gen_min_s32(TCGv_i32 res, TCGv_i32 op1, TCGv_i32 op2)
59
-{
60
- tcg_gen_movcond_i32(TCG_COND_LE, res, op1, op2, op1, op2);
61
-}
62
-
63
-static void gen_min_u32(TCGv_i32 res, TCGv_i32 op1, TCGv_i32 op2)
64
-{
65
- tcg_gen_movcond_i32(TCG_COND_LEU, res, op1, op2, op1, op2);
66
-}
67
-
68
/* Pairwise op subgroup of C3.6.16.
69
*
70
* This is called directly or via the handle_3same_float for float pairwise
71
@@ -XXX,XX +XXX,XX @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
72
static NeonGenTwoOpFn * const fns[3][2] = {
73
{ gen_helper_neon_pmax_s8, gen_helper_neon_pmax_u8 },
74
{ gen_helper_neon_pmax_s16, gen_helper_neon_pmax_u16 },
75
- { gen_max_s32, gen_max_u32 },
76
+ { tcg_gen_smax_i32, tcg_gen_umax_i32 },
77
};
78
genfn = fns[size][u];
79
break;
80
@@ -XXX,XX +XXX,XX @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
81
static NeonGenTwoOpFn * const fns[3][2] = {
82
{ gen_helper_neon_pmin_s8, gen_helper_neon_pmin_u8 },
83
{ gen_helper_neon_pmin_s16, gen_helper_neon_pmin_u16 },
84
- { gen_min_s32, gen_min_u32 },
85
+ { tcg_gen_smin_i32, tcg_gen_umin_i32 },
86
};
87
genfn = fns[size][u];
88
break;
89
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
90
static NeonGenTwoOpFn * const fns[3][2] = {
91
{ gen_helper_neon_max_s8, gen_helper_neon_max_u8 },
92
{ gen_helper_neon_max_s16, gen_helper_neon_max_u16 },
93
- { gen_max_s32, gen_max_u32 },
94
+ { tcg_gen_smax_i32, tcg_gen_umax_i32 },
95
};
96
genfn = fns[size][u];
97
break;
98
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
99
static NeonGenTwoOpFn * const fns[3][2] = {
100
{ gen_helper_neon_min_s8, gen_helper_neon_min_u8 },
101
{ gen_helper_neon_min_s16, gen_helper_neon_min_u16 },
102
- { gen_min_s32, gen_min_u32 },
103
+ { tcg_gen_smin_i32, tcg_gen_umin_i32 },
104
};
105
genfn = fns[size][u];
106
break;
107
--
108
2.17.0
109
110
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The generic expanders replace nearly identical code in the translator.
4
5
Acked-by: Max Filippov <jcmvbkbc@gmail.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180508151437.4232-4-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/xtensa/translate.c | 50 ++++++++++++++++++++++++++-------------
11
1 file changed, 33 insertions(+), 17 deletions(-)
12
13
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/xtensa/translate.c
16
+++ b/target/xtensa/translate.c
17
@@ -XXX,XX +XXX,XX @@ static void translate_clamps(DisasContext *dc, const uint32_t arg[],
18
TCGv_i32 tmp1 = tcg_const_i32(-1u << arg[2]);
19
TCGv_i32 tmp2 = tcg_const_i32((1 << arg[2]) - 1);
20
21
- tcg_gen_movcond_i32(TCG_COND_GT, tmp1,
22
- cpu_R[arg[1]], tmp1, cpu_R[arg[1]], tmp1);
23
- tcg_gen_movcond_i32(TCG_COND_LT, cpu_R[arg[0]],
24
- tmp1, tmp2, tmp1, tmp2);
25
+ tcg_gen_smax_i32(tmp1, tmp1, cpu_R[arg[1]]);
26
+ tcg_gen_smin_i32(cpu_R[arg[0]], tmp1, tmp2);
27
tcg_temp_free(tmp1);
28
tcg_temp_free(tmp2);
29
}
30
@@ -XXX,XX +XXX,XX @@ static void translate_memw(DisasContext *dc, const uint32_t arg[],
31
tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
32
}
33
34
-static void translate_minmax(DisasContext *dc, const uint32_t arg[],
35
- const uint32_t par[])
36
+static void translate_smin(DisasContext *dc, const uint32_t arg[],
37
+ const uint32_t par[])
38
{
39
if (gen_window_check3(dc, arg[0], arg[1], arg[2])) {
40
- tcg_gen_movcond_i32(par[0], cpu_R[arg[0]],
41
- cpu_R[arg[1]], cpu_R[arg[2]],
42
- cpu_R[arg[1]], cpu_R[arg[2]]);
43
+ tcg_gen_smin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
44
+ }
45
+}
46
+
47
+static void translate_umin(DisasContext *dc, const uint32_t arg[],
48
+ const uint32_t par[])
49
+{
50
+ if (gen_window_check3(dc, arg[0], arg[1], arg[2])) {
51
+ tcg_gen_umin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
52
+ }
53
+}
54
+
55
+static void translate_smax(DisasContext *dc, const uint32_t arg[],
56
+ const uint32_t par[])
57
+{
58
+ if (gen_window_check3(dc, arg[0], arg[1], arg[2])) {
59
+ tcg_gen_smax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
60
+ }
61
+}
62
+
63
+static void translate_umax(DisasContext *dc, const uint32_t arg[],
64
+ const uint32_t par[])
65
+{
66
+ if (gen_window_check3(dc, arg[0], arg[1], arg[2])) {
67
+ tcg_gen_umax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
68
}
69
}
70
71
@@ -XXX,XX +XXX,XX @@ static const XtensaOpcodeOps core_ops[] = {
72
.par = (const uint32_t[]){TCG_COND_NE},
73
}, {
74
.name = "max",
75
- .translate = translate_minmax,
76
- .par = (const uint32_t[]){TCG_COND_GE},
77
+ .translate = translate_smax,
78
}, {
79
.name = "maxu",
80
- .translate = translate_minmax,
81
- .par = (const uint32_t[]){TCG_COND_GEU},
82
+ .translate = translate_umax,
83
}, {
84
.name = "memw",
85
.translate = translate_memw,
86
}, {
87
.name = "min",
88
- .translate = translate_minmax,
89
- .par = (const uint32_t[]){TCG_COND_LT},
90
+ .translate = translate_smin,
91
}, {
92
.name = "minu",
93
- .translate = translate_minmax,
94
- .par = (const uint32_t[]){TCG_COND_LTU},
95
+ .translate = translate_umin,
96
}, {
97
.name = "mov",
98
.translate = translate_mov,
99
--
100
2.17.0
101
102
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Given that this atomic operation will be used by both risc-v
4
and aarch64, let's not duplicate code across the two targets.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180508151437.4232-5-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
accel/tcg/atomic_template.h | 71 +++++++++++++++++++++++++++++++++++++
12
accel/tcg/tcg-runtime.h | 8 +++++
13
tcg/tcg-op.h | 34 ++++++++++++++++++
14
tcg/tcg.h | 8 +++++
15
tcg/tcg-op.c | 8 +++++
16
5 files changed, 129 insertions(+)
17
18
diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/accel/tcg/atomic_template.h
21
+++ b/accel/tcg/atomic_template.h
22
@@ -XXX,XX +XXX,XX @@
23
#elif DATA_SIZE == 8
24
# define SUFFIX q
25
# define DATA_TYPE uint64_t
26
+# define SDATA_TYPE int64_t
27
# define BSWAP bswap64
28
#elif DATA_SIZE == 4
29
# define SUFFIX l
30
# define DATA_TYPE uint32_t
31
+# define SDATA_TYPE int32_t
32
# define BSWAP bswap32
33
#elif DATA_SIZE == 2
34
# define SUFFIX w
35
# define DATA_TYPE uint16_t
36
+# define SDATA_TYPE int16_t
37
# define BSWAP bswap16
38
#elif DATA_SIZE == 1
39
# define SUFFIX b
40
# define DATA_TYPE uint8_t
41
+# define SDATA_TYPE int8_t
42
# define BSWAP
43
#else
44
# error unsupported data size
45
@@ -XXX,XX +XXX,XX @@ GEN_ATOMIC_HELPER(or_fetch)
46
GEN_ATOMIC_HELPER(xor_fetch)
47
48
#undef GEN_ATOMIC_HELPER
49
+
50
+/* These helpers are, as a whole, full barriers. Within the helper,
51
+ * the leading barrier is explicit and the trailing barrier is within
52
+ * cmpxchg primitive.
53
+ */
54
+#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
55
+ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
56
+ ABI_TYPE xval EXTRA_ARGS) \
57
+{ \
58
+ ATOMIC_MMU_DECLS; \
59
+ XDATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
60
+ XDATA_TYPE cmp, old, new, val = xval; \
61
+ smp_mb(); \
62
+ cmp = atomic_read__nocheck(haddr); \
63
+ do { \
64
+ old = cmp; new = FN(old, val); \
65
+ cmp = atomic_cmpxchg__nocheck(haddr, old, new); \
66
+ } while (cmp != old); \
67
+ ATOMIC_MMU_CLEANUP; \
68
+ return RET; \
69
+}
70
+
71
+GEN_ATOMIC_HELPER_FN(fetch_smin, MIN, SDATA_TYPE, old)
72
+GEN_ATOMIC_HELPER_FN(fetch_umin, MIN, DATA_TYPE, old)
73
+GEN_ATOMIC_HELPER_FN(fetch_smax, MAX, SDATA_TYPE, old)
74
+GEN_ATOMIC_HELPER_FN(fetch_umax, MAX, DATA_TYPE, old)
75
+
76
+GEN_ATOMIC_HELPER_FN(smin_fetch, MIN, SDATA_TYPE, new)
77
+GEN_ATOMIC_HELPER_FN(umin_fetch, MIN, DATA_TYPE, new)
78
+GEN_ATOMIC_HELPER_FN(smax_fetch, MAX, SDATA_TYPE, new)
79
+GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
80
+
81
+#undef GEN_ATOMIC_HELPER_FN
82
#endif /* DATA SIZE >= 16 */
83
84
#undef END
85
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(add_fetch)(CPUArchState *env, target_ulong addr,
86
ldo = ldn;
87
}
88
}
89
+
90
+/* These helpers are, as a whole, full barriers. Within the helper,
91
+ * the leading barrier is explicit and the trailing barrier is within
92
+ * cmpxchg primitive.
93
+ */
94
+#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
95
+ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
96
+ ABI_TYPE xval EXTRA_ARGS) \
97
+{ \
98
+ ATOMIC_MMU_DECLS; \
99
+ XDATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
100
+ XDATA_TYPE ldo, ldn, old, new, val = xval; \
101
+ smp_mb(); \
102
+ ldn = atomic_read__nocheck(haddr); \
103
+ do { \
104
+ ldo = ldn; old = BSWAP(ldo); new = FN(old, val); \
105
+ ldn = atomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new)); \
106
+ } while (ldo != ldn); \
107
+ ATOMIC_MMU_CLEANUP; \
108
+ return RET; \
109
+}
110
+
111
+GEN_ATOMIC_HELPER_FN(fetch_smin, MIN, SDATA_TYPE, old)
112
+GEN_ATOMIC_HELPER_FN(fetch_umin, MIN, DATA_TYPE, old)
113
+GEN_ATOMIC_HELPER_FN(fetch_smax, MAX, SDATA_TYPE, old)
114
+GEN_ATOMIC_HELPER_FN(fetch_umax, MAX, DATA_TYPE, old)
115
+
116
+GEN_ATOMIC_HELPER_FN(smin_fetch, MIN, SDATA_TYPE, new)
117
+GEN_ATOMIC_HELPER_FN(umin_fetch, MIN, DATA_TYPE, new)
118
+GEN_ATOMIC_HELPER_FN(smax_fetch, MAX, SDATA_TYPE, new)
119
+GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
120
+
121
+#undef GEN_ATOMIC_HELPER_FN
122
#endif /* DATA_SIZE >= 16 */
123
124
#undef END
125
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(add_fetch)(CPUArchState *env, target_ulong addr,
126
#undef BSWAP
127
#undef ABI_TYPE
128
#undef DATA_TYPE
129
+#undef SDATA_TYPE
130
#undef SUFFIX
131
#undef DATA_SIZE
132
diff --git a/accel/tcg/tcg-runtime.h b/accel/tcg/tcg-runtime.h
133
index XXXXXXX..XXXXXXX 100644
134
--- a/accel/tcg/tcg-runtime.h
135
+++ b/accel/tcg/tcg-runtime.h
136
@@ -XXX,XX +XXX,XX @@ GEN_ATOMIC_HELPERS(fetch_add)
137
GEN_ATOMIC_HELPERS(fetch_and)
138
GEN_ATOMIC_HELPERS(fetch_or)
139
GEN_ATOMIC_HELPERS(fetch_xor)
140
+GEN_ATOMIC_HELPERS(fetch_smin)
141
+GEN_ATOMIC_HELPERS(fetch_umin)
142
+GEN_ATOMIC_HELPERS(fetch_smax)
143
+GEN_ATOMIC_HELPERS(fetch_umax)
144
145
GEN_ATOMIC_HELPERS(add_fetch)
146
GEN_ATOMIC_HELPERS(and_fetch)
147
GEN_ATOMIC_HELPERS(or_fetch)
148
GEN_ATOMIC_HELPERS(xor_fetch)
149
+GEN_ATOMIC_HELPERS(smin_fetch)
150
+GEN_ATOMIC_HELPERS(umin_fetch)
151
+GEN_ATOMIC_HELPERS(smax_fetch)
152
+GEN_ATOMIC_HELPERS(umax_fetch)
153
154
GEN_ATOMIC_HELPERS(xchg)
155
156
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
157
index XXXXXXX..XXXXXXX 100644
158
--- a/tcg/tcg-op.h
159
+++ b/tcg/tcg-op.h
160
@@ -XXX,XX +XXX,XX @@ void tcg_gen_atomic_cmpxchg_i64(TCGv_i64, TCGv, TCGv_i64, TCGv_i64,
161
162
void tcg_gen_atomic_xchg_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
163
void tcg_gen_atomic_xchg_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
164
+
165
void tcg_gen_atomic_fetch_add_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
166
void tcg_gen_atomic_fetch_add_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
167
void tcg_gen_atomic_fetch_and_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
168
@@ -XXX,XX +XXX,XX @@ void tcg_gen_atomic_fetch_or_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
169
void tcg_gen_atomic_fetch_or_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
170
void tcg_gen_atomic_fetch_xor_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
171
void tcg_gen_atomic_fetch_xor_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
172
+void tcg_gen_atomic_fetch_smin_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
173
+void tcg_gen_atomic_fetch_smin_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
174
+void tcg_gen_atomic_fetch_umin_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
175
+void tcg_gen_atomic_fetch_umin_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
176
+void tcg_gen_atomic_fetch_smax_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
177
+void tcg_gen_atomic_fetch_smax_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
178
+void tcg_gen_atomic_fetch_umax_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
179
+void tcg_gen_atomic_fetch_umax_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
180
+
181
void tcg_gen_atomic_add_fetch_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
182
void tcg_gen_atomic_add_fetch_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
183
void tcg_gen_atomic_and_fetch_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
184
@@ -XXX,XX +XXX,XX @@ void tcg_gen_atomic_or_fetch_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
185
void tcg_gen_atomic_or_fetch_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
186
void tcg_gen_atomic_xor_fetch_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
187
void tcg_gen_atomic_xor_fetch_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
188
+void tcg_gen_atomic_smin_fetch_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
189
+void tcg_gen_atomic_smin_fetch_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
190
+void tcg_gen_atomic_umin_fetch_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
191
+void tcg_gen_atomic_umin_fetch_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
192
+void tcg_gen_atomic_smax_fetch_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
193
+void tcg_gen_atomic_smax_fetch_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
194
+void tcg_gen_atomic_umax_fetch_i32(TCGv_i32, TCGv, TCGv_i32, TCGArg, TCGMemOp);
195
+void tcg_gen_atomic_umax_fetch_i64(TCGv_i64, TCGv, TCGv_i64, TCGArg, TCGMemOp);
196
197
void tcg_gen_mov_vec(TCGv_vec, TCGv_vec);
198
void tcg_gen_dup_i32_vec(unsigned vece, TCGv_vec, TCGv_i32);
199
@@ -XXX,XX +XXX,XX @@ void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t);
200
#define tcg_gen_atomic_fetch_and_tl tcg_gen_atomic_fetch_and_i64
201
#define tcg_gen_atomic_fetch_or_tl tcg_gen_atomic_fetch_or_i64
202
#define tcg_gen_atomic_fetch_xor_tl tcg_gen_atomic_fetch_xor_i64
203
+#define tcg_gen_atomic_fetch_smin_tl tcg_gen_atomic_fetch_smin_i64
204
+#define tcg_gen_atomic_fetch_umin_tl tcg_gen_atomic_fetch_umin_i64
205
+#define tcg_gen_atomic_fetch_smax_tl tcg_gen_atomic_fetch_smax_i64
206
+#define tcg_gen_atomic_fetch_umax_tl tcg_gen_atomic_fetch_umax_i64
207
#define tcg_gen_atomic_add_fetch_tl tcg_gen_atomic_add_fetch_i64
208
#define tcg_gen_atomic_and_fetch_tl tcg_gen_atomic_and_fetch_i64
209
#define tcg_gen_atomic_or_fetch_tl tcg_gen_atomic_or_fetch_i64
210
#define tcg_gen_atomic_xor_fetch_tl tcg_gen_atomic_xor_fetch_i64
211
+#define tcg_gen_atomic_smin_fetch_tl tcg_gen_atomic_smin_fetch_i64
212
+#define tcg_gen_atomic_umin_fetch_tl tcg_gen_atomic_umin_fetch_i64
213
+#define tcg_gen_atomic_smax_fetch_tl tcg_gen_atomic_smax_fetch_i64
214
+#define tcg_gen_atomic_umax_fetch_tl tcg_gen_atomic_umax_fetch_i64
215
#define tcg_gen_dup_tl_vec tcg_gen_dup_i64_vec
216
#else
217
#define tcg_gen_movi_tl tcg_gen_movi_i32
218
@@ -XXX,XX +XXX,XX @@ void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t);
219
#define tcg_gen_atomic_fetch_and_tl tcg_gen_atomic_fetch_and_i32
220
#define tcg_gen_atomic_fetch_or_tl tcg_gen_atomic_fetch_or_i32
221
#define tcg_gen_atomic_fetch_xor_tl tcg_gen_atomic_fetch_xor_i32
222
+#define tcg_gen_atomic_fetch_smin_tl tcg_gen_atomic_fetch_smin_i32
223
+#define tcg_gen_atomic_fetch_umin_tl tcg_gen_atomic_fetch_umin_i32
224
+#define tcg_gen_atomic_fetch_smax_tl tcg_gen_atomic_fetch_smax_i32
225
+#define tcg_gen_atomic_fetch_umax_tl tcg_gen_atomic_fetch_umax_i32
226
#define tcg_gen_atomic_add_fetch_tl tcg_gen_atomic_add_fetch_i32
227
#define tcg_gen_atomic_and_fetch_tl tcg_gen_atomic_and_fetch_i32
228
#define tcg_gen_atomic_or_fetch_tl tcg_gen_atomic_or_fetch_i32
229
#define tcg_gen_atomic_xor_fetch_tl tcg_gen_atomic_xor_fetch_i32
230
+#define tcg_gen_atomic_smin_fetch_tl tcg_gen_atomic_smin_fetch_i32
231
+#define tcg_gen_atomic_umin_fetch_tl tcg_gen_atomic_umin_fetch_i32
232
+#define tcg_gen_atomic_smax_fetch_tl tcg_gen_atomic_smax_fetch_i32
233
+#define tcg_gen_atomic_umax_fetch_tl tcg_gen_atomic_umax_fetch_i32
234
#define tcg_gen_dup_tl_vec tcg_gen_dup_i32_vec
235
#endif
236
237
diff --git a/tcg/tcg.h b/tcg/tcg.h
238
index XXXXXXX..XXXXXXX 100644
239
--- a/tcg/tcg.h
240
+++ b/tcg/tcg.h
241
@@ -XXX,XX +XXX,XX @@ GEN_ATOMIC_HELPER_ALL(fetch_sub)
242
GEN_ATOMIC_HELPER_ALL(fetch_and)
243
GEN_ATOMIC_HELPER_ALL(fetch_or)
244
GEN_ATOMIC_HELPER_ALL(fetch_xor)
245
+GEN_ATOMIC_HELPER_ALL(fetch_smin)
246
+GEN_ATOMIC_HELPER_ALL(fetch_umin)
247
+GEN_ATOMIC_HELPER_ALL(fetch_smax)
248
+GEN_ATOMIC_HELPER_ALL(fetch_umax)
249
250
GEN_ATOMIC_HELPER_ALL(add_fetch)
251
GEN_ATOMIC_HELPER_ALL(sub_fetch)
252
GEN_ATOMIC_HELPER_ALL(and_fetch)
253
GEN_ATOMIC_HELPER_ALL(or_fetch)
254
GEN_ATOMIC_HELPER_ALL(xor_fetch)
255
+GEN_ATOMIC_HELPER_ALL(smin_fetch)
256
+GEN_ATOMIC_HELPER_ALL(umin_fetch)
257
+GEN_ATOMIC_HELPER_ALL(smax_fetch)
258
+GEN_ATOMIC_HELPER_ALL(umax_fetch)
259
260
GEN_ATOMIC_HELPER_ALL(xchg)
261
262
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
263
index XXXXXXX..XXXXXXX 100644
264
--- a/tcg/tcg-op.c
265
+++ b/tcg/tcg-op.c
266
@@ -XXX,XX +XXX,XX @@ GEN_ATOMIC_HELPER(fetch_add, add, 0)
267
GEN_ATOMIC_HELPER(fetch_and, and, 0)
268
GEN_ATOMIC_HELPER(fetch_or, or, 0)
269
GEN_ATOMIC_HELPER(fetch_xor, xor, 0)
270
+GEN_ATOMIC_HELPER(fetch_smin, smin, 0)
271
+GEN_ATOMIC_HELPER(fetch_umin, umin, 0)
272
+GEN_ATOMIC_HELPER(fetch_smax, smax, 0)
273
+GEN_ATOMIC_HELPER(fetch_umax, umax, 0)
274
275
GEN_ATOMIC_HELPER(add_fetch, add, 1)
276
GEN_ATOMIC_HELPER(and_fetch, and, 1)
277
GEN_ATOMIC_HELPER(or_fetch, or, 1)
278
GEN_ATOMIC_HELPER(xor_fetch, xor, 1)
279
+GEN_ATOMIC_HELPER(smin_fetch, smin, 1)
280
+GEN_ATOMIC_HELPER(umin_fetch, umin, 1)
281
+GEN_ATOMIC_HELPER(smax_fetch, smax, 1)
282
+GEN_ATOMIC_HELPER(umax_fetch, umax, 1)
283
284
static void tcg_gen_mov2_i32(TCGv_i32 r, TCGv_i32 a, TCGv_i32 b)
285
{
286
--
287
2.17.0
288
289
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180508151437.4232-6-richard.henderson@linaro.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
accel/tcg/atomic_template.h | 49 ++++++-------------------------------
10
1 file changed, 7 insertions(+), 42 deletions(-)
11
12
diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/accel/tcg/atomic_template.h
15
+++ b/accel/tcg/atomic_template.h
16
@@ -XXX,XX +XXX,XX @@ GEN_ATOMIC_HELPER(xor_fetch)
17
18
#undef GEN_ATOMIC_HELPER
19
20
-/* Note that for addition, we need to use a separate cmpxchg loop instead
21
- of bswaps for the reverse-host-endian helpers. */
22
-ABI_TYPE ATOMIC_NAME(fetch_add)(CPUArchState *env, target_ulong addr,
23
- ABI_TYPE val EXTRA_ARGS)
24
-{
25
- ATOMIC_MMU_DECLS;
26
- DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
27
- DATA_TYPE ldo, ldn, ret, sto;
28
-
29
- ldo = atomic_read__nocheck(haddr);
30
- while (1) {
31
- ret = BSWAP(ldo);
32
- sto = BSWAP(ret + val);
33
- ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto);
34
- if (ldn == ldo) {
35
- ATOMIC_MMU_CLEANUP;
36
- return ret;
37
- }
38
- ldo = ldn;
39
- }
40
-}
41
-
42
-ABI_TYPE ATOMIC_NAME(add_fetch)(CPUArchState *env, target_ulong addr,
43
- ABI_TYPE val EXTRA_ARGS)
44
-{
45
- ATOMIC_MMU_DECLS;
46
- DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
47
- DATA_TYPE ldo, ldn, ret, sto;
48
-
49
- ldo = atomic_read__nocheck(haddr);
50
- while (1) {
51
- ret = BSWAP(ldo) + val;
52
- sto = BSWAP(ret);
53
- ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto);
54
- if (ldn == ldo) {
55
- ATOMIC_MMU_CLEANUP;
56
- return ret;
57
- }
58
- ldo = ldn;
59
- }
60
-}
61
-
62
/* These helpers are, as a whole, full barriers. Within the helper,
63
* the leading barrier is explicit and the trailing barrier is within
64
* cmpxchg primitive.
65
@@ -XXX,XX +XXX,XX @@ GEN_ATOMIC_HELPER_FN(umin_fetch, MIN, DATA_TYPE, new)
66
GEN_ATOMIC_HELPER_FN(smax_fetch, MAX, SDATA_TYPE, new)
67
GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
68
69
+/* Note that for addition, we need to use a separate cmpxchg loop instead
70
+ of bswaps for the reverse-host-endian helpers. */
71
+#define ADD(X, Y) (X + Y)
72
+GEN_ATOMIC_HELPER_FN(fetch_add, ADD, DATA_TYPE, old)
73
+GEN_ATOMIC_HELPER_FN(add_fetch, ADD, DATA_TYPE, new)
74
+#undef ADD
75
+
76
#undef GEN_ATOMIC_HELPER_FN
77
#endif /* DATA_SIZE >= 16 */
78
79
--
80
2.17.0
81
82
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Reviewed-by: Michael Clark <mjc@sifive.com>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180508151437.4232-7-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
target/riscv/translate.c | 72 +++++++++++-----------------------------
9
1 file changed, 20 insertions(+), 52 deletions(-)
10
11
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/riscv/translate.c
14
+++ b/target/riscv/translate.c
15
@@ -XXX,XX +XXX,XX @@ static void gen_atomic(DisasContext *ctx, uint32_t opc,
16
TCGv src1, src2, dat;
17
TCGLabel *l1, *l2;
18
TCGMemOp mop;
19
- TCGCond cond;
20
bool aq, rl;
21
22
/* Extract the size of the atomic operation. */
23
@@ -XXX,XX +XXX,XX @@ static void gen_atomic(DisasContext *ctx, uint32_t opc,
24
tcg_gen_atomic_fetch_or_tl(src2, src1, src2, ctx->mem_idx, mop);
25
gen_set_gpr(rd, src2);
26
break;
27
-
28
case OPC_RISC_AMOMIN:
29
- cond = TCG_COND_LT;
30
- goto do_minmax;
31
- case OPC_RISC_AMOMAX:
32
- cond = TCG_COND_GT;
33
- goto do_minmax;
34
- case OPC_RISC_AMOMINU:
35
- cond = TCG_COND_LTU;
36
- goto do_minmax;
37
- case OPC_RISC_AMOMAXU:
38
- cond = TCG_COND_GTU;
39
- goto do_minmax;
40
- do_minmax:
41
- /* Handle the RL barrier. The AQ barrier is handled along the
42
- parallel path by the SC atomic cmpxchg. On the serial path,
43
- of course, barriers do not matter. */
44
- if (rl) {
45
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
46
- }
47
- if (tb_cflags(ctx->tb) & CF_PARALLEL) {
48
- l1 = gen_new_label();
49
- gen_set_label(l1);
50
- } else {
51
- l1 = NULL;
52
- }
53
-
54
gen_get_gpr(src1, rs1);
55
gen_get_gpr(src2, rs2);
56
- if ((mop & MO_SSIZE) == MO_SL) {
57
- /* Sign-extend the register comparison input. */
58
- tcg_gen_ext32s_tl(src2, src2);
59
- }
60
- dat = tcg_temp_local_new();
61
- tcg_gen_qemu_ld_tl(dat, src1, ctx->mem_idx, mop);
62
- tcg_gen_movcond_tl(cond, src2, dat, src2, dat, src2);
63
-
64
- if (tb_cflags(ctx->tb) & CF_PARALLEL) {
65
- /* Parallel context. Make this operation atomic by verifying
66
- that the memory didn't change while we computed the result. */
67
- tcg_gen_atomic_cmpxchg_tl(src2, src1, dat, src2, ctx->mem_idx, mop);
68
-
69
- /* If the cmpxchg failed, retry. */
70
- /* ??? There is an assumption here that this will eventually
71
- succeed, such that we don't live-lock. This is not unlike
72
- a similar loop that the compiler would generate for e.g.
73
- __atomic_fetch_and_xor, so don't worry about it. */
74
- tcg_gen_brcond_tl(TCG_COND_NE, dat, src2, l1);
75
- } else {
76
- /* Serial context. Directly store the result. */
77
- tcg_gen_qemu_st_tl(src2, src1, ctx->mem_idx, mop);
78
- }
79
- gen_set_gpr(rd, dat);
80
- tcg_temp_free(dat);
81
+ tcg_gen_atomic_fetch_smin_tl(src2, src1, src2, ctx->mem_idx, mop);
82
+ gen_set_gpr(rd, src2);
83
+ break;
84
+ case OPC_RISC_AMOMAX:
85
+ gen_get_gpr(src1, rs1);
86
+ gen_get_gpr(src2, rs2);
87
+ tcg_gen_atomic_fetch_smax_tl(src2, src1, src2, ctx->mem_idx, mop);
88
+ gen_set_gpr(rd, src2);
89
+ break;
90
+ case OPC_RISC_AMOMINU:
91
+ gen_get_gpr(src1, rs1);
92
+ gen_get_gpr(src2, rs2);
93
+ tcg_gen_atomic_fetch_umin_tl(src2, src1, src2, ctx->mem_idx, mop);
94
+ gen_set_gpr(rd, src2);
95
+ break;
96
+ case OPC_RISC_AMOMAXU:
97
+ gen_get_gpr(src1, rs1);
98
+ gen_get_gpr(src2, rs2);
99
+ tcg_gen_atomic_fetch_umax_tl(src2, src1, src2, ctx->mem_idx, mop);
100
+ gen_set_gpr(rd, src2);
101
break;
102
103
default:
104
--
105
2.17.0
106
107
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The insns in the ARMv8.1-Atomics are added to the existing
4
load/store exclusive and load/store reg opcode spaces.
5
Rearrange the top-level decoders for these to accomodate.
6
The Atomics insns themselves still generate Unallocated.
7
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180508151437.4232-8-richard.henderson@linaro.org
10
[PMM: Drop the ARM_FEATURE_V8_1 feature flag]
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/cpu.h | 1 +
15
linux-user/elfload.c | 1 +
16
target/arm/translate-a64.c | 182 +++++++++++++++++++++++++++----------
17
3 files changed, 138 insertions(+), 46 deletions(-)
18
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ enum arm_features {
24
ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
25
ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
26
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
27
+ ARM_FEATURE_V8_ATOMICS, /* ARMv8.1-Atomics feature */
28
ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
29
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
30
ARM_FEATURE_V8_FCMA, /* has complex number part of v8.3 extensions. */
31
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/linux-user/elfload.c
34
+++ b/linux-user/elfload.c
35
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
36
GET_FEATURE(ARM_FEATURE_V8_SHA512, ARM_HWCAP_A64_SHA512);
37
GET_FEATURE(ARM_FEATURE_V8_FP16,
38
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
39
+ GET_FEATURE(ARM_FEATURE_V8_ATOMICS, ARM_HWCAP_A64_ATOMICS);
40
GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
41
GET_FEATURE(ARM_FEATURE_V8_FCMA, ARM_HWCAP_A64_FCMA);
42
#undef GET_FEATURE
43
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/translate-a64.c
46
+++ b/target/arm/translate-a64.c
47
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
48
int rt = extract32(insn, 0, 5);
49
int rn = extract32(insn, 5, 5);
50
int rt2 = extract32(insn, 10, 5);
51
- int is_lasr = extract32(insn, 15, 1);
52
int rs = extract32(insn, 16, 5);
53
- int is_pair = extract32(insn, 21, 1);
54
- int is_store = !extract32(insn, 22, 1);
55
- int is_excl = !extract32(insn, 23, 1);
56
+ int is_lasr = extract32(insn, 15, 1);
57
+ int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
58
int size = extract32(insn, 30, 2);
59
TCGv_i64 tcg_addr;
60
61
- if ((!is_excl && !is_pair && !is_lasr) ||
62
- (!is_excl && is_pair) ||
63
- (is_pair && size < 2)) {
64
- unallocated_encoding(s);
65
+ switch (o2_L_o1_o0) {
66
+ case 0x0: /* STXR */
67
+ case 0x1: /* STLXR */
68
+ if (rn == 31) {
69
+ gen_check_sp_alignment(s);
70
+ }
71
+ if (is_lasr) {
72
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
73
+ }
74
+ tcg_addr = read_cpu_reg_sp(s, rn, 1);
75
+ gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, false);
76
return;
77
- }
78
79
- if (rn == 31) {
80
- gen_check_sp_alignment(s);
81
- }
82
- tcg_addr = read_cpu_reg_sp(s, rn, 1);
83
-
84
- /* Note that since TCG is single threaded load-acquire/store-release
85
- * semantics require no extra if (is_lasr) { ... } handling.
86
- */
87
-
88
- if (is_excl) {
89
- if (!is_store) {
90
- s->is_ldex = true;
91
- gen_load_exclusive(s, rt, rt2, tcg_addr, size, is_pair);
92
- if (is_lasr) {
93
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
94
- }
95
- } else {
96
- if (is_lasr) {
97
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
98
- }
99
- gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, is_pair);
100
+ case 0x4: /* LDXR */
101
+ case 0x5: /* LDAXR */
102
+ if (rn == 31) {
103
+ gen_check_sp_alignment(s);
104
}
105
- } else {
106
- TCGv_i64 tcg_rt = cpu_reg(s, rt);
107
- bool iss_sf = disas_ldst_compute_iss_sf(size, false, 0);
108
+ tcg_addr = read_cpu_reg_sp(s, rn, 1);
109
+ s->is_ldex = true;
110
+ gen_load_exclusive(s, rt, rt2, tcg_addr, size, false);
111
+ if (is_lasr) {
112
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
113
+ }
114
+ return;
115
116
+ case 0x9: /* STLR */
117
/* Generate ISS for non-exclusive accesses including LASR. */
118
- if (is_store) {
119
+ if (rn == 31) {
120
+ gen_check_sp_alignment(s);
121
+ }
122
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
123
+ tcg_addr = read_cpu_reg_sp(s, rn, 1);
124
+ do_gpr_st(s, cpu_reg(s, rt), tcg_addr, size, true, rt,
125
+ disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
126
+ return;
127
+
128
+ case 0xd: /* LDAR */
129
+ /* Generate ISS for non-exclusive accesses including LASR. */
130
+ if (rn == 31) {
131
+ gen_check_sp_alignment(s);
132
+ }
133
+ tcg_addr = read_cpu_reg_sp(s, rn, 1);
134
+ do_gpr_ld(s, cpu_reg(s, rt), tcg_addr, size, false, false, true, rt,
135
+ disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
136
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
137
+ return;
138
+
139
+ case 0x2: case 0x3: /* CASP / STXP */
140
+ if (size & 2) { /* STXP / STLXP */
141
+ if (rn == 31) {
142
+ gen_check_sp_alignment(s);
143
+ }
144
if (is_lasr) {
145
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
146
}
147
- do_gpr_st(s, tcg_rt, tcg_addr, size,
148
- true, rt, iss_sf, is_lasr);
149
- } else {
150
- do_gpr_ld(s, tcg_rt, tcg_addr, size, false, false,
151
- true, rt, iss_sf, is_lasr);
152
+ tcg_addr = read_cpu_reg_sp(s, rn, 1);
153
+ gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, true);
154
+ return;
155
+ }
156
+ /* CASP / CASPL */
157
+ break;
158
+
159
+ case 0x6: case 0x7: /* CASP / LDXP */
160
+ if (size & 2) { /* LDXP / LDAXP */
161
+ if (rn == 31) {
162
+ gen_check_sp_alignment(s);
163
+ }
164
+ tcg_addr = read_cpu_reg_sp(s, rn, 1);
165
+ s->is_ldex = true;
166
+ gen_load_exclusive(s, rt, rt2, tcg_addr, size, true);
167
if (is_lasr) {
168
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
169
}
170
+ return;
171
}
172
+ /* CASPA / CASPAL */
173
+ break;
174
+
175
+ case 0xa: /* CAS */
176
+ case 0xb: /* CASL */
177
+ case 0xe: /* CASA */
178
+ case 0xf: /* CASAL */
179
+ break;
180
}
181
+ unallocated_encoding(s);
182
}
183
184
/*
185
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
186
}
187
}
188
189
+/* Atomic memory operations
190
+ *
191
+ * 31 30 27 26 24 22 21 16 15 12 10 5 0
192
+ * +------+-------+---+-----+-----+---+----+----+-----+-----+----+-----+
193
+ * | size | 1 1 1 | V | 0 0 | A R | 1 | Rs | o3 | opc | 0 0 | Rn | Rt |
194
+ * +------+-------+---+-----+-----+--------+----+-----+-----+----+-----+
195
+ *
196
+ * Rt: the result register
197
+ * Rn: base address or SP
198
+ * Rs: the source register for the operation
199
+ * V: vector flag (always 0 as of v8.3)
200
+ * A: acquire flag
201
+ * R: release flag
202
+ */
203
+static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
204
+ int size, int rt, bool is_vector)
205
+{
206
+ int rs = extract32(insn, 16, 5);
207
+ int rn = extract32(insn, 5, 5);
208
+ int o3_opc = extract32(insn, 12, 4);
209
+ int feature = ARM_FEATURE_V8_ATOMICS;
210
+
211
+ if (is_vector) {
212
+ unallocated_encoding(s);
213
+ return;
214
+ }
215
+ switch (o3_opc) {
216
+ case 000: /* LDADD */
217
+ case 001: /* LDCLR */
218
+ case 002: /* LDEOR */
219
+ case 003: /* LDSET */
220
+ case 004: /* LDSMAX */
221
+ case 005: /* LDSMIN */
222
+ case 006: /* LDUMAX */
223
+ case 007: /* LDUMIN */
224
+ case 010: /* SWP */
225
+ default:
226
+ unallocated_encoding(s);
227
+ return;
228
+ }
229
+ if (!arm_dc_feature(s, feature)) {
230
+ unallocated_encoding(s);
231
+ return;
232
+ }
233
+
234
+ (void)rs;
235
+ (void)rn;
236
+}
237
+
238
/* Load/store register (all forms) */
239
static void disas_ldst_reg(DisasContext *s, uint32_t insn)
240
{
241
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
242
243
switch (extract32(insn, 24, 2)) {
244
case 0:
245
- if (extract32(insn, 21, 1) == 1 && extract32(insn, 10, 2) == 2) {
246
- disas_ldst_reg_roffset(s, insn, opc, size, rt, is_vector);
247
- } else {
248
+ if (extract32(insn, 21, 1) == 0) {
249
/* Load/store register (unscaled immediate)
250
* Load/store immediate pre/post-indexed
251
* Load/store register unprivileged
252
*/
253
disas_ldst_reg_imm9(s, insn, opc, size, rt, is_vector);
254
+ return;
255
+ }
256
+ switch (extract32(insn, 10, 2)) {
257
+ case 0:
258
+ disas_ldst_atomic(s, insn, size, rt, is_vector);
259
+ return;
260
+ case 2:
261
+ disas_ldst_reg_roffset(s, insn, opc, size, rt, is_vector);
262
+ return;
263
}
264
break;
265
case 1:
266
disas_ldst_reg_unsigned_imm(s, insn, opc, size, rt, is_vector);
267
- break;
268
- default:
269
- unallocated_encoding(s);
270
- break;
271
+ return;
272
}
273
+ unallocated_encoding(s);
274
}
275
276
/* AdvSIMD load/store multiple structures
277
--
278
2.17.0
279
280
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
This implements all of the v8.1-Atomics instructions except
4
for compare-and-swap, which is decoded elsewhere.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180508151437.4232-9-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/translate-a64.c | 38 ++++++++++++++++++++++++++++++++++++--
12
1 file changed, 36 insertions(+), 2 deletions(-)
13
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
17
+++ b/target/arm/translate-a64.c
18
@@ -XXX,XX +XXX,XX @@ typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
19
typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
20
typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
21
typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
22
+typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, TCGMemOp);
23
24
/* Note that the gvec expanders operate on offsets + sizes. */
25
typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t);
26
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
27
int rn = extract32(insn, 5, 5);
28
int o3_opc = extract32(insn, 12, 4);
29
int feature = ARM_FEATURE_V8_ATOMICS;
30
+ TCGv_i64 tcg_rn, tcg_rs;
31
+ AtomicThreeOpFn *fn;
32
33
if (is_vector) {
34
unallocated_encoding(s);
35
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
36
}
37
switch (o3_opc) {
38
case 000: /* LDADD */
39
+ fn = tcg_gen_atomic_fetch_add_i64;
40
+ break;
41
case 001: /* LDCLR */
42
+ fn = tcg_gen_atomic_fetch_and_i64;
43
+ break;
44
case 002: /* LDEOR */
45
+ fn = tcg_gen_atomic_fetch_xor_i64;
46
+ break;
47
case 003: /* LDSET */
48
+ fn = tcg_gen_atomic_fetch_or_i64;
49
+ break;
50
case 004: /* LDSMAX */
51
+ fn = tcg_gen_atomic_fetch_smax_i64;
52
+ break;
53
case 005: /* LDSMIN */
54
+ fn = tcg_gen_atomic_fetch_smin_i64;
55
+ break;
56
case 006: /* LDUMAX */
57
+ fn = tcg_gen_atomic_fetch_umax_i64;
58
+ break;
59
case 007: /* LDUMIN */
60
+ fn = tcg_gen_atomic_fetch_umin_i64;
61
+ break;
62
case 010: /* SWP */
63
+ fn = tcg_gen_atomic_xchg_i64;
64
+ break;
65
default:
66
unallocated_encoding(s);
67
return;
68
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
69
return;
70
}
71
72
- (void)rs;
73
- (void)rn;
74
+ if (rn == 31) {
75
+ gen_check_sp_alignment(s);
76
+ }
77
+ tcg_rn = cpu_reg_sp(s, rn);
78
+ tcg_rs = read_cpu_reg(s, rs, true);
79
+
80
+ if (o3_opc == 1) { /* LDCLR */
81
+ tcg_gen_not_i64(tcg_rs, tcg_rs);
82
+ }
83
+
84
+ /* The tcg atomic primitives are all full barriers. Therefore we
85
+ * can ignore the Acquire and Release bits of this instruction.
86
+ */
87
+ fn(cpu_reg(s, rt), tcg_rn, tcg_rs, get_mem_index(s),
88
+ s->be_data | size | MO_ALIGN);
89
}
90
91
/* Load/store register (all forms) */
92
--
93
2.17.0
94
95
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180508151437.4232-10-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
target/arm/helper-a64.h | 2 +
9
target/arm/helper-a64.c | 43 ++++++++++++++
10
target/arm/translate-a64.c | 119 ++++++++++++++++++++++++++++++++++++-
11
3 files changed, 161 insertions(+), 3 deletions(-)
12
13
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-a64.h
16
+++ b/target/arm/helper-a64.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(paired_cmpxchg64_le_parallel, TCG_CALL_NO_WG,
18
DEF_HELPER_FLAGS_4(paired_cmpxchg64_be, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
19
DEF_HELPER_FLAGS_4(paired_cmpxchg64_be_parallel, TCG_CALL_NO_WG,
20
i64, env, i64, i64, i64)
21
+DEF_HELPER_5(casp_le_parallel, void, env, i32, i64, i64, i64)
22
+DEF_HELPER_5(casp_be_parallel, void, env, i32, i64, i64, i64)
23
DEF_HELPER_FLAGS_3(advsimd_maxh, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
24
DEF_HELPER_FLAGS_3(advsimd_minh, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
25
DEF_HELPER_FLAGS_3(advsimd_maxnumh, TCG_CALL_NO_RWG, f16, f16, f16, ptr)
26
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/helper-a64.c
29
+++ b/target/arm/helper-a64.c
30
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr,
31
return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, true, GETPC());
32
}
33
34
+/* Writes back the old data into Rs. */
35
+void HELPER(casp_le_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
36
+ uint64_t new_lo, uint64_t new_hi)
37
+{
38
+ uintptr_t ra = GETPC();
39
+#ifndef CONFIG_ATOMIC128
40
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
41
+#else
42
+ Int128 oldv, cmpv, newv;
43
+
44
+ cmpv = int128_make128(env->xregs[rs], env->xregs[rs + 1]);
45
+ newv = int128_make128(new_lo, new_hi);
46
+
47
+ int mem_idx = cpu_mmu_index(env, false);
48
+ TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
49
+ oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra);
50
+
51
+ env->xregs[rs] = int128_getlo(oldv);
52
+ env->xregs[rs + 1] = int128_gethi(oldv);
53
+#endif
54
+}
55
+
56
+void HELPER(casp_be_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
57
+ uint64_t new_hi, uint64_t new_lo)
58
+{
59
+ uintptr_t ra = GETPC();
60
+#ifndef CONFIG_ATOMIC128
61
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
62
+#else
63
+ Int128 oldv, cmpv, newv;
64
+
65
+ cmpv = int128_make128(env->xregs[rs + 1], env->xregs[rs]);
66
+ newv = int128_make128(new_lo, new_hi);
67
+
68
+ int mem_idx = cpu_mmu_index(env, false);
69
+ TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
70
+ oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
71
+
72
+ env->xregs[rs + 1] = int128_getlo(oldv);
73
+ env->xregs[rs] = int128_gethi(oldv);
74
+#endif
75
+}
76
+
77
/*
78
* AdvSIMD half-precision
79
*/
80
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/translate-a64.c
83
+++ b/target/arm/translate-a64.c
84
@@ -XXX,XX +XXX,XX @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
85
tcg_gen_movi_i64(cpu_exclusive_addr, -1);
86
}
87
88
+static void gen_compare_and_swap(DisasContext *s, int rs, int rt,
89
+ int rn, int size)
90
+{
91
+ TCGv_i64 tcg_rs = cpu_reg(s, rs);
92
+ TCGv_i64 tcg_rt = cpu_reg(s, rt);
93
+ int memidx = get_mem_index(s);
94
+ TCGv_i64 addr = cpu_reg_sp(s, rn);
95
+
96
+ if (rn == 31) {
97
+ gen_check_sp_alignment(s);
98
+ }
99
+ tcg_gen_atomic_cmpxchg_i64(tcg_rs, addr, tcg_rs, tcg_rt, memidx,
100
+ size | MO_ALIGN | s->be_data);
101
+}
102
+
103
+static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
104
+ int rn, int size)
105
+{
106
+ TCGv_i64 s1 = cpu_reg(s, rs);
107
+ TCGv_i64 s2 = cpu_reg(s, rs + 1);
108
+ TCGv_i64 t1 = cpu_reg(s, rt);
109
+ TCGv_i64 t2 = cpu_reg(s, rt + 1);
110
+ TCGv_i64 addr = cpu_reg_sp(s, rn);
111
+ int memidx = get_mem_index(s);
112
+
113
+ if (rn == 31) {
114
+ gen_check_sp_alignment(s);
115
+ }
116
+
117
+ if (size == 2) {
118
+ TCGv_i64 cmp = tcg_temp_new_i64();
119
+ TCGv_i64 val = tcg_temp_new_i64();
120
+
121
+ if (s->be_data == MO_LE) {
122
+ tcg_gen_concat32_i64(val, t1, t2);
123
+ tcg_gen_concat32_i64(cmp, s1, s2);
124
+ } else {
125
+ tcg_gen_concat32_i64(val, t2, t1);
126
+ tcg_gen_concat32_i64(cmp, s2, s1);
127
+ }
128
+
129
+ tcg_gen_atomic_cmpxchg_i64(cmp, addr, cmp, val, memidx,
130
+ MO_64 | MO_ALIGN | s->be_data);
131
+ tcg_temp_free_i64(val);
132
+
133
+ if (s->be_data == MO_LE) {
134
+ tcg_gen_extr32_i64(s1, s2, cmp);
135
+ } else {
136
+ tcg_gen_extr32_i64(s2, s1, cmp);
137
+ }
138
+ tcg_temp_free_i64(cmp);
139
+ } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
140
+ TCGv_i32 tcg_rs = tcg_const_i32(rs);
141
+
142
+ if (s->be_data == MO_LE) {
143
+ gen_helper_casp_le_parallel(cpu_env, tcg_rs, addr, t1, t2);
144
+ } else {
145
+ gen_helper_casp_be_parallel(cpu_env, tcg_rs, addr, t1, t2);
146
+ }
147
+ tcg_temp_free_i32(tcg_rs);
148
+ } else {
149
+ TCGv_i64 d1 = tcg_temp_new_i64();
150
+ TCGv_i64 d2 = tcg_temp_new_i64();
151
+ TCGv_i64 a2 = tcg_temp_new_i64();
152
+ TCGv_i64 c1 = tcg_temp_new_i64();
153
+ TCGv_i64 c2 = tcg_temp_new_i64();
154
+ TCGv_i64 zero = tcg_const_i64(0);
155
+
156
+ /* Load the two words, in memory order. */
157
+ tcg_gen_qemu_ld_i64(d1, addr, memidx,
158
+ MO_64 | MO_ALIGN_16 | s->be_data);
159
+ tcg_gen_addi_i64(a2, addr, 8);
160
+ tcg_gen_qemu_ld_i64(d2, addr, memidx, MO_64 | s->be_data);
161
+
162
+ /* Compare the two words, also in memory order. */
163
+ tcg_gen_setcond_i64(TCG_COND_EQ, c1, d1, s1);
164
+ tcg_gen_setcond_i64(TCG_COND_EQ, c2, d2, s2);
165
+ tcg_gen_and_i64(c2, c2, c1);
166
+
167
+ /* If compare equal, write back new data, else write back old data. */
168
+ tcg_gen_movcond_i64(TCG_COND_NE, c1, c2, zero, t1, d1);
169
+ tcg_gen_movcond_i64(TCG_COND_NE, c2, c2, zero, t2, d2);
170
+ tcg_gen_qemu_st_i64(c1, addr, memidx, MO_64 | s->be_data);
171
+ tcg_gen_qemu_st_i64(c2, a2, memidx, MO_64 | s->be_data);
172
+ tcg_temp_free_i64(a2);
173
+ tcg_temp_free_i64(c1);
174
+ tcg_temp_free_i64(c2);
175
+ tcg_temp_free_i64(zero);
176
+
177
+ /* Write back the data from memory to Rs. */
178
+ tcg_gen_mov_i64(s1, d1);
179
+ tcg_gen_mov_i64(s2, d2);
180
+ tcg_temp_free_i64(d1);
181
+ tcg_temp_free_i64(d2);
182
+ }
183
+}
184
+
185
/* Update the Sixty-Four bit (SF) registersize. This logic is derived
186
* from the ARMv8 specs for LDR (Shared decode for all encodings).
187
*/
188
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
189
gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, true);
190
return;
191
}
192
- /* CASP / CASPL */
193
+ if (rt2 == 31
194
+ && ((rt | rs) & 1) == 0
195
+ && arm_dc_feature(s, ARM_FEATURE_V8_ATOMICS)) {
196
+ /* CASP / CASPL */
197
+ gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
198
+ return;
199
+ }
200
break;
201
202
- case 0x6: case 0x7: /* CASP / LDXP */
203
+ case 0x6: case 0x7: /* CASPA / LDXP */
204
if (size & 2) { /* LDXP / LDAXP */
205
if (rn == 31) {
206
gen_check_sp_alignment(s);
207
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
208
}
209
return;
210
}
211
- /* CASPA / CASPAL */
212
+ if (rt2 == 31
213
+ && ((rt | rs) & 1) == 0
214
+ && arm_dc_feature(s, ARM_FEATURE_V8_ATOMICS)) {
215
+ /* CASPA / CASPAL */
216
+ gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
217
+ return;
218
+ }
219
break;
220
221
case 0xa: /* CAS */
222
case 0xb: /* CASL */
223
case 0xe: /* CASA */
224
case 0xf: /* CASAL */
225
+ if (rt2 == 31 && arm_dc_feature(s, ARM_FEATURE_V8_ATOMICS)) {
226
+ gen_compare_and_swap(s, rs, rt, rn, size);
227
+ return;
228
+ }
229
break;
230
}
231
unallocated_encoding(s);
232
--
233
2.17.0
234
235
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180508151437.4232-11-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
target/arm/cpu64.c | 1 +
9
1 file changed, 1 insertion(+)
10
11
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu64.c
14
+++ b/target/arm/cpu64.c
15
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
16
set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
17
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
18
set_feature(&cpu->env, ARM_FEATURE_CRC);
19
+ set_feature(&cpu->env, ARM_FEATURE_V8_ATOMICS);
20
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
21
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
22
set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
23
--
24
2.17.0
25
26
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
While we have some of the scalar paths for *CVF for fp16,
4
we failed to decode the fp16 version of these instructions.
5
6
Cc: qemu-stable@nongnu.org
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180502221552.3873-2-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate-a64.c | 33 ++++++++++++++++++++-------------
13
1 file changed, 20 insertions(+), 13 deletions(-)
14
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
18
+++ b/target/arm/translate-a64.c
19
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_intfp_conv(DisasContext *s, bool is_scalar,
20
int immh, int immb, int opcode,
21
int rn, int rd)
22
{
23
- bool is_double = extract32(immh, 3, 1);
24
- int size = is_double ? MO_64 : MO_32;
25
- int elements;
26
+ int size, elements, fracbits;
27
int immhb = immh << 3 | immb;
28
- int fracbits = (is_double ? 128 : 64) - immhb;
29
30
- if (!extract32(immh, 2, 2)) {
31
+ if (immh & 8) {
32
+ size = MO_64;
33
+ if (!is_scalar && !is_q) {
34
+ unallocated_encoding(s);
35
+ return;
36
+ }
37
+ } else if (immh & 4) {
38
+ size = MO_32;
39
+ } else if (immh & 2) {
40
+ size = MO_16;
41
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
42
+ unallocated_encoding(s);
43
+ return;
44
+ }
45
+ } else {
46
+ /* immh == 0 would be a failure of the decode logic */
47
+ g_assert(immh == 1);
48
unallocated_encoding(s);
49
return;
50
}
51
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_intfp_conv(DisasContext *s, bool is_scalar,
52
if (is_scalar) {
53
elements = 1;
54
} else {
55
- elements = is_double ? 2 : is_q ? 4 : 2;
56
- if (is_double && !is_q) {
57
- unallocated_encoding(s);
58
- return;
59
- }
60
+ elements = (8 << is_q) >> size;
61
}
62
+ fracbits = (16 << size) - immhb;
63
64
if (!fp_access_check(s)) {
65
return;
66
}
67
68
- /* immh == 0 would be a failure of the decode logic */
69
- g_assert(immh);
70
-
71
handle_simd_intfp_conv(s, rd, rn, elements, !is_u, fracbits, size);
72
}
73
74
--
75
2.17.0
76
77
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
While we have some of the scalar paths for FCVT for fp16,
4
we failed to decode the fp16 version of these instructions.
5
6
Cc: qemu-stable@nongnu.org
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180502221552.3873-3-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate-a64.c | 65 +++++++++++++++++++++++++++-----------
13
1 file changed, 46 insertions(+), 19 deletions(-)
14
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
18
+++ b/target/arm/translate-a64.c
19
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
20
bool is_q, bool is_u,
21
int immh, int immb, int rn, int rd)
22
{
23
- bool is_double = extract32(immh, 3, 1);
24
int immhb = immh << 3 | immb;
25
- int fracbits = (is_double ? 128 : 64) - immhb;
26
- int pass;
27
+ int pass, size, fracbits;
28
TCGv_ptr tcg_fpstatus;
29
TCGv_i32 tcg_rmode, tcg_shift;
30
31
- if (!extract32(immh, 2, 2)) {
32
- unallocated_encoding(s);
33
- return;
34
- }
35
-
36
- if (!is_scalar && !is_q && is_double) {
37
+ if (immh & 0x8) {
38
+ size = MO_64;
39
+ if (!is_scalar && !is_q) {
40
+ unallocated_encoding(s);
41
+ return;
42
+ }
43
+ } else if (immh & 0x4) {
44
+ size = MO_32;
45
+ } else if (immh & 0x2) {
46
+ size = MO_16;
47
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
48
+ unallocated_encoding(s);
49
+ return;
50
+ }
51
+ } else {
52
+ /* Should have split out AdvSIMD modified immediate earlier. */
53
+ assert(immh == 1);
54
unallocated_encoding(s);
55
return;
56
}
57
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
58
assert(!(is_scalar && is_q));
59
60
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
61
- tcg_fpstatus = get_fpstatus_ptr(false);
62
+ tcg_fpstatus = get_fpstatus_ptr(size == MO_16);
63
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
64
+ fracbits = (16 << size) - immhb;
65
tcg_shift = tcg_const_i32(fracbits);
66
67
- if (is_double) {
68
+ if (size == MO_64) {
69
int maxpass = is_scalar ? 1 : 2;
70
71
for (pass = 0; pass < maxpass; pass++) {
72
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
73
}
74
clear_vec_high(s, is_q, rd);
75
} else {
76
- int maxpass = is_scalar ? 1 : is_q ? 4 : 2;
77
+ void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
78
+ int maxpass = is_scalar ? 1 : ((8 << is_q) >> size);
79
+
80
+ switch (size) {
81
+ case MO_16:
82
+ if (is_u) {
83
+ fn = gen_helper_vfp_toulh;
84
+ } else {
85
+ fn = gen_helper_vfp_toslh;
86
+ }
87
+ break;
88
+ case MO_32:
89
+ if (is_u) {
90
+ fn = gen_helper_vfp_touls;
91
+ } else {
92
+ fn = gen_helper_vfp_tosls;
93
+ }
94
+ break;
95
+ default:
96
+ g_assert_not_reached();
97
+ }
98
+
99
for (pass = 0; pass < maxpass; pass++) {
100
TCGv_i32 tcg_op = tcg_temp_new_i32();
101
102
- read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
103
- if (is_u) {
104
- gen_helper_vfp_touls(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
105
- } else {
106
- gen_helper_vfp_tosls(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
107
- }
108
+ read_vec_element_i32(s, tcg_op, rn, pass, size);
109
+ fn(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
110
if (is_scalar) {
111
write_fp_sreg(s, rd, tcg_op);
112
} else {
113
- write_vec_element_i32(s, tcg_op, rd, pass, MO_32);
114
+ write_vec_element_i32(s, tcg_op, rd, pass, size);
115
}
116
tcg_temp_free_i32(tcg_op);
117
}
118
--
119
2.17.0
120
121
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
The instruction "ucvtf v0.4h, v04h, #2", with input 0x8000u,
4
overflows the intermediate float16 to infinity before we have a
5
chance to scale the output. Use float64 as the intermediate type
6
so that no input argument (uint32_t in this case) can overflow
7
or round before scaling. Given the declared argument, the signed
8
int32_t function has the same problem.
9
10
When converting from float16 to integer, using u/int32_t instead
11
of u/int16_t means that the bounding is incorrect.
12
13
Cc: qemu-stable@nongnu.org
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20180502221552.3873-4-richard.henderson@linaro.org
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
target/arm/helper.h | 4 +--
20
target/arm/helper.c | 53 ++++++++++++++++++++++++++++++++++++--
21
target/arm/translate-a64.c | 4 +--
22
3 files changed, 55 insertions(+), 6 deletions(-)
23
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.h
27
+++ b/target/arm/helper.h
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_toshd_round_to_zero, i64, f64, i32, ptr)
29
DEF_HELPER_3(vfp_tosld_round_to_zero, i64, f64, i32, ptr)
30
DEF_HELPER_3(vfp_touhd_round_to_zero, i64, f64, i32, ptr)
31
DEF_HELPER_3(vfp_tould_round_to_zero, i64, f64, i32, ptr)
32
-DEF_HELPER_3(vfp_toulh, i32, f16, i32, ptr)
33
-DEF_HELPER_3(vfp_toslh, i32, f16, i32, ptr)
34
+DEF_HELPER_3(vfp_touhh, i32, f16, i32, ptr)
35
+DEF_HELPER_3(vfp_toshh, i32, f16, i32, ptr)
36
DEF_HELPER_3(vfp_toshs, i32, f32, i32, ptr)
37
DEF_HELPER_3(vfp_tosls, i32, f32, i32, ptr)
38
DEF_HELPER_3(vfp_tosqs, i64, f32, i32, ptr)
39
diff --git a/target/arm/helper.c b/target/arm/helper.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/helper.c
42
+++ b/target/arm/helper.c
43
@@ -XXX,XX +XXX,XX @@ VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
44
VFP_CONV_FIX(uh, s, 32, 32, uint16)
45
VFP_CONV_FIX(ul, s, 32, 32, uint32)
46
VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
47
-VFP_CONV_FIX_A64(sl, h, 16, 32, int32)
48
-VFP_CONV_FIX_A64(ul, h, 16, 32, uint32)
49
+
50
#undef VFP_CONV_FIX
51
#undef VFP_CONV_FIX_FLOAT
52
#undef VFP_CONV_FLOAT_FIX_ROUND
53
+#undef VFP_CONV_FIX_A64
54
+
55
+/* Conversion to/from f16 can overflow to infinity before/after scaling.
56
+ * Therefore we convert to f64 (which does not round), scale,
57
+ * and then convert f64 to f16 (which may round).
58
+ */
59
+
60
+static float16 do_postscale_fp16(float64 f, int shift, float_status *fpst)
61
+{
62
+ return float64_to_float16(float64_scalbn(f, -shift, fpst), true, fpst);
63
+}
64
+
65
+float16 HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
66
+{
67
+ return do_postscale_fp16(int32_to_float64(x, fpst), shift, fpst);
68
+}
69
+
70
+float16 HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
71
+{
72
+ return do_postscale_fp16(uint32_to_float64(x, fpst), shift, fpst);
73
+}
74
+
75
+static float64 do_prescale_fp16(float16 f, int shift, float_status *fpst)
76
+{
77
+ if (unlikely(float16_is_any_nan(f))) {
78
+ float_raise(float_flag_invalid, fpst);
79
+ return 0;
80
+ } else {
81
+ int old_exc_flags = get_float_exception_flags(fpst);
82
+ float64 ret;
83
+
84
+ ret = float16_to_float64(f, true, fpst);
85
+ ret = float64_scalbn(ret, shift, fpst);
86
+ old_exc_flags |= get_float_exception_flags(fpst)
87
+ & float_flag_input_denormal;
88
+ set_float_exception_flags(old_exc_flags, fpst);
89
+
90
+ return ret;
91
+ }
92
+}
93
+
94
+uint32_t HELPER(vfp_toshh)(float16 x, uint32_t shift, void *fpst)
95
+{
96
+ return float64_to_int16(do_prescale_fp16(x, shift, fpst), fpst);
97
+}
98
+
99
+uint32_t HELPER(vfp_touhh)(float16 x, uint32_t shift, void *fpst)
100
+{
101
+ return float64_to_uint16(do_prescale_fp16(x, shift, fpst), fpst);
102
+}
103
104
/* Set the current fp rounding mode and return the old one.
105
* The argument is a softfloat float_round_ value.
106
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/target/arm/translate-a64.c
109
+++ b/target/arm/translate-a64.c
110
@@ -XXX,XX +XXX,XX @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
111
switch (size) {
112
case MO_16:
113
if (is_u) {
114
- fn = gen_helper_vfp_toulh;
115
+ fn = gen_helper_vfp_touhh;
116
} else {
117
- fn = gen_helper_vfp_toslh;
118
+ fn = gen_helper_vfp_toshh;
119
}
120
break;
121
case MO_32:
122
--
123
2.17.0
124
125
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Use write_fp_dreg and clear_vec_high to zero the bits
4
that need zeroing for these cases.
5
6
Cc: qemu-stable@nongnu.org
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180502221552.3873-5-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate-a64.c | 17 +++++------------
13
1 file changed, 5 insertions(+), 12 deletions(-)
14
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
18
+++ b/target/arm/translate-a64.c
19
@@ -XXX,XX +XXX,XX @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
20
21
if (itof) {
22
TCGv_i64 tcg_rn = cpu_reg(s, rn);
23
+ TCGv_i64 tmp;
24
25
switch (type) {
26
case 0:
27
- {
28
/* 32 bit */
29
- TCGv_i64 tmp = tcg_temp_new_i64();
30
+ tmp = tcg_temp_new_i64();
31
tcg_gen_ext32u_i64(tmp, tcg_rn);
32
- tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(s, rd, MO_64));
33
- tcg_gen_movi_i64(tmp, 0);
34
- tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(s, rd));
35
+ write_fp_dreg(s, rd, tmp);
36
tcg_temp_free_i64(tmp);
37
break;
38
- }
39
case 1:
40
- {
41
/* 64 bit */
42
- TCGv_i64 tmp = tcg_const_i64(0);
43
- tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(s, rd, MO_64));
44
- tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(s, rd));
45
- tcg_temp_free_i64(tmp);
46
+ write_fp_dreg(s, rd, tcg_rn);
47
break;
48
- }
49
case 2:
50
/* 64 bit to top half. */
51
tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(s, rd));
52
+ clear_vec_high(s, true, rd);
53
break;
54
}
55
} else {
56
--
57
2.17.0
58
59
diff view generated by jsdifflib