1
Arm queue -- mostly the first slice of my Musca patches.
1
Another arm pullreq; nothing particularly exciting here.
2
2
3
thanks
4
-- PMM
3
-- PMM
5
4
6
The following changes since commit fc3dbb90f2eb069801bfb4cfe9cbc83cf9c5f4a9:
7
5
8
Merge remote-tracking branch 'remotes/jnsnow/tags/bitmaps-pull-request' into staging (2019-02-21 13:09:33 +0000)
6
The following changes since commit e27d5b488ef08408691bfed61f34ee2858136287:
7
8
Merge remote-tracking branch 'remotes/juanquintela/tags/pull-migration-pull-request' into staging (2020-02-28 14:02:31 +0000)
9
9
10
are available in the Git repository at:
10
are available in the Git repository at:
11
11
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190221
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200228
13
13
14
for you to fetch changes up to 3733f80308d2a7f23f5e39b039e0547aba6c07f1:
14
for you to fetch changes up to 1904f9b5f1d94fe12fe021db6b504c87d684f6db:
15
15
16
hw/arm/armsse: Make 0x5... alias region work for per-CPU devices (2019-02-21 18:17:48 +0000)
16
hw/intc/arm_gic_kvm: Don't assume kernel can provide a GICv2 (2020-02-28 16:14:57 +0000)
17
17
18
----------------------------------------------------------------
18
----------------------------------------------------------------
19
target-arm queue:
19
target-arm queue:
20
* Model the Arm "Musca" development boards: "musca-a" and "musca-b1"
20
* hw/arm: Use TYPE_PL011 to create serial port
21
* Implement the ARMv8.3-JSConv extension
21
* target/arm: Set ID_MMFR4.HPDS for aarch64_max_initfn
22
* v8M MPU should use background region as default, not always
22
* hw/arm/integratorcp: Map the audio codec controller
23
* Stop unintentional sign extension in pmu_init
23
* GICv2: Correctly implement the limited number of priority bits
24
* target/arm: refactoring of VFP related feature checks and decode
25
* xilinx_zynq: Fix USB port instantiation
26
* acceptance tests for n800, n810, integratorcp
27
* Implement v8.3-RCPC, v8.4-RCPC, v8.3-CCIDX
28
* arm_gic_kvm: Don't assume kernel can provide a GICv2
29
(provide better error message for user error)
24
30
25
----------------------------------------------------------------
31
----------------------------------------------------------------
26
Aaron Lindsay OS (1):
32
Gavin Shan (1):
27
target/arm: Stop unintentional sign extension in pmu_init
33
hw/arm: Use TYPE_PL011 to create serial port
28
34
29
Peter Maydell (16):
35
Guenter Roeck (2):
30
hw/arm/armsse: Fix memory leak in error-exit path
36
hw/arm/xilinx_zynq: Fix USB port instantiation
31
target/arm: v8M MPU should use background region as default, not always
37
hw/usb/hcd-ehci-sysbus: Remove obsolete xlnx, ps7-usb class
32
hw/misc/tz-ppc: Support having unused ports in the middle of the range
33
hw/timer/pl031: Allow use as an embedded-struct device
34
hw/timer/pl031: Convert to using trace events
35
hw/char/pl011: Allow use as an embedded-struct device
36
hw/char/pl011: Support all interrupt lines
37
hw/char/pl011: Use '0x' prefix when logging hex numbers
38
hw/arm/armsse: Document SRAM_ADDR_WIDTH property in header comment
39
hw/arm/armsse: Allow boards to specify init-svtor
40
hw/arm/musca.c: Implement models of the Musca-A and -B1 boards
41
hw/arm/musca: Add PPCs
42
hw/arm/musca: Add MPCs
43
hw/arm/musca: Wire up PL031 RTC
44
hw/arm/musca: Wire up PL011 UARTs
45
hw/arm/armsse: Make 0x5... alias region work for per-CPU devices
46
38
47
Richard Henderson (4):
39
Peter Maydell (5):
48
target/arm: Restructure disas_fp_int_conv
40
target/arm: Fix wrong use of FIELD_EX32 on ID_AA64DFR0
49
target/arm: Split out vfp_helper.c
41
target/arm: Implement v8.3-RCPC
50
target/arm: Rearrange Floating-point data-processing (2 regs)
42
target/arm: Implement v8.4-RCPC
51
target/arm: Implement ARMv8.3-JSConv
43
target/arm: Implement ARMv8.3-CCIDX
44
hw/intc/arm_gic_kvm: Don't assume kernel can provide a GICv2
52
45
53
hw/arm/Makefile.objs | 1 +
46
Philippe Mathieu-Daudé (3):
54
target/arm/Makefile.objs | 2 +-
47
hw/arm/integratorcp: Map the audio codec controller
55
include/hw/arm/armsse.h | 7 +-
48
tests/acceptance: Extract boot_integratorcp() from test_integratorcp()
56
include/hw/char/pl011.h | 34 ++
49
tests/acceptance/integratorcp: Verify Tux is displayed on framebuffer
57
include/hw/misc/tz-ppc.h | 8 +-
58
include/hw/timer/pl031.h | 44 ++
59
target/arm/cpu.h | 10 +
60
target/arm/helper.h | 3 +
61
hw/arm/armsse.c | 44 +-
62
hw/arm/musca.c | 669 ++++++++++++++++++++++
63
hw/char/pl011.c | 81 +--
64
hw/misc/tz-ppc.c | 32 ++
65
hw/timer/pl031.c | 80 ++-
66
target/arm/cpu.c | 1 +
67
target/arm/cpu64.c | 2 +
68
target/arm/helper.c | 1072 +----------------------------------
69
target/arm/translate-a64.c | 120 ++--
70
target/arm/translate.c | 237 ++++----
71
target/arm/vfp_helper.c | 1176 +++++++++++++++++++++++++++++++++++++++
72
MAINTAINERS | 7 +
73
default-configs/arm-softmmu.mak | 1 +
74
hw/timer/trace-events | 6 +
75
22 files changed, 2307 insertions(+), 1330 deletions(-)
76
create mode 100644 include/hw/timer/pl031.h
77
create mode 100644 hw/arm/musca.c
78
create mode 100644 target/arm/vfp_helper.c
79
50
51
Richard Henderson (17):
52
target/arm: Set ID_MMFR4.HPDS for aarch64_max_initfn
53
target/arm: Add isar_feature_aa32_vfp_simd
54
target/arm: Rename isar_feature_aa32_fpdp_v2
55
target/arm: Add isar_feature_aa32_{fpsp_v2, fpsp_v3, fpdp_v3}
56
target/arm: Add isar_feature_aa64_fp_simd, isar_feature_aa32_vfp
57
target/arm: Perform fpdp_v2 check first
58
target/arm: Replace ARM_FEATURE_VFP3 checks with fp{sp, dp}_v3
59
target/arm: Add missing checks for fpsp_v2
60
target/arm: Replace ARM_FEATURE_VFP4 with isar_feature_aa32_simdfmac
61
target/arm: Remove ARM_FEATURE_VFP check from disas_vfp_insn
62
target/arm: Move VLLDM and VLSTM to vfp.decode
63
target/arm: Move the vfp decodetree calls next to the base isa
64
linux-user/arm: Replace ARM_FEATURE_VFP* tests for HWCAP
65
target/arm: Remove ARM_FEATURE_VFP*
66
target/arm: Add formats for some vfp 2 and 3-register insns
67
target/arm: Split VFM decode
68
target/arm: Split VMINMAXNM decode
69
70
Sai Pavan Boddu (3):
71
arm_gic: Mask the un-supported priority bits
72
cpu/a9mpcore: Set number of GIC priority bits to 5
73
cpu/arm11mpcore: Set number of GIC priority bits to 4
74
75
Thomas Huth (2):
76
tests/acceptance: Add a test for the N800 and N810 arm machines
77
tests/acceptance: Add a test for the integratorcp arm machine
78
79
include/hw/intc/arm_gic.h | 2 +
80
include/hw/intc/arm_gic_common.h | 1 +
81
target/arm/cpu.h | 88 +++++-
82
hw/arm/integratorcp.c | 1 +
83
hw/arm/sbsa-ref.c | 3 +-
84
hw/arm/virt.c | 3 +-
85
hw/arm/xilinx_zynq.c | 5 +-
86
hw/arm/xlnx-versal.c | 3 +-
87
hw/cpu/a9mpcore.c | 4 +
88
hw/cpu/arm11mpcore.c | 5 +
89
hw/intc/arm_gic.c | 33 +-
90
hw/intc/arm_gic_common.c | 1 +
91
hw/intc/arm_gic_kvm.c | 9 +
92
hw/intc/armv7m_nvic.c | 20 +-
93
hw/usb/hcd-ehci-sysbus.c | 17 -
94
linux-user/arm/signal.c | 4 +-
95
linux-user/elfload.c | 25 +-
96
target/arm/arch_dump.c | 11 +-
97
target/arm/cpu.c | 44 +--
98
target/arm/cpu64.c | 5 +-
99
target/arm/helper.c | 23 +-
100
target/arm/kvm32.c | 5 -
101
target/arm/kvm64.c | 1 -
102
target/arm/m_helper.c | 11 +-
103
target/arm/machine.c | 5 +-
104
target/arm/translate-a64.c | 114 +++++++
105
target/arm/translate-vfp.inc.c | 448 +++++++++++++++++----------
106
target/arm/translate.c | 122 ++------
107
MAINTAINERS | 2 +
108
hw/arm/Kconfig | 1 +
109
target/arm/vfp-uncond.decode | 12 +-
110
target/arm/vfp.decode | 153 ++++-----
111
tests/acceptance/machine_arm_integratorcp.py | 99 ++++++
112
tests/acceptance/machine_arm_n8x0.py | 49 +++
113
34 files changed, 865 insertions(+), 464 deletions(-)
114
create mode 100644 tests/acceptance/machine_arm_integratorcp.py
115
create mode 100644 tests/acceptance/machine_arm_n8x0.py
116
diff view generated by jsdifflib
New patch
1
From: Gavin Shan <gshan@redhat.com>
1
2
3
This uses TYPE_PL011 when creating the serial port so that the code
4
looks cleaner.
5
6
Signed-off-by: Gavin Shan <gshan@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20200224222223.4128-1-gshan@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/arm/sbsa-ref.c | 3 ++-
13
hw/arm/virt.c | 3 ++-
14
hw/arm/xlnx-versal.c | 3 ++-
15
3 files changed, 6 insertions(+), 3 deletions(-)
16
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/sbsa-ref.c
20
+++ b/hw/arm/sbsa-ref.c
21
@@ -XXX,XX +XXX,XX @@
22
#include "hw/pci-host/gpex.h"
23
#include "hw/qdev-properties.h"
24
#include "hw/usb.h"
25
+#include "hw/char/pl011.h"
26
#include "net/net.h"
27
28
#define RAMLIMIT_GB 8192
29
@@ -XXX,XX +XXX,XX @@ static void create_uart(const SBSAMachineState *sms, int uart,
30
{
31
hwaddr base = sbsa_ref_memmap[uart].base;
32
int irq = sbsa_ref_irqmap[uart];
33
- DeviceState *dev = qdev_create(NULL, "pl011");
34
+ DeviceState *dev = qdev_create(NULL, TYPE_PL011);
35
SysBusDevice *s = SYS_BUS_DEVICE(dev);
36
37
qdev_prop_set_chr(dev, "chardev", chr);
38
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/arm/virt.c
41
+++ b/hw/arm/virt.c
42
@@ -XXX,XX +XXX,XX @@
43
#include "hw/mem/nvdimm.h"
44
#include "hw/acpi/generic_event_device.h"
45
#include "hw/virtio/virtio-iommu.h"
46
+#include "hw/char/pl011.h"
47
48
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
49
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
50
@@ -XXX,XX +XXX,XX @@ static void create_uart(const VirtMachineState *vms, int uart,
51
int irq = vms->irqmap[uart];
52
const char compat[] = "arm,pl011\0arm,primecell";
53
const char clocknames[] = "uartclk\0apb_pclk";
54
- DeviceState *dev = qdev_create(NULL, "pl011");
55
+ DeviceState *dev = qdev_create(NULL, TYPE_PL011);
56
SysBusDevice *s = SYS_BUS_DEVICE(dev);
57
58
qdev_prop_set_chr(dev, "chardev", chr);
59
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/arm/xlnx-versal.c
62
+++ b/hw/arm/xlnx-versal.c
63
@@ -XXX,XX +XXX,XX @@
64
#include "hw/misc/unimp.h"
65
#include "hw/intc/arm_gicv3_common.h"
66
#include "hw/arm/xlnx-versal.h"
67
+#include "hw/char/pl011.h"
68
69
#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
70
#define GEM_REVISION 0x40070106
71
@@ -XXX,XX +XXX,XX @@ static void versal_create_uarts(Versal *s, qemu_irq *pic)
72
DeviceState *dev;
73
MemoryRegion *mr;
74
75
- dev = qdev_create(NULL, "pl011");
76
+ dev = qdev_create(NULL, TYPE_PL011);
77
s->lpd.iou.uart[i] = SYS_BUS_DEVICE(dev);
78
qdev_prop_set_chr(dev, "chardev", serial_hd(i));
79
object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
80
--
81
2.20.1
82
83
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
For opcodes 0-5, move some if conditions into the structure
3
We had set this for aarch32-only in arm_max_initfn, but
4
of a switch statement. For opcodes 6 & 7, decode everything
4
failed to set the same bit for aarch64.
5
at once with a second switch.
6
5
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190215192302.27855-2-richard.henderson@linaro.org
7
Message-id: 20200218190958.745-2-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/translate-a64.c | 94 ++++++++++++++++++++------------------
11
target/arm/cpu64.c | 1 +
13
1 file changed, 49 insertions(+), 45 deletions(-)
12
1 file changed, 1 insertion(+)
14
13
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
16
--- a/target/arm/cpu64.c
18
+++ b/target/arm/translate-a64.c
17
+++ b/target/arm/cpu64.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
20
int type = extract32(insn, 22, 2);
19
cpu->isar.id_mmfr3 = u;
21
bool sbit = extract32(insn, 29, 1);
20
22
bool sf = extract32(insn, 31, 1);
21
u = cpu->isar.id_mmfr4;
23
+ bool itof = false;
22
+ u = FIELD_DP32(u, ID_MMFR4, HPDS, 1); /* AA32HPD */
24
23
u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
25
if (sbit) {
24
cpu->isar.id_mmfr4 = u;
26
- unallocated_encoding(s);
27
- return;
28
+ goto do_unallocated;
29
}
30
31
- if (opcode > 5) {
32
- /* FMOV */
33
- bool itof = opcode & 1;
34
-
35
- if (rmode >= 2) {
36
- unallocated_encoding(s);
37
- return;
38
- }
39
-
40
- switch (sf << 3 | type << 1 | rmode) {
41
- case 0x0: /* 32 bit */
42
- case 0xa: /* 64 bit */
43
- case 0xd: /* 64 bit to top half of quad */
44
- break;
45
- case 0x6: /* 16-bit float, 32-bit int */
46
- case 0xe: /* 16-bit float, 64-bit int */
47
- if (dc_isar_feature(aa64_fp16, s)) {
48
- break;
49
- }
50
- /* fallthru */
51
- default:
52
- /* all other sf/type/rmode combinations are invalid */
53
- unallocated_encoding(s);
54
- return;
55
- }
56
-
57
- if (!fp_access_check(s)) {
58
- return;
59
- }
60
- handle_fmov(s, rd, rn, type, itof);
61
- } else {
62
- /* actual FP conversions */
63
- bool itof = extract32(opcode, 1, 1);
64
-
65
- if (rmode != 0 && opcode > 1) {
66
- unallocated_encoding(s);
67
- return;
68
+ switch (opcode) {
69
+ case 2: /* SCVTF */
70
+ case 3: /* UCVTF */
71
+ itof = true;
72
+ /* fallthru */
73
+ case 4: /* FCVTAS */
74
+ case 5: /* FCVTAU */
75
+ if (rmode != 0) {
76
+ goto do_unallocated;
77
}
78
+ /* fallthru */
79
+ case 0: /* FCVT[NPMZ]S */
80
+ case 1: /* FCVT[NPMZ]U */
81
switch (type) {
82
case 0: /* float32 */
83
case 1: /* float64 */
84
break;
85
case 3: /* float16 */
86
- if (dc_isar_feature(aa64_fp16, s)) {
87
- break;
88
+ if (!dc_isar_feature(aa64_fp16, s)) {
89
+ goto do_unallocated;
90
}
91
- /* fallthru */
92
+ break;
93
default:
94
- unallocated_encoding(s);
95
- return;
96
+ goto do_unallocated;
97
}
98
-
99
if (!fp_access_check(s)) {
100
return;
101
}
102
handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
103
+ break;
104
+
105
+ default:
106
+ switch (sf << 7 | type << 5 | rmode << 3 | opcode) {
107
+ case 0b01100110: /* FMOV half <-> 32-bit int */
108
+ case 0b01100111:
109
+ case 0b11100110: /* FMOV half <-> 64-bit int */
110
+ case 0b11100111:
111
+ if (!dc_isar_feature(aa64_fp16, s)) {
112
+ goto do_unallocated;
113
+ }
114
+ /* fallthru */
115
+ case 0b00000110: /* FMOV 32-bit */
116
+ case 0b00000111:
117
+ case 0b10100110: /* FMOV 64-bit */
118
+ case 0b10100111:
119
+ case 0b11001110: /* FMOV top half of 128-bit */
120
+ case 0b11001111:
121
+ if (!fp_access_check(s)) {
122
+ return;
123
+ }
124
+ itof = opcode & 1;
125
+ handle_fmov(s, rd, rn, type, itof);
126
+ break;
127
+
128
+ default:
129
+ do_unallocated:
130
+ unallocated_encoding(s);
131
+ return;
132
+ }
133
+ break;
134
}
135
}
136
25
137
--
26
--
138
2.20.1
27
2.20.1
139
28
140
29
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
The Linux kernel displays errors why trying to detect the PL041
4
audio interface:
5
6
Linux version 4.16.0 (linus@genomnajs) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #142 PREEMPT Wed May 9 13:24:55 CEST 2018
7
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00093177
8
CPU: VIVT data cache, VIVT instruction cache
9
OF: fdt: Machine model: ARM Integrator/CP
10
...
11
OF: amba_device_add() failed (-19) for /fpga/aaci@1d000000
12
13
Since we have it already modelled, simply plug it.
14
15
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20200223233033.15371-2-f4bug@amsat.org
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
hw/arm/integratorcp.c | 1 +
21
hw/arm/Kconfig | 1 +
22
2 files changed, 2 insertions(+)
23
24
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/arm/integratorcp.c
27
+++ b/hw/arm/integratorcp.c
28
@@ -XXX,XX +XXX,XX @@ static void integratorcp_init(MachineState *machine)
29
qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
30
qdev_connect_gpio_out(dev, 1,
31
qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0));
32
+ sysbus_create_varargs("pl041", 0x1d000000, pic[25], NULL);
33
34
if (nd_table[0].used)
35
smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
36
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/Kconfig
39
+++ b/hw/arm/Kconfig
40
@@ -XXX,XX +XXX,XX @@ config INTEGRATOR
41
select INTEGRATOR_DEBUG
42
select PL011 # UART
43
select PL031 # RTC
44
+ select PL041 # audio
45
select PL050 # keyboard/mouse
46
select PL110 # pl111 LCD controller
47
select PL181 # display
48
--
49
2.20.1
50
51
diff view generated by jsdifflib
1
The Peripheral Protection Controller's handling of unused ports
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
is that if there is nothing connected to the port's downstream
3
then it does not create the sysbus MMIO region for the upstream
4
end of the port. This results in odd behaviour when there is
5
an unused port in the middle of the range: since sysbus MMIO
6
regions are implicitly consecutively allocated, any used ports
7
above the unused ones end up with sysbus MMIO region numbers
8
that don't match the port number.
9
2
10
Avoid this numbering mismatch by creating dummy MMIO regions
3
The GICv2 allows the implementation to implement a variable number
11
for the unused ports. This doesn't change anything for our
4
of priority bits; unimplemented bits in the priority registers
12
existing boards, which don't have any gaps in the middle of
5
are read as zeros, writes ignored. We were previously always
13
the port ranges they use; but it will be needed for the Musca
6
implementing a full 8 bits of priority, which is allowed but not
14
board.
7
what the real hardware typically does (which is usually to have
8
4 or 5 bits of priority).
15
9
10
Add a new device property to allow the number of implemented
11
property bits to be specified.
12
13
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
14
Message-id: 1582537164-764-2-git-send-email-sai.pavan.boddu@xilinx.com
15
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
[PMM: improved commit message]
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
---
19
---
19
include/hw/misc/tz-ppc.h | 8 +++++++-
20
include/hw/intc/arm_gic.h | 2 ++
20
hw/misc/tz-ppc.c | 32 ++++++++++++++++++++++++++++++++
21
include/hw/intc/arm_gic_common.h | 1 +
21
2 files changed, 39 insertions(+), 1 deletion(-)
22
hw/intc/arm_gic.c | 33 ++++++++++++++++++++++++++++++--
23
hw/intc/arm_gic_common.c | 1 +
24
4 files changed, 35 insertions(+), 2 deletions(-)
22
25
23
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
26
diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h
24
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/misc/tz-ppc.h
28
--- a/include/hw/intc/arm_gic.h
26
+++ b/include/hw/misc/tz-ppc.h
29
+++ b/include/hw/intc/arm_gic.h
27
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@
28
*
31
29
* QEMU interface:
32
/* Number of SGI target-list bits */
30
* + sysbus MMIO regions 0..15: MemoryRegions defining the upstream end
33
#define GIC_TARGETLIST_BITS 8
31
- * of each of the 16 ports of the PPC
34
+#define GIC_MAX_PRIORITY_BITS 8
32
+ * of each of the 16 ports of the PPC. When a port is unused (i.e. no
35
+#define GIC_MIN_PRIORITY_BITS 4
33
+ * downstream MemoryRegion is connected to it) at the end of the 0..15
36
34
+ * range then no sysbus MMIO region is created for its upstream. When an
37
#define TYPE_ARM_GIC "arm_gic"
35
+ * unused port lies in the middle of the range with other used ports at
38
#define ARM_GIC(obj) \
36
+ * higher port numbers, a dummy MMIO region is created to ensure that
39
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
37
+ * port N's upstream is always sysbus MMIO region N. Dummy regions should
38
+ * not be mapped, and will assert if any access is made to them.
39
* + Property "port[0..15]": MemoryRegion defining the downstream device(s)
40
* for each of the 16 ports of the PPC
41
* + Named GPIO inputs "cfg_nonsec[0..15]": set to 1 if the port should be
42
diff --git a/hw/misc/tz-ppc.c b/hw/misc/tz-ppc.c
43
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/tz-ppc.c
41
--- a/include/hw/intc/arm_gic_common.h
45
+++ b/hw/misc/tz-ppc.c
42
+++ b/include/hw/intc/arm_gic_common.h
46
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps tz_ppc_ops = {
43
@@ -XXX,XX +XXX,XX @@ typedef struct GICState {
47
.endianness = DEVICE_LITTLE_ENDIAN,
44
uint16_t priority_mask[GIC_NCPU_VCPU];
48
};
45
uint16_t running_priority[GIC_NCPU_VCPU];
49
46
uint16_t current_pending[GIC_NCPU_VCPU];
50
+static bool tz_ppc_dummy_accepts(void *opaque, hwaddr addr,
47
+ uint32_t n_prio_bits;
51
+ unsigned size, bool is_write,
48
52
+ MemTxAttrs attrs)
49
/* If we present the GICv2 without security extensions to a guest,
50
* the guest can configure the GICC_CTLR to configure group 1 binary point
51
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/intc/arm_gic.c
54
+++ b/hw/intc/arm_gic.c
55
@@ -XXX,XX +XXX,XX @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
56
return ret;
57
}
58
59
+static uint32_t gic_fullprio_mask(GICState *s, int cpu)
53
+{
60
+{
54
+ /*
61
+ /*
55
+ * Board code should never map the upstream end of an unused port,
62
+ * Return a mask word which clears the unimplemented priority
56
+ * so we should never try to make a memory access to it.
63
+ * bits from a priority value for an interrupt. (Not to be
64
+ * confused with the group priority, whose mask depends on BPR.)
57
+ */
65
+ */
58
+ g_assert_not_reached();
66
+ int priBits;
67
+
68
+ if (gic_is_vcpu(cpu)) {
69
+ priBits = GIC_VIRT_MAX_GROUP_PRIO_BITS;
70
+ } else {
71
+ priBits = s->n_prio_bits;
72
+ }
73
+ return ~0U << (8 - priBits);
59
+}
74
+}
60
+
75
+
61
+static const MemoryRegionOps tz_ppc_dummy_ops = {
76
void gic_dist_set_priority(GICState *s, int cpu, int irq, uint8_t val,
62
+ .valid.accepts = tz_ppc_dummy_accepts,
77
MemTxAttrs attrs)
63
+};
78
{
79
@@ -XXX,XX +XXX,XX @@ void gic_dist_set_priority(GICState *s, int cpu, int irq, uint8_t val,
80
val = 0x80 | (val >> 1); /* Non-secure view */
81
}
82
83
+ val &= gic_fullprio_mask(s, cpu);
64
+
84
+
65
static void tz_ppc_reset(DeviceState *dev)
85
if (irq < GIC_INTERNAL) {
66
{
86
s->priority1[irq][cpu] = val;
67
TZPPC *s = TZ_PPC(dev);
87
} else {
68
@@ -XXX,XX +XXX,XX @@ static void tz_ppc_realize(DeviceState *dev, Error **errp)
88
@@ -XXX,XX +XXX,XX @@ static uint32_t gic_dist_get_priority(GICState *s, int cpu, int irq,
69
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
89
}
70
TZPPC *s = TZ_PPC(dev);
90
prio = (prio << 1) & 0xff; /* Non-secure view */
71
int i;
91
}
72
+ int max_port = 0;
92
- return prio;
73
93
+ return prio & gic_fullprio_mask(s, cpu);
74
/* We can't create the upstream end of the port until realize,
94
}
75
* as we don't know the size of the MR used as the downstream until then.
95
76
*/
96
static void gic_set_priority_mask(GICState *s, int cpu, uint8_t pmask,
77
for (i = 0; i < TZ_NUM_PORTS; i++) {
97
@@ -XXX,XX +XXX,XX @@ static void gic_set_priority_mask(GICState *s, int cpu, uint8_t pmask,
78
+ if (s->port[i].downstream) {
98
return;
79
+ max_port = i;
99
}
80
+ }
100
}
101
- s->priority_mask[cpu] = pmask;
102
+ s->priority_mask[cpu] = pmask & gic_fullprio_mask(s, cpu);
103
}
104
105
static uint32_t gic_get_priority_mask(GICState *s, int cpu, MemTxAttrs attrs)
106
@@ -XXX,XX +XXX,XX @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
107
return;
108
}
109
110
+ if (s->n_prio_bits > GIC_MAX_PRIORITY_BITS ||
111
+ (s->virt_extn ? s->n_prio_bits < GIC_VIRT_MAX_GROUP_PRIO_BITS :
112
+ s->n_prio_bits < GIC_MIN_PRIORITY_BITS)) {
113
+ error_setg(errp, "num-priority-bits cannot be greater than %d"
114
+ " or less than %d", GIC_MAX_PRIORITY_BITS,
115
+ s->virt_extn ? GIC_VIRT_MAX_GROUP_PRIO_BITS :
116
+ GIC_MIN_PRIORITY_BITS);
117
+ return;
81
+ }
118
+ }
82
+
119
+
83
+ for (i = 0; i <= max_port; i++) {
120
/* This creates distributor, main CPU interface (s->cpuiomem[0]) and if
84
TZPPCPort *port = &s->port[i];
121
* enabled, virtualization extensions related interfaces (main virtual
85
char *name;
122
* interface (s->vifaceiomem[0]) and virtual CPU interface).
86
uint64_t size;
123
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
87
124
index XXXXXXX..XXXXXXX 100644
88
if (!port->downstream) {
125
--- a/hw/intc/arm_gic_common.c
89
+ /*
126
+++ b/hw/intc/arm_gic_common.c
90
+ * Create dummy sysbus MMIO region so the sysbus region
127
@@ -XXX,XX +XXX,XX @@ static Property arm_gic_common_properties[] = {
91
+ * numbering doesn't get out of sync with the port numbers.
128
DEFINE_PROP_BOOL("has-security-extensions", GICState, security_extn, 0),
92
+ * The size is entirely arbitrary.
129
/* True if the GIC should implement the virtualization extensions */
93
+ */
130
DEFINE_PROP_BOOL("has-virtualization-extensions", GICState, virt_extn, 0),
94
+ name = g_strdup_printf("tz-ppc-dummy-port[%d]", i);
131
+ DEFINE_PROP_UINT32("num-priority-bits", GICState, n_prio_bits, 8),
95
+ memory_region_init_io(&port->upstream, obj, &tz_ppc_dummy_ops,
132
DEFINE_PROP_END_OF_LIST(),
96
+ port, name, 0x10000);
133
};
97
+ sysbus_init_mmio(sbd, &port->upstream);
98
+ g_free(name);
99
continue;
100
}
101
134
102
--
135
--
103
2.20.1
136
2.20.1
104
137
105
138
diff view generated by jsdifflib
1
The PL011 UART has six interrupt lines:
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
2
* RX (receive data)
3
* TX (transmit data)
4
* RT (receive timeout)
5
* MS (modem status)
6
* E (errors)
7
* combined (logical OR of all the above)
8
2
9
So far we have only emulated the combined interrupt line;
3
All A9 CPUs have a GIC with 5 bits of priority.
10
add support for the others, so that boards that wire them
11
up to different interrupt controller inputs can do so.
12
4
5
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 1582537164-764-3-git-send-email-sai.pavan.boddu@xilinx.com
8
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
---
11
---
16
include/hw/char/pl011.h | 2 +-
12
hw/cpu/a9mpcore.c | 4 ++++
17
hw/char/pl011.c | 46 +++++++++++++++++++++++++++++++++++++++--
13
1 file changed, 4 insertions(+)
18
2 files changed, 45 insertions(+), 3 deletions(-)
19
14
20
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
15
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/char/pl011.h
17
--- a/hw/cpu/a9mpcore.c
23
+++ b/include/hw/char/pl011.h
18
+++ b/hw/cpu/a9mpcore.c
24
@@ -XXX,XX +XXX,XX @@ typedef struct PL011State {
25
int read_count;
26
int read_trigger;
27
CharBackend chr;
28
- qemu_irq irq;
29
+ qemu_irq irq[6];
30
const unsigned char *id;
31
} PL011State;
32
33
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/char/pl011.c
36
+++ b/hw/char/pl011.c
37
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
38
* This code is licensed under the GPL.
20
#include "hw/qdev-properties.h"
39
*/
21
#include "hw/core/cpu.h"
40
22
41
+/*
23
+#define A9_GIC_NUM_PRIORITY_BITS 5
42
+ * QEMU interface:
43
+ * + sysbus MMIO region 0: device registers
44
+ * + sysbus IRQ 0: UARTINTR (combined interrupt line)
45
+ * + sysbus IRQ 1: UARTRXINTR (receive FIFO interrupt line)
46
+ * + sysbus IRQ 2: UARTTXINTR (transmit FIFO interrupt line)
47
+ * + sysbus IRQ 3: UARTRTINTR (receive timeout interrupt line)
48
+ * + sysbus IRQ 4: UARTMSINTR (momem status interrupt line)
49
+ * + sysbus IRQ 5: UARTEINTR (error interrupt line)
50
+ */
51
+
24
+
52
#include "qemu/osdep.h"
25
static void a9mp_priv_set_irq(void *opaque, int irq, int level)
53
#include "hw/char/pl011.h"
54
#include "hw/sysbus.h"
55
@@ -XXX,XX +XXX,XX @@
56
#define PL011_FLAG_TXFF 0x20
57
#define PL011_FLAG_RXFE 0x10
58
59
+/* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */
60
+#define INT_OE (1 << 10)
61
+#define INT_BE (1 << 9)
62
+#define INT_PE (1 << 8)
63
+#define INT_FE (1 << 7)
64
+#define INT_RT (1 << 6)
65
+#define INT_TX (1 << 5)
66
+#define INT_RX (1 << 4)
67
+#define INT_DSR (1 << 3)
68
+#define INT_DCD (1 << 2)
69
+#define INT_CTS (1 << 1)
70
+#define INT_RI (1 << 0)
71
+#define INT_E (INT_OE | INT_BE | INT_PE | INT_FE)
72
+#define INT_MS (INT_RI | INT_DSR | INT_DCD | INT_CTS)
73
+
74
static const unsigned char pl011_id_arm[8] =
75
{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
76
static const unsigned char pl011_id_luminary[8] =
77
{ 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
78
79
+/* Which bits in the interrupt status matter for each outbound IRQ line ? */
80
+static const uint32_t irqmask[] = {
81
+ INT_E | INT_MS | INT_RT | INT_TX | INT_RX, /* combined IRQ */
82
+ INT_RX,
83
+ INT_TX,
84
+ INT_RT,
85
+ INT_MS,
86
+ INT_E,
87
+};
88
+
89
static void pl011_update(PL011State *s)
90
{
26
{
91
uint32_t flags;
27
A9MPPrivState *s = (A9MPPrivState *)opaque;
92
+ int i;
28
@@ -XXX,XX +XXX,XX @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
93
29
gicdev = DEVICE(&s->gic);
94
flags = s->int_level & s->int_enabled;
30
qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
95
trace_pl011_irq_state(flags != 0);
31
qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
96
- qemu_set_irq(s->irq, flags != 0);
32
+ qdev_prop_set_uint32(gicdev, "num-priority-bits",
97
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
33
+ A9_GIC_NUM_PRIORITY_BITS);
98
+ qemu_set_irq(s->irq[i], (flags & irqmask[i]) != 0);
34
99
+ }
35
/* Make the GIC's TZ support match the CPUs. We assume that
100
}
36
* either all the CPUs have TZ, or none do.
101
102
static uint64_t pl011_read(void *opaque, hwaddr offset,
103
@@ -XXX,XX +XXX,XX @@ static void pl011_init(Object *obj)
104
{
105
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
106
PL011State *s = PL011(obj);
107
+ int i;
108
109
memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
110
sysbus_init_mmio(sbd, &s->iomem);
111
- sysbus_init_irq(sbd, &s->irq);
112
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
113
+ sysbus_init_irq(sbd, &s->irq[i]);
114
+ }
115
116
s->read_trigger = 1;
117
s->ifl = 0x12;
118
--
37
--
119
2.20.1
38
2.20.1
120
39
121
40
diff view generated by jsdifflib
New patch
1
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
1
2
3
The GIC built into the ARM11MPCore is always implemented with 4
4
priority bits; set the GIC property accordingly.
5
6
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 1582537164-764-4-git-send-email-sai.pavan.boddu@xilinx.com
9
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: tweaked commit message]
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/cpu/arm11mpcore.c | 5 +++++
15
1 file changed, 5 insertions(+)
16
17
diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/cpu/arm11mpcore.c
20
+++ b/hw/cpu/arm11mpcore.c
21
@@ -XXX,XX +XXX,XX @@
22
#include "hw/irq.h"
23
#include "hw/qdev-properties.h"
24
25
+#define ARM11MPCORE_NUM_GIC_PRIORITY_BITS 4
26
27
static void mpcore_priv_set_irq(void *opaque, int irq, int level)
28
{
29
@@ -XXX,XX +XXX,XX @@ static void mpcore_priv_realize(DeviceState *dev, Error **errp)
30
31
qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
32
qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
33
+ qdev_prop_set_uint32(gicdev, "num-priority-bits",
34
+ ARM11MPCORE_NUM_GIC_PRIORITY_BITS);
35
+
36
+
37
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
38
if (err != NULL) {
39
error_propagate(errp, err);
40
--
41
2.20.1
42
43
diff view generated by jsdifflib
1
From: Aaron Lindsay OS <aaron@os.amperecomputing.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This was introduced by
3
Use this in the places that were checking ARM_FEATURE_VFP, and
4
commit bf8d09694ccc07487cd73d7562081fdaec3370c8
4
are obviously testing for the existance of the register set
5
target/arm: Don't clear supported PMU events when initializing PMCEID1
5
as opposed to testing for some particular instruction extension.
6
and identified by Coverity (CID 1398645).
6
7
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
9
Reported-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20190219144621.450-1-aaron@os.amperecomputing.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20200224222232.13807-2-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
target/arm/helper.c | 2 +-
12
target/arm/cpu.h | 9 +++++++++
15
1 file changed, 1 insertion(+), 1 deletion(-)
13
hw/intc/armv7m_nvic.c | 20 ++++++++++----------
16
14
linux-user/arm/signal.c | 4 ++--
15
target/arm/arch_dump.c | 11 ++++++-----
16
target/arm/cpu.c | 4 ++--
17
target/arm/helper.c | 4 ++--
18
target/arm/m_helper.c | 11 ++++++-----
19
7 files changed, 37 insertions(+), 26 deletions(-)
20
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
26
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
27
}
28
29
+static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id)
30
+{
31
+ /*
32
+ * Return true if either VFP or SIMD is implemented.
33
+ * In this case, a minimum of VFP w/ D0-D15.
34
+ */
35
+ return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) > 0;
36
+}
37
+
38
static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id)
39
{
40
/* Return true if D16-D31 are implemented */
41
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/intc/armv7m_nvic.c
44
+++ b/hw/intc/armv7m_nvic.c
45
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
46
case 0xd84: /* CSSELR */
47
return cpu->env.v7m.csselr[attrs.secure];
48
case 0xd88: /* CPACR */
49
- if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
50
+ if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
51
return 0;
52
}
53
return cpu->env.v7m.cpacr[attrs.secure];
54
case 0xd8c: /* NSACR */
55
- if (!attrs.secure || !arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
56
+ if (!attrs.secure || !cpu_isar_feature(aa32_vfp_simd, cpu)) {
57
return 0;
58
}
59
return cpu->env.v7m.nsacr;
60
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
61
}
62
return cpu->env.v7m.sfar;
63
case 0xf34: /* FPCCR */
64
- if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
65
+ if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
66
return 0;
67
}
68
if (attrs.secure) {
69
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
70
return value;
71
}
72
case 0xf38: /* FPCAR */
73
- if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
74
+ if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
75
return 0;
76
}
77
return cpu->env.v7m.fpcar[attrs.secure];
78
case 0xf3c: /* FPDSCR */
79
- if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
80
+ if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
81
return 0;
82
}
83
return cpu->env.v7m.fpdscr[attrs.secure];
84
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
85
}
86
break;
87
case 0xd88: /* CPACR */
88
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
89
+ if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
90
/* We implement only the Floating Point extension's CP10/CP11 */
91
cpu->env.v7m.cpacr[attrs.secure] = value & (0xf << 20);
92
}
93
break;
94
case 0xd8c: /* NSACR */
95
- if (attrs.secure && arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
96
+ if (attrs.secure && cpu_isar_feature(aa32_vfp_simd, cpu)) {
97
/* We implement only the Floating Point extension's CP10/CP11 */
98
cpu->env.v7m.nsacr = value & (3 << 10);
99
}
100
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
101
break;
102
}
103
case 0xf34: /* FPCCR */
104
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
105
+ if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
106
/* Not all bits here are banked. */
107
uint32_t fpccr_s;
108
109
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
110
}
111
break;
112
case 0xf38: /* FPCAR */
113
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
114
+ if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
115
value &= ~7;
116
cpu->env.v7m.fpcar[attrs.secure] = value;
117
}
118
break;
119
case 0xf3c: /* FPDSCR */
120
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
121
+ if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
122
value &= 0x07c00000;
123
cpu->env.v7m.fpdscr[attrs.secure] = value;
124
}
125
diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/linux-user/arm/signal.c
128
+++ b/linux-user/arm/signal.c
129
@@ -XXX,XX +XXX,XX @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
130
setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
131
/* Save coprocessor signal frame. */
132
regspace = uc->tuc_regspace;
133
- if (arm_feature(env, ARM_FEATURE_VFP)) {
134
+ if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
135
regspace = setup_sigframe_v2_vfp(regspace, env);
136
}
137
if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
138
@@ -XXX,XX +XXX,XX @@ static int do_sigframe_return_v2(CPUARMState *env,
139
140
/* Restore coprocessor signal frame */
141
regspace = uc->tuc_regspace;
142
- if (arm_feature(env, ARM_FEATURE_VFP)) {
143
+ if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
144
regspace = restore_sigframe_v2_vfp(env, regspace);
145
if (!regspace) {
146
return 1;
147
diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c
148
index XXXXXXX..XXXXXXX 100644
149
--- a/target/arm/arch_dump.c
150
+++ b/target/arm/arch_dump.c
151
@@ -XXX,XX +XXX,XX @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
152
int cpuid, void *opaque)
153
{
154
struct arm_note note;
155
- CPUARMState *env = &ARM_CPU(cs)->env;
156
+ ARMCPU *cpu = ARM_CPU(cs);
157
+ CPUARMState *env = &cpu->env;
158
DumpState *s = opaque;
159
- int ret, i, fpvalid = !!arm_feature(env, ARM_FEATURE_VFP);
160
+ int ret, i;
161
+ bool fpvalid = cpu_isar_feature(aa32_vfp_simd, cpu);
162
163
arm_note_init(&note, s, "CORE", 5, NT_PRSTATUS, sizeof(note.prstatus));
164
165
@@ -XXX,XX +XXX,XX @@ int cpu_get_dump_info(ArchDumpInfo *info,
166
ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
167
{
168
ARMCPU *cpu = ARM_CPU(first_cpu);
169
- CPUARMState *env = &cpu->env;
170
size_t note_size;
171
172
if (class == ELFCLASS64) {
173
@@ -XXX,XX +XXX,XX @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
174
note_size += AARCH64_PRFPREG_NOTE_SIZE;
175
#ifdef TARGET_AARCH64
176
if (cpu_isar_feature(aa64_sve, cpu)) {
177
- note_size += AARCH64_SVE_NOTE_SIZE(env);
178
+ note_size += AARCH64_SVE_NOTE_SIZE(&cpu->env);
179
}
180
#endif
181
} else {
182
note_size = ARM_PRSTATUS_NOTE_SIZE;
183
- if (arm_feature(env, ARM_FEATURE_VFP)) {
184
+ if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
185
note_size += ARM_VFP_NOTE_SIZE;
186
}
187
}
188
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
189
index XXXXXXX..XXXXXXX 100644
190
--- a/target/arm/cpu.c
191
+++ b/target/arm/cpu.c
192
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
193
env->v7m.ccr[M_REG_S] |= R_V7M_CCR_UNALIGN_TRP_MASK;
194
}
195
196
- if (arm_feature(env, ARM_FEATURE_VFP)) {
197
+ if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
198
env->v7m.fpccr[M_REG_NS] = R_V7M_FPCCR_ASPEN_MASK;
199
env->v7m.fpccr[M_REG_S] = R_V7M_FPCCR_ASPEN_MASK |
200
R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK;
201
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
202
int numvfpregs = 0;
203
if (cpu_isar_feature(aa32_simd_r32, cpu)) {
204
numvfpregs = 32;
205
- } else if (arm_feature(env, ARM_FEATURE_VFP)) {
206
+ } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
207
numvfpregs = 16;
208
}
209
for (i = 0; i < numvfpregs; i++) {
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
210
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
211
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
212
--- a/target/arm/helper.c
20
+++ b/target/arm/helper.c
213
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu)
214
@@ -XXX,XX +XXX,XX @@ static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
22
215
* ASEDIS [31] and D32DIS [30] are both UNK/SBZP without VFP.
23
if (cnt->supported(&cpu->env)) {
216
* TRCDIS [28] is RAZ/WI since we do not implement a trace macrocell.
24
supported_event_map[cnt->number] = i;
217
*/
25
- uint64_t event_mask = 1 << (cnt->number & 0x1f);
218
- if (arm_feature(env, ARM_FEATURE_VFP)) {
26
+ uint64_t event_mask = 1ULL << (cnt->number & 0x1f);
219
+ if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
27
if (cnt->number & 0x20) {
220
/* VFP coprocessor: cp10 & cp11 [23:20] */
28
cpu->pmceid1 |= event_mask;
221
mask |= (1 << 31) | (1 << 30) | (0xf << 20);
29
} else {
222
223
@@ -XXX,XX +XXX,XX @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
224
} else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
225
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
226
35, "arm-vfp3.xml", 0);
227
- } else if (arm_feature(env, ARM_FEATURE_VFP)) {
228
+ } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
229
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
230
19, "arm-vfp.xml", 0);
231
}
232
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
233
index XXXXXXX..XXXXXXX 100644
234
--- a/target/arm/m_helper.c
235
+++ b/target/arm/m_helper.c
236
@@ -XXX,XX +XXX,XX @@ static uint32_t v7m_integrity_sig(CPUARMState *env, uint32_t lr)
237
*/
238
uint32_t sig = 0xfefa125a;
239
240
- if (!arm_feature(env, ARM_FEATURE_VFP) || (lr & R_V7M_EXCRET_FTYPE_MASK)) {
241
+ if (!cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))
242
+ || (lr & R_V7M_EXCRET_FTYPE_MASK)) {
243
sig |= 1;
244
}
245
return sig;
246
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
247
248
if (dotailchain) {
249
/* Sanitize LR FType and PREFIX bits */
250
- if (!arm_feature(env, ARM_FEATURE_VFP)) {
251
+ if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
252
lr |= R_V7M_EXCRET_FTYPE_MASK;
253
}
254
lr = deposit32(lr, 24, 8, 0xff);
255
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
256
257
ftype = excret & R_V7M_EXCRET_FTYPE_MASK;
258
259
- if (!arm_feature(env, ARM_FEATURE_VFP) && !ftype) {
260
+ if (!ftype && !cpu_isar_feature(aa32_vfp_simd, cpu)) {
261
qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero FTYPE in exception "
262
"exit PC value 0x%" PRIx32 " is UNPREDICTABLE "
263
"if FPU not present\n",
264
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
265
* SFPA is RAZ/WI from NS. FPCA is RO if NSACR.CP10 == 0,
266
* RES0 if the FPU is not present, and is stored in the S bank
267
*/
268
- if (arm_feature(env, ARM_FEATURE_VFP) &&
269
+ if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env)) &&
270
extract32(env->v7m.nsacr, 10, 1)) {
271
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
272
env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
273
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
274
env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
275
env->v7m.control[env->v7m.secure] |= val & R_V7M_CONTROL_NPRIV_MASK;
276
}
277
- if (arm_feature(env, ARM_FEATURE_VFP)) {
278
+ if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
279
/*
280
* SFPA is RAZ/WI from NS or if no FPU.
281
* FPCA is RO if NSACR.CP10 == 0, RES0 if the FPU is not present.
30
--
282
--
31
2.20.1
283
2.20.1
32
284
33
285
diff view generated by jsdifflib
1
The Musca boards have DAPLink firmware that sets the initial
1
From: Richard Henderson <richard.henderson@linaro.org>
2
secure VTOR value (the location of the vector table) differently
2
3
depending on the boot mode (from flash, from RAM, etc). Export
3
The old name, isar_feature_aa32_fpdp, does not reflect
4
the init-svtor as a QOM property of the ARMSSE object so that
4
that the test includes VFPv2. We will introduce another
5
the board can change it.
5
feature tests for VFPv3.
6
6
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200224222232.13807-3-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
---
11
include/hw/arm/armsse.h | 3 +++
12
target/arm/cpu.h | 4 ++--
12
hw/arm/armsse.c | 8 ++++----
13
target/arm/translate-vfp.inc.c | 40 +++++++++++++++++-----------------
13
2 files changed, 7 insertions(+), 4 deletions(-)
14
2 files changed, 22 insertions(+), 22 deletions(-)
14
15
15
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/armsse.h
18
--- a/target/arm/cpu.h
18
+++ b/include/hw/arm/armsse.h
19
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
20
* if necessary.)
21
return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0;
21
* + QOM property "SRAM_ADDR_WIDTH" sets the number of bits used for the
22
}
22
* address of each SRAM bank (and thus the total amount of internal SRAM)
23
23
+ * + QOM property "init-svtor" sets the initial value of the CPU SVTOR register
24
-static inline bool isar_feature_aa32_fpdp(const ARMISARegisters *id)
24
+ * (where it expects to load the PC and SP from the vector table on reset)
25
+static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id)
25
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
26
{
26
* which are wired to its NVIC lines 32 .. n+32
27
- /* Return true if CPU supports double precision floating point */
27
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
28
+ /* Return true if CPU supports double precision floating point, VFPv2 */
28
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
29
return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0;
29
uint32_t exp_numirq;
30
}
30
uint32_t mainclk_frq;
31
31
uint32_t sram_addr_width;
32
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
32
+ uint32_t init_svtor;
33
} ARMSSE;
34
35
typedef struct ARMSSEInfo ARMSSEInfo;
36
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
37
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/armsse.c
34
--- a/target/arm/translate-vfp.inc.c
39
+++ b/hw/arm/armsse.c
35
+++ b/target/arm/translate-vfp.inc.c
40
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
36
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
41
* the INITSVTOR* registers before powering up the CPUs in any case,
37
return false;
42
* so the hardware's default value doesn't matter. QEMU doesn't emulate
38
}
43
* the control processor, so instead we behave in the way that the
39
44
- * firmware does. All boards currently known about have firmware that
40
- if (dp && !dc_isar_feature(aa32_fpdp, s)) {
45
- * sets the INITSVTOR0 and INITSVTOR1 registers to 0x10000000, like the
41
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
46
- * IoTKit default. We can make this more configurable if necessary.
42
return false;
47
+ * firmware does. The initial value is configurable by the board code
43
}
48
+ * to match whatever its firmware does.
44
49
*/
45
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
50
- qdev_prop_set_uint32(cpudev, "init-svtor", 0x10000000);
46
return false;
51
+ qdev_prop_set_uint32(cpudev, "init-svtor", s->init_svtor);
47
}
52
/*
48
53
* Start all CPUs except CPU0 powered down. In real hardware it is
49
- if (dp && !dc_isar_feature(aa32_fpdp, s)) {
54
* a configurable property of the SSE-200 which CPUs start powered up
50
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
55
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
51
return false;
56
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
52
}
57
DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
53
58
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
54
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
59
+ DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
55
return false;
60
DEFINE_PROP_END_OF_LIST()
56
}
61
};
57
58
- if (dp && !dc_isar_feature(aa32_fpdp, s)) {
59
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
60
return false;
61
}
62
63
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
64
return false;
65
}
66
67
- if (dp && !dc_isar_feature(aa32_fpdp, s)) {
68
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
69
return false;
70
}
71
72
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
73
return false;
74
}
75
76
- if (!dc_isar_feature(aa32_fpdp, s)) {
77
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
78
return false;
79
}
80
81
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
82
return false;
83
}
84
85
- if (!dc_isar_feature(aa32_fpdp, s)) {
86
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
87
return false;
88
}
89
90
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
91
return false;
92
}
93
94
- if (!dc_isar_feature(aa32_fpdp, s)) {
95
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
96
return false;
97
}
98
99
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
100
return false;
101
}
102
103
- if (!dc_isar_feature(aa32_fpdp, s)) {
104
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
105
return false;
106
}
107
108
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
109
return false;
110
}
111
112
- if (!dc_isar_feature(aa32_fpdp, s)) {
113
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
114
return false;
115
}
116
117
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
118
return false;
119
}
120
121
- if (!dc_isar_feature(aa32_fpdp, s)) {
122
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
123
return false;
124
}
125
126
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
127
return false;
128
}
129
130
- if (!dc_isar_feature(aa32_fpdp, s)) {
131
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
132
return false;
133
}
134
135
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
136
return false;
137
}
138
139
- if (!dc_isar_feature(aa32_fpdp, s)) {
140
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
141
return false;
142
}
143
144
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
145
return false;
146
}
147
148
- if (!dc_isar_feature(aa32_fpdp, s)) {
149
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
150
return false;
151
}
152
153
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
154
return false;
155
}
156
157
- if (!dc_isar_feature(aa32_fpdp, s)) {
158
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
159
return false;
160
}
161
162
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
163
return false;
164
}
165
166
- if (!dc_isar_feature(aa32_fpdp, s)) {
167
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
168
return false;
169
}
170
171
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
172
return false;
173
}
174
175
- if (!dc_isar_feature(aa32_fpdp, s)) {
176
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
177
return false;
178
}
179
180
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
181
return false;
182
}
183
184
- if (!dc_isar_feature(aa32_fpdp, s)) {
185
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
186
return false;
187
}
188
189
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
190
return false;
191
}
192
193
- if (!dc_isar_feature(aa32_fpdp, s)) {
194
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
195
return false;
196
}
197
198
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
199
return false;
200
}
201
202
- if (!dc_isar_feature(aa32_fpdp, s)) {
203
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
204
return false;
205
}
206
207
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
208
return false;
209
}
210
211
- if (!dc_isar_feature(aa32_fpdp, s)) {
212
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
213
return false;
214
}
62
215
63
--
216
--
64
2.20.1
217
2.20.1
65
218
66
219
diff view generated by jsdifflib
1
The Musca board puts its SRAM and flash behind TrustZone
1
From: Richard Henderson <richard.henderson@linaro.org>
2
Memory Protection Controllers (MPCs). Each MPC sits between
3
the CPU and the RAM/flash, and also has a set of memory mapped
4
control registers. Wire up the MPCs, and the memory behind them.
5
For the moment we implement the flash as simple ROM, which
6
cannot be reprogrammed by the guest.
7
2
3
We will shortly use these to test for VFPv2 and VFPv3
4
in different situations.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200224222232.13807-4-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
10
---
11
hw/arm/musca.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++---
11
target/arm/cpu.h | 18 ++++++++++++++++++
12
1 file changed, 147 insertions(+), 8 deletions(-)
12
1 file changed, 18 insertions(+)
13
13
14
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/musca.c
16
--- a/target/arm/cpu.h
17
+++ b/hw/arm/musca.c
17
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
19
#include "hw/arm/armsse.h"
19
return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0;
20
#include "hw/boards.h"
21
#include "hw/core/split-irq.h"
22
+#include "hw/misc/tz-mpc.h"
23
#include "hw/misc/tz-ppc.h"
24
#include "hw/misc/unimp.h"
25
26
#define MUSCA_NUMIRQ_MAX 96
27
#define MUSCA_PPC_MAX 3
28
+#define MUSCA_MPC_MAX 5
29
+
30
+typedef struct MPCInfo MPCInfo;
31
32
typedef enum MuscaType {
33
MUSCA_A,
34
@@ -XXX,XX +XXX,XX @@ typedef struct {
35
uint32_t init_svtor;
36
int sram_addr_width;
37
int num_irqs;
38
+ const MPCInfo *mpc_info;
39
+ int num_mpcs;
40
} MuscaMachineClass;
41
42
typedef struct {
43
MachineState parent;
44
45
ARMSSE sse;
46
+ /* RAM and flash */
47
+ MemoryRegion ram[MUSCA_MPC_MAX];
48
SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
49
SplitIRQ sec_resp_splitter;
50
TZPPC ppc[MUSCA_PPC_MAX];
51
MemoryRegion container;
52
UnimplementedDeviceState eflash[2];
53
UnimplementedDeviceState qspi;
54
- UnimplementedDeviceState mpc[5];
55
+ TZMPC mpc[MUSCA_MPC_MAX];
56
UnimplementedDeviceState mhu[2];
57
UnimplementedDeviceState pwm[3];
58
UnimplementedDeviceState i2s;
59
@@ -XXX,XX +XXX,XX @@ typedef struct {
60
UnimplementedDeviceState pvt;
61
UnimplementedDeviceState sdio;
62
UnimplementedDeviceState gpio;
63
+ UnimplementedDeviceState cryptoisland;
64
} MuscaMachineState;
65
66
#define TYPE_MUSCA_MACHINE "musca"
67
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MuscaMachineState *mms,
68
return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
69
}
20
}
70
21
71
+typedef enum MPCInfoType {
22
+static inline bool isar_feature_aa32_fpsp_v2(const ARMISARegisters *id)
72
+ MPC_RAM,
73
+ MPC_ROM,
74
+ MPC_CRYPTOISLAND,
75
+} MPCInfoType;
76
+
77
+struct MPCInfo {
78
+ const char *name;
79
+ hwaddr addr;
80
+ hwaddr size;
81
+ MPCInfoType type;
82
+};
83
+
84
+/* Order of the MPCs here must match the order of the bits in SECMPCINTSTATUS */
85
+static const MPCInfo a_mpc_info[] = { {
86
+ .name = "qspi",
87
+ .type = MPC_ROM,
88
+ .addr = 0x00200000,
89
+ .size = 0x00800000,
90
+ }, {
91
+ .name = "sram",
92
+ .type = MPC_RAM,
93
+ .addr = 0x00000000,
94
+ .size = 0x00200000,
95
+ }
96
+};
97
+
98
+static const MPCInfo b1_mpc_info[] = { {
99
+ .name = "qspi",
100
+ .type = MPC_ROM,
101
+ .addr = 0x00000000,
102
+ .size = 0x02000000,
103
+ }, {
104
+ .name = "sram",
105
+ .type = MPC_RAM,
106
+ .addr = 0x0a400000,
107
+ .size = 0x00080000,
108
+ }, {
109
+ .name = "eflash0",
110
+ .type = MPC_ROM,
111
+ .addr = 0x0a000000,
112
+ .size = 0x00200000,
113
+ }, {
114
+ .name = "eflash1",
115
+ .type = MPC_ROM,
116
+ .addr = 0x0a200000,
117
+ .size = 0x00200000,
118
+ }, {
119
+ .name = "cryptoisland",
120
+ .type = MPC_CRYPTOISLAND,
121
+ .addr = 0x0a000000,
122
+ .size = 0x00200000,
123
+ }
124
+};
125
+
126
+static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque,
127
+ const char *name, hwaddr size)
128
+{
23
+{
129
+ /*
24
+ /* Return true if CPU supports single precision floating point, VFPv2 */
130
+ * Create an MPC and the RAM or flash behind it.
25
+ return FIELD_EX32(id->mvfr0, MVFR0, FPSP) > 0;
131
+ * MPC 0: eFlash 0
132
+ * MPC 1: eFlash 1
133
+ * MPC 2: SRAM
134
+ * MPC 3: QSPI flash
135
+ * MPC 4: CryptoIsland
136
+ * For now we implement the flash regions as ROM (ie not programmable)
137
+ * (with their control interface memory regions being unimplemented
138
+ * stubs behind the PPCs).
139
+ * The whole CryptoIsland region behind its MPC is an unimplemented stub.
140
+ */
141
+ MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms);
142
+ TZMPC *mpc = opaque;
143
+ int i = mpc - &mms->mpc[0];
144
+ MemoryRegion *downstream;
145
+ MemoryRegion *upstream;
146
+ UnimplementedDeviceState *uds;
147
+ char *mpcname;
148
+ const MPCInfo *mpcinfo = mmc->mpc_info;
149
+
150
+ mpcname = g_strdup_printf("%s-mpc", mpcinfo[i].name);
151
+
152
+ switch (mpcinfo[i].type) {
153
+ case MPC_ROM:
154
+ downstream = &mms->ram[i];
155
+ memory_region_init_rom(downstream, NULL, mpcinfo[i].name,
156
+ mpcinfo[i].size, &error_fatal);
157
+ break;
158
+ case MPC_RAM:
159
+ downstream = &mms->ram[i];
160
+ memory_region_init_ram(downstream, NULL, mpcinfo[i].name,
161
+ mpcinfo[i].size, &error_fatal);
162
+ break;
163
+ case MPC_CRYPTOISLAND:
164
+ /* We don't implement the CryptoIsland yet */
165
+ uds = &mms->cryptoisland;
166
+ sysbus_init_child_obj(OBJECT(mms), name, uds,
167
+ sizeof(UnimplementedDeviceState),
168
+ TYPE_UNIMPLEMENTED_DEVICE);
169
+ qdev_prop_set_string(DEVICE(uds), "name", mpcinfo[i].name);
170
+ qdev_prop_set_uint64(DEVICE(uds), "size", mpcinfo[i].size);
171
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
172
+ downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
173
+ break;
174
+ default:
175
+ g_assert_not_reached();
176
+ }
177
+
178
+ sysbus_init_child_obj(OBJECT(mms), mpcname, mpc, sizeof(mms->mpc[0]),
179
+ TYPE_TZ_MPC);
180
+ object_property_set_link(OBJECT(mpc), OBJECT(downstream),
181
+ "downstream", &error_fatal);
182
+ object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal);
183
+ /* Map the upstream end of the MPC into system memory */
184
+ upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
185
+ memory_region_add_subregion(get_system_memory(), mpcinfo[i].addr, upstream);
186
+ /* and connect its interrupt to the SSE-200 */
187
+ qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
188
+ qdev_get_gpio_in_named(DEVICE(&mms->sse),
189
+ "mpcexp_status", i));
190
+
191
+ g_free(mpcname);
192
+ /* Return the register interface MR for our caller to map behind the PPC */
193
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
194
+}
26
+}
195
+
27
+
196
static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
28
+static inline bool isar_feature_aa32_fpsp_v3(const ARMISARegisters *id)
197
const char *name, hwaddr size)
29
+{
30
+ /* Return true if CPU supports single precision floating point, VFPv3 */
31
+ return FIELD_EX32(id->mvfr0, MVFR0, FPSP) >= 2;
32
+}
33
+
34
static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id)
198
{
35
{
199
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
36
/* Return true if CPU supports double precision floating point, VFPv2 */
200
{ "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 },
37
return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0;
201
{ "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 },
202
{ "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 },
203
- { "mpc0", make_unimp_dev, &mms->mpc[0], 0x12000, 0x1000 },
204
- { "mpc1", make_unimp_dev, &mms->mpc[1], 0x13000, 0x1000 },
205
+ { "mpc0", make_mpc, &mms->mpc[0], 0x12000, 0x1000 },
206
+ { "mpc1", make_mpc, &mms->mpc[1], 0x13000, 0x1000 },
207
};
208
209
memory_region_init(container, OBJECT(mms), "musca-device-container", size);
210
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
211
int i;
212
213
assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
214
+ assert(mmc->num_mpcs <= MUSCA_MPC_MAX);
215
216
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
217
error_report("This board can only be used with CPU %s",
218
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
219
{ "eflash1", make_unimp_dev, &mms->eflash[1],
220
0x52500000, 0x1000 },
221
{ "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 },
222
- { "mpc0", make_unimp_dev, &mms->mpc[0], 0x52000000, 0x1000 },
223
- { "mpc1", make_unimp_dev, &mms->mpc[1], 0x52100000, 0x1000 },
224
- { "mpc2", make_unimp_dev, &mms->mpc[2], 0x52200000, 0x1000 },
225
- { "mpc3", make_unimp_dev, &mms->mpc[3], 0x52300000, 0x1000 },
226
+ { "mpc0", make_mpc, &mms->mpc[0], 0x52000000, 0x1000 },
227
+ { "mpc1", make_mpc, &mms->mpc[1], 0x52100000, 0x1000 },
228
+ { "mpc2", make_mpc, &mms->mpc[2], 0x52200000, 0x1000 },
229
+ { "mpc3", make_mpc, &mms->mpc[3], 0x52300000, 0x1000 },
230
{ "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 },
231
{ "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 },
232
{ }, /* port 9: unused */
233
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
234
{ }, /* port 11: unused */
235
{ }, /* port 12: unused */
236
{ }, /* port 13: unused */
237
- { "mpc4", make_unimp_dev, &mms->mpc[4], 0x52e00000, 0x1000 },
238
+ { "mpc4", make_mpc, &mms->mpc[4], 0x52e00000, 0x1000 },
239
},
240
}, {
241
.name = "apb_ppcexp1",
242
@@ -XXX,XX +XXX,XX @@ static void musca_a_class_init(ObjectClass *oc, void *data)
243
mmc->init_svtor = 0x10200000;
244
mmc->sram_addr_width = 15;
245
mmc->num_irqs = 64;
246
+ mmc->mpc_info = a_mpc_info;
247
+ mmc->num_mpcs = ARRAY_SIZE(a_mpc_info);
248
}
38
}
249
39
250
static void musca_b1_class_init(ObjectClass *oc, void *data)
40
+static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id)
251
@@ -XXX,XX +XXX,XX @@ static void musca_b1_class_init(ObjectClass *oc, void *data)
41
+{
252
mmc->init_svtor = 0x10000000;
42
+ /* Return true if CPU supports double precision floating point, VFPv3 */
253
mmc->sram_addr_width = 17;
43
+ return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2;
254
mmc->num_irqs = 96;
44
+}
255
+ mmc->mpc_info = b1_mpc_info;
45
+
256
+ mmc->num_mpcs = ARRAY_SIZE(b1_mpc_info);
46
/*
257
}
47
* We always set the FP and SIMD FP16 fields to indicate identical
258
48
* levels of support (assuming SIMD is implemented at all), so
259
static const TypeInfo musca_info = {
260
--
49
--
261
2.20.1
50
2.20.1
262
51
263
52
diff view generated by jsdifflib
1
Wire up the PL031 RTC for the Musca board.
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We cannot easily create "any" functions for these, because the
4
ID_AA64PFR0 fields for FP and SIMD signal "enabled" with zero.
5
Which means that an aarch32-only cpu will return incorrect results
6
when testing the aarch64 registers.
7
8
To use these, we must either have context or additionally test
9
vs ARM_FEATURE_AARCH64.
10
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20200224222232.13807-5-richard.henderson@linaro.org
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
15
---
6
hw/arm/musca.c | 26 +++++++++++++++++++++++---
16
target/arm/cpu.h | 11 +++++++++++
7
1 file changed, 23 insertions(+), 3 deletions(-)
17
target/arm/cpu.c | 9 ++++++---
18
target/arm/machine.c | 5 +++--
19
3 files changed, 20 insertions(+), 5 deletions(-)
8
20
9
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
10
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
11
--- a/hw/arm/musca.c
23
--- a/target/arm/cpu.h
12
+++ b/hw/arm/musca.c
24
+++ b/target/arm/cpu.h
13
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id)
14
#include "hw/misc/tz-mpc.h"
26
return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2;
15
#include "hw/misc/tz-ppc.h"
27
}
16
#include "hw/misc/unimp.h"
28
17
+#include "hw/timer/pl031.h"
29
+static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id)
18
19
#define MUSCA_NUMIRQ_MAX 96
20
#define MUSCA_PPC_MAX 3
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
22
UnimplementedDeviceState spi;
23
UnimplementedDeviceState scc;
24
UnimplementedDeviceState timer;
25
- UnimplementedDeviceState rtc;
26
+ PL031State rtc;
27
UnimplementedDeviceState pvt;
28
UnimplementedDeviceState sdio;
29
UnimplementedDeviceState gpio;
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
31
*/
32
#define SYSCLK_FRQ 40000000
33
34
+static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno)
35
+{
30
+{
36
+ /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
31
+ return isar_feature_aa32_fpsp_v2(id) || isar_feature_aa32_fpdp_v2(id);
37
+ assert(irqno < MUSCA_NUMIRQ_MAX);
38
+
39
+ return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
40
+}
32
+}
41
+
33
+
42
/*
34
/*
43
* Most of the devices in the Musca board sit behind Peripheral Protection
35
* We always set the FP and SIMD FP16 fields to indicate identical
44
* Controllers. These data structures define the layout of which devices
36
* levels of support (assuming SIMD is implemented at all), so
45
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque,
37
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id)
46
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
38
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2;
47
}
39
}
48
40
49
+static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque,
41
+static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id)
50
+ const char *name, hwaddr size)
51
+{
42
+{
52
+ PL031State *rtc = opaque;
43
+ /* We always set the AdvSIMD and FP fields identically. */
53
+
44
+ return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) != 0xf;
54
+ sysbus_init_child_obj(OBJECT(mms), name, rtc, sizeof(mms->rtc), TYPE_PL031);
55
+ object_property_set_bool(OBJECT(rtc), true, "realized", &error_fatal);
56
+ sysbus_connect_irq(SYS_BUS_DEVICE(rtc), 0, get_sse_irq_in(mms, 39));
57
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0);
58
+}
45
+}
59
+
46
+
60
static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
47
static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
61
const char *name, hwaddr size)
62
{
48
{
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
49
/* We always set the AdvSIMD and FP fields identically wrt FP16. */
64
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
50
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
65
{ "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 },
51
index XXXXXXX..XXXXXXX 100644
66
{ "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 },
52
--- a/target/arm/cpu.c
67
- { "rtc", make_unimp_dev, &mms->rtc, 0x8000, 0x1000 },
53
+++ b/target/arm/cpu.c
68
+ { "rtc", make_rtc, &mms->rtc, 0x8000, 0x1000 },
54
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
69
{ "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 },
55
* KVM does not currently allow us to lie to the guest about its
70
{ "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 },
56
* ID/feature registers, so the guest always sees what the host has.
71
{ "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 },
57
*/
72
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
58
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
73
{ "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
59
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)
74
{ "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 },
60
+ ? cpu_isar_feature(aa64_fp_simd, cpu)
75
{ "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 },
61
+ : cpu_isar_feature(aa32_vfp, cpu)) {
76
- { "rtc", make_unimp_dev, &mms->rtc, 0x4010d000, 0x1000 },
62
cpu->has_vfp = true;
77
+ { "rtc", make_rtc, &mms->rtc, 0x4010d000, 0x1000 },
63
if (!kvm_enabled()) {
78
{ "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 },
64
qdev_property_add_static(DEVICE(obj), &arm_cpu_has_vfp_property);
79
{ "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 },
65
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
80
},
66
* We rely on no XScale CPU having VFP so we can use the same bits in the
67
* TB flags field for VECSTRIDE and XSCALE_CPAR.
68
*/
69
- assert(!(arm_feature(env, ARM_FEATURE_VFP) &&
70
- arm_feature(env, ARM_FEATURE_XSCALE)));
71
+ assert(arm_feature(&cpu->env, ARM_FEATURE_AARCH64) ||
72
+ !cpu_isar_feature(aa32_vfp_simd, cpu) ||
73
+ !arm_feature(env, ARM_FEATURE_XSCALE));
74
75
if (arm_feature(env, ARM_FEATURE_V7) &&
76
!arm_feature(env, ARM_FEATURE_M) &&
77
diff --git a/target/arm/machine.c b/target/arm/machine.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/target/arm/machine.c
80
+++ b/target/arm/machine.c
81
@@ -XXX,XX +XXX,XX @@
82
static bool vfp_needed(void *opaque)
83
{
84
ARMCPU *cpu = opaque;
85
- CPUARMState *env = &cpu->env;
86
87
- return arm_feature(env, ARM_FEATURE_VFP);
88
+ return (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)
89
+ ? cpu_isar_feature(aa64_fp_simd, cpu)
90
+ : cpu_isar_feature(aa32_vfp_simd, cpu));
91
}
92
93
static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
81
--
94
--
82
2.20.1
95
2.20.1
83
96
84
97
diff view generated by jsdifflib
1
Coverity points out (CID 1398632, CID 1398650) that we
1
From: Richard Henderson <richard.henderson@linaro.org>
2
leak a couple of allocated strings in the error-exit
2
3
code path for setting up the MHUs in the ARMSSE.
3
Shuffle the order of the checks so that we test the ISA
4
Fix this bug by moving the allocate-and-free of each
4
before we test anything else, such as the register arguments.
5
string to be closer to the use, so we do the free before
5
6
doing the error-exit check.
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Fixes: f8574705f62b38a ("hw/arm/armsse: Add unimplemented-device stubs for MHUs")
8
Message-id: 20200224222232.13807-7-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Message-id: 20190215113707.24553-1-peter.maydell@linaro.org
12
---
10
---
13
hw/arm/armsse.c | 10 ++++++----
11
target/arm/translate-vfp.inc.c | 140 +++++++++++++++++----------------
14
1 file changed, 6 insertions(+), 4 deletions(-)
12
1 file changed, 71 insertions(+), 69 deletions(-)
15
13
16
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
14
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/armsse.c
16
--- a/target/arm/translate-vfp.inc.c
19
+++ b/hw/arm/armsse.c
17
+++ b/target/arm/translate-vfp.inc.c
20
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
18
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
21
19
return false;
22
if (info->has_mhus) {
20
}
23
for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
21
24
- char *name = g_strdup_printf("MHU%d", i);
22
- /* UNDEF accesses to D16-D31 if they don't exist */
25
- char *port = g_strdup_printf("port[%d]", i + 3);
23
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
26
+ char *name;
24
- ((a->vm | a->vn | a->vd) & 0x10)) {
27
+ char *port;
25
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
28
26
return false;
29
+ name = g_strdup_printf("MHU%d", i);
27
}
30
qdev_prop_set_string(DEVICE(&s->mhu[i]), "name", name);
28
31
qdev_prop_set_uint64(DEVICE(&s->mhu[i]), "size", 0x1000);
29
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
32
object_property_set_bool(OBJECT(&s->mhu[i]), true,
30
+ /* UNDEF accesses to D16-D31 if they don't exist */
33
"realized", &err);
31
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
34
+ g_free(name);
32
+ ((a->vm | a->vn | a->vd) & 0x10)) {
35
if (err) {
33
return false;
36
error_propagate(errp, err);
34
}
37
return;
35
38
}
36
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
39
+ port = g_strdup_printf("port[%d]", i + 3);
37
return false;
40
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mhu[i]), 0);
38
}
41
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr),
39
42
port, &err);
40
- /* UNDEF accesses to D16-D31 if they don't exist */
43
+ g_free(port);
41
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
44
if (err) {
42
- ((a->vm | a->vn | a->vd) & 0x10)) {
45
error_propagate(errp, err);
43
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
46
return;
44
return false;
47
}
45
}
48
- g_free(name);
46
49
- g_free(port);
47
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
50
}
48
+ /* UNDEF accesses to D16-D31 if they don't exist */
51
}
49
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
50
+ ((a->vm | a->vn | a->vd) & 0x10)) {
51
return false;
52
}
53
54
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
55
return false;
56
}
57
58
- /* UNDEF accesses to D16-D31 if they don't exist */
59
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
60
- ((a->vm | a->vd) & 0x10)) {
61
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
62
return false;
63
}
64
65
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
66
+ /* UNDEF accesses to D16-D31 if they don't exist */
67
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
68
+ ((a->vm | a->vd) & 0x10)) {
69
return false;
70
}
71
72
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
73
return false;
74
}
75
76
- /* UNDEF accesses to D16-D31 if they don't exist */
77
- if (dp && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
78
+ if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
79
return false;
80
}
81
82
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
83
+ /* UNDEF accesses to D16-D31 if they don't exist */
84
+ if (dp && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
85
return false;
86
}
87
88
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
89
TCGv_i64 f0, f1, fd;
90
TCGv_ptr fpst;
91
92
- /* UNDEF accesses to D16-D31 if they don't exist */
93
- if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vn | vm) & 0x10)) {
94
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
95
return false;
96
}
97
98
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
99
+ /* UNDEF accesses to D16-D31 if they don't exist */
100
+ if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vn | vm) & 0x10)) {
101
return false;
102
}
103
104
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
105
int veclen = s->vec_len;
106
TCGv_i64 f0, fd;
107
108
- /* UNDEF accesses to D16-D31 if they don't exist */
109
- if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vm) & 0x10)) {
110
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
111
return false;
112
}
113
114
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
115
+ /* UNDEF accesses to D16-D31 if they don't exist */
116
+ if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vm) & 0x10)) {
117
return false;
118
}
119
120
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
121
return false;
122
}
123
124
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
125
+ /* UNDEF accesses to D16-D31 if they don't exist. */
126
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
127
+ ((a->vd | a->vn | a->vm) & 0x10)) {
128
return false;
129
}
130
131
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
132
133
vd = a->vd;
134
135
- /* UNDEF accesses to D16-D31 if they don't exist. */
136
- if (!dc_isar_feature(aa32_simd_r32, s) && (vd & 0x10)) {
137
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
138
return false;
139
}
140
141
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
142
+ /* UNDEF accesses to D16-D31 if they don't exist. */
143
+ if (!dc_isar_feature(aa32_simd_r32, s) && (vd & 0x10)) {
144
return false;
145
}
146
147
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
148
{
149
TCGv_i64 vd, vm;
150
151
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
152
+ return false;
153
+ }
154
+
155
/* Vm/M bits must be zero for the Z variant */
156
if (a->z && a->vm != 0) {
157
return false;
158
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
159
return false;
160
}
161
162
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
163
- return false;
164
- }
165
-
166
if (!vfp_access_check(s)) {
167
return true;
168
}
169
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
170
TCGv_i32 tmp;
171
TCGv_i64 vd;
172
173
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
174
+ return false;
175
+ }
176
+
177
if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
178
return false;
179
}
180
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
181
return false;
182
}
183
184
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
185
- return false;
186
- }
187
-
188
if (!vfp_access_check(s)) {
189
return true;
190
}
191
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
192
TCGv_i32 tmp;
193
TCGv_i64 vm;
194
195
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
196
+ return false;
197
+ }
198
+
199
if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
200
return false;
201
}
202
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
203
return false;
204
}
205
206
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
207
- return false;
208
- }
209
-
210
if (!vfp_access_check(s)) {
211
return true;
212
}
213
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
214
TCGv_ptr fpst;
215
TCGv_i64 tmp;
216
217
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
218
+ return false;
219
+ }
220
+
221
if (!dc_isar_feature(aa32_vrint, s)) {
222
return false;
223
}
224
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
225
return false;
226
}
227
228
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
229
- return false;
230
- }
231
-
232
if (!vfp_access_check(s)) {
233
return true;
234
}
235
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
236
TCGv_i64 tmp;
237
TCGv_i32 tcg_rmode;
238
239
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
240
+ return false;
241
+ }
242
+
243
if (!dc_isar_feature(aa32_vrint, s)) {
244
return false;
245
}
246
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
247
return false;
248
}
249
250
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
251
- return false;
252
- }
253
-
254
if (!vfp_access_check(s)) {
255
return true;
256
}
257
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
258
TCGv_ptr fpst;
259
TCGv_i64 tmp;
260
261
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
262
+ return false;
263
+ }
264
+
265
if (!dc_isar_feature(aa32_vrint, s)) {
266
return false;
267
}
268
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
269
return false;
270
}
271
272
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
273
- return false;
274
- }
275
-
276
if (!vfp_access_check(s)) {
277
return true;
278
}
279
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
280
TCGv_i64 vd;
281
TCGv_i32 vm;
282
283
- /* UNDEF accesses to D16-D31 if they don't exist. */
284
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
285
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
286
return false;
287
}
288
289
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
290
+ /* UNDEF accesses to D16-D31 if they don't exist. */
291
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
292
return false;
293
}
294
295
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
296
TCGv_i64 vm;
297
TCGv_i32 vd;
298
299
- /* UNDEF accesses to D16-D31 if they don't exist. */
300
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
301
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
302
return false;
303
}
304
305
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
306
+ /* UNDEF accesses to D16-D31 if they don't exist. */
307
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
308
return false;
309
}
310
311
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
312
TCGv_i64 vd;
313
TCGv_ptr fpst;
314
315
- /* UNDEF accesses to D16-D31 if they don't exist. */
316
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
317
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
318
return false;
319
}
320
321
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
322
+ /* UNDEF accesses to D16-D31 if they don't exist. */
323
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
324
return false;
325
}
326
327
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
328
TCGv_i32 vd;
329
TCGv_i64 vm;
330
331
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
332
+ return false;
333
+ }
334
+
335
if (!dc_isar_feature(aa32_jscvt, s)) {
336
return false;
337
}
338
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
339
return false;
340
}
341
342
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
343
- return false;
344
- }
345
-
346
if (!vfp_access_check(s)) {
347
return true;
348
}
349
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
350
TCGv_ptr fpst;
351
int frac_bits;
352
353
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
354
+ return false;
355
+ }
356
+
357
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
358
return false;
359
}
360
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
361
return false;
362
}
363
364
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
365
- return false;
366
- }
367
-
368
if (!vfp_access_check(s)) {
369
return true;
370
}
371
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
372
TCGv_i64 vm;
373
TCGv_ptr fpst;
374
375
- /* UNDEF accesses to D16-D31 if they don't exist. */
376
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
377
+ if (!dc_isar_feature(aa32_fpdp_v2, s)) {
378
return false;
379
}
380
381
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
382
+ /* UNDEF accesses to D16-D31 if they don't exist. */
383
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
384
return false;
385
}
52
386
53
--
387
--
54
2.20.1
388
2.20.1
55
389
56
390
diff view generated by jsdifflib
1
Convert the debug printing in the PL031 device to use trace events,
1
From: Richard Henderson <richard.henderson@linaro.org>
2
and augment it to cover the interesting parts of device operation.
3
2
3
Sort this check to the start of a trans_* function.
4
Merge this with any existing test for fpdp_v2.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200224222232.13807-8-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
10
---
8
hw/timer/pl031.c | 55 +++++++++++++++++++++++--------------------
11
target/arm/translate-vfp.inc.c | 24 ++++++++----------------
9
hw/timer/trace-events | 6 +++++
12
1 file changed, 8 insertions(+), 16 deletions(-)
10
2 files changed, 36 insertions(+), 25 deletions(-)
11
13
12
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
14
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/timer/pl031.c
16
--- a/target/arm/translate-vfp.inc.c
15
+++ b/hw/timer/pl031.c
17
+++ b/target/arm/translate-vfp.inc.c
16
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
17
#include "sysemu/sysemu.h"
19
* VFPv2 allows access to FPSID from userspace; VFPv3 restricts
18
#include "qemu/cutils.h"
20
* all ID registers to privileged access only.
19
#include "qemu/log.h"
21
*/
22
- if (IS_USER(s) && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
23
+ if (IS_USER(s) && dc_isar_feature(aa32_fpsp_v3, s)) {
24
return false;
25
}
26
ignore_vfp_enabled = true;
27
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
28
case ARM_VFP_FPINST:
29
case ARM_VFP_FPINST2:
30
/* Not present in VFPv3 */
31
- if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
32
+ if (IS_USER(s) || dc_isar_feature(aa32_fpsp_v3, s)) {
33
return false;
34
}
35
break;
36
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
37
38
vd = a->vd;
39
40
- if (!dc_isar_feature(aa32_fpshvec, s) &&
41
- (veclen != 0 || s->vec_stride != 0)) {
42
+ if (!dc_isar_feature(aa32_fpsp_v3, s)) {
43
return false;
44
}
45
46
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
47
+ if (!dc_isar_feature(aa32_fpshvec, s) &&
48
+ (veclen != 0 || s->vec_stride != 0)) {
49
return false;
50
}
51
52
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
53
54
vd = a->vd;
55
56
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
57
+ if (!dc_isar_feature(aa32_fpdp_v3, s)) {
58
return false;
59
}
60
61
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
62
return false;
63
}
64
65
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
66
- return false;
67
- }
20
-
68
-
21
-//#define DEBUG_PL031
69
if (!vfp_access_check(s)) {
70
return true;
71
}
72
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
73
TCGv_ptr fpst;
74
int frac_bits;
75
76
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
77
+ if (!dc_isar_feature(aa32_fpsp_v3, s)) {
78
return false;
79
}
80
81
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
82
TCGv_ptr fpst;
83
int frac_bits;
84
85
- if (!dc_isar_feature(aa32_fpdp_v2, s)) {
86
- return false;
87
- }
22
-
88
-
23
-#ifdef DEBUG_PL031
89
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
24
-#define DPRINTF(fmt, ...) \
90
+ if (!dc_isar_feature(aa32_fpdp_v3, s)) {
25
-do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
91
return false;
26
-#else
27
-#define DPRINTF(fmt, ...) do {} while(0)
28
-#endif
29
+#include "trace.h"
30
31
#define RTC_DR 0x00 /* Data read register */
32
#define RTC_MR 0x04 /* Match register */
33
@@ -XXX,XX +XXX,XX @@ static const unsigned char pl031_id[] = {
34
35
static void pl031_update(PL031State *s)
36
{
37
- qemu_set_irq(s->irq, s->is & s->im);
38
+ uint32_t flags = s->is & s->im;
39
+
40
+ trace_pl031_irq_state(flags);
41
+ qemu_set_irq(s->irq, flags);
42
}
43
44
static void pl031_interrupt(void * opaque)
45
@@ -XXX,XX +XXX,XX @@ static void pl031_interrupt(void * opaque)
46
PL031State *s = (PL031State *)opaque;
47
48
s->is = 1;
49
- DPRINTF("Alarm raised\n");
50
+ trace_pl031_alarm_raised();
51
pl031_update(s);
52
}
53
54
@@ -XXX,XX +XXX,XX @@ static void pl031_set_alarm(PL031State *s)
55
/* The timer wraps around. This subtraction also wraps in the same way,
56
and gives correct results when alarm < now_ticks. */
57
ticks = s->mr - pl031_get_count(s);
58
- DPRINTF("Alarm set in %ud ticks\n", ticks);
59
+ trace_pl031_set_alarm(ticks);
60
if (ticks == 0) {
61
timer_del(s->timer);
62
pl031_interrupt(s);
63
@@ -XXX,XX +XXX,XX @@ static uint64_t pl031_read(void *opaque, hwaddr offset,
64
unsigned size)
65
{
66
PL031State *s = (PL031State *)opaque;
67
-
68
- if (offset >= 0xfe0 && offset < 0x1000)
69
- return pl031_id[(offset - 0xfe0) >> 2];
70
+ uint64_t r;
71
72
switch (offset) {
73
case RTC_DR:
74
- return pl031_get_count(s);
75
+ r = pl031_get_count(s);
76
+ break;
77
case RTC_MR:
78
- return s->mr;
79
+ r = s->mr;
80
+ break;
81
case RTC_IMSC:
82
- return s->im;
83
+ r = s->im;
84
+ break;
85
case RTC_RIS:
86
- return s->is;
87
+ r = s->is;
88
+ break;
89
case RTC_LR:
90
- return s->lr;
91
+ r = s->lr;
92
+ break;
93
case RTC_CR:
94
/* RTC is permanently enabled. */
95
- return 1;
96
+ r = 1;
97
+ break;
98
case RTC_MIS:
99
- return s->is & s->im;
100
+ r = s->is & s->im;
101
+ break;
102
+ case 0xfe0 ... 0xfff:
103
+ r = pl031_id[(offset - 0xfe0) >> 2];
104
+ break;
105
case RTC_ICR:
106
qemu_log_mask(LOG_GUEST_ERROR,
107
"pl031: read of write-only register at offset 0x%x\n",
108
(int)offset);
109
+ r = 0;
110
break;
111
default:
112
qemu_log_mask(LOG_GUEST_ERROR,
113
"pl031_read: Bad offset 0x%x\n", (int)offset);
114
+ r = 0;
115
break;
116
}
92
}
117
93
118
- return 0;
119
+ trace_pl031_read(offset, r);
120
+ return r;
121
}
122
123
static void pl031_write(void * opaque, hwaddr offset,
124
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
125
{
126
PL031State *s = (PL031State *)opaque;
127
128
+ trace_pl031_write(offset, value);
129
130
switch (offset) {
131
case RTC_LR:
132
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
133
break;
134
case RTC_IMSC:
135
s->im = value & 1;
136
- DPRINTF("Interrupt mask %d\n", s->im);
137
pl031_update(s);
138
break;
139
case RTC_ICR:
140
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
141
cleared when bit 0 of the written value is set. However the
142
arm926e documentation (DDI0287B) states that the interrupt is
143
cleared when any value is written. */
144
- DPRINTF("Interrupt cleared");
145
s->is = 0;
146
pl031_update(s);
147
break;
148
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
149
index XXXXXXX..XXXXXXX 100644
150
--- a/hw/timer/trace-events
151
+++ b/hw/timer/trace-events
152
@@ -XXX,XX +XXX,XX @@ xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec
153
nrf51_timer_read(uint64_t addr, uint32_t value, unsigned size) "read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
154
nrf51_timer_write(uint64_t addr, uint32_t value, unsigned size) "write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
155
156
+# hw/timer/pl031.c
157
+pl031_irq_state(int level) "irq state %d"
158
+pl031_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
159
+pl031_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
160
+pl031_alarm_raised(void) "alarm raised"
161
+pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks"
162
--
94
--
163
2.20.1
95
2.20.1
164
96
165
97
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
We will eventually remove the early ARM_FEATURE_VFP test,
4
so add a proper test for each trans_* that does not already
5
have another ISA test.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200224222232.13807-9-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate-vfp.inc.c | 78 ++++++++++++++++++++++++++++++----
13
1 file changed, 69 insertions(+), 9 deletions(-)
14
15
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-vfp.inc.c
18
+++ b/target/arm/translate-vfp.inc.c
19
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
20
int pass;
21
uint32_t offset;
22
23
+ /* SIZE == 2 is a VFP instruction; otherwise NEON. */
24
+ if (a->size == 2
25
+ ? !dc_isar_feature(aa32_fpsp_v2, s)
26
+ : !arm_dc_feature(s, ARM_FEATURE_NEON)) {
27
+ return false;
28
+ }
29
+
30
/* UNDEF accesses to D16-D31 if they don't exist */
31
if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
32
return false;
33
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
34
pass = extract32(offset, 2, 1);
35
offset = extract32(offset, 0, 2) * 8;
36
37
- if (a->size != 2 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
38
- return false;
39
- }
40
-
41
if (!vfp_access_check(s)) {
42
return true;
43
}
44
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
45
int pass;
46
uint32_t offset;
47
48
+ /* SIZE == 2 is a VFP instruction; otherwise NEON. */
49
+ if (a->size == 2
50
+ ? !dc_isar_feature(aa32_fpsp_v2, s)
51
+ : !arm_dc_feature(s, ARM_FEATURE_NEON)) {
52
+ return false;
53
+ }
54
+
55
/* UNDEF accesses to D16-D31 if they don't exist */
56
if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
57
return false;
58
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
59
pass = extract32(offset, 2, 1);
60
offset = extract32(offset, 0, 2) * 8;
61
62
- if (a->size != 2 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
63
- return false;
64
- }
65
-
66
if (!vfp_access_check(s)) {
67
return true;
68
}
69
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
70
TCGv_i32 tmp;
71
bool ignore_vfp_enabled = false;
72
73
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
74
+ return false;
75
+ }
76
+
77
if (arm_dc_feature(s, ARM_FEATURE_M)) {
78
/*
79
* The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
80
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a)
81
{
82
TCGv_i32 tmp;
83
84
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
85
+ return false;
86
+ }
87
+
88
if (!vfp_access_check(s)) {
89
return true;
90
}
91
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_sp(DisasContext *s, arg_VMOV_64_sp *a)
92
{
93
TCGv_i32 tmp;
94
95
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
96
+ return false;
97
+ }
98
+
99
/*
100
* VMOV between two general-purpose registers and two single precision
101
* floating point registers
102
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_dp *a)
103
104
/*
105
* VMOV between two general-purpose registers and one double precision
106
- * floating point register
107
+ * floating point register. Note that this does not require support
108
+ * for double precision arithmetic.
109
*/
110
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
111
+ return false;
112
+ }
113
114
/* UNDEF accesses to D16-D31 if they don't exist */
115
if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
116
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a)
117
uint32_t offset;
118
TCGv_i32 addr, tmp;
119
120
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
121
+ return false;
122
+ }
123
+
124
if (!vfp_access_check(s)) {
125
return true;
126
}
127
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a)
128
TCGv_i32 addr;
129
TCGv_i64 tmp;
130
131
+ /* Note that this does not require support for double arithmetic. */
132
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
133
+ return false;
134
+ }
135
+
136
/* UNDEF accesses to D16-D31 if they don't exist */
137
if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
138
return false;
139
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_sp(DisasContext *s, arg_VLDM_VSTM_sp *a)
140
TCGv_i32 addr, tmp;
141
int i, n;
142
143
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
144
+ return false;
145
+ }
146
+
147
n = a->imm;
148
149
if (n == 0 || (a->vd + n) > 32) {
150
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
151
TCGv_i64 tmp;
152
int i, n;
153
154
+ /* Note that this does not require support for double arithmetic. */
155
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
156
+ return false;
157
+ }
158
+
159
n = a->imm >> 1;
160
161
if (n == 0 || (a->vd + n) > 32 || n > 16) {
162
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn,
163
TCGv_i32 f0, f1, fd;
164
TCGv_ptr fpst;
165
166
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
167
+ return false;
168
+ }
169
+
170
if (!dc_isar_feature(aa32_fpshvec, s) &&
171
(veclen != 0 || s->vec_stride != 0)) {
172
return false;
173
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
174
int veclen = s->vec_len;
175
TCGv_i32 f0, fd;
176
177
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
178
+ return false;
179
+ }
180
+
181
if (!dc_isar_feature(aa32_fpshvec, s) &&
182
(veclen != 0 || s->vec_stride != 0)) {
183
return false;
184
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a)
185
{
186
TCGv_i32 vd, vm;
187
188
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
189
+ return false;
190
+ }
191
+
192
/* Vm/M bits must be zero for the Z variant */
193
if (a->z && a->vm != 0) {
194
return false;
195
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a)
196
TCGv_i32 vm;
197
TCGv_ptr fpst;
198
199
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
200
+ return false;
201
+ }
202
+
203
if (!vfp_access_check(s)) {
204
return true;
205
}
206
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a)
207
TCGv_i32 vm;
208
TCGv_ptr fpst;
209
210
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
211
+ return false;
212
+ }
213
+
214
if (!vfp_access_check(s)) {
215
return true;
216
}
217
--
218
2.20.1
219
220
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
All remaining tests for VFP4 are for fused multiply-add insns.
4
5
Since the MVFR1 field is used for both VFP and NEON, move its adjustment
6
from the !has_neon block to the (!has_vfp && !has_neon) block.
7
8
Test for vfp of the appropraite width alongside the test for simdfmac
9
within translate-vfp.inc.c. Within disas_neon_data_insn, we have
10
already tested for ARM_FEATURE_NEON.
11
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20190215192302.27855-5-richard.henderson@linaro.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
[PMM: fixed a couple of comment typos]
14
Message-id: 20200224222232.13807-10-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
16
---
9
target/arm/cpu.h | 10 +++++
17
target/arm/cpu.h | 12 ++++++++++++
10
target/arm/helper.h | 3 ++
18
target/arm/cpu.c | 6 +++++-
11
target/arm/cpu.c | 1 +
19
target/arm/translate-vfp.inc.c | 22 ++++++++++++++++++----
12
target/arm/cpu64.c | 2 +
20
target/arm/translate.c | 2 +-
13
target/arm/translate-a64.c | 26 +++++++++++
21
4 files changed, 36 insertions(+), 6 deletions(-)
14
target/arm/translate.c | 10 +++++
15
target/arm/vfp_helper.c | 88 ++++++++++++++++++++++++++++++++++++++
16
7 files changed, 140 insertions(+)
17
22
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
23
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
25
--- a/target/arm/cpu.h
21
+++ b/target/arm/cpu.h
26
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id)
27
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id)
23
return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0;
28
return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1;
24
}
29
}
25
30
26
+static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id)
31
+/*
32
+ * Note that this ID register field covers both VFP and Neon FMAC,
33
+ * so should usually be tested in combination with some other
34
+ * check that confirms the presence of whichever of VFP or Neon is
35
+ * relevant, to avoid accidentally enabling a Neon feature on
36
+ * a VFP-no-Neon core or vice-versa.
37
+ */
38
+static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id)
27
+{
39
+{
28
+ return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0;
40
+ return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0;
29
+}
41
+}
30
+
42
+
31
static inline bool isar_feature_aa32_dp(const ARMISARegisters *id)
43
static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id)
32
{
44
{
33
return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0;
45
return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1;
34
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_dp(const ARMISARegisters *id)
35
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0;
36
}
37
38
+static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
39
+{
40
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
41
+}
42
+
43
static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
44
{
45
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0;
46
diff --git a/target/arm/helper.h b/target/arm/helper.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/helper.h
49
+++ b/target/arm/helper.h
50
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(rintd_exact, TCG_CALL_NO_RWG, f64, f64, ptr)
51
DEF_HELPER_FLAGS_2(rints, TCG_CALL_NO_RWG, f32, f32, ptr)
52
DEF_HELPER_FLAGS_2(rintd, TCG_CALL_NO_RWG, f64, f64, ptr)
53
54
+DEF_HELPER_FLAGS_2(vjcvt, TCG_CALL_NO_RWG, i32, f64, env)
55
+DEF_HELPER_FLAGS_2(fjcvtzs, TCG_CALL_NO_RWG, i64, f64, ptr)
56
+
57
/* neon_helper.c */
58
DEF_HELPER_FLAGS_3(neon_qadd_u8, TCG_CALL_NO_RWG, i32, env, i32, i32)
59
DEF_HELPER_FLAGS_3(neon_qadd_s8, TCG_CALL_NO_RWG, i32, env, i32, i32)
60
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
46
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
61
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/cpu.c
48
--- a/target/arm/cpu.c
63
+++ b/target/arm/cpu.c
49
+++ b/target/arm/cpu.c
64
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
50
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
65
cpu->isar.id_isar5 = t;
51
u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
66
52
u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
67
t = cpu->isar.id_isar6;
53
u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
68
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
54
- u = FIELD_DP32(u, MVFR1, SIMDFMAC, 0);
69
t = FIELD_DP32(t, ID_ISAR6, DP, 1);
55
cpu->isar.mvfr1 = u;
70
cpu->isar.id_isar6 = t;
56
71
57
u = cpu->isar.mvfr2;
72
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
58
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
59
u = cpu->isar.mvfr0;
60
u = FIELD_DP32(u, MVFR0, SIMDREG, 0);
61
cpu->isar.mvfr0 = u;
62
+
63
+ /* Despite the name, this field covers both VFP and Neon */
64
+ u = cpu->isar.mvfr1;
65
+ u = FIELD_DP32(u, MVFR1, SIMDFMAC, 0);
66
+ cpu->isar.mvfr1 = u;
67
}
68
69
if (arm_feature(env, ARM_FEATURE_M) && !cpu->has_dsp) {
70
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
73
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
74
--- a/target/arm/cpu64.c
72
--- a/target/arm/translate-vfp.inc.c
75
+++ b/target/arm/cpu64.c
73
+++ b/target/arm/translate-vfp.inc.c
76
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
74
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
77
cpu->isar.id_aa64isar0 = t;
75
78
76
/*
79
t = cpu->isar.id_aa64isar1;
77
* Present in VFPv4 only.
80
+ t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
78
+ * Note that we can't rely on the SIMDFMAC check alone, because
81
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
79
+ * in a Neon-no-VFP core that ID register field will be non-zero.
82
t = FIELD_DP64(t, ID_AA64ISAR1, APA, 1); /* PAuth, architected only */
80
+ */
83
t = FIELD_DP64(t, ID_AA64ISAR1, API, 0);
81
+ if (!dc_isar_feature(aa32_simdfmac, s) ||
84
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
82
+ !dc_isar_feature(aa32_fpsp_v2, s)) {
85
cpu->isar.id_isar5 = u;
83
+ return false;
86
84
+ }
87
u = cpu->isar.id_isar6;
85
+ /*
88
+ u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1);
86
* In v7A, UNPREDICTABLE with non-zero vector length/stride; from
89
u = FIELD_DP32(u, ID_ISAR6, DP, 1);
87
* v8A, must UNDEF. We choose to UNDEF for both v7A and v8A.
90
cpu->isar.id_isar6 = u;
88
*/
91
89
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4) ||
92
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
90
- (s->vec_len != 0 || s->vec_stride != 0)) {
93
index XXXXXXX..XXXXXXX 100644
91
+ if (s->vec_len != 0 || s->vec_stride != 0) {
94
--- a/target/arm/translate-a64.c
92
return false;
95
+++ b/target/arm/translate-a64.c
96
@@ -XXX,XX +XXX,XX @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
97
}
93
}
98
}
94
99
95
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
100
+static void handle_fjcvtzs(DisasContext *s, int rd, int rn)
96
101
+{
97
/*
102
+ TCGv_i64 t = read_fp_dreg(s, rn);
98
* Present in VFPv4 only.
103
+ TCGv_ptr fpstatus = get_fpstatus_ptr(false);
99
+ * Note that we can't rely on the SIMDFMAC check alone, because
104
+
100
+ * in a Neon-no-VFP core that ID register field will be non-zero.
105
+ gen_helper_fjcvtzs(t, t, fpstatus);
101
+ */
106
+
102
+ if (!dc_isar_feature(aa32_simdfmac, s) ||
107
+ tcg_temp_free_ptr(fpstatus);
103
+ !dc_isar_feature(aa32_fpdp_v2, s)) {
108
+
104
+ return false;
109
+ tcg_gen_ext32u_i64(cpu_reg(s, rd), t);
105
+ }
110
+ tcg_gen_extrh_i64_i32(cpu_ZF, t);
106
+ /*
111
+ tcg_gen_movi_i32(cpu_CF, 0);
107
* In v7A, UNPREDICTABLE with non-zero vector length/stride; from
112
+ tcg_gen_movi_i32(cpu_NF, 0);
108
* v8A, must UNDEF. We choose to UNDEF for both v7A and v8A.
113
+ tcg_gen_movi_i32(cpu_VF, 0);
109
*/
114
+
110
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4) ||
115
+ tcg_temp_free_i64(t);
111
- (s->vec_len != 0 || s->vec_stride != 0)) {
116
+}
112
+ if (s->vec_len != 0 || s->vec_stride != 0) {
117
+
113
return false;
118
/* Floating point <-> integer conversions
114
}
119
* 31 30 29 28 24 23 22 21 20 19 18 16 15 10 9 5 4 0
115
120
* +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
121
@@ -XXX,XX +XXX,XX @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
122
handle_fmov(s, rd, rn, type, itof);
123
break;
124
125
+ case 0b00111110: /* FJCVTZS */
126
+ if (!dc_isar_feature(aa64_jscvt, s)) {
127
+ goto do_unallocated;
128
+ } else if (fp_access_check(s)) {
129
+ handle_fjcvtzs(s, rd, rn);
130
+ }
131
+ break;
132
+
133
default:
134
do_unallocated:
135
unallocated_encoding(s);
136
diff --git a/target/arm/translate.c b/target/arm/translate.c
116
diff --git a/target/arm/translate.c b/target/arm/translate.c
137
index XXXXXXX..XXXXXXX 100644
117
index XXXXXXX..XXXXXXX 100644
138
--- a/target/arm/translate.c
118
--- a/target/arm/translate.c
139
+++ b/target/arm/translate.c
119
+++ b/target/arm/translate.c
140
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
120
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
141
rm_is_dp = false;
121
}
142
break;
122
break;
143
123
case NEON_3R_VFM_VQRDMLSH:
144
+ case 0x13: /* vjcvt */
124
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
145
+ if (!dp || !dc_isar_feature(aa32_jscvt, s)) {
125
+ if (!dc_isar_feature(aa32_simdfmac, s)) {
146
+ return 1;
126
return 1;
147
+ }
127
}
148
+ rd_is_dp = false;
128
break;
149
+ break;
150
+
151
default:
152
return 1;
153
}
154
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
155
case 17: /* fsito */
156
gen_vfp_sito(dp, 0);
157
break;
158
+ case 19: /* vjcvt */
159
+ gen_helper_vjcvt(cpu_F0s, cpu_F0d, cpu_env);
160
+ break;
161
case 20: /* fshto */
162
gen_vfp_shto(dp, 16 - rm, 0);
163
break;
164
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/target/arm/vfp_helper.c
167
+++ b/target/arm/vfp_helper.c
168
@@ -XXX,XX +XXX,XX @@ int arm_rmode_to_sf(int rmode)
169
}
170
return rmode;
171
}
172
+
173
+/*
174
+ * Implement float64 to int32_t conversion without saturation;
175
+ * the result is supplied modulo 2^32.
176
+ */
177
+uint64_t HELPER(fjcvtzs)(float64 value, void *vstatus)
178
+{
179
+ float_status *status = vstatus;
180
+ uint32_t exp, sign;
181
+ uint64_t frac;
182
+ uint32_t inexact = 1; /* !Z */
183
+
184
+ sign = extract64(value, 63, 1);
185
+ exp = extract64(value, 52, 11);
186
+ frac = extract64(value, 0, 52);
187
+
188
+ if (exp == 0) {
189
+ /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */
190
+ inexact = sign;
191
+ if (frac != 0) {
192
+ if (status->flush_inputs_to_zero) {
193
+ float_raise(float_flag_input_denormal, status);
194
+ } else {
195
+ float_raise(float_flag_inexact, status);
196
+ inexact = 1;
197
+ }
198
+ }
199
+ frac = 0;
200
+ } else if (exp == 0x7ff) {
201
+ /* This operation raises Invalid for both NaN and overflow (Inf). */
202
+ float_raise(float_flag_invalid, status);
203
+ frac = 0;
204
+ } else {
205
+ int true_exp = exp - 1023;
206
+ int shift = true_exp - 52;
207
+
208
+ /* Restore implicit bit. */
209
+ frac |= 1ull << 52;
210
+
211
+ /* Shift the fraction into place. */
212
+ if (shift >= 0) {
213
+ /* The number is so large we must shift the fraction left. */
214
+ if (shift >= 64) {
215
+ /* The fraction is shifted out entirely. */
216
+ frac = 0;
217
+ } else {
218
+ frac <<= shift;
219
+ }
220
+ } else if (shift > -64) {
221
+ /* Normal case -- shift right and notice if bits shift out. */
222
+ inexact = (frac << (64 + shift)) != 0;
223
+ frac >>= -shift;
224
+ } else {
225
+ /* The fraction is shifted out entirely. */
226
+ frac = 0;
227
+ }
228
+
229
+ /* Notice overflow or inexact exceptions. */
230
+ if (true_exp > 31 || frac > (sign ? 0x80000000ull : 0x7fffffff)) {
231
+ /* Overflow, for which this operation raises invalid. */
232
+ float_raise(float_flag_invalid, status);
233
+ inexact = 1;
234
+ } else if (inexact) {
235
+ float_raise(float_flag_inexact, status);
236
+ }
237
+
238
+ /* Honor the sign. */
239
+ if (sign) {
240
+ frac = -frac;
241
+ }
242
+ }
243
+
244
+ /* Pack the result and the env->ZF representation of Z together. */
245
+ return deposit64(frac, 32, 32, inexact);
246
+}
247
+
248
+uint32_t HELPER(vjcvt)(float64 value, CPUARMState *env)
249
+{
250
+ uint64_t pair = HELPER(fjcvtzs)(value, &env->vfp.fp_status);
251
+ uint32_t result = pair;
252
+ uint32_t z = (pair >> 32) == 0;
253
+
254
+ /* Store Z, clear NCV, in FPSCR.NZCV. */
255
+ env->vfp.xregs[ARM_VFP_FPSCR]
256
+ = (env->vfp.xregs[ARM_VFP_FPSCR] & ~CPSR_NZCV) | (z * CPSR_Z);
257
+
258
+ return result;
259
+}
260
--
129
--
261
2.20.1
130
2.20.1
262
131
263
132
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
We now have proper ISA checks within each trans_* function.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200224222232.13807-11-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/translate.c | 4 ----
11
1 file changed, 4 deletions(-)
12
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
16
+++ b/target/arm/translate.c
17
@@ -XXX,XX +XXX,XX @@ static void gen_neon_dup_high16(TCGv_i32 var)
18
*/
19
static int disas_vfp_insn(DisasContext *s, uint32_t insn)
20
{
21
- if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
22
- return 1;
23
- }
24
-
25
/*
26
* If the decodetree decoder handles this insn it will always
27
* emit code to either execute the insn or generate an appropriate
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Now that we no longer have an early check for ARM_FEATURE_VFP,
4
we can use the proper ISA check in trans_VLLDM_VLSTM.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20200224222232.13807-12-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/translate-vfp.inc.c | 39 +++++++++++++++++++++++++
12
target/arm/translate.c | 53 ++++++----------------------------
13
target/arm/vfp.decode | 2 ++
14
3 files changed, 50 insertions(+), 44 deletions(-)
15
16
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-vfp.inc.c
19
+++ b/target/arm/translate-vfp.inc.c
20
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
21
tcg_temp_free_ptr(fpst);
22
return true;
23
}
24
+
25
+/*
26
+ * Decode VLLDM and VLSTM are nonstandard because:
27
+ * * if there is no FPU then these insns must NOP in
28
+ * Secure state and UNDEF in Nonsecure state
29
+ * * if there is an FPU then these insns do not have
30
+ * the usual behaviour that vfp_access_check() provides of
31
+ * being controlled by CPACR/NSACR enable bits or the
32
+ * lazy-stacking logic.
33
+ */
34
+static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
35
+{
36
+ TCGv_i32 fptr;
37
+
38
+ if (!arm_dc_feature(s, ARM_FEATURE_M) ||
39
+ !arm_dc_feature(s, ARM_FEATURE_V8)) {
40
+ return false;
41
+ }
42
+ /* If not secure, UNDEF. */
43
+ if (!s->v8m_secure) {
44
+ return false;
45
+ }
46
+ /* If no fpu, NOP. */
47
+ if (!dc_isar_feature(aa32_vfp, s)) {
48
+ return true;
49
+ }
50
+
51
+ fptr = load_reg(s, a->rn);
52
+ if (a->l) {
53
+ gen_helper_v7m_vlldm(cpu_env, fptr);
54
+ } else {
55
+ gen_helper_v7m_vlstm(cpu_env, fptr);
56
+ }
57
+ tcg_temp_free_i32(fptr);
58
+
59
+ /* End the TB, because we have updated FP control bits */
60
+ s->base.is_jmp = DISAS_UPDATE;
61
+ return true;
62
+}
63
diff --git a/target/arm/translate.c b/target/arm/translate.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate.c
66
+++ b/target/arm/translate.c
67
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
68
goto illegal_op; /* op0 = 0b11 : unallocated */
69
}
70
71
- /*
72
- * Decode VLLDM and VLSTM first: these are nonstandard because:
73
- * * if there is no FPU then these insns must NOP in
74
- * Secure state and UNDEF in Nonsecure state
75
- * * if there is an FPU then these insns do not have
76
- * the usual behaviour that disas_vfp_insn() provides of
77
- * being controlled by CPACR/NSACR enable bits or the
78
- * lazy-stacking logic.
79
- */
80
- if (arm_dc_feature(s, ARM_FEATURE_V8) &&
81
- (insn & 0xffa00f00) == 0xec200a00) {
82
- /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
83
- * - VLLDM, VLSTM
84
- * We choose to UNDEF if the RAZ bits are non-zero.
85
- */
86
- if (!s->v8m_secure || (insn & 0x0040f0ff)) {
87
+ if (disas_vfp_insn(s, insn)) {
88
+ if (((insn >> 8) & 0xe) == 10 &&
89
+ dc_isar_feature(aa32_fpsp_v2, s)) {
90
+ /* FP, and the CPU supports it */
91
goto illegal_op;
92
+ } else {
93
+ /* All other insns: NOCP */
94
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
95
+ syn_uncategorized(),
96
+ default_exception_el(s));
97
}
98
-
99
- if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
100
- uint32_t rn = (insn >> 16) & 0xf;
101
- TCGv_i32 fptr = load_reg(s, rn);
102
-
103
- if (extract32(insn, 20, 1)) {
104
- gen_helper_v7m_vlldm(cpu_env, fptr);
105
- } else {
106
- gen_helper_v7m_vlstm(cpu_env, fptr);
107
- }
108
- tcg_temp_free_i32(fptr);
109
-
110
- /* End the TB, because we have updated FP control bits */
111
- s->base.is_jmp = DISAS_UPDATE;
112
- }
113
- break;
114
}
115
- if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
116
- ((insn >> 8) & 0xe) == 10) {
117
- /* FP, and the CPU supports it */
118
- if (disas_vfp_insn(s, insn)) {
119
- goto illegal_op;
120
- }
121
- break;
122
- }
123
-
124
- /* All other insns: NOCP */
125
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized(),
126
- default_exception_el(s));
127
break;
128
}
129
if ((insn & 0xfe000a00) == 0xfc000800
130
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
131
index XXXXXXX..XXXXXXX 100644
132
--- a/target/arm/vfp.decode
133
+++ b/target/arm/vfp.decode
134
@@ -XXX,XX +XXX,XX @@ VCVT_sp_int ---- 1110 1.11 110 s:1 .... 1010 rz:1 1.0 .... \
135
vd=%vd_sp vm=%vm_sp
136
VCVT_dp_int ---- 1110 1.11 110 s:1 .... 1011 rz:1 1.0 .... \
137
vd=%vd_sp vm=%vm_dp
138
+
139
+VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
140
--
141
2.20.1
142
143
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
There are lots of special cases within these insns. Split the
3
Have the calls adjacent as an intermediate step toward
4
major argument decode/loading/saving into no_output (compares),
4
actually merging the decodes.
5
rd_is_dp, and rm_is_dp.
6
7
We still need to special case argument load for compare (rd as
8
input, rm as zero) and vcvt fixed (rd as input+output), but lots
9
of special cases do disappear.
10
11
Now that we have a full switch at the beginning, hoist the ISA
12
checks from the code generation.
13
5
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20190215192302.27855-4-richard.henderson@linaro.org
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20200224222232.13807-13-richard.henderson@linaro.org
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
10
---
19
target/arm/translate.c | 227 ++++++++++++++++++++---------------------
11
target/arm/translate.c | 83 +++++++++++++++---------------------------
20
1 file changed, 111 insertions(+), 116 deletions(-)
12
1 file changed, 29 insertions(+), 54 deletions(-)
21
13
22
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
23
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/translate.c
16
--- a/target/arm/translate.c
25
+++ b/target/arm/translate.c
17
+++ b/target/arm/translate.c
26
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static void gen_neon_dup_high16(TCGv_i32 var)
19
tcg_temp_free_i32(tmp);
20
}
21
22
-/*
23
- * Disassemble a VFP instruction. Returns nonzero if an error occurred
24
- * (ie. an undefined instruction).
25
- */
26
-static int disas_vfp_insn(DisasContext *s, uint32_t insn)
27
-{
28
- /*
29
- * If the decodetree decoder handles this insn it will always
30
- * emit code to either execute the insn or generate an appropriate
31
- * exception; so we don't need to ever return non-zero to tell
32
- * the calling code to emit an UNDEF exception.
33
- */
34
- if (extract32(insn, 28, 4) == 0xf) {
35
- if (disas_vfp_uncond(s, insn)) {
36
- return 0;
37
- }
38
- } else {
39
- if (disas_vfp(s, insn)) {
40
- return 0;
41
- }
42
- }
43
- /* If the decodetree decoder didn't handle this insn, it must be UNDEF */
44
- return 1;
45
-}
46
-
47
static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
48
{
49
#ifndef CONFIG_USER_ONLY
50
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
51
ARCH(5);
52
53
/* Unconditional instructions. */
54
- if (disas_a32_uncond(s, insn)) {
55
+ /* TODO: Perhaps merge these into one decodetree output file. */
56
+ if (disas_a32_uncond(s, insn) ||
57
+ disas_vfp_uncond(s, insn)) {
58
return;
59
}
60
/* fall back to legacy decoder */
61
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
27
}
62
}
63
return;
64
}
65
- if ((insn & 0x0f000e10) == 0x0e000a00) {
66
- /* VFP. */
67
- if (disas_vfp_insn(s, insn)) {
68
- goto illegal_op;
69
- }
70
- return;
71
- }
72
if ((insn & 0x0e000f00) == 0x0c000100) {
73
if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
74
/* iWMMXt register transfer. */
75
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
76
arm_skip_unless(s, cond);
77
}
78
79
- if (disas_a32(s, insn)) {
80
+ /* TODO: Perhaps merge these into one decodetree output file. */
81
+ if (disas_a32(s, insn) ||
82
+ disas_vfp(s, insn)) {
83
return;
84
}
85
/* fall back to legacy decoder */
86
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
87
case 0xd:
88
case 0xe:
89
if (((insn >> 8) & 0xe) == 10) {
90
- /* VFP. */
91
- if (disas_vfp_insn(s, insn)) {
92
- goto illegal_op;
93
- }
94
- } else if (disas_coproc_insn(s, insn)) {
95
+ /* VFP, but failed disas_vfp. */
96
+ goto illegal_op;
97
+ }
98
+ if (disas_coproc_insn(s, insn)) {
99
/* Coprocessor. */
100
goto illegal_op;
101
}
102
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
103
ARCH(6T2);
104
}
105
106
- if (disas_t32(s, insn)) {
107
+ /*
108
+ * TODO: Perhaps merge these into one decodetree output file.
109
+ * Note disas_vfp is written for a32 with cond field in the
110
+ * top nibble. The t32 encoding requires 0xe in the top nibble.
111
+ */
112
+ if (disas_t32(s, insn) ||
113
+ disas_vfp_uncond(s, insn) ||
114
+ ((insn >> 28) == 0xe && disas_vfp(s, insn))) {
115
return;
116
}
117
/* fall back to legacy decoder */
118
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
119
goto illegal_op; /* op0 = 0b11 : unallocated */
120
}
121
122
- if (disas_vfp_insn(s, insn)) {
123
- if (((insn >> 8) & 0xe) == 10 &&
124
- dc_isar_feature(aa32_fpsp_v2, s)) {
125
- /* FP, and the CPU supports it */
126
- goto illegal_op;
127
- } else {
128
- /* All other insns: NOCP */
129
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
130
- syn_uncategorized(),
131
- default_exception_el(s));
132
- }
133
+ if (((insn >> 8) & 0xe) == 10 &&
134
+ dc_isar_feature(aa32_fpsp_v2, s)) {
135
+ /* FP, and the CPU supports it */
136
+ goto illegal_op;
137
+ } else {
138
+ /* All other insns: NOCP */
139
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
140
+ syn_uncategorized(),
141
+ default_exception_el(s));
142
}
143
break;
144
}
145
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
146
goto illegal_op;
147
}
148
} else if (((insn >> 8) & 0xe) == 10) {
149
- if (disas_vfp_insn(s, insn)) {
150
- goto illegal_op;
151
- }
152
+ /* VFP, but failed disas_vfp. */
153
+ goto illegal_op;
28
} else {
154
} else {
29
/* data processing */
155
if (insn & (1 << 28))
30
+ bool rd_is_dp = dp;
156
goto illegal_op;
31
+ bool rm_is_dp = dp;
32
+ bool no_output = false;
33
+
34
/* The opcode is in bits 23, 21, 20 and 6. */
35
op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
36
- if (dp) {
37
- if (op == 15) {
38
- /* rn is opcode */
39
- rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
40
- } else {
41
- /* rn is register number */
42
- VFP_DREG_N(rn, insn);
43
- }
44
+ rn = VFP_SREG_N(insn);
45
46
- if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
47
- ((rn & 0x1e) == 0x6))) {
48
- /* Integer or single/half precision destination. */
49
- rd = VFP_SREG_D(insn);
50
- } else {
51
- VFP_DREG_D(rd, insn);
52
- }
53
- if (op == 15 &&
54
- (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
55
- ((rn & 0x1e) == 0x4))) {
56
- /* VCVT from int or half precision is always from S reg
57
- * regardless of dp bit. VCVT with immediate frac_bits
58
- * has same format as SREG_M.
59
+ if (op == 15) {
60
+ /* rn is opcode, encoded as per VFP_SREG_N. */
61
+ switch (rn) {
62
+ case 0x00: /* vmov */
63
+ case 0x01: /* vabs */
64
+ case 0x02: /* vneg */
65
+ case 0x03: /* vsqrt */
66
+ break;
67
+
68
+ case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
69
+ case 0x05: /* vcvtt.f64.f16, vcvtt.f32.f16 */
70
+ /*
71
+ * VCVTB, VCVTT: only present with the halfprec extension
72
+ * UNPREDICTABLE if bit 8 is set prior to ARMv8
73
+ * (we choose to UNDEF)
74
*/
75
- rm = VFP_SREG_M(insn);
76
- } else {
77
- VFP_DREG_M(rm, insn);
78
+ if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
79
+ !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
80
+ return 1;
81
+ }
82
+ rm_is_dp = false;
83
+ break;
84
+ case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
85
+ case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
86
+ if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
87
+ !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
88
+ return 1;
89
+ }
90
+ rd_is_dp = false;
91
+ break;
92
+
93
+ case 0x08: case 0x0a: /* vcmp, vcmpz */
94
+ case 0x09: case 0x0b: /* vcmpe, vcmpez */
95
+ no_output = true;
96
+ break;
97
+
98
+ case 0x0c: /* vrintr */
99
+ case 0x0d: /* vrintz */
100
+ case 0x0e: /* vrintx */
101
+ break;
102
+
103
+ case 0x0f: /* vcvt double<->single */
104
+ rd_is_dp = !dp;
105
+ break;
106
+
107
+ case 0x10: /* vcvt.fxx.u32 */
108
+ case 0x11: /* vcvt.fxx.s32 */
109
+ rm_is_dp = false;
110
+ break;
111
+ case 0x18: /* vcvtr.u32.fxx */
112
+ case 0x19: /* vcvtz.u32.fxx */
113
+ case 0x1a: /* vcvtr.s32.fxx */
114
+ case 0x1b: /* vcvtz.s32.fxx */
115
+ rd_is_dp = false;
116
+ break;
117
+
118
+ case 0x14: /* vcvt fp <-> fixed */
119
+ case 0x15:
120
+ case 0x16:
121
+ case 0x17:
122
+ case 0x1c:
123
+ case 0x1d:
124
+ case 0x1e:
125
+ case 0x1f:
126
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
127
+ return 1;
128
+ }
129
+ /* Immediate frac_bits has same format as SREG_M. */
130
+ rm_is_dp = false;
131
+ break;
132
+
133
+ default:
134
+ return 1;
135
}
136
+ } else if (dp) {
137
+ /* rn is register number */
138
+ VFP_DREG_N(rn, insn);
139
+ }
140
+
141
+ if (rd_is_dp) {
142
+ VFP_DREG_D(rd, insn);
143
+ } else {
144
+ rd = VFP_SREG_D(insn);
145
+ }
146
+ if (rm_is_dp) {
147
+ VFP_DREG_M(rm, insn);
148
} else {
149
- rn = VFP_SREG_N(insn);
150
- if (op == 15 && rn == 15) {
151
- /* Double precision destination. */
152
- VFP_DREG_D(rd, insn);
153
- } else {
154
- rd = VFP_SREG_D(insn);
155
- }
156
- /* NB that we implicitly rely on the encoding for the frac_bits
157
- * in VCVT of fixed to float being the same as that of an SREG_M
158
- */
159
rm = VFP_SREG_M(insn);
160
}
161
162
veclen = s->vec_len;
163
- if (op == 15 && rn > 3)
164
+ if (op == 15 && rn > 3) {
165
veclen = 0;
166
+ }
167
168
/* Shut up compiler warnings. */
169
delta_m = 0;
170
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
171
/* Load the initial operands. */
172
if (op == 15) {
173
switch (rn) {
174
- case 16:
175
- case 17:
176
- /* Integer source */
177
- gen_mov_F0_vreg(0, rm);
178
- break;
179
- case 8:
180
- case 9:
181
- /* Compare */
182
+ case 0x08: case 0x09: /* Compare */
183
gen_mov_F0_vreg(dp, rd);
184
gen_mov_F1_vreg(dp, rm);
185
break;
186
- case 10:
187
- case 11:
188
- /* Compare with zero */
189
+ case 0x0a: case 0x0b: /* Compare with zero */
190
gen_mov_F0_vreg(dp, rd);
191
gen_vfp_F1_ld0(dp);
192
break;
193
- case 20:
194
- case 21:
195
- case 22:
196
- case 23:
197
- case 28:
198
- case 29:
199
- case 30:
200
- case 31:
201
+ case 0x14: /* vcvt fp <-> fixed */
202
+ case 0x15:
203
+ case 0x16:
204
+ case 0x17:
205
+ case 0x1c:
206
+ case 0x1d:
207
+ case 0x1e:
208
+ case 0x1f:
209
/* Source and destination the same. */
210
gen_mov_F0_vreg(dp, rd);
211
break;
212
- case 4:
213
- case 5:
214
- case 6:
215
- case 7:
216
- /* VCVTB, VCVTT: only present with the halfprec extension
217
- * UNPREDICTABLE if bit 8 is set prior to ARMv8
218
- * (we choose to UNDEF)
219
- */
220
- if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
221
- !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
222
- return 1;
223
- }
224
- if (!extract32(rn, 1, 1)) {
225
- /* Half precision source. */
226
- gen_mov_F0_vreg(0, rm);
227
- break;
228
- }
229
- /* Otherwise fall through */
230
default:
231
/* One source operand. */
232
- gen_mov_F0_vreg(dp, rm);
233
+ gen_mov_F0_vreg(rm_is_dp, rm);
234
break;
235
}
236
} else {
237
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
238
break;
239
}
240
case 15: /* single<->double conversion */
241
- if (dp)
242
+ if (dp) {
243
gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
244
- else
245
+ } else {
246
gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
247
+ }
248
break;
249
case 16: /* fuito */
250
gen_vfp_uito(dp, 0);
251
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
252
gen_vfp_sito(dp, 0);
253
break;
254
case 20: /* fshto */
255
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
256
- return 1;
257
- }
258
gen_vfp_shto(dp, 16 - rm, 0);
259
break;
260
case 21: /* fslto */
261
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
262
- return 1;
263
- }
264
gen_vfp_slto(dp, 32 - rm, 0);
265
break;
266
case 22: /* fuhto */
267
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
268
- return 1;
269
- }
270
gen_vfp_uhto(dp, 16 - rm, 0);
271
break;
272
case 23: /* fulto */
273
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
274
- return 1;
275
- }
276
gen_vfp_ulto(dp, 32 - rm, 0);
277
break;
278
case 24: /* ftoui */
279
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
280
gen_vfp_tosiz(dp, 0);
281
break;
282
case 28: /* ftosh */
283
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
284
- return 1;
285
- }
286
gen_vfp_tosh(dp, 16 - rm, 0);
287
break;
288
case 29: /* ftosl */
289
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
290
- return 1;
291
- }
292
gen_vfp_tosl(dp, 32 - rm, 0);
293
break;
294
case 30: /* ftouh */
295
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
296
- return 1;
297
- }
298
gen_vfp_touh(dp, 16 - rm, 0);
299
break;
300
case 31: /* ftoul */
301
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
302
- return 1;
303
- }
304
gen_vfp_toul(dp, 32 - rm, 0);
305
break;
306
default: /* undefined */
307
- return 1;
308
+ g_assert_not_reached();
309
}
310
break;
311
default: /* undefined */
312
return 1;
313
}
314
315
- /* Write back the result. */
316
- if (op == 15 && (rn >= 8 && rn <= 11)) {
317
- /* Comparison, do nothing. */
318
- } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
319
- (rn & 0x1e) == 0x6)) {
320
- /* VCVT double to int: always integer result.
321
- * VCVT double to half precision is always a single
322
- * precision result.
323
- */
324
- gen_mov_vreg_F0(0, rd);
325
- } else if (op == 15 && rn == 15) {
326
- /* conversion */
327
- gen_mov_vreg_F0(!dp, rd);
328
- } else {
329
- gen_mov_vreg_F0(dp, rd);
330
+ /* Write back the result, if any. */
331
+ if (!no_output) {
332
+ gen_mov_vreg_F0(rd_is_dp, rd);
333
}
334
335
/* break out of the loop if we have finished */
336
- if (veclen == 0)
337
+ if (veclen == 0) {
338
break;
339
+ }
340
341
if (op == 15 && delta_m == 0) {
342
/* single source one-many */
343
--
157
--
344
2.20.1
158
2.20.1
345
159
346
160
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Use isar feature tests instead of feature bit tests.
4
5
Although none of QEMUs current cpus have VFPv3 without D32,
6
replace the large comment explaining why with one line that
7
sets ARM_HWCAP_ARM_VFPv3D16 under the correct conditions.
8
Mirror the test sequence used in the linux kernel.
9
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20200224222232.13807-14-richard.henderson@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
linux-user/elfload.c | 23 +++++++++++++----------
16
1 file changed, 13 insertions(+), 10 deletions(-)
17
18
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/linux-user/elfload.c
21
+++ b/linux-user/elfload.c
22
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
23
24
/* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */
25
GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP);
26
- GET_FEATURE(ARM_FEATURE_VFP, ARM_HWCAP_ARM_VFP);
27
GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT);
28
GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE);
29
GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON);
30
- GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPv3);
31
GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS);
32
- GET_FEATURE(ARM_FEATURE_VFP4, ARM_HWCAP_ARM_VFPv4);
33
+ GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE);
34
GET_FEATURE_ID(aa32_arm_div, ARM_HWCAP_ARM_IDIVA);
35
GET_FEATURE_ID(aa32_thumb_div, ARM_HWCAP_ARM_IDIVT);
36
- /* All QEMU's VFPv3 CPUs have 32 registers, see VFP_DREG in translate.c.
37
- * Note that the ARM_HWCAP_ARM_VFPv3D16 bit is always the inverse of
38
- * ARM_HWCAP_ARM_VFPD32 (and so always clear for QEMU); it is unrelated
39
- * to our VFP_FP16 feature bit.
40
- */
41
- GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPD32);
42
- GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE);
43
+ GET_FEATURE_ID(aa32_vfp, ARM_HWCAP_ARM_VFP);
44
+
45
+ if (cpu_isar_feature(aa32_fpsp_v3, cpu) ||
46
+ cpu_isar_feature(aa32_fpdp_v3, cpu)) {
47
+ hwcaps |= ARM_HWCAP_ARM_VFPv3;
48
+ if (cpu_isar_feature(aa32_simd_r32, cpu)) {
49
+ hwcaps |= ARM_HWCAP_ARM_VFPD32;
50
+ } else {
51
+ hwcaps |= ARM_HWCAP_ARM_VFPv3D16;
52
+ }
53
+ }
54
+ GET_FEATURE_ID(aa32_simdfmac, ARM_HWCAP_ARM_VFPv4);
55
56
return hwcaps;
57
}
58
--
59
2.20.1
60
61
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
We have converted all tests against these features
4
to ISAR tests.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200224222232.13807-15-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/cpu.h | 3 ---
12
target/arm/cpu.c | 25 -------------------------
13
target/arm/cpu64.c | 3 ---
14
target/arm/kvm32.c | 5 -----
15
target/arm/kvm64.c | 1 -
16
5 files changed, 37 deletions(-)
17
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
21
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ QEMU_BUILD_BUG_ON(ARRAY_SIZE(((ARMCPU *)0)->ccsidr) <= R_V7M_CSSELR_INDEX_MASK);
23
* mapping in linux-user/elfload.c:get_elf_hwcap().
24
*/
25
enum arm_features {
26
- ARM_FEATURE_VFP,
27
ARM_FEATURE_AUXCR, /* ARM1026 Auxiliary control register. */
28
ARM_FEATURE_XSCALE, /* Intel XScale extensions. */
29
ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension. */
30
@@ -XXX,XX +XXX,XX @@ enum arm_features {
31
ARM_FEATURE_V7,
32
ARM_FEATURE_THUMB2,
33
ARM_FEATURE_PMSA, /* no MMU; may have Memory Protection Unit */
34
- ARM_FEATURE_VFP3,
35
ARM_FEATURE_NEON,
36
ARM_FEATURE_M, /* Microcontroller profile. */
37
ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */
38
@@ -XXX,XX +XXX,XX @@ enum arm_features {
39
ARM_FEATURE_V5,
40
ARM_FEATURE_STRONGARM,
41
ARM_FEATURE_VAPA, /* cp15 VA to PA lookups */
42
- ARM_FEATURE_VFP4, /* VFPv4 (implies that NEON is v2) */
43
ARM_FEATURE_GENERIC_TIMER,
44
ARM_FEATURE_MVFR, /* Media and VFP Feature Registers 0 and 1 */
45
ARM_FEATURE_DUMMY_C15_REGS, /* RAZ/WI all of cp15 crn=15 */
46
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu.c
49
+++ b/target/arm/cpu.c
50
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
51
if (arm_feature(&cpu->env, ARM_FEATURE_M)) {
52
set_feature(&cpu->env, ARM_FEATURE_PMSA);
53
}
54
- /* Similarly for the VFP feature bits */
55
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP4)) {
56
- set_feature(&cpu->env, ARM_FEATURE_VFP3);
57
- }
58
- if (arm_feature(&cpu->env, ARM_FEATURE_VFP3)) {
59
- set_feature(&cpu->env, ARM_FEATURE_VFP);
60
- }
61
62
if (arm_feature(&cpu->env, ARM_FEATURE_CBAR) ||
63
arm_feature(&cpu->env, ARM_FEATURE_CBAR_RO)) {
64
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
65
uint64_t t;
66
uint32_t u;
67
68
- unset_feature(env, ARM_FEATURE_VFP);
69
- unset_feature(env, ARM_FEATURE_VFP3);
70
- unset_feature(env, ARM_FEATURE_VFP4);
71
-
72
t = cpu->isar.id_aa64isar1;
73
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 0);
74
cpu->isar.id_aa64isar1 = t;
75
@@ -XXX,XX +XXX,XX @@ static void arm926_initfn(Object *obj)
76
77
cpu->dtb_compatible = "arm,arm926";
78
set_feature(&cpu->env, ARM_FEATURE_V5);
79
- set_feature(&cpu->env, ARM_FEATURE_VFP);
80
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
81
set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN);
82
cpu->midr = 0x41069265;
83
@@ -XXX,XX +XXX,XX @@ static void arm1026_initfn(Object *obj)
84
85
cpu->dtb_compatible = "arm,arm1026";
86
set_feature(&cpu->env, ARM_FEATURE_V5);
87
- set_feature(&cpu->env, ARM_FEATURE_VFP);
88
set_feature(&cpu->env, ARM_FEATURE_AUXCR);
89
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
90
set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN);
91
@@ -XXX,XX +XXX,XX @@ static void arm1136_r2_initfn(Object *obj)
92
93
cpu->dtb_compatible = "arm,arm1136";
94
set_feature(&cpu->env, ARM_FEATURE_V6);
95
- set_feature(&cpu->env, ARM_FEATURE_VFP);
96
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
97
set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
98
set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
99
@@ -XXX,XX +XXX,XX @@ static void arm1136_initfn(Object *obj)
100
cpu->dtb_compatible = "arm,arm1136";
101
set_feature(&cpu->env, ARM_FEATURE_V6K);
102
set_feature(&cpu->env, ARM_FEATURE_V6);
103
- set_feature(&cpu->env, ARM_FEATURE_VFP);
104
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
105
set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
106
set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS);
107
@@ -XXX,XX +XXX,XX @@ static void arm1176_initfn(Object *obj)
108
109
cpu->dtb_compatible = "arm,arm1176";
110
set_feature(&cpu->env, ARM_FEATURE_V6K);
111
- set_feature(&cpu->env, ARM_FEATURE_VFP);
112
set_feature(&cpu->env, ARM_FEATURE_VAPA);
113
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
114
set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG);
115
@@ -XXX,XX +XXX,XX @@ static void arm11mpcore_initfn(Object *obj)
116
117
cpu->dtb_compatible = "arm,arm11mpcore";
118
set_feature(&cpu->env, ARM_FEATURE_V6K);
119
- set_feature(&cpu->env, ARM_FEATURE_VFP);
120
set_feature(&cpu->env, ARM_FEATURE_VAPA);
121
set_feature(&cpu->env, ARM_FEATURE_MPIDR);
122
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
123
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
124
set_feature(&cpu->env, ARM_FEATURE_M);
125
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
126
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
127
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
128
cpu->midr = 0x410fc240; /* r0p0 */
129
cpu->pmsav7_dregion = 8;
130
cpu->isar.mvfr0 = 0x10110021;
131
@@ -XXX,XX +XXX,XX @@ static void cortex_m7_initfn(Object *obj)
132
set_feature(&cpu->env, ARM_FEATURE_M);
133
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
134
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
135
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
136
cpu->midr = 0x411fc272; /* r1p2 */
137
cpu->pmsav7_dregion = 8;
138
cpu->isar.mvfr0 = 0x10110221;
139
@@ -XXX,XX +XXX,XX @@ static void cortex_m33_initfn(Object *obj)
140
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
141
set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
142
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
143
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
144
cpu->midr = 0x410fd213; /* r0p3 */
145
cpu->pmsav7_dregion = 16;
146
cpu->sau_sregion = 8;
147
@@ -XXX,XX +XXX,XX @@ static void cortex_r5f_initfn(Object *obj)
148
ARMCPU *cpu = ARM_CPU(obj);
149
150
cortex_r5_initfn(obj);
151
- set_feature(&cpu->env, ARM_FEATURE_VFP3);
152
cpu->isar.mvfr0 = 0x10110221;
153
cpu->isar.mvfr1 = 0x00000011;
154
}
155
@@ -XXX,XX +XXX,XX @@ static void cortex_a8_initfn(Object *obj)
156
157
cpu->dtb_compatible = "arm,cortex-a8";
158
set_feature(&cpu->env, ARM_FEATURE_V7);
159
- set_feature(&cpu->env, ARM_FEATURE_VFP3);
160
set_feature(&cpu->env, ARM_FEATURE_NEON);
161
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
162
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
163
@@ -XXX,XX +XXX,XX @@ static void cortex_a9_initfn(Object *obj)
164
165
cpu->dtb_compatible = "arm,cortex-a9";
166
set_feature(&cpu->env, ARM_FEATURE_V7);
167
- set_feature(&cpu->env, ARM_FEATURE_VFP3);
168
set_feature(&cpu->env, ARM_FEATURE_NEON);
169
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
170
set_feature(&cpu->env, ARM_FEATURE_EL3);
171
@@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj)
172
173
cpu->dtb_compatible = "arm,cortex-a7";
174
set_feature(&cpu->env, ARM_FEATURE_V7VE);
175
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
176
set_feature(&cpu->env, ARM_FEATURE_NEON);
177
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
178
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
179
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
180
181
cpu->dtb_compatible = "arm,cortex-a15";
182
set_feature(&cpu->env, ARM_FEATURE_V7VE);
183
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
184
set_feature(&cpu->env, ARM_FEATURE_NEON);
185
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
186
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
187
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
188
index XXXXXXX..XXXXXXX 100644
189
--- a/target/arm/cpu64.c
190
+++ b/target/arm/cpu64.c
191
@@ -XXX,XX +XXX,XX @@ static void aarch64_a57_initfn(Object *obj)
192
193
cpu->dtb_compatible = "arm,cortex-a57";
194
set_feature(&cpu->env, ARM_FEATURE_V8);
195
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
196
set_feature(&cpu->env, ARM_FEATURE_NEON);
197
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
198
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
199
@@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj)
200
201
cpu->dtb_compatible = "arm,cortex-a53";
202
set_feature(&cpu->env, ARM_FEATURE_V8);
203
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
204
set_feature(&cpu->env, ARM_FEATURE_NEON);
205
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
206
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
207
@@ -XXX,XX +XXX,XX @@ static void aarch64_a72_initfn(Object *obj)
208
209
cpu->dtb_compatible = "arm,cortex-a72";
210
set_feature(&cpu->env, ARM_FEATURE_V8);
211
- set_feature(&cpu->env, ARM_FEATURE_VFP4);
212
set_feature(&cpu->env, ARM_FEATURE_NEON);
213
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
214
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
215
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/target/arm/kvm32.c
218
+++ b/target/arm/kvm32.c
219
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
220
* bits, but a few must be tested.
221
*/
222
set_feature(&features, ARM_FEATURE_V7VE);
223
- set_feature(&features, ARM_FEATURE_VFP3);
224
set_feature(&features, ARM_FEATURE_GENERIC_TIMER);
225
226
if (extract32(id_pfr0, 12, 4) == 1) {
227
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
228
if (extract32(ahcf->isar.mvfr1, 12, 4) == 1) {
229
set_feature(&features, ARM_FEATURE_NEON);
230
}
231
- if (extract32(ahcf->isar.mvfr1, 28, 4) == 1) {
232
- /* FMAC support implies VFPv4 */
233
- set_feature(&features, ARM_FEATURE_VFP4);
234
- }
235
236
ahcf->features = features;
237
238
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
239
index XXXXXXX..XXXXXXX 100644
240
--- a/target/arm/kvm64.c
241
+++ b/target/arm/kvm64.c
242
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
243
* feature bits.
244
*/
245
set_feature(&features, ARM_FEATURE_V8);
246
- set_feature(&features, ARM_FEATURE_VFP4);
247
set_feature(&features, ARM_FEATURE_NEON);
248
set_feature(&features, ARM_FEATURE_AARCH64);
249
set_feature(&features, ARM_FEATURE_PMU);
250
--
251
2.20.1
252
253
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Those vfp instructions without extra opcode fields can
4
share a common @format for brevity.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200224222232.13807-16-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/vfp.decode | 134 ++++++++++++++++--------------------------
12
1 file changed, 52 insertions(+), 82 deletions(-)
13
14
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/vfp.decode
17
+++ b/target/arm/vfp.decode
18
@@ -XXX,XX +XXX,XX @@
19
20
%vmov_imm 16:4 0:4
21
22
+@vfp_dnm_s ................................ vm=%vm_sp vn=%vn_sp vd=%vd_sp
23
+@vfp_dnm_d ................................ vm=%vm_dp vn=%vn_dp vd=%vd_dp
24
+
25
+@vfp_dm_ss ................................ vm=%vm_sp vd=%vd_sp
26
+@vfp_dm_dd ................................ vm=%vm_dp vd=%vd_dp
27
+@vfp_dm_ds ................................ vm=%vm_sp vd=%vd_dp
28
+@vfp_dm_sd ................................ vm=%vm_dp vd=%vd_sp
29
+
30
# VMOV scalar to general-purpose register; note that this does
31
# include some Neon cases.
32
VMOV_to_gp ---- 1110 u:1 1. 1 .... rt:4 1011 ... 1 0000 \
33
@@ -XXX,XX +XXX,XX @@ VDUP ---- 1110 1 b:1 q:1 0 .... rt:4 1011 . 0 e:1 1 0000 \
34
vn=%vn_dp
35
36
VMSR_VMRS ---- 1110 111 l:1 reg:4 rt:4 1010 0001 0000
37
-VMOV_single ---- 1110 000 l:1 .... rt:4 1010 . 001 0000 \
38
- vn=%vn_sp
39
+VMOV_single ---- 1110 000 l:1 .... rt:4 1010 . 001 0000 vn=%vn_sp
40
41
-VMOV_64_sp ---- 1100 010 op:1 rt2:4 rt:4 1010 00.1 .... \
42
- vm=%vm_sp
43
-VMOV_64_dp ---- 1100 010 op:1 rt2:4 rt:4 1011 00.1 .... \
44
- vm=%vm_dp
45
+VMOV_64_sp ---- 1100 010 op:1 rt2:4 rt:4 1010 00.1 .... vm=%vm_sp
46
+VMOV_64_dp ---- 1100 010 op:1 rt2:4 rt:4 1011 00.1 .... vm=%vm_dp
47
48
# Note that the half-precision variants of VLDR and VSTR are
49
# not part of this decodetree at all because they have bits [9:8] == 0b01
50
-VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 \
51
- vd=%vd_sp
52
-VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 \
53
- vd=%vd_dp
54
+VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
55
+VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
56
57
# We split the load/store multiple up into two patterns to avoid
58
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
59
@@ -XXX,XX +XXX,XX @@ VLDM_VSTM_dp ---- 1101 0.1 l:1 rn:4 .... 1011 imm:8 \
60
vd=%vd_dp p=1 u=0 w=1
61
62
# 3-register VFP data-processing; bits [23,21:20,6] identify the operation.
63
-VMLA_sp ---- 1110 0.00 .... .... 1010 .0.0 .... \
64
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
65
-VMLA_dp ---- 1110 0.00 .... .... 1011 .0.0 .... \
66
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
67
+VMLA_sp ---- 1110 0.00 .... .... 1010 .0.0 .... @vfp_dnm_s
68
+VMLA_dp ---- 1110 0.00 .... .... 1011 .0.0 .... @vfp_dnm_d
69
70
-VMLS_sp ---- 1110 0.00 .... .... 1010 .1.0 .... \
71
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
72
-VMLS_dp ---- 1110 0.00 .... .... 1011 .1.0 .... \
73
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
74
+VMLS_sp ---- 1110 0.00 .... .... 1010 .1.0 .... @vfp_dnm_s
75
+VMLS_dp ---- 1110 0.00 .... .... 1011 .1.0 .... @vfp_dnm_d
76
77
-VNMLS_sp ---- 1110 0.01 .... .... 1010 .0.0 .... \
78
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
79
-VNMLS_dp ---- 1110 0.01 .... .... 1011 .0.0 .... \
80
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
81
+VNMLS_sp ---- 1110 0.01 .... .... 1010 .0.0 .... @vfp_dnm_s
82
+VNMLS_dp ---- 1110 0.01 .... .... 1011 .0.0 .... @vfp_dnm_d
83
84
-VNMLA_sp ---- 1110 0.01 .... .... 1010 .1.0 .... \
85
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
86
-VNMLA_dp ---- 1110 0.01 .... .... 1011 .1.0 .... \
87
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
88
+VNMLA_sp ---- 1110 0.01 .... .... 1010 .1.0 .... @vfp_dnm_s
89
+VNMLA_dp ---- 1110 0.01 .... .... 1011 .1.0 .... @vfp_dnm_d
90
91
-VMUL_sp ---- 1110 0.10 .... .... 1010 .0.0 .... \
92
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
93
-VMUL_dp ---- 1110 0.10 .... .... 1011 .0.0 .... \
94
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
95
+VMUL_sp ---- 1110 0.10 .... .... 1010 .0.0 .... @vfp_dnm_s
96
+VMUL_dp ---- 1110 0.10 .... .... 1011 .0.0 .... @vfp_dnm_d
97
98
-VNMUL_sp ---- 1110 0.10 .... .... 1010 .1.0 .... \
99
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
100
-VNMUL_dp ---- 1110 0.10 .... .... 1011 .1.0 .... \
101
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
102
+VNMUL_sp ---- 1110 0.10 .... .... 1010 .1.0 .... @vfp_dnm_s
103
+VNMUL_dp ---- 1110 0.10 .... .... 1011 .1.0 .... @vfp_dnm_d
104
105
-VADD_sp ---- 1110 0.11 .... .... 1010 .0.0 .... \
106
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
107
-VADD_dp ---- 1110 0.11 .... .... 1011 .0.0 .... \
108
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
109
+VADD_sp ---- 1110 0.11 .... .... 1010 .0.0 .... @vfp_dnm_s
110
+VADD_dp ---- 1110 0.11 .... .... 1011 .0.0 .... @vfp_dnm_d
111
112
-VSUB_sp ---- 1110 0.11 .... .... 1010 .1.0 .... \
113
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
114
-VSUB_dp ---- 1110 0.11 .... .... 1011 .1.0 .... \
115
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
116
+VSUB_sp ---- 1110 0.11 .... .... 1010 .1.0 .... @vfp_dnm_s
117
+VSUB_dp ---- 1110 0.11 .... .... 1011 .1.0 .... @vfp_dnm_d
118
119
-VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... \
120
- vm=%vm_sp vn=%vn_sp vd=%vd_sp
121
-VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... \
122
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
123
+VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
124
+VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
125
126
VFM_sp ---- 1110 1.01 .... .... 1010 . o2:1 . 0 .... \
127
vm=%vm_sp vn=%vn_sp vd=%vd_sp o1=1
128
@@ -XXX,XX +XXX,XX @@ VMOV_imm_sp ---- 1110 1.11 .... .... 1010 0000 .... \
129
VMOV_imm_dp ---- 1110 1.11 .... .... 1011 0000 .... \
130
vd=%vd_dp imm=%vmov_imm
131
132
-VMOV_reg_sp ---- 1110 1.11 0000 .... 1010 01.0 .... \
133
- vd=%vd_sp vm=%vm_sp
134
-VMOV_reg_dp ---- 1110 1.11 0000 .... 1011 01.0 .... \
135
- vd=%vd_dp vm=%vm_dp
136
+VMOV_reg_sp ---- 1110 1.11 0000 .... 1010 01.0 .... @vfp_dm_ss
137
+VMOV_reg_dp ---- 1110 1.11 0000 .... 1011 01.0 .... @vfp_dm_dd
138
139
-VABS_sp ---- 1110 1.11 0000 .... 1010 11.0 .... \
140
- vd=%vd_sp vm=%vm_sp
141
-VABS_dp ---- 1110 1.11 0000 .... 1011 11.0 .... \
142
- vd=%vd_dp vm=%vm_dp
143
+VABS_sp ---- 1110 1.11 0000 .... 1010 11.0 .... @vfp_dm_ss
144
+VABS_dp ---- 1110 1.11 0000 .... 1011 11.0 .... @vfp_dm_dd
145
146
-VNEG_sp ---- 1110 1.11 0001 .... 1010 01.0 .... \
147
- vd=%vd_sp vm=%vm_sp
148
-VNEG_dp ---- 1110 1.11 0001 .... 1011 01.0 .... \
149
- vd=%vd_dp vm=%vm_dp
150
+VNEG_sp ---- 1110 1.11 0001 .... 1010 01.0 .... @vfp_dm_ss
151
+VNEG_dp ---- 1110 1.11 0001 .... 1011 01.0 .... @vfp_dm_dd
152
153
-VSQRT_sp ---- 1110 1.11 0001 .... 1010 11.0 .... \
154
- vd=%vd_sp vm=%vm_sp
155
-VSQRT_dp ---- 1110 1.11 0001 .... 1011 11.0 .... \
156
- vd=%vd_dp vm=%vm_dp
157
+VSQRT_sp ---- 1110 1.11 0001 .... 1010 11.0 .... @vfp_dm_ss
158
+VSQRT_dp ---- 1110 1.11 0001 .... 1011 11.0 .... @vfp_dm_dd
159
160
VCMP_sp ---- 1110 1.11 010 z:1 .... 1010 e:1 1.0 .... \
161
vd=%vd_sp vm=%vm_sp
162
@@ -XXX,XX +XXX,XX @@ VCVT_f32_f16 ---- 1110 1.11 0010 .... 1010 t:1 1.0 .... \
163
VCVT_f64_f16 ---- 1110 1.11 0010 .... 1011 t:1 1.0 .... \
164
vd=%vd_dp vm=%vm_sp
165
166
-# VCVTB and VCVTT to f16: Vd format is always vd_sp; Vm format depends on size bit
167
+# VCVTB and VCVTT to f16: Vd format is always vd_sp;
168
+# Vm format depends on size bit
169
VCVT_f16_f32 ---- 1110 1.11 0011 .... 1010 t:1 1.0 .... \
170
vd=%vd_sp vm=%vm_sp
171
VCVT_f16_f64 ---- 1110 1.11 0011 .... 1011 t:1 1.0 .... \
172
vd=%vd_sp vm=%vm_dp
173
174
-VRINTR_sp ---- 1110 1.11 0110 .... 1010 01.0 .... \
175
- vd=%vd_sp vm=%vm_sp
176
-VRINTR_dp ---- 1110 1.11 0110 .... 1011 01.0 .... \
177
- vd=%vd_dp vm=%vm_dp
178
+VRINTR_sp ---- 1110 1.11 0110 .... 1010 01.0 .... @vfp_dm_ss
179
+VRINTR_dp ---- 1110 1.11 0110 .... 1011 01.0 .... @vfp_dm_dd
180
181
-VRINTZ_sp ---- 1110 1.11 0110 .... 1010 11.0 .... \
182
- vd=%vd_sp vm=%vm_sp
183
-VRINTZ_dp ---- 1110 1.11 0110 .... 1011 11.0 .... \
184
- vd=%vd_dp vm=%vm_dp
185
+VRINTZ_sp ---- 1110 1.11 0110 .... 1010 11.0 .... @vfp_dm_ss
186
+VRINTZ_dp ---- 1110 1.11 0110 .... 1011 11.0 .... @vfp_dm_dd
187
188
-VRINTX_sp ---- 1110 1.11 0111 .... 1010 01.0 .... \
189
- vd=%vd_sp vm=%vm_sp
190
-VRINTX_dp ---- 1110 1.11 0111 .... 1011 01.0 .... \
191
- vd=%vd_dp vm=%vm_dp
192
+VRINTX_sp ---- 1110 1.11 0111 .... 1010 01.0 .... @vfp_dm_ss
193
+VRINTX_dp ---- 1110 1.11 0111 .... 1011 01.0 .... @vfp_dm_dd
194
195
-# VCVT between single and double: Vm precision depends on size; Vd is its reverse
196
-VCVT_sp ---- 1110 1.11 0111 .... 1010 11.0 .... \
197
- vd=%vd_dp vm=%vm_sp
198
-VCVT_dp ---- 1110 1.11 0111 .... 1011 11.0 .... \
199
- vd=%vd_sp vm=%vm_dp
200
+# VCVT between single and double:
201
+# Vm precision depends on size; Vd is its reverse
202
+VCVT_sp ---- 1110 1.11 0111 .... 1010 11.0 .... @vfp_dm_ds
203
+VCVT_dp ---- 1110 1.11 0111 .... 1011 11.0 .... @vfp_dm_sd
204
205
# VCVT from integer to floating point: Vm always single; Vd depends on size
206
VCVT_int_sp ---- 1110 1.11 1000 .... 1010 s:1 1.0 .... \
207
@@ -XXX,XX +XXX,XX @@ VCVT_int_dp ---- 1110 1.11 1000 .... 1011 s:1 1.0 .... \
208
vd=%vd_dp vm=%vm_sp
209
210
# VJCVT is always dp to sp
211
-VJCVT ---- 1110 1.11 1001 .... 1011 11.0 .... \
212
- vd=%vd_sp vm=%vm_dp
213
+VJCVT ---- 1110 1.11 1001 .... 1011 11.0 .... @vfp_dm_sd
214
215
# VCVT between floating-point and fixed-point. The immediate value
216
# is in the same format as a Vm single-precision register number.
217
--
218
2.20.1
219
220
diff view generated by jsdifflib
1
The Musca-A and Musca-B1 development boards are based on the
1
From: Richard Henderson <richard.henderson@linaro.org>
2
SSE-200 subsystem for embedded. Implement an initial skeleton
3
model of these boards, which are similar but not identical.
4
2
5
This commit creates the board model with the SSE and the IRQ
3
Passing the raw o1 and o2 fields from the manual is less
6
splitters to wire IRQs up to its two CPUs. As yet there
4
instructive than it might be. Do the full decode and let
7
are no devices and no memory: these will be added later.
5
the trans_* functions pass in booleans to a helper.
8
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200224222232.13807-17-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
11
---
12
hw/arm/Makefile.objs | 1 +
12
target/arm/translate-vfp.inc.c | 52 ++++++++++++++++++++++++++++++----
13
hw/arm/musca.c | 197 ++++++++++++++++++++++++++++++++
13
target/arm/vfp.decode | 17 +++++------
14
MAINTAINERS | 6 +
14
2 files changed, 55 insertions(+), 14 deletions(-)
15
default-configs/arm-softmmu.mak | 1 +
16
4 files changed, 205 insertions(+)
17
create mode 100644 hw/arm/musca.c
18
15
19
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
16
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/Makefile.objs
18
--- a/target/arm/translate-vfp.inc.c
22
+++ b/hw/arm/Makefile.objs
19
+++ b/target/arm/translate-vfp.inc.c
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
20
@@ -XXX,XX +XXX,XX @@ static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_dp *a)
24
obj-$(CONFIG_MPS2) += mps2.o
21
return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false);
25
obj-$(CONFIG_MPS2) += mps2-tz.o
22
}
26
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
23
27
+obj-$(CONFIG_MUSCA) += musca.o
24
-static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
28
obj-$(CONFIG_ARMSSE) += armsse.o
25
+static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
29
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
26
{
30
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
27
/*
31
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
28
* VFNMA : fd = muladd(-fd, fn, fm)
32
new file mode 100644
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
33
index XXXXXXX..XXXXXXX
30
34
--- /dev/null
31
neon_load_reg32(vn, a->vn);
35
+++ b/hw/arm/musca.c
32
neon_load_reg32(vm, a->vm);
36
@@ -XXX,XX +XXX,XX @@
33
- if (a->o2) {
37
+/*
34
+ if (neg_n) {
38
+ * Arm Musca-B1 test chip board emulation
35
/* VFNMS, VFMS */
39
+ *
36
gen_helper_vfp_negs(vn, vn);
40
+ * Copyright (c) 2019 Linaro Limited
37
}
41
+ * Written by Peter Maydell
38
neon_load_reg32(vd, a->vd);
42
+ *
39
- if (a->o1 & 1) {
43
+ * This program is free software; you can redistribute it and/or modify
40
+ if (neg_d) {
44
+ * it under the terms of the GNU General Public License version 2 or
41
/* VFNMA, VFNMS */
45
+ * (at your option) any later version.
42
gen_helper_vfp_negs(vd, vd);
46
+ */
43
}
47
+
44
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
48
+/*
45
return true;
49
+ * The Musca boards are a reference implementation of a system using
46
}
50
+ * the SSE-200 subsystem for embedded:
47
51
+ * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-a-test-chip-board
48
-static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
52
+ * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-b-test-chip-board
49
+static bool trans_VFMA_sp(DisasContext *s, arg_VFMA_sp *a)
53
+ * We model the A and B1 variants of this board, as described in the TRMs:
54
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101107_0000_00_en/index.html
55
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101312_0000_00_en/index.html
56
+ */
57
+
58
+#include "qemu/osdep.h"
59
+#include "qemu/error-report.h"
60
+#include "qapi/error.h"
61
+#include "exec/address-spaces.h"
62
+#include "hw/arm/arm.h"
63
+#include "hw/arm/armsse.h"
64
+#include "hw/boards.h"
65
+#include "hw/core/split-irq.h"
66
+
67
+#define MUSCA_NUMIRQ_MAX 96
68
+
69
+typedef enum MuscaType {
70
+ MUSCA_A,
71
+ MUSCA_B1,
72
+} MuscaType;
73
+
74
+typedef struct {
75
+ MachineClass parent;
76
+ MuscaType type;
77
+ uint32_t init_svtor;
78
+ int sram_addr_width;
79
+ int num_irqs;
80
+} MuscaMachineClass;
81
+
82
+typedef struct {
83
+ MachineState parent;
84
+
85
+ ARMSSE sse;
86
+ SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
87
+} MuscaMachineState;
88
+
89
+#define TYPE_MUSCA_MACHINE "musca"
90
+#define TYPE_MUSCA_A_MACHINE MACHINE_TYPE_NAME("musca-a")
91
+#define TYPE_MUSCA_B1_MACHINE MACHINE_TYPE_NAME("musca-b1")
92
+
93
+#define MUSCA_MACHINE(obj) \
94
+ OBJECT_CHECK(MuscaMachineState, obj, TYPE_MUSCA_MACHINE)
95
+#define MUSCA_MACHINE_GET_CLASS(obj) \
96
+ OBJECT_GET_CLASS(MuscaMachineClass, obj, TYPE_MUSCA_MACHINE)
97
+#define MUSCA_MACHINE_CLASS(klass) \
98
+ OBJECT_CLASS_CHECK(MuscaMachineClass, klass, TYPE_MUSCA_MACHINE)
99
+
100
+/*
101
+ * Main SYSCLK frequency in Hz
102
+ * TODO this should really be different for the two cores, but we
103
+ * don't model that in our SSE-200 model yet.
104
+ */
105
+#define SYSCLK_FRQ 40000000
106
+
107
+static void musca_init(MachineState *machine)
108
+{
50
+{
109
+ MuscaMachineState *mms = MUSCA_MACHINE(machine);
51
+ return do_vfm_sp(s, a, false, false);
110
+ MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms);
111
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
112
+ MemoryRegion *system_memory = get_system_memory();
113
+ DeviceState *ssedev;
114
+ int i;
115
+
116
+ assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
117
+
118
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
119
+ error_report("This board can only be used with CPU %s",
120
+ mc->default_cpu_type);
121
+ exit(1);
122
+ }
123
+
124
+ sysbus_init_child_obj(OBJECT(machine), "sse-200", &mms->sse,
125
+ sizeof(mms->sse), TYPE_SSE200);
126
+ ssedev = DEVICE(&mms->sse);
127
+ object_property_set_link(OBJECT(&mms->sse), OBJECT(system_memory),
128
+ "memory", &error_fatal);
129
+ qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
130
+ qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
131
+ qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
132
+ qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ);
133
+ object_property_set_bool(OBJECT(&mms->sse), true, "realized",
134
+ &error_fatal);
135
+
136
+ /*
137
+ * We need to create splitters to feed the IRQ inputs
138
+ * for each CPU in the SSE-200 from each device in the board.
139
+ */
140
+ for (i = 0; i < mmc->num_irqs; i++) {
141
+ char *name = g_strdup_printf("musca-irq-splitter%d", i);
142
+ SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
143
+
144
+ object_initialize_child(OBJECT(machine), name,
145
+ splitter, sizeof(*splitter),
146
+ TYPE_SPLIT_IRQ, &error_fatal, NULL);
147
+ g_free(name);
148
+
149
+ object_property_set_int(OBJECT(splitter), 2, "num-lines",
150
+ &error_fatal);
151
+ object_property_set_bool(OBJECT(splitter), true, "realized",
152
+ &error_fatal);
153
+ qdev_connect_gpio_out(DEVICE(splitter), 0,
154
+ qdev_get_gpio_in_named(ssedev, "EXP_IRQ", i));
155
+ qdev_connect_gpio_out(DEVICE(splitter), 1,
156
+ qdev_get_gpio_in_named(ssedev,
157
+ "EXP_CPU1_IRQ", i));
158
+ }
159
+
160
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
161
+}
52
+}
162
+
53
+
163
+static void musca_class_init(ObjectClass *oc, void *data)
54
+static bool trans_VFMS_sp(DisasContext *s, arg_VFMS_sp *a)
164
+{
55
+{
165
+ MachineClass *mc = MACHINE_CLASS(oc);
56
+ return do_vfm_sp(s, a, true, false);
166
+
167
+ mc->default_cpus = 2;
168
+ mc->min_cpus = mc->default_cpus;
169
+ mc->max_cpus = mc->default_cpus;
170
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
171
+ mc->init = musca_init;
172
+}
57
+}
173
+
58
+
174
+static void musca_a_class_init(ObjectClass *oc, void *data)
59
+static bool trans_VFNMA_sp(DisasContext *s, arg_VFNMA_sp *a)
175
+{
60
+{
176
+ MachineClass *mc = MACHINE_CLASS(oc);
61
+ return do_vfm_sp(s, a, false, true);
177
+ MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc);
178
+
179
+ mc->desc = "ARM Musca-A board (dual Cortex-M33)";
180
+ mmc->type = MUSCA_A;
181
+ mmc->init_svtor = 0x10200000;
182
+ mmc->sram_addr_width = 15;
183
+ mmc->num_irqs = 64;
184
+}
62
+}
185
+
63
+
186
+static void musca_b1_class_init(ObjectClass *oc, void *data)
64
+static bool trans_VFNMS_sp(DisasContext *s, arg_VFNMS_sp *a)
187
+{
65
+{
188
+ MachineClass *mc = MACHINE_CLASS(oc);
66
+ return do_vfm_sp(s, a, true, true);
189
+ MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc);
190
+
191
+ mc->desc = "ARM Musca-B1 board (dual Cortex-M33)";
192
+ mmc->type = MUSCA_B1;
193
+ /*
194
+ * This matches the DAPlink firmware which boots from QSPI. There
195
+ * is also a firmware blob which boots from the eFlash, which
196
+ * uses init_svtor = 0x1A000000. QEMU doesn't currently support that,
197
+ * though we could in theory expose a machine property on the command
198
+ * line to allow the user to request eFlash boot.
199
+ */
200
+ mmc->init_svtor = 0x10000000;
201
+ mmc->sram_addr_width = 17;
202
+ mmc->num_irqs = 96;
203
+}
67
+}
204
+
68
+
205
+static const TypeInfo musca_info = {
69
+static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
206
+ .name = TYPE_MUSCA_MACHINE,
70
{
207
+ .parent = TYPE_MACHINE,
71
/*
208
+ .abstract = true,
72
* VFNMA : fd = muladd(-fd, fn, fm)
209
+ .instance_size = sizeof(MuscaMachineState),
73
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
210
+ .class_size = sizeof(MuscaMachineClass),
74
211
+ .class_init = musca_class_init,
75
neon_load_reg64(vn, a->vn);
212
+};
76
neon_load_reg64(vm, a->vm);
213
+
77
- if (a->o2) {
214
+static const TypeInfo musca_a_info = {
78
+ if (neg_n) {
215
+ .name = TYPE_MUSCA_A_MACHINE,
79
/* VFNMS, VFMS */
216
+ .parent = TYPE_MUSCA_MACHINE,
80
gen_helper_vfp_negd(vn, vn);
217
+ .class_init = musca_a_class_init,
81
}
218
+};
82
neon_load_reg64(vd, a->vd);
219
+
83
- if (a->o1 & 1) {
220
+static const TypeInfo musca_b1_info = {
84
+ if (neg_d) {
221
+ .name = TYPE_MUSCA_B1_MACHINE,
85
/* VFNMA, VFNMS */
222
+ .parent = TYPE_MUSCA_MACHINE,
86
gen_helper_vfp_negd(vd, vd);
223
+ .class_init = musca_b1_class_init,
87
}
224
+};
88
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_dp *a)
225
+
89
return true;
226
+static void musca_machine_init(void)
90
}
91
92
+static bool trans_VFMA_dp(DisasContext *s, arg_VFMA_dp *a)
227
+{
93
+{
228
+ type_register_static(&musca_info);
94
+ return do_vfm_dp(s, a, false, false);
229
+ type_register_static(&musca_a_info);
230
+ type_register_static(&musca_b1_info);
231
+}
95
+}
232
+
96
+
233
+type_init(musca_machine_init);
97
+static bool trans_VFMS_dp(DisasContext *s, arg_VFMS_dp *a)
234
diff --git a/MAINTAINERS b/MAINTAINERS
98
+{
99
+ return do_vfm_dp(s, a, true, false);
100
+}
101
+
102
+static bool trans_VFNMA_dp(DisasContext *s, arg_VFNMA_dp *a)
103
+{
104
+ return do_vfm_dp(s, a, false, true);
105
+}
106
+
107
+static bool trans_VFNMS_dp(DisasContext *s, arg_VFNMS_dp *a)
108
+{
109
+ return do_vfm_dp(s, a, true, true);
110
+}
111
+
112
static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
113
{
114
uint32_t delta_d = 0;
115
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
235
index XXXXXXX..XXXXXXX 100644
116
index XXXXXXX..XXXXXXX 100644
236
--- a/MAINTAINERS
117
--- a/target/arm/vfp.decode
237
+++ b/MAINTAINERS
118
+++ b/target/arm/vfp.decode
238
@@ -XXX,XX +XXX,XX @@ F: include/hw/misc/iotkit-sysinfo.h
119
@@ -XXX,XX +XXX,XX @@ VSUB_dp ---- 1110 0.11 .... .... 1011 .1.0 .... @vfp_dnm_d
239
F: hw/misc/armsse-cpuid.c
120
VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
240
F: include/hw/misc/armsse-cpuid.h
121
VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
241
122
242
+Musca
123
-VFM_sp ---- 1110 1.01 .... .... 1010 . o2:1 . 0 .... \
243
+M: Peter Maydell <peter.maydell@linaro.org>
124
- vm=%vm_sp vn=%vn_sp vd=%vd_sp o1=1
244
+L: qemu-arm@nongnu.org
125
-VFM_dp ---- 1110 1.01 .... .... 1011 . o2:1 . 0 .... \
245
+S: Maintained
126
- vm=%vm_dp vn=%vn_dp vd=%vd_dp o1=1
246
+F: hw/arm/musca.c
127
-VFM_sp ---- 1110 1.10 .... .... 1010 . o2:1 . 0 .... \
128
- vm=%vm_sp vn=%vn_sp vd=%vd_sp o1=2
129
-VFM_dp ---- 1110 1.10 .... .... 1011 . o2:1 . 0 .... \
130
- vm=%vm_dp vn=%vn_dp vd=%vd_dp o1=2
131
+VFMA_sp ---- 1110 1.10 .... .... 1010 .0. 0 .... @vfp_dnm_s
132
+VFMS_sp ---- 1110 1.10 .... .... 1010 .1. 0 .... @vfp_dnm_s
133
+VFNMA_sp ---- 1110 1.01 .... .... 1010 .0. 0 .... @vfp_dnm_s
134
+VFNMS_sp ---- 1110 1.01 .... .... 1010 .1. 0 .... @vfp_dnm_s
247
+
135
+
248
Musicpal
136
+VFMA_dp ---- 1110 1.10 .... .... 1011 .0.0 .... @vfp_dnm_d
249
M: Jan Kiszka <jan.kiszka@web.de>
137
+VFMS_dp ---- 1110 1.10 .... .... 1011 .1.0 .... @vfp_dnm_d
250
M: Peter Maydell <peter.maydell@linaro.org>
138
+VFNMA_dp ---- 1110 1.01 .... .... 1011 .0.0 .... @vfp_dnm_d
251
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
139
+VFNMS_dp ---- 1110 1.01 .... .... 1011 .1.0 .... @vfp_dnm_d
252
index XXXXXXX..XXXXXXX 100644
140
253
--- a/default-configs/arm-softmmu.mak
141
VMOV_imm_sp ---- 1110 1.11 .... .... 1010 0000 .... \
254
+++ b/default-configs/arm-softmmu.mak
142
vd=%vd_sp imm=%vmov_imm
255
@@ -XXX,XX +XXX,XX @@ CONFIG_TUSB6010=y
256
CONFIG_IMX=y
257
CONFIG_MAINSTONE=y
258
CONFIG_MPS2=y
259
+CONFIG_MUSCA=y
260
CONFIG_NSERIES=y
261
CONFIG_RASPI=y
262
CONFIG_REALVIEW=y
263
--
143
--
264
2.20.1
144
2.20.1
265
145
266
146
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Move all of the fp helpers out of helper.c into a new file.
3
Passing the raw op field from the manual is less instructive
4
This is code movement only. Since helper.c has no copyright
4
than it might be. Do the full decode and use the existing
5
header, take the one from cpu.h for the new file.
5
helpers to perform the expansion.
6
6
7
Since these are v8 insns, VECLEN+VECSTRIDE are already RES0.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190215192302.27855-3-richard.henderson@linaro.org
11
Message-id: 20200224222232.13807-18-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
target/arm/Makefile.objs | 2 +-
14
target/arm/translate-vfp.inc.c | 109 +++++++++++----------------------
13
target/arm/helper.c | 1062 -------------------------------------
15
target/arm/vfp-uncond.decode | 12 ++--
14
target/arm/vfp_helper.c | 1088 ++++++++++++++++++++++++++++++++++++++
16
2 files changed, 44 insertions(+), 77 deletions(-)
15
3 files changed, 1089 insertions(+), 1063 deletions(-)
16
create mode 100644 target/arm/vfp_helper.c
17
17
18
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
18
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
19
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/Makefile.objs
20
--- a/target/arm/translate-vfp.inc.c
21
+++ b/target/arm/Makefile.objs
21
+++ b/target/arm/translate-vfp.inc.c
22
@@ -XXX,XX +XXX,XX @@ obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o
22
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
23
obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
23
return true;
24
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
25
obj-y += translate.o op_helper.o helper.o cpu.o
26
-obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o
27
+obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o vfp_helper.o
28
obj-y += gdbstub.o
29
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
30
obj-$(TARGET_AARCH64) += pauth_helper.o
31
diff --git a/target/arm/helper.c b/target/arm/helper.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/helper.c
34
+++ b/target/arm/helper.c
35
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
36
return (a & mask) | (b & ~mask);
37
}
24
}
38
25
39
-/* VFP support. We follow the convention used for VFP instructions:
26
-static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
40
- Single precision routines have a "s" suffix, double precision a
27
-{
41
- "d" suffix. */
28
- uint32_t rd, rn, rm;
29
- bool dp = a->dp;
30
- bool vmin = a->op;
31
- TCGv_ptr fpst;
42
-
32
-
43
-/* Convert host exception flags to vfp form. */
33
- if (!dc_isar_feature(aa32_vminmaxnm, s)) {
44
-static inline int vfp_exceptbits_from_host(int host_bits)
45
-{
46
- int target_bits = 0;
47
-
48
- if (host_bits & float_flag_invalid)
49
- target_bits |= 1;
50
- if (host_bits & float_flag_divbyzero)
51
- target_bits |= 2;
52
- if (host_bits & float_flag_overflow)
53
- target_bits |= 4;
54
- if (host_bits & (float_flag_underflow | float_flag_output_denormal))
55
- target_bits |= 8;
56
- if (host_bits & float_flag_inexact)
57
- target_bits |= 0x10;
58
- if (host_bits & float_flag_input_denormal)
59
- target_bits |= 0x80;
60
- return target_bits;
61
-}
62
-
63
-uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
64
-{
65
- uint32_t i, fpscr;
66
-
67
- fpscr = env->vfp.xregs[ARM_VFP_FPSCR]
68
- | (env->vfp.vec_len << 16)
69
- | (env->vfp.vec_stride << 20);
70
-
71
- i = get_float_exception_flags(&env->vfp.fp_status);
72
- i |= get_float_exception_flags(&env->vfp.standard_fp_status);
73
- /* FZ16 does not generate an input denormal exception. */
74
- i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
75
- & ~float_flag_input_denormal);
76
- fpscr |= vfp_exceptbits_from_host(i);
77
-
78
- i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
79
- fpscr |= i ? FPCR_QC : 0;
80
-
81
- return fpscr;
82
-}
83
-
84
-uint32_t vfp_get_fpscr(CPUARMState *env)
85
-{
86
- return HELPER(vfp_get_fpscr)(env);
87
-}
88
-
89
-/* Convert vfp exception flags to target form. */
90
-static inline int vfp_exceptbits_to_host(int target_bits)
91
-{
92
- int host_bits = 0;
93
-
94
- if (target_bits & 1)
95
- host_bits |= float_flag_invalid;
96
- if (target_bits & 2)
97
- host_bits |= float_flag_divbyzero;
98
- if (target_bits & 4)
99
- host_bits |= float_flag_overflow;
100
- if (target_bits & 8)
101
- host_bits |= float_flag_underflow;
102
- if (target_bits & 0x10)
103
- host_bits |= float_flag_inexact;
104
- if (target_bits & 0x80)
105
- host_bits |= float_flag_input_denormal;
106
- return host_bits;
107
-}
108
-
109
-void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
110
-{
111
- int i;
112
- uint32_t changed = env->vfp.xregs[ARM_VFP_FPSCR];
113
-
114
- /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
115
- if (!cpu_isar_feature(aa64_fp16, arm_env_get_cpu(env))) {
116
- val &= ~FPCR_FZ16;
117
- }
118
-
119
- /*
120
- * We don't implement trapped exception handling, so the
121
- * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
122
- *
123
- * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
124
- * (which are stored in fp_status), and the other RES0 bits
125
- * in between, then we clear all of the low 16 bits.
126
- */
127
- env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
128
- env->vfp.vec_len = (val >> 16) & 7;
129
- env->vfp.vec_stride = (val >> 20) & 3;
130
-
131
- /*
132
- * The bit we set within fpscr_q is arbitrary; the register as a
133
- * whole being zero/non-zero is what counts.
134
- */
135
- env->vfp.qc[0] = val & FPCR_QC;
136
- env->vfp.qc[1] = 0;
137
- env->vfp.qc[2] = 0;
138
- env->vfp.qc[3] = 0;
139
-
140
- changed ^= val;
141
- if (changed & (3 << 22)) {
142
- i = (val >> 22) & 3;
143
- switch (i) {
144
- case FPROUNDING_TIEEVEN:
145
- i = float_round_nearest_even;
146
- break;
147
- case FPROUNDING_POSINF:
148
- i = float_round_up;
149
- break;
150
- case FPROUNDING_NEGINF:
151
- i = float_round_down;
152
- break;
153
- case FPROUNDING_ZERO:
154
- i = float_round_to_zero;
155
- break;
156
- }
157
- set_float_rounding_mode(i, &env->vfp.fp_status);
158
- set_float_rounding_mode(i, &env->vfp.fp_status_f16);
159
- }
160
- if (changed & FPCR_FZ16) {
161
- bool ftz_enabled = val & FPCR_FZ16;
162
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
163
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
164
- }
165
- if (changed & FPCR_FZ) {
166
- bool ftz_enabled = val & FPCR_FZ;
167
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status);
168
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status);
169
- }
170
- if (changed & FPCR_DN) {
171
- bool dnan_enabled = val & FPCR_DN;
172
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status);
173
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16);
174
- }
175
-
176
- /* The exception flags are ORed together when we read fpscr so we
177
- * only need to preserve the current state in one of our
178
- * float_status values.
179
- */
180
- i = vfp_exceptbits_to_host(val);
181
- set_float_exception_flags(i, &env->vfp.fp_status);
182
- set_float_exception_flags(0, &env->vfp.fp_status_f16);
183
- set_float_exception_flags(0, &env->vfp.standard_fp_status);
184
-}
185
-
186
-void vfp_set_fpscr(CPUARMState *env, uint32_t val)
187
-{
188
- HELPER(vfp_set_fpscr)(env, val);
189
-}
190
-
191
-#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
192
-
193
-#define VFP_BINOP(name) \
194
-float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
195
-{ \
196
- float_status *fpst = fpstp; \
197
- return float32_ ## name(a, b, fpst); \
198
-} \
199
-float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
200
-{ \
201
- float_status *fpst = fpstp; \
202
- return float64_ ## name(a, b, fpst); \
203
-}
204
-VFP_BINOP(add)
205
-VFP_BINOP(sub)
206
-VFP_BINOP(mul)
207
-VFP_BINOP(div)
208
-VFP_BINOP(min)
209
-VFP_BINOP(max)
210
-VFP_BINOP(minnum)
211
-VFP_BINOP(maxnum)
212
-#undef VFP_BINOP
213
-
214
-float32 VFP_HELPER(neg, s)(float32 a)
215
-{
216
- return float32_chs(a);
217
-}
218
-
219
-float64 VFP_HELPER(neg, d)(float64 a)
220
-{
221
- return float64_chs(a);
222
-}
223
-
224
-float32 VFP_HELPER(abs, s)(float32 a)
225
-{
226
- return float32_abs(a);
227
-}
228
-
229
-float64 VFP_HELPER(abs, d)(float64 a)
230
-{
231
- return float64_abs(a);
232
-}
233
-
234
-float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
235
-{
236
- return float32_sqrt(a, &env->vfp.fp_status);
237
-}
238
-
239
-float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
240
-{
241
- return float64_sqrt(a, &env->vfp.fp_status);
242
-}
243
-
244
-static void softfloat_to_vfp_compare(CPUARMState *env, int cmp)
245
-{
246
- uint32_t flags;
247
- switch (cmp) {
248
- case float_relation_equal:
249
- flags = 0x6;
250
- break;
251
- case float_relation_less:
252
- flags = 0x8;
253
- break;
254
- case float_relation_greater:
255
- flags = 0x2;
256
- break;
257
- case float_relation_unordered:
258
- flags = 0x3;
259
- break;
260
- default:
261
- g_assert_not_reached();
262
- }
263
- env->vfp.xregs[ARM_VFP_FPSCR] =
264
- deposit32(env->vfp.xregs[ARM_VFP_FPSCR], 28, 4, flags);
265
-}
266
-
267
-/* XXX: check quiet/signaling case */
268
-#define DO_VFP_cmp(p, type) \
269
-void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
270
-{ \
271
- softfloat_to_vfp_compare(env, \
272
- type ## _compare_quiet(a, b, &env->vfp.fp_status)); \
273
-} \
274
-void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
275
-{ \
276
- softfloat_to_vfp_compare(env, \
277
- type ## _compare(a, b, &env->vfp.fp_status)); \
278
-}
279
-DO_VFP_cmp(s, float32)
280
-DO_VFP_cmp(d, float64)
281
-#undef DO_VFP_cmp
282
-
283
-/* Integer to float and float to integer conversions */
284
-
285
-#define CONV_ITOF(name, ftype, fsz, sign) \
286
-ftype HELPER(name)(uint32_t x, void *fpstp) \
287
-{ \
288
- float_status *fpst = fpstp; \
289
- return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
290
-}
291
-
292
-#define CONV_FTOI(name, ftype, fsz, sign, round) \
293
-sign##int32_t HELPER(name)(ftype x, void *fpstp) \
294
-{ \
295
- float_status *fpst = fpstp; \
296
- if (float##fsz##_is_any_nan(x)) { \
297
- float_raise(float_flag_invalid, fpst); \
298
- return 0; \
299
- } \
300
- return float##fsz##_to_##sign##int32##round(x, fpst); \
301
-}
302
-
303
-#define FLOAT_CONVS(name, p, ftype, fsz, sign) \
304
- CONV_ITOF(vfp_##name##to##p, ftype, fsz, sign) \
305
- CONV_FTOI(vfp_to##name##p, ftype, fsz, sign, ) \
306
- CONV_FTOI(vfp_to##name##z##p, ftype, fsz, sign, _round_to_zero)
307
-
308
-FLOAT_CONVS(si, h, uint32_t, 16, )
309
-FLOAT_CONVS(si, s, float32, 32, )
310
-FLOAT_CONVS(si, d, float64, 64, )
311
-FLOAT_CONVS(ui, h, uint32_t, 16, u)
312
-FLOAT_CONVS(ui, s, float32, 32, u)
313
-FLOAT_CONVS(ui, d, float64, 64, u)
314
-
315
-#undef CONV_ITOF
316
-#undef CONV_FTOI
317
-#undef FLOAT_CONVS
318
-
319
-/* floating point conversion */
320
-float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
321
-{
322
- return float32_to_float64(x, &env->vfp.fp_status);
323
-}
324
-
325
-float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
326
-{
327
- return float64_to_float32(x, &env->vfp.fp_status);
328
-}
329
-
330
-/* VFP3 fixed point conversion. */
331
-#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
332
-float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
333
- void *fpstp) \
334
-{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
335
-
336
-#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
337
-uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
338
- void *fpst) \
339
-{ \
340
- if (unlikely(float##fsz##_is_any_nan(x))) { \
341
- float_raise(float_flag_invalid, fpst); \
342
- return 0; \
343
- } \
344
- return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
345
-}
346
-
347
-#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
348
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
349
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
350
- float_round_to_zero, _round_to_zero) \
351
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
352
- get_float_rounding_mode(fpst), )
353
-
354
-#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
355
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
356
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
357
- get_float_rounding_mode(fpst), )
358
-
359
-VFP_CONV_FIX(sh, d, 64, 64, int16)
360
-VFP_CONV_FIX(sl, d, 64, 64, int32)
361
-VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
362
-VFP_CONV_FIX(uh, d, 64, 64, uint16)
363
-VFP_CONV_FIX(ul, d, 64, 64, uint32)
364
-VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
365
-VFP_CONV_FIX(sh, s, 32, 32, int16)
366
-VFP_CONV_FIX(sl, s, 32, 32, int32)
367
-VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
368
-VFP_CONV_FIX(uh, s, 32, 32, uint16)
369
-VFP_CONV_FIX(ul, s, 32, 32, uint32)
370
-VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
371
-
372
-#undef VFP_CONV_FIX
373
-#undef VFP_CONV_FIX_FLOAT
374
-#undef VFP_CONV_FLOAT_FIX_ROUND
375
-#undef VFP_CONV_FIX_A64
376
-
377
-uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
378
-{
379
- return int32_to_float16_scalbn(x, -shift, fpst);
380
-}
381
-
382
-uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
383
-{
384
- return uint32_to_float16_scalbn(x, -shift, fpst);
385
-}
386
-
387
-uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
388
-{
389
- return int64_to_float16_scalbn(x, -shift, fpst);
390
-}
391
-
392
-uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
393
-{
394
- return uint64_to_float16_scalbn(x, -shift, fpst);
395
-}
396
-
397
-uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
398
-{
399
- if (unlikely(float16_is_any_nan(x))) {
400
- float_raise(float_flag_invalid, fpst);
401
- return 0;
402
- }
403
- return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
404
- shift, fpst);
405
-}
406
-
407
-uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
408
-{
409
- if (unlikely(float16_is_any_nan(x))) {
410
- float_raise(float_flag_invalid, fpst);
411
- return 0;
412
- }
413
- return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
414
- shift, fpst);
415
-}
416
-
417
-uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
418
-{
419
- if (unlikely(float16_is_any_nan(x))) {
420
- float_raise(float_flag_invalid, fpst);
421
- return 0;
422
- }
423
- return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
424
- shift, fpst);
425
-}
426
-
427
-uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
428
-{
429
- if (unlikely(float16_is_any_nan(x))) {
430
- float_raise(float_flag_invalid, fpst);
431
- return 0;
432
- }
433
- return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
434
- shift, fpst);
435
-}
436
-
437
-uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
438
-{
439
- if (unlikely(float16_is_any_nan(x))) {
440
- float_raise(float_flag_invalid, fpst);
441
- return 0;
442
- }
443
- return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
444
- shift, fpst);
445
-}
446
-
447
-uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
448
-{
449
- if (unlikely(float16_is_any_nan(x))) {
450
- float_raise(float_flag_invalid, fpst);
451
- return 0;
452
- }
453
- return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
454
- shift, fpst);
455
-}
456
-
457
-/* Set the current fp rounding mode and return the old one.
458
- * The argument is a softfloat float_round_ value.
459
- */
460
-uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
461
-{
462
- float_status *fp_status = fpstp;
463
-
464
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
465
- set_float_rounding_mode(rmode, fp_status);
466
-
467
- return prev_rmode;
468
-}
469
-
470
-/* Set the current fp rounding mode in the standard fp status and return
471
- * the old one. This is for NEON instructions that need to change the
472
- * rounding mode but wish to use the standard FPSCR values for everything
473
- * else. Always set the rounding mode back to the correct value after
474
- * modifying it.
475
- * The argument is a softfloat float_round_ value.
476
- */
477
-uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
478
-{
479
- float_status *fp_status = &env->vfp.standard_fp_status;
480
-
481
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
482
- set_float_rounding_mode(rmode, fp_status);
483
-
484
- return prev_rmode;
485
-}
486
-
487
-/* Half precision conversions. */
488
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode)
489
-{
490
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
491
- * it would affect flushing input denormals.
492
- */
493
- float_status *fpst = fpstp;
494
- flag save = get_flush_inputs_to_zero(fpst);
495
- set_flush_inputs_to_zero(false, fpst);
496
- float32 r = float16_to_float32(a, !ahp_mode, fpst);
497
- set_flush_inputs_to_zero(save, fpst);
498
- return r;
499
-}
500
-
501
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode)
502
-{
503
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
504
- * it would affect flushing output denormals.
505
- */
506
- float_status *fpst = fpstp;
507
- flag save = get_flush_to_zero(fpst);
508
- set_flush_to_zero(false, fpst);
509
- float16 r = float32_to_float16(a, !ahp_mode, fpst);
510
- set_flush_to_zero(save, fpst);
511
- return r;
512
-}
513
-
514
-float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, void *fpstp, uint32_t ahp_mode)
515
-{
516
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
517
- * it would affect flushing input denormals.
518
- */
519
- float_status *fpst = fpstp;
520
- flag save = get_flush_inputs_to_zero(fpst);
521
- set_flush_inputs_to_zero(false, fpst);
522
- float64 r = float16_to_float64(a, !ahp_mode, fpst);
523
- set_flush_inputs_to_zero(save, fpst);
524
- return r;
525
-}
526
-
527
-uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
528
-{
529
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
530
- * it would affect flushing output denormals.
531
- */
532
- float_status *fpst = fpstp;
533
- flag save = get_flush_to_zero(fpst);
534
- set_flush_to_zero(false, fpst);
535
- float16 r = float64_to_float16(a, !ahp_mode, fpst);
536
- set_flush_to_zero(save, fpst);
537
- return r;
538
-}
539
-
540
-#define float32_two make_float32(0x40000000)
541
-#define float32_three make_float32(0x40400000)
542
-#define float32_one_point_five make_float32(0x3fc00000)
543
-
544
-float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
545
-{
546
- float_status *s = &env->vfp.standard_fp_status;
547
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
548
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
549
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
550
- float_raise(float_flag_input_denormal, s);
551
- }
552
- return float32_two;
553
- }
554
- return float32_sub(float32_two, float32_mul(a, b, s), s);
555
-}
556
-
557
-float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
558
-{
559
- float_status *s = &env->vfp.standard_fp_status;
560
- float32 product;
561
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
562
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
563
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
564
- float_raise(float_flag_input_denormal, s);
565
- }
566
- return float32_one_point_five;
567
- }
568
- product = float32_mul(a, b, s);
569
- return float32_div(float32_sub(float32_three, product, s), float32_two, s);
570
-}
571
-
572
-/* NEON helpers. */
573
-
574
-/* Constants 256 and 512 are used in some helpers; we avoid relying on
575
- * int->float conversions at run-time. */
576
-#define float64_256 make_float64(0x4070000000000000LL)
577
-#define float64_512 make_float64(0x4080000000000000LL)
578
-#define float16_maxnorm make_float16(0x7bff)
579
-#define float32_maxnorm make_float32(0x7f7fffff)
580
-#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
581
-
582
-/* Reciprocal functions
583
- *
584
- * The algorithm that must be used to calculate the estimate
585
- * is specified by the ARM ARM, see FPRecipEstimate()/RecipEstimate
586
- */
587
-
588
-/* See RecipEstimate()
589
- *
590
- * input is a 9 bit fixed point number
591
- * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
592
- * result range 256 .. 511 for a number from 1.0 to 511/256.
593
- */
594
-
595
-static int recip_estimate(int input)
596
-{
597
- int a, b, r;
598
- assert(256 <= input && input < 512);
599
- a = (input * 2) + 1;
600
- b = (1 << 19) / a;
601
- r = (b + 1) >> 1;
602
- assert(256 <= r && r < 512);
603
- return r;
604
-}
605
-
606
-/*
607
- * Common wrapper to call recip_estimate
608
- *
609
- * The parameters are exponent and 64 bit fraction (without implicit
610
- * bit) where the binary point is nominally at bit 52. Returns a
611
- * float64 which can then be rounded to the appropriate size by the
612
- * callee.
613
- */
614
-
615
-static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac)
616
-{
617
- uint32_t scaled, estimate;
618
- uint64_t result_frac;
619
- int result_exp;
620
-
621
- /* Handle sub-normals */
622
- if (*exp == 0) {
623
- if (extract64(frac, 51, 1) == 0) {
624
- *exp = -1;
625
- frac <<= 2;
626
- } else {
627
- frac <<= 1;
628
- }
629
- }
630
-
631
- /* scaled = UInt('1':fraction<51:44>) */
632
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
633
- estimate = recip_estimate(scaled);
634
-
635
- result_exp = exp_off - *exp;
636
- result_frac = deposit64(0, 44, 8, estimate);
637
- if (result_exp == 0) {
638
- result_frac = deposit64(result_frac >> 1, 51, 1, 1);
639
- } else if (result_exp == -1) {
640
- result_frac = deposit64(result_frac >> 2, 50, 2, 1);
641
- result_exp = 0;
642
- }
643
-
644
- *exp = result_exp;
645
-
646
- return result_frac;
647
-}
648
-
649
-static bool round_to_inf(float_status *fpst, bool sign_bit)
650
-{
651
- switch (fpst->float_rounding_mode) {
652
- case float_round_nearest_even: /* Round to Nearest */
653
- return true;
654
- case float_round_up: /* Round to +Inf */
655
- return !sign_bit;
656
- case float_round_down: /* Round to -Inf */
657
- return sign_bit;
658
- case float_round_to_zero: /* Round to Zero */
659
- return false;
34
- return false;
660
- }
35
- }
661
-
36
-
662
- g_assert_not_reached();
37
- if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
38
- return false;
39
- }
40
-
41
- /* UNDEF accesses to D16-D31 if they don't exist */
42
- if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
43
- ((a->vm | a->vn | a->vd) & 0x10)) {
44
- return false;
45
- }
46
-
47
- rd = a->vd;
48
- rn = a->vn;
49
- rm = a->vm;
50
-
51
- if (!vfp_access_check(s)) {
52
- return true;
53
- }
54
-
55
- fpst = get_fpstatus_ptr(0);
56
-
57
- if (dp) {
58
- TCGv_i64 frn, frm, dest;
59
-
60
- frn = tcg_temp_new_i64();
61
- frm = tcg_temp_new_i64();
62
- dest = tcg_temp_new_i64();
63
-
64
- neon_load_reg64(frn, rn);
65
- neon_load_reg64(frm, rm);
66
- if (vmin) {
67
- gen_helper_vfp_minnumd(dest, frn, frm, fpst);
68
- } else {
69
- gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
70
- }
71
- neon_store_reg64(dest, rd);
72
- tcg_temp_free_i64(frn);
73
- tcg_temp_free_i64(frm);
74
- tcg_temp_free_i64(dest);
75
- } else {
76
- TCGv_i32 frn, frm, dest;
77
-
78
- frn = tcg_temp_new_i32();
79
- frm = tcg_temp_new_i32();
80
- dest = tcg_temp_new_i32();
81
-
82
- neon_load_reg32(frn, rn);
83
- neon_load_reg32(frm, rm);
84
- if (vmin) {
85
- gen_helper_vfp_minnums(dest, frn, frm, fpst);
86
- } else {
87
- gen_helper_vfp_maxnums(dest, frn, frm, fpst);
88
- }
89
- neon_store_reg32(dest, rd);
90
- tcg_temp_free_i32(frn);
91
- tcg_temp_free_i32(frm);
92
- tcg_temp_free_i32(dest);
93
- }
94
-
95
- tcg_temp_free_ptr(fpst);
96
- return true;
663
-}
97
-}
664
-
98
-
665
-uint32_t HELPER(recpe_f16)(uint32_t input, void *fpstp)
99
/*
666
-{
100
* Table for converting the most common AArch32 encoding of
667
- float_status *fpst = fpstp;
101
* rounding mode to arm_fprounding order (which matches the
668
- float16 f16 = float16_squash_input_denormal(input, fpst);
102
@@ -XXX,XX +XXX,XX @@ static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_dp *a)
669
- uint32_t f16_val = float16_val(f16);
103
return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false);
670
- uint32_t f16_sign = float16_is_neg(f16);
104
}
671
- int f16_exp = extract32(f16_val, 10, 5);
105
672
- uint32_t f16_frac = extract32(f16_val, 0, 10);
106
+static bool trans_VMINNM_sp(DisasContext *s, arg_VMINNM_sp *a)
673
- uint64_t f64_frac;
674
-
675
- if (float16_is_any_nan(f16)) {
676
- float16 nan = f16;
677
- if (float16_is_signaling_nan(f16, fpst)) {
678
- float_raise(float_flag_invalid, fpst);
679
- nan = float16_silence_nan(f16, fpst);
680
- }
681
- if (fpst->default_nan_mode) {
682
- nan = float16_default_nan(fpst);
683
- }
684
- return nan;
685
- } else if (float16_is_infinity(f16)) {
686
- return float16_set_sign(float16_zero, float16_is_neg(f16));
687
- } else if (float16_is_zero(f16)) {
688
- float_raise(float_flag_divbyzero, fpst);
689
- return float16_set_sign(float16_infinity, float16_is_neg(f16));
690
- } else if (float16_abs(f16) < (1 << 8)) {
691
- /* Abs(value) < 2.0^-16 */
692
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
693
- if (round_to_inf(fpst, f16_sign)) {
694
- return float16_set_sign(float16_infinity, f16_sign);
695
- } else {
696
- return float16_set_sign(float16_maxnorm, f16_sign);
697
- }
698
- } else if (f16_exp >= 29 && fpst->flush_to_zero) {
699
- float_raise(float_flag_underflow, fpst);
700
- return float16_set_sign(float16_zero, float16_is_neg(f16));
701
- }
702
-
703
- f64_frac = call_recip_estimate(&f16_exp, 29,
704
- ((uint64_t) f16_frac) << (52 - 10));
705
-
706
- /* result = sign : result_exp<4:0> : fraction<51:42> */
707
- f16_val = deposit32(0, 15, 1, f16_sign);
708
- f16_val = deposit32(f16_val, 10, 5, f16_exp);
709
- f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
710
- return make_float16(f16_val);
711
-}
712
-
713
-float32 HELPER(recpe_f32)(float32 input, void *fpstp)
714
-{
715
- float_status *fpst = fpstp;
716
- float32 f32 = float32_squash_input_denormal(input, fpst);
717
- uint32_t f32_val = float32_val(f32);
718
- bool f32_sign = float32_is_neg(f32);
719
- int f32_exp = extract32(f32_val, 23, 8);
720
- uint32_t f32_frac = extract32(f32_val, 0, 23);
721
- uint64_t f64_frac;
722
-
723
- if (float32_is_any_nan(f32)) {
724
- float32 nan = f32;
725
- if (float32_is_signaling_nan(f32, fpst)) {
726
- float_raise(float_flag_invalid, fpst);
727
- nan = float32_silence_nan(f32, fpst);
728
- }
729
- if (fpst->default_nan_mode) {
730
- nan = float32_default_nan(fpst);
731
- }
732
- return nan;
733
- } else if (float32_is_infinity(f32)) {
734
- return float32_set_sign(float32_zero, float32_is_neg(f32));
735
- } else if (float32_is_zero(f32)) {
736
- float_raise(float_flag_divbyzero, fpst);
737
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
738
- } else if (float32_abs(f32) < (1ULL << 21)) {
739
- /* Abs(value) < 2.0^-128 */
740
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
741
- if (round_to_inf(fpst, f32_sign)) {
742
- return float32_set_sign(float32_infinity, f32_sign);
743
- } else {
744
- return float32_set_sign(float32_maxnorm, f32_sign);
745
- }
746
- } else if (f32_exp >= 253 && fpst->flush_to_zero) {
747
- float_raise(float_flag_underflow, fpst);
748
- return float32_set_sign(float32_zero, float32_is_neg(f32));
749
- }
750
-
751
- f64_frac = call_recip_estimate(&f32_exp, 253,
752
- ((uint64_t) f32_frac) << (52 - 23));
753
-
754
- /* result = sign : result_exp<7:0> : fraction<51:29> */
755
- f32_val = deposit32(0, 31, 1, f32_sign);
756
- f32_val = deposit32(f32_val, 23, 8, f32_exp);
757
- f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
758
- return make_float32(f32_val);
759
-}
760
-
761
-float64 HELPER(recpe_f64)(float64 input, void *fpstp)
762
-{
763
- float_status *fpst = fpstp;
764
- float64 f64 = float64_squash_input_denormal(input, fpst);
765
- uint64_t f64_val = float64_val(f64);
766
- bool f64_sign = float64_is_neg(f64);
767
- int f64_exp = extract64(f64_val, 52, 11);
768
- uint64_t f64_frac = extract64(f64_val, 0, 52);
769
-
770
- /* Deal with any special cases */
771
- if (float64_is_any_nan(f64)) {
772
- float64 nan = f64;
773
- if (float64_is_signaling_nan(f64, fpst)) {
774
- float_raise(float_flag_invalid, fpst);
775
- nan = float64_silence_nan(f64, fpst);
776
- }
777
- if (fpst->default_nan_mode) {
778
- nan = float64_default_nan(fpst);
779
- }
780
- return nan;
781
- } else if (float64_is_infinity(f64)) {
782
- return float64_set_sign(float64_zero, float64_is_neg(f64));
783
- } else if (float64_is_zero(f64)) {
784
- float_raise(float_flag_divbyzero, fpst);
785
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
786
- } else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
787
- /* Abs(value) < 2.0^-1024 */
788
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
789
- if (round_to_inf(fpst, f64_sign)) {
790
- return float64_set_sign(float64_infinity, f64_sign);
791
- } else {
792
- return float64_set_sign(float64_maxnorm, f64_sign);
793
- }
794
- } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
795
- float_raise(float_flag_underflow, fpst);
796
- return float64_set_sign(float64_zero, float64_is_neg(f64));
797
- }
798
-
799
- f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac);
800
-
801
- /* result = sign : result_exp<10:0> : fraction<51:0>; */
802
- f64_val = deposit64(0, 63, 1, f64_sign);
803
- f64_val = deposit64(f64_val, 52, 11, f64_exp);
804
- f64_val = deposit64(f64_val, 0, 52, f64_frac);
805
- return make_float64(f64_val);
806
-}
807
-
808
-/* The algorithm that must be used to calculate the estimate
809
- * is specified by the ARM ARM.
810
- */
811
-
812
-static int do_recip_sqrt_estimate(int a)
813
-{
814
- int b, estimate;
815
-
816
- assert(128 <= a && a < 512);
817
- if (a < 256) {
818
- a = a * 2 + 1;
819
- } else {
820
- a = (a >> 1) << 1;
821
- a = (a + 1) * 2;
822
- }
823
- b = 512;
824
- while (a * (b + 1) * (b + 1) < (1 << 28)) {
825
- b += 1;
826
- }
827
- estimate = (b + 1) / 2;
828
- assert(256 <= estimate && estimate < 512);
829
-
830
- return estimate;
831
-}
832
-
833
-
834
-static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac)
835
-{
836
- int estimate;
837
- uint32_t scaled;
838
-
839
- if (*exp == 0) {
840
- while (extract64(frac, 51, 1) == 0) {
841
- frac = frac << 1;
842
- *exp -= 1;
843
- }
844
- frac = extract64(frac, 0, 51) << 1;
845
- }
846
-
847
- if (*exp & 1) {
848
- /* scaled = UInt('01':fraction<51:45>) */
849
- scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
850
- } else {
851
- /* scaled = UInt('1':fraction<51:44>) */
852
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
853
- }
854
- estimate = do_recip_sqrt_estimate(scaled);
855
-
856
- *exp = (exp_off - *exp) / 2;
857
- return extract64(estimate, 0, 8) << 44;
858
-}
859
-
860
-uint32_t HELPER(rsqrte_f16)(uint32_t input, void *fpstp)
861
-{
862
- float_status *s = fpstp;
863
- float16 f16 = float16_squash_input_denormal(input, s);
864
- uint16_t val = float16_val(f16);
865
- bool f16_sign = float16_is_neg(f16);
866
- int f16_exp = extract32(val, 10, 5);
867
- uint16_t f16_frac = extract32(val, 0, 10);
868
- uint64_t f64_frac;
869
-
870
- if (float16_is_any_nan(f16)) {
871
- float16 nan = f16;
872
- if (float16_is_signaling_nan(f16, s)) {
873
- float_raise(float_flag_invalid, s);
874
- nan = float16_silence_nan(f16, s);
875
- }
876
- if (s->default_nan_mode) {
877
- nan = float16_default_nan(s);
878
- }
879
- return nan;
880
- } else if (float16_is_zero(f16)) {
881
- float_raise(float_flag_divbyzero, s);
882
- return float16_set_sign(float16_infinity, f16_sign);
883
- } else if (f16_sign) {
884
- float_raise(float_flag_invalid, s);
885
- return float16_default_nan(s);
886
- } else if (float16_is_infinity(f16)) {
887
- return float16_zero;
888
- }
889
-
890
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
891
- * preserving the parity of the exponent. */
892
-
893
- f64_frac = ((uint64_t) f16_frac) << (52 - 10);
894
-
895
- f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac);
896
-
897
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
898
- val = deposit32(0, 15, 1, f16_sign);
899
- val = deposit32(val, 10, 5, f16_exp);
900
- val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
901
- return make_float16(val);
902
-}
903
-
904
-float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
905
-{
906
- float_status *s = fpstp;
907
- float32 f32 = float32_squash_input_denormal(input, s);
908
- uint32_t val = float32_val(f32);
909
- uint32_t f32_sign = float32_is_neg(f32);
910
- int f32_exp = extract32(val, 23, 8);
911
- uint32_t f32_frac = extract32(val, 0, 23);
912
- uint64_t f64_frac;
913
-
914
- if (float32_is_any_nan(f32)) {
915
- float32 nan = f32;
916
- if (float32_is_signaling_nan(f32, s)) {
917
- float_raise(float_flag_invalid, s);
918
- nan = float32_silence_nan(f32, s);
919
- }
920
- if (s->default_nan_mode) {
921
- nan = float32_default_nan(s);
922
- }
923
- return nan;
924
- } else if (float32_is_zero(f32)) {
925
- float_raise(float_flag_divbyzero, s);
926
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
927
- } else if (float32_is_neg(f32)) {
928
- float_raise(float_flag_invalid, s);
929
- return float32_default_nan(s);
930
- } else if (float32_is_infinity(f32)) {
931
- return float32_zero;
932
- }
933
-
934
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
935
- * preserving the parity of the exponent. */
936
-
937
- f64_frac = ((uint64_t) f32_frac) << 29;
938
-
939
- f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac);
940
-
941
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(15) */
942
- val = deposit32(0, 31, 1, f32_sign);
943
- val = deposit32(val, 23, 8, f32_exp);
944
- val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
945
- return make_float32(val);
946
-}
947
-
948
-float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
949
-{
950
- float_status *s = fpstp;
951
- float64 f64 = float64_squash_input_denormal(input, s);
952
- uint64_t val = float64_val(f64);
953
- bool f64_sign = float64_is_neg(f64);
954
- int f64_exp = extract64(val, 52, 11);
955
- uint64_t f64_frac = extract64(val, 0, 52);
956
-
957
- if (float64_is_any_nan(f64)) {
958
- float64 nan = f64;
959
- if (float64_is_signaling_nan(f64, s)) {
960
- float_raise(float_flag_invalid, s);
961
- nan = float64_silence_nan(f64, s);
962
- }
963
- if (s->default_nan_mode) {
964
- nan = float64_default_nan(s);
965
- }
966
- return nan;
967
- } else if (float64_is_zero(f64)) {
968
- float_raise(float_flag_divbyzero, s);
969
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
970
- } else if (float64_is_neg(f64)) {
971
- float_raise(float_flag_invalid, s);
972
- return float64_default_nan(s);
973
- } else if (float64_is_infinity(f64)) {
974
- return float64_zero;
975
- }
976
-
977
- f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac);
978
-
979
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
980
- val = deposit64(0, 61, 1, f64_sign);
981
- val = deposit64(val, 52, 11, f64_exp);
982
- val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
983
- return make_float64(val);
984
-}
985
-
986
-uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
987
-{
988
- /* float_status *s = fpstp; */
989
- int input, estimate;
990
-
991
- if ((a & 0x80000000) == 0) {
992
- return 0xffffffff;
993
- }
994
-
995
- input = extract32(a, 23, 9);
996
- estimate = recip_estimate(input);
997
-
998
- return deposit32(0, (32 - 9), 9, estimate);
999
-}
1000
-
1001
-uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
1002
-{
1003
- int estimate;
1004
-
1005
- if ((a & 0xc0000000) == 0) {
1006
- return 0xffffffff;
1007
- }
1008
-
1009
- estimate = do_recip_sqrt_estimate(extract32(a, 23, 9));
1010
-
1011
- return deposit32(0, 23, 9, estimate);
1012
-}
1013
-
1014
-/* VFPv4 fused multiply-accumulate */
1015
-float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
1016
-{
1017
- float_status *fpst = fpstp;
1018
- return float32_muladd(a, b, c, 0, fpst);
1019
-}
1020
-
1021
-float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
1022
-{
1023
- float_status *fpst = fpstp;
1024
- return float64_muladd(a, b, c, 0, fpst);
1025
-}
1026
-
1027
-/* ARMv8 round to integral */
1028
-float32 HELPER(rints_exact)(float32 x, void *fp_status)
1029
-{
1030
- return float32_round_to_int(x, fp_status);
1031
-}
1032
-
1033
-float64 HELPER(rintd_exact)(float64 x, void *fp_status)
1034
-{
1035
- return float64_round_to_int(x, fp_status);
1036
-}
1037
-
1038
-float32 HELPER(rints)(float32 x, void *fp_status)
1039
-{
1040
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1041
- float32 ret;
1042
-
1043
- ret = float32_round_to_int(x, fp_status);
1044
-
1045
- /* Suppress any inexact exceptions the conversion produced */
1046
- if (!(old_flags & float_flag_inexact)) {
1047
- new_flags = get_float_exception_flags(fp_status);
1048
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1049
- }
1050
-
1051
- return ret;
1052
-}
1053
-
1054
-float64 HELPER(rintd)(float64 x, void *fp_status)
1055
-{
1056
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1057
- float64 ret;
1058
-
1059
- ret = float64_round_to_int(x, fp_status);
1060
-
1061
- new_flags = get_float_exception_flags(fp_status);
1062
-
1063
- /* Suppress any inexact exceptions the conversion produced */
1064
- if (!(old_flags & float_flag_inexact)) {
1065
- new_flags = get_float_exception_flags(fp_status);
1066
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1067
- }
1068
-
1069
- return ret;
1070
-}
1071
-
1072
-/* Convert ARM rounding mode to softfloat */
1073
-int arm_rmode_to_sf(int rmode)
1074
-{
1075
- switch (rmode) {
1076
- case FPROUNDING_TIEAWAY:
1077
- rmode = float_round_ties_away;
1078
- break;
1079
- case FPROUNDING_ODD:
1080
- /* FIXME: add support for TIEAWAY and ODD */
1081
- qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
1082
- rmode);
1083
- /* fall through for now */
1084
- case FPROUNDING_TIEEVEN:
1085
- default:
1086
- rmode = float_round_nearest_even;
1087
- break;
1088
- case FPROUNDING_POSINF:
1089
- rmode = float_round_up;
1090
- break;
1091
- case FPROUNDING_NEGINF:
1092
- rmode = float_round_down;
1093
- break;
1094
- case FPROUNDING_ZERO:
1095
- rmode = float_round_to_zero;
1096
- break;
1097
- }
1098
- return rmode;
1099
-}
1100
-
1101
/* CRC helpers.
1102
* The upper bytes of val (above the number specified by 'bytes') must have
1103
* been zeroed out by the caller.
1104
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
1105
new file mode 100644
1106
index XXXXXXX..XXXXXXX
1107
--- /dev/null
1108
+++ b/target/arm/vfp_helper.c
1109
@@ -XXX,XX +XXX,XX @@
1110
+/*
1111
+ * ARM VFP floating-point operations
1112
+ *
1113
+ * Copyright (c) 2003 Fabrice Bellard
1114
+ *
1115
+ * This library is free software; you can redistribute it and/or
1116
+ * modify it under the terms of the GNU Lesser General Public
1117
+ * License as published by the Free Software Foundation; either
1118
+ * version 2.1 of the License, or (at your option) any later version.
1119
+ *
1120
+ * This library is distributed in the hope that it will be useful,
1121
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1122
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1123
+ * Lesser General Public License for more details.
1124
+ *
1125
+ * You should have received a copy of the GNU Lesser General Public
1126
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1127
+ */
1128
+
1129
+#include "qemu/osdep.h"
1130
+#include "qemu/log.h"
1131
+#include "cpu.h"
1132
+#include "exec/helper-proto.h"
1133
+#include "fpu/softfloat.h"
1134
+#include "internals.h"
1135
+
1136
+
1137
+/* VFP support. We follow the convention used for VFP instructions:
1138
+ Single precision routines have a "s" suffix, double precision a
1139
+ "d" suffix. */
1140
+
1141
+/* Convert host exception flags to vfp form. */
1142
+static inline int vfp_exceptbits_from_host(int host_bits)
1143
+{
107
+{
1144
+ int target_bits = 0;
108
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1145
+
109
+ return false;
1146
+ if (host_bits & float_flag_invalid)
110
+ }
1147
+ target_bits |= 1;
111
+ return do_vfp_3op_sp(s, gen_helper_vfp_minnums,
1148
+ if (host_bits & float_flag_divbyzero)
112
+ a->vd, a->vn, a->vm, false);
1149
+ target_bits |= 2;
1150
+ if (host_bits & float_flag_overflow)
1151
+ target_bits |= 4;
1152
+ if (host_bits & (float_flag_underflow | float_flag_output_denormal))
1153
+ target_bits |= 8;
1154
+ if (host_bits & float_flag_inexact)
1155
+ target_bits |= 0x10;
1156
+ if (host_bits & float_flag_input_denormal)
1157
+ target_bits |= 0x80;
1158
+ return target_bits;
1159
+}
113
+}
1160
+
114
+
1161
+uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
115
+static bool trans_VMAXNM_sp(DisasContext *s, arg_VMAXNM_sp *a)
1162
+{
116
+{
1163
+ uint32_t i, fpscr;
117
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1164
+
118
+ return false;
1165
+ fpscr = env->vfp.xregs[ARM_VFP_FPSCR]
119
+ }
1166
+ | (env->vfp.vec_len << 16)
120
+ return do_vfp_3op_sp(s, gen_helper_vfp_maxnums,
1167
+ | (env->vfp.vec_stride << 20);
121
+ a->vd, a->vn, a->vm, false);
1168
+
1169
+ i = get_float_exception_flags(&env->vfp.fp_status);
1170
+ i |= get_float_exception_flags(&env->vfp.standard_fp_status);
1171
+ /* FZ16 does not generate an input denormal exception. */
1172
+ i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
1173
+ & ~float_flag_input_denormal);
1174
+ fpscr |= vfp_exceptbits_from_host(i);
1175
+
1176
+ i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
1177
+ fpscr |= i ? FPCR_QC : 0;
1178
+
1179
+ return fpscr;
1180
+}
122
+}
1181
+
123
+
1182
+uint32_t vfp_get_fpscr(CPUARMState *env)
124
+static bool trans_VMINNM_dp(DisasContext *s, arg_VMINNM_dp *a)
1183
+{
125
+{
1184
+ return HELPER(vfp_get_fpscr)(env);
126
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
127
+ return false;
128
+ }
129
+ return do_vfp_3op_dp(s, gen_helper_vfp_minnumd,
130
+ a->vd, a->vn, a->vm, false);
1185
+}
131
+}
1186
+
132
+
1187
+/* Convert vfp exception flags to target form. */
133
+static bool trans_VMAXNM_dp(DisasContext *s, arg_VMAXNM_dp *a)
1188
+static inline int vfp_exceptbits_to_host(int target_bits)
1189
+{
134
+{
1190
+ int host_bits = 0;
135
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1191
+
136
+ return false;
1192
+ if (target_bits & 1)
137
+ }
1193
+ host_bits |= float_flag_invalid;
138
+ return do_vfp_3op_dp(s, gen_helper_vfp_maxnumd,
1194
+ if (target_bits & 2)
139
+ a->vd, a->vn, a->vm, false);
1195
+ host_bits |= float_flag_divbyzero;
1196
+ if (target_bits & 4)
1197
+ host_bits |= float_flag_overflow;
1198
+ if (target_bits & 8)
1199
+ host_bits |= float_flag_underflow;
1200
+ if (target_bits & 0x10)
1201
+ host_bits |= float_flag_inexact;
1202
+ if (target_bits & 0x80)
1203
+ host_bits |= float_flag_input_denormal;
1204
+ return host_bits;
1205
+}
140
+}
1206
+
141
+
1207
+void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
142
static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
1208
+{
143
{
1209
+ int i;
144
/*
1210
+ uint32_t changed = env->vfp.xregs[ARM_VFP_FPSCR];
145
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
146
index XXXXXXX..XXXXXXX 100644
147
--- a/target/arm/vfp-uncond.decode
148
+++ b/target/arm/vfp-uncond.decode
149
@@ -XXX,XX +XXX,XX @@
150
%vd_dp 22:1 12:4
151
%vd_sp 12:4 22:1
152
153
+@vfp_dnm_s ................................ vm=%vm_sp vn=%vn_sp vd=%vd_sp
154
+@vfp_dnm_d ................................ vm=%vm_dp vn=%vn_dp vd=%vd_dp
1211
+
155
+
1212
+ /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
156
VSEL 1111 1110 0. cc:2 .... .... 1010 .0.0 .... \
1213
+ if (!cpu_isar_feature(aa64_fp16, arm_env_get_cpu(env))) {
157
vm=%vm_sp vn=%vn_sp vd=%vd_sp dp=0
1214
+ val &= ~FPCR_FZ16;
158
VSEL 1111 1110 0. cc:2 .... .... 1011 .0.0 .... \
1215
+ }
159
vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
160
161
-VMINMAXNM 1111 1110 1.00 .... .... 1010 . op:1 .0 .... \
162
- vm=%vm_sp vn=%vn_sp vd=%vd_sp dp=0
163
-VMINMAXNM 1111 1110 1.00 .... .... 1011 . op:1 .0 .... \
164
- vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
165
+VMAXNM_sp 1111 1110 1.00 .... .... 1010 .0.0 .... @vfp_dnm_s
166
+VMINNM_sp 1111 1110 1.00 .... .... 1010 .1.0 .... @vfp_dnm_s
1216
+
167
+
1217
+ /*
168
+VMAXNM_dp 1111 1110 1.00 .... .... 1011 .0.0 .... @vfp_dnm_d
1218
+ * We don't implement trapped exception handling, so the
169
+VMINNM_dp 1111 1110 1.00 .... .... 1011 .1.0 .... @vfp_dnm_d
1219
+ * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
170
1220
+ *
171
VRINT 1111 1110 1.11 10 rm:2 .... 1010 01.0 .... \
1221
+ * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
172
vm=%vm_sp vd=%vd_sp dp=0
1222
+ * (which are stored in fp_status), and the other RES0 bits
1223
+ * in between, then we clear all of the low 16 bits.
1224
+ */
1225
+ env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
1226
+ env->vfp.vec_len = (val >> 16) & 7;
1227
+ env->vfp.vec_stride = (val >> 20) & 3;
1228
+
1229
+ /*
1230
+ * The bit we set within fpscr_q is arbitrary; the register as a
1231
+ * whole being zero/non-zero is what counts.
1232
+ */
1233
+ env->vfp.qc[0] = val & FPCR_QC;
1234
+ env->vfp.qc[1] = 0;
1235
+ env->vfp.qc[2] = 0;
1236
+ env->vfp.qc[3] = 0;
1237
+
1238
+ changed ^= val;
1239
+ if (changed & (3 << 22)) {
1240
+ i = (val >> 22) & 3;
1241
+ switch (i) {
1242
+ case FPROUNDING_TIEEVEN:
1243
+ i = float_round_nearest_even;
1244
+ break;
1245
+ case FPROUNDING_POSINF:
1246
+ i = float_round_up;
1247
+ break;
1248
+ case FPROUNDING_NEGINF:
1249
+ i = float_round_down;
1250
+ break;
1251
+ case FPROUNDING_ZERO:
1252
+ i = float_round_to_zero;
1253
+ break;
1254
+ }
1255
+ set_float_rounding_mode(i, &env->vfp.fp_status);
1256
+ set_float_rounding_mode(i, &env->vfp.fp_status_f16);
1257
+ }
1258
+ if (changed & FPCR_FZ16) {
1259
+ bool ftz_enabled = val & FPCR_FZ16;
1260
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
1261
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
1262
+ }
1263
+ if (changed & FPCR_FZ) {
1264
+ bool ftz_enabled = val & FPCR_FZ;
1265
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status);
1266
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status);
1267
+ }
1268
+ if (changed & FPCR_DN) {
1269
+ bool dnan_enabled = val & FPCR_DN;
1270
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status);
1271
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16);
1272
+ }
1273
+
1274
+ /* The exception flags are ORed together when we read fpscr so we
1275
+ * only need to preserve the current state in one of our
1276
+ * float_status values.
1277
+ */
1278
+ i = vfp_exceptbits_to_host(val);
1279
+ set_float_exception_flags(i, &env->vfp.fp_status);
1280
+ set_float_exception_flags(0, &env->vfp.fp_status_f16);
1281
+ set_float_exception_flags(0, &env->vfp.standard_fp_status);
1282
+}
1283
+
1284
+void vfp_set_fpscr(CPUARMState *env, uint32_t val)
1285
+{
1286
+ HELPER(vfp_set_fpscr)(env, val);
1287
+}
1288
+
1289
+#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
1290
+
1291
+#define VFP_BINOP(name) \
1292
+float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
1293
+{ \
1294
+ float_status *fpst = fpstp; \
1295
+ return float32_ ## name(a, b, fpst); \
1296
+} \
1297
+float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
1298
+{ \
1299
+ float_status *fpst = fpstp; \
1300
+ return float64_ ## name(a, b, fpst); \
1301
+}
1302
+VFP_BINOP(add)
1303
+VFP_BINOP(sub)
1304
+VFP_BINOP(mul)
1305
+VFP_BINOP(div)
1306
+VFP_BINOP(min)
1307
+VFP_BINOP(max)
1308
+VFP_BINOP(minnum)
1309
+VFP_BINOP(maxnum)
1310
+#undef VFP_BINOP
1311
+
1312
+float32 VFP_HELPER(neg, s)(float32 a)
1313
+{
1314
+ return float32_chs(a);
1315
+}
1316
+
1317
+float64 VFP_HELPER(neg, d)(float64 a)
1318
+{
1319
+ return float64_chs(a);
1320
+}
1321
+
1322
+float32 VFP_HELPER(abs, s)(float32 a)
1323
+{
1324
+ return float32_abs(a);
1325
+}
1326
+
1327
+float64 VFP_HELPER(abs, d)(float64 a)
1328
+{
1329
+ return float64_abs(a);
1330
+}
1331
+
1332
+float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
1333
+{
1334
+ return float32_sqrt(a, &env->vfp.fp_status);
1335
+}
1336
+
1337
+float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
1338
+{
1339
+ return float64_sqrt(a, &env->vfp.fp_status);
1340
+}
1341
+
1342
+static void softfloat_to_vfp_compare(CPUARMState *env, int cmp)
1343
+{
1344
+ uint32_t flags;
1345
+ switch (cmp) {
1346
+ case float_relation_equal:
1347
+ flags = 0x6;
1348
+ break;
1349
+ case float_relation_less:
1350
+ flags = 0x8;
1351
+ break;
1352
+ case float_relation_greater:
1353
+ flags = 0x2;
1354
+ break;
1355
+ case float_relation_unordered:
1356
+ flags = 0x3;
1357
+ break;
1358
+ default:
1359
+ g_assert_not_reached();
1360
+ }
1361
+ env->vfp.xregs[ARM_VFP_FPSCR] =
1362
+ deposit32(env->vfp.xregs[ARM_VFP_FPSCR], 28, 4, flags);
1363
+}
1364
+
1365
+/* XXX: check quiet/signaling case */
1366
+#define DO_VFP_cmp(p, type) \
1367
+void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
1368
+{ \
1369
+ softfloat_to_vfp_compare(env, \
1370
+ type ## _compare_quiet(a, b, &env->vfp.fp_status)); \
1371
+} \
1372
+void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
1373
+{ \
1374
+ softfloat_to_vfp_compare(env, \
1375
+ type ## _compare(a, b, &env->vfp.fp_status)); \
1376
+}
1377
+DO_VFP_cmp(s, float32)
1378
+DO_VFP_cmp(d, float64)
1379
+#undef DO_VFP_cmp
1380
+
1381
+/* Integer to float and float to integer conversions */
1382
+
1383
+#define CONV_ITOF(name, ftype, fsz, sign) \
1384
+ftype HELPER(name)(uint32_t x, void *fpstp) \
1385
+{ \
1386
+ float_status *fpst = fpstp; \
1387
+ return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
1388
+}
1389
+
1390
+#define CONV_FTOI(name, ftype, fsz, sign, round) \
1391
+sign##int32_t HELPER(name)(ftype x, void *fpstp) \
1392
+{ \
1393
+ float_status *fpst = fpstp; \
1394
+ if (float##fsz##_is_any_nan(x)) { \
1395
+ float_raise(float_flag_invalid, fpst); \
1396
+ return 0; \
1397
+ } \
1398
+ return float##fsz##_to_##sign##int32##round(x, fpst); \
1399
+}
1400
+
1401
+#define FLOAT_CONVS(name, p, ftype, fsz, sign) \
1402
+ CONV_ITOF(vfp_##name##to##p, ftype, fsz, sign) \
1403
+ CONV_FTOI(vfp_to##name##p, ftype, fsz, sign, ) \
1404
+ CONV_FTOI(vfp_to##name##z##p, ftype, fsz, sign, _round_to_zero)
1405
+
1406
+FLOAT_CONVS(si, h, uint32_t, 16, )
1407
+FLOAT_CONVS(si, s, float32, 32, )
1408
+FLOAT_CONVS(si, d, float64, 64, )
1409
+FLOAT_CONVS(ui, h, uint32_t, 16, u)
1410
+FLOAT_CONVS(ui, s, float32, 32, u)
1411
+FLOAT_CONVS(ui, d, float64, 64, u)
1412
+
1413
+#undef CONV_ITOF
1414
+#undef CONV_FTOI
1415
+#undef FLOAT_CONVS
1416
+
1417
+/* floating point conversion */
1418
+float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
1419
+{
1420
+ return float32_to_float64(x, &env->vfp.fp_status);
1421
+}
1422
+
1423
+float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
1424
+{
1425
+ return float64_to_float32(x, &env->vfp.fp_status);
1426
+}
1427
+
1428
+/* VFP3 fixed point conversion. */
1429
+#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
1430
+float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
1431
+ void *fpstp) \
1432
+{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
1433
+
1434
+#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
1435
+uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
1436
+ void *fpst) \
1437
+{ \
1438
+ if (unlikely(float##fsz##_is_any_nan(x))) { \
1439
+ float_raise(float_flag_invalid, fpst); \
1440
+ return 0; \
1441
+ } \
1442
+ return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
1443
+}
1444
+
1445
+#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
1446
+VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
1447
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
1448
+ float_round_to_zero, _round_to_zero) \
1449
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
1450
+ get_float_rounding_mode(fpst), )
1451
+
1452
+#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
1453
+VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
1454
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
1455
+ get_float_rounding_mode(fpst), )
1456
+
1457
+VFP_CONV_FIX(sh, d, 64, 64, int16)
1458
+VFP_CONV_FIX(sl, d, 64, 64, int32)
1459
+VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
1460
+VFP_CONV_FIX(uh, d, 64, 64, uint16)
1461
+VFP_CONV_FIX(ul, d, 64, 64, uint32)
1462
+VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
1463
+VFP_CONV_FIX(sh, s, 32, 32, int16)
1464
+VFP_CONV_FIX(sl, s, 32, 32, int32)
1465
+VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
1466
+VFP_CONV_FIX(uh, s, 32, 32, uint16)
1467
+VFP_CONV_FIX(ul, s, 32, 32, uint32)
1468
+VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
1469
+
1470
+#undef VFP_CONV_FIX
1471
+#undef VFP_CONV_FIX_FLOAT
1472
+#undef VFP_CONV_FLOAT_FIX_ROUND
1473
+#undef VFP_CONV_FIX_A64
1474
+
1475
+uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
1476
+{
1477
+ return int32_to_float16_scalbn(x, -shift, fpst);
1478
+}
1479
+
1480
+uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
1481
+{
1482
+ return uint32_to_float16_scalbn(x, -shift, fpst);
1483
+}
1484
+
1485
+uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
1486
+{
1487
+ return int64_to_float16_scalbn(x, -shift, fpst);
1488
+}
1489
+
1490
+uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
1491
+{
1492
+ return uint64_to_float16_scalbn(x, -shift, fpst);
1493
+}
1494
+
1495
+uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
1496
+{
1497
+ if (unlikely(float16_is_any_nan(x))) {
1498
+ float_raise(float_flag_invalid, fpst);
1499
+ return 0;
1500
+ }
1501
+ return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
1502
+ shift, fpst);
1503
+}
1504
+
1505
+uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
1506
+{
1507
+ if (unlikely(float16_is_any_nan(x))) {
1508
+ float_raise(float_flag_invalid, fpst);
1509
+ return 0;
1510
+ }
1511
+ return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
1512
+ shift, fpst);
1513
+}
1514
+
1515
+uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
1516
+{
1517
+ if (unlikely(float16_is_any_nan(x))) {
1518
+ float_raise(float_flag_invalid, fpst);
1519
+ return 0;
1520
+ }
1521
+ return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
1522
+ shift, fpst);
1523
+}
1524
+
1525
+uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
1526
+{
1527
+ if (unlikely(float16_is_any_nan(x))) {
1528
+ float_raise(float_flag_invalid, fpst);
1529
+ return 0;
1530
+ }
1531
+ return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
1532
+ shift, fpst);
1533
+}
1534
+
1535
+uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
1536
+{
1537
+ if (unlikely(float16_is_any_nan(x))) {
1538
+ float_raise(float_flag_invalid, fpst);
1539
+ return 0;
1540
+ }
1541
+ return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
1542
+ shift, fpst);
1543
+}
1544
+
1545
+uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
1546
+{
1547
+ if (unlikely(float16_is_any_nan(x))) {
1548
+ float_raise(float_flag_invalid, fpst);
1549
+ return 0;
1550
+ }
1551
+ return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
1552
+ shift, fpst);
1553
+}
1554
+
1555
+/* Set the current fp rounding mode and return the old one.
1556
+ * The argument is a softfloat float_round_ value.
1557
+ */
1558
+uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
1559
+{
1560
+ float_status *fp_status = fpstp;
1561
+
1562
+ uint32_t prev_rmode = get_float_rounding_mode(fp_status);
1563
+ set_float_rounding_mode(rmode, fp_status);
1564
+
1565
+ return prev_rmode;
1566
+}
1567
+
1568
+/* Set the current fp rounding mode in the standard fp status and return
1569
+ * the old one. This is for NEON instructions that need to change the
1570
+ * rounding mode but wish to use the standard FPSCR values for everything
1571
+ * else. Always set the rounding mode back to the correct value after
1572
+ * modifying it.
1573
+ * The argument is a softfloat float_round_ value.
1574
+ */
1575
+uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
1576
+{
1577
+ float_status *fp_status = &env->vfp.standard_fp_status;
1578
+
1579
+ uint32_t prev_rmode = get_float_rounding_mode(fp_status);
1580
+ set_float_rounding_mode(rmode, fp_status);
1581
+
1582
+ return prev_rmode;
1583
+}
1584
+
1585
+/* Half precision conversions. */
1586
+float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode)
1587
+{
1588
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
1589
+ * it would affect flushing input denormals.
1590
+ */
1591
+ float_status *fpst = fpstp;
1592
+ flag save = get_flush_inputs_to_zero(fpst);
1593
+ set_flush_inputs_to_zero(false, fpst);
1594
+ float32 r = float16_to_float32(a, !ahp_mode, fpst);
1595
+ set_flush_inputs_to_zero(save, fpst);
1596
+ return r;
1597
+}
1598
+
1599
+uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode)
1600
+{
1601
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
1602
+ * it would affect flushing output denormals.
1603
+ */
1604
+ float_status *fpst = fpstp;
1605
+ flag save = get_flush_to_zero(fpst);
1606
+ set_flush_to_zero(false, fpst);
1607
+ float16 r = float32_to_float16(a, !ahp_mode, fpst);
1608
+ set_flush_to_zero(save, fpst);
1609
+ return r;
1610
+}
1611
+
1612
+float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, void *fpstp, uint32_t ahp_mode)
1613
+{
1614
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
1615
+ * it would affect flushing input denormals.
1616
+ */
1617
+ float_status *fpst = fpstp;
1618
+ flag save = get_flush_inputs_to_zero(fpst);
1619
+ set_flush_inputs_to_zero(false, fpst);
1620
+ float64 r = float16_to_float64(a, !ahp_mode, fpst);
1621
+ set_flush_inputs_to_zero(save, fpst);
1622
+ return r;
1623
+}
1624
+
1625
+uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
1626
+{
1627
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
1628
+ * it would affect flushing output denormals.
1629
+ */
1630
+ float_status *fpst = fpstp;
1631
+ flag save = get_flush_to_zero(fpst);
1632
+ set_flush_to_zero(false, fpst);
1633
+ float16 r = float64_to_float16(a, !ahp_mode, fpst);
1634
+ set_flush_to_zero(save, fpst);
1635
+ return r;
1636
+}
1637
+
1638
+#define float32_two make_float32(0x40000000)
1639
+#define float32_three make_float32(0x40400000)
1640
+#define float32_one_point_five make_float32(0x3fc00000)
1641
+
1642
+float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
1643
+{
1644
+ float_status *s = &env->vfp.standard_fp_status;
1645
+ if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
1646
+ (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
1647
+ if (!(float32_is_zero(a) || float32_is_zero(b))) {
1648
+ float_raise(float_flag_input_denormal, s);
1649
+ }
1650
+ return float32_two;
1651
+ }
1652
+ return float32_sub(float32_two, float32_mul(a, b, s), s);
1653
+}
1654
+
1655
+float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
1656
+{
1657
+ float_status *s = &env->vfp.standard_fp_status;
1658
+ float32 product;
1659
+ if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
1660
+ (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
1661
+ if (!(float32_is_zero(a) || float32_is_zero(b))) {
1662
+ float_raise(float_flag_input_denormal, s);
1663
+ }
1664
+ return float32_one_point_five;
1665
+ }
1666
+ product = float32_mul(a, b, s);
1667
+ return float32_div(float32_sub(float32_three, product, s), float32_two, s);
1668
+}
1669
+
1670
+/* NEON helpers. */
1671
+
1672
+/* Constants 256 and 512 are used in some helpers; we avoid relying on
1673
+ * int->float conversions at run-time. */
1674
+#define float64_256 make_float64(0x4070000000000000LL)
1675
+#define float64_512 make_float64(0x4080000000000000LL)
1676
+#define float16_maxnorm make_float16(0x7bff)
1677
+#define float32_maxnorm make_float32(0x7f7fffff)
1678
+#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
1679
+
1680
+/* Reciprocal functions
1681
+ *
1682
+ * The algorithm that must be used to calculate the estimate
1683
+ * is specified by the ARM ARM, see FPRecipEstimate()/RecipEstimate
1684
+ */
1685
+
1686
+/* See RecipEstimate()
1687
+ *
1688
+ * input is a 9 bit fixed point number
1689
+ * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
1690
+ * result range 256 .. 511 for a number from 1.0 to 511/256.
1691
+ */
1692
+
1693
+static int recip_estimate(int input)
1694
+{
1695
+ int a, b, r;
1696
+ assert(256 <= input && input < 512);
1697
+ a = (input * 2) + 1;
1698
+ b = (1 << 19) / a;
1699
+ r = (b + 1) >> 1;
1700
+ assert(256 <= r && r < 512);
1701
+ return r;
1702
+}
1703
+
1704
+/*
1705
+ * Common wrapper to call recip_estimate
1706
+ *
1707
+ * The parameters are exponent and 64 bit fraction (without implicit
1708
+ * bit) where the binary point is nominally at bit 52. Returns a
1709
+ * float64 which can then be rounded to the appropriate size by the
1710
+ * callee.
1711
+ */
1712
+
1713
+static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac)
1714
+{
1715
+ uint32_t scaled, estimate;
1716
+ uint64_t result_frac;
1717
+ int result_exp;
1718
+
1719
+ /* Handle sub-normals */
1720
+ if (*exp == 0) {
1721
+ if (extract64(frac, 51, 1) == 0) {
1722
+ *exp = -1;
1723
+ frac <<= 2;
1724
+ } else {
1725
+ frac <<= 1;
1726
+ }
1727
+ }
1728
+
1729
+ /* scaled = UInt('1':fraction<51:44>) */
1730
+ scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
1731
+ estimate = recip_estimate(scaled);
1732
+
1733
+ result_exp = exp_off - *exp;
1734
+ result_frac = deposit64(0, 44, 8, estimate);
1735
+ if (result_exp == 0) {
1736
+ result_frac = deposit64(result_frac >> 1, 51, 1, 1);
1737
+ } else if (result_exp == -1) {
1738
+ result_frac = deposit64(result_frac >> 2, 50, 2, 1);
1739
+ result_exp = 0;
1740
+ }
1741
+
1742
+ *exp = result_exp;
1743
+
1744
+ return result_frac;
1745
+}
1746
+
1747
+static bool round_to_inf(float_status *fpst, bool sign_bit)
1748
+{
1749
+ switch (fpst->float_rounding_mode) {
1750
+ case float_round_nearest_even: /* Round to Nearest */
1751
+ return true;
1752
+ case float_round_up: /* Round to +Inf */
1753
+ return !sign_bit;
1754
+ case float_round_down: /* Round to -Inf */
1755
+ return sign_bit;
1756
+ case float_round_to_zero: /* Round to Zero */
1757
+ return false;
1758
+ }
1759
+
1760
+ g_assert_not_reached();
1761
+}
1762
+
1763
+uint32_t HELPER(recpe_f16)(uint32_t input, void *fpstp)
1764
+{
1765
+ float_status *fpst = fpstp;
1766
+ float16 f16 = float16_squash_input_denormal(input, fpst);
1767
+ uint32_t f16_val = float16_val(f16);
1768
+ uint32_t f16_sign = float16_is_neg(f16);
1769
+ int f16_exp = extract32(f16_val, 10, 5);
1770
+ uint32_t f16_frac = extract32(f16_val, 0, 10);
1771
+ uint64_t f64_frac;
1772
+
1773
+ if (float16_is_any_nan(f16)) {
1774
+ float16 nan = f16;
1775
+ if (float16_is_signaling_nan(f16, fpst)) {
1776
+ float_raise(float_flag_invalid, fpst);
1777
+ nan = float16_silence_nan(f16, fpst);
1778
+ }
1779
+ if (fpst->default_nan_mode) {
1780
+ nan = float16_default_nan(fpst);
1781
+ }
1782
+ return nan;
1783
+ } else if (float16_is_infinity(f16)) {
1784
+ return float16_set_sign(float16_zero, float16_is_neg(f16));
1785
+ } else if (float16_is_zero(f16)) {
1786
+ float_raise(float_flag_divbyzero, fpst);
1787
+ return float16_set_sign(float16_infinity, float16_is_neg(f16));
1788
+ } else if (float16_abs(f16) < (1 << 8)) {
1789
+ /* Abs(value) < 2.0^-16 */
1790
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
1791
+ if (round_to_inf(fpst, f16_sign)) {
1792
+ return float16_set_sign(float16_infinity, f16_sign);
1793
+ } else {
1794
+ return float16_set_sign(float16_maxnorm, f16_sign);
1795
+ }
1796
+ } else if (f16_exp >= 29 && fpst->flush_to_zero) {
1797
+ float_raise(float_flag_underflow, fpst);
1798
+ return float16_set_sign(float16_zero, float16_is_neg(f16));
1799
+ }
1800
+
1801
+ f64_frac = call_recip_estimate(&f16_exp, 29,
1802
+ ((uint64_t) f16_frac) << (52 - 10));
1803
+
1804
+ /* result = sign : result_exp<4:0> : fraction<51:42> */
1805
+ f16_val = deposit32(0, 15, 1, f16_sign);
1806
+ f16_val = deposit32(f16_val, 10, 5, f16_exp);
1807
+ f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
1808
+ return make_float16(f16_val);
1809
+}
1810
+
1811
+float32 HELPER(recpe_f32)(float32 input, void *fpstp)
1812
+{
1813
+ float_status *fpst = fpstp;
1814
+ float32 f32 = float32_squash_input_denormal(input, fpst);
1815
+ uint32_t f32_val = float32_val(f32);
1816
+ bool f32_sign = float32_is_neg(f32);
1817
+ int f32_exp = extract32(f32_val, 23, 8);
1818
+ uint32_t f32_frac = extract32(f32_val, 0, 23);
1819
+ uint64_t f64_frac;
1820
+
1821
+ if (float32_is_any_nan(f32)) {
1822
+ float32 nan = f32;
1823
+ if (float32_is_signaling_nan(f32, fpst)) {
1824
+ float_raise(float_flag_invalid, fpst);
1825
+ nan = float32_silence_nan(f32, fpst);
1826
+ }
1827
+ if (fpst->default_nan_mode) {
1828
+ nan = float32_default_nan(fpst);
1829
+ }
1830
+ return nan;
1831
+ } else if (float32_is_infinity(f32)) {
1832
+ return float32_set_sign(float32_zero, float32_is_neg(f32));
1833
+ } else if (float32_is_zero(f32)) {
1834
+ float_raise(float_flag_divbyzero, fpst);
1835
+ return float32_set_sign(float32_infinity, float32_is_neg(f32));
1836
+ } else if (float32_abs(f32) < (1ULL << 21)) {
1837
+ /* Abs(value) < 2.0^-128 */
1838
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
1839
+ if (round_to_inf(fpst, f32_sign)) {
1840
+ return float32_set_sign(float32_infinity, f32_sign);
1841
+ } else {
1842
+ return float32_set_sign(float32_maxnorm, f32_sign);
1843
+ }
1844
+ } else if (f32_exp >= 253 && fpst->flush_to_zero) {
1845
+ float_raise(float_flag_underflow, fpst);
1846
+ return float32_set_sign(float32_zero, float32_is_neg(f32));
1847
+ }
1848
+
1849
+ f64_frac = call_recip_estimate(&f32_exp, 253,
1850
+ ((uint64_t) f32_frac) << (52 - 23));
1851
+
1852
+ /* result = sign : result_exp<7:0> : fraction<51:29> */
1853
+ f32_val = deposit32(0, 31, 1, f32_sign);
1854
+ f32_val = deposit32(f32_val, 23, 8, f32_exp);
1855
+ f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
1856
+ return make_float32(f32_val);
1857
+}
1858
+
1859
+float64 HELPER(recpe_f64)(float64 input, void *fpstp)
1860
+{
1861
+ float_status *fpst = fpstp;
1862
+ float64 f64 = float64_squash_input_denormal(input, fpst);
1863
+ uint64_t f64_val = float64_val(f64);
1864
+ bool f64_sign = float64_is_neg(f64);
1865
+ int f64_exp = extract64(f64_val, 52, 11);
1866
+ uint64_t f64_frac = extract64(f64_val, 0, 52);
1867
+
1868
+ /* Deal with any special cases */
1869
+ if (float64_is_any_nan(f64)) {
1870
+ float64 nan = f64;
1871
+ if (float64_is_signaling_nan(f64, fpst)) {
1872
+ float_raise(float_flag_invalid, fpst);
1873
+ nan = float64_silence_nan(f64, fpst);
1874
+ }
1875
+ if (fpst->default_nan_mode) {
1876
+ nan = float64_default_nan(fpst);
1877
+ }
1878
+ return nan;
1879
+ } else if (float64_is_infinity(f64)) {
1880
+ return float64_set_sign(float64_zero, float64_is_neg(f64));
1881
+ } else if (float64_is_zero(f64)) {
1882
+ float_raise(float_flag_divbyzero, fpst);
1883
+ return float64_set_sign(float64_infinity, float64_is_neg(f64));
1884
+ } else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
1885
+ /* Abs(value) < 2.0^-1024 */
1886
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
1887
+ if (round_to_inf(fpst, f64_sign)) {
1888
+ return float64_set_sign(float64_infinity, f64_sign);
1889
+ } else {
1890
+ return float64_set_sign(float64_maxnorm, f64_sign);
1891
+ }
1892
+ } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
1893
+ float_raise(float_flag_underflow, fpst);
1894
+ return float64_set_sign(float64_zero, float64_is_neg(f64));
1895
+ }
1896
+
1897
+ f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac);
1898
+
1899
+ /* result = sign : result_exp<10:0> : fraction<51:0>; */
1900
+ f64_val = deposit64(0, 63, 1, f64_sign);
1901
+ f64_val = deposit64(f64_val, 52, 11, f64_exp);
1902
+ f64_val = deposit64(f64_val, 0, 52, f64_frac);
1903
+ return make_float64(f64_val);
1904
+}
1905
+
1906
+/* The algorithm that must be used to calculate the estimate
1907
+ * is specified by the ARM ARM.
1908
+ */
1909
+
1910
+static int do_recip_sqrt_estimate(int a)
1911
+{
1912
+ int b, estimate;
1913
+
1914
+ assert(128 <= a && a < 512);
1915
+ if (a < 256) {
1916
+ a = a * 2 + 1;
1917
+ } else {
1918
+ a = (a >> 1) << 1;
1919
+ a = (a + 1) * 2;
1920
+ }
1921
+ b = 512;
1922
+ while (a * (b + 1) * (b + 1) < (1 << 28)) {
1923
+ b += 1;
1924
+ }
1925
+ estimate = (b + 1) / 2;
1926
+ assert(256 <= estimate && estimate < 512);
1927
+
1928
+ return estimate;
1929
+}
1930
+
1931
+
1932
+static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac)
1933
+{
1934
+ int estimate;
1935
+ uint32_t scaled;
1936
+
1937
+ if (*exp == 0) {
1938
+ while (extract64(frac, 51, 1) == 0) {
1939
+ frac = frac << 1;
1940
+ *exp -= 1;
1941
+ }
1942
+ frac = extract64(frac, 0, 51) << 1;
1943
+ }
1944
+
1945
+ if (*exp & 1) {
1946
+ /* scaled = UInt('01':fraction<51:45>) */
1947
+ scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
1948
+ } else {
1949
+ /* scaled = UInt('1':fraction<51:44>) */
1950
+ scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
1951
+ }
1952
+ estimate = do_recip_sqrt_estimate(scaled);
1953
+
1954
+ *exp = (exp_off - *exp) / 2;
1955
+ return extract64(estimate, 0, 8) << 44;
1956
+}
1957
+
1958
+uint32_t HELPER(rsqrte_f16)(uint32_t input, void *fpstp)
1959
+{
1960
+ float_status *s = fpstp;
1961
+ float16 f16 = float16_squash_input_denormal(input, s);
1962
+ uint16_t val = float16_val(f16);
1963
+ bool f16_sign = float16_is_neg(f16);
1964
+ int f16_exp = extract32(val, 10, 5);
1965
+ uint16_t f16_frac = extract32(val, 0, 10);
1966
+ uint64_t f64_frac;
1967
+
1968
+ if (float16_is_any_nan(f16)) {
1969
+ float16 nan = f16;
1970
+ if (float16_is_signaling_nan(f16, s)) {
1971
+ float_raise(float_flag_invalid, s);
1972
+ nan = float16_silence_nan(f16, s);
1973
+ }
1974
+ if (s->default_nan_mode) {
1975
+ nan = float16_default_nan(s);
1976
+ }
1977
+ return nan;
1978
+ } else if (float16_is_zero(f16)) {
1979
+ float_raise(float_flag_divbyzero, s);
1980
+ return float16_set_sign(float16_infinity, f16_sign);
1981
+ } else if (f16_sign) {
1982
+ float_raise(float_flag_invalid, s);
1983
+ return float16_default_nan(s);
1984
+ } else if (float16_is_infinity(f16)) {
1985
+ return float16_zero;
1986
+ }
1987
+
1988
+ /* Scale and normalize to a double-precision value between 0.25 and 1.0,
1989
+ * preserving the parity of the exponent. */
1990
+
1991
+ f64_frac = ((uint64_t) f16_frac) << (52 - 10);
1992
+
1993
+ f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac);
1994
+
1995
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
1996
+ val = deposit32(0, 15, 1, f16_sign);
1997
+ val = deposit32(val, 10, 5, f16_exp);
1998
+ val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
1999
+ return make_float16(val);
2000
+}
2001
+
2002
+float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
2003
+{
2004
+ float_status *s = fpstp;
2005
+ float32 f32 = float32_squash_input_denormal(input, s);
2006
+ uint32_t val = float32_val(f32);
2007
+ uint32_t f32_sign = float32_is_neg(f32);
2008
+ int f32_exp = extract32(val, 23, 8);
2009
+ uint32_t f32_frac = extract32(val, 0, 23);
2010
+ uint64_t f64_frac;
2011
+
2012
+ if (float32_is_any_nan(f32)) {
2013
+ float32 nan = f32;
2014
+ if (float32_is_signaling_nan(f32, s)) {
2015
+ float_raise(float_flag_invalid, s);
2016
+ nan = float32_silence_nan(f32, s);
2017
+ }
2018
+ if (s->default_nan_mode) {
2019
+ nan = float32_default_nan(s);
2020
+ }
2021
+ return nan;
2022
+ } else if (float32_is_zero(f32)) {
2023
+ float_raise(float_flag_divbyzero, s);
2024
+ return float32_set_sign(float32_infinity, float32_is_neg(f32));
2025
+ } else if (float32_is_neg(f32)) {
2026
+ float_raise(float_flag_invalid, s);
2027
+ return float32_default_nan(s);
2028
+ } else if (float32_is_infinity(f32)) {
2029
+ return float32_zero;
2030
+ }
2031
+
2032
+ /* Scale and normalize to a double-precision value between 0.25 and 1.0,
2033
+ * preserving the parity of the exponent. */
2034
+
2035
+ f64_frac = ((uint64_t) f32_frac) << 29;
2036
+
2037
+ f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac);
2038
+
2039
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(15) */
2040
+ val = deposit32(0, 31, 1, f32_sign);
2041
+ val = deposit32(val, 23, 8, f32_exp);
2042
+ val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
2043
+ return make_float32(val);
2044
+}
2045
+
2046
+float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
2047
+{
2048
+ float_status *s = fpstp;
2049
+ float64 f64 = float64_squash_input_denormal(input, s);
2050
+ uint64_t val = float64_val(f64);
2051
+ bool f64_sign = float64_is_neg(f64);
2052
+ int f64_exp = extract64(val, 52, 11);
2053
+ uint64_t f64_frac = extract64(val, 0, 52);
2054
+
2055
+ if (float64_is_any_nan(f64)) {
2056
+ float64 nan = f64;
2057
+ if (float64_is_signaling_nan(f64, s)) {
2058
+ float_raise(float_flag_invalid, s);
2059
+ nan = float64_silence_nan(f64, s);
2060
+ }
2061
+ if (s->default_nan_mode) {
2062
+ nan = float64_default_nan(s);
2063
+ }
2064
+ return nan;
2065
+ } else if (float64_is_zero(f64)) {
2066
+ float_raise(float_flag_divbyzero, s);
2067
+ return float64_set_sign(float64_infinity, float64_is_neg(f64));
2068
+ } else if (float64_is_neg(f64)) {
2069
+ float_raise(float_flag_invalid, s);
2070
+ return float64_default_nan(s);
2071
+ } else if (float64_is_infinity(f64)) {
2072
+ return float64_zero;
2073
+ }
2074
+
2075
+ f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac);
2076
+
2077
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
2078
+ val = deposit64(0, 61, 1, f64_sign);
2079
+ val = deposit64(val, 52, 11, f64_exp);
2080
+ val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
2081
+ return make_float64(val);
2082
+}
2083
+
2084
+uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
2085
+{
2086
+ /* float_status *s = fpstp; */
2087
+ int input, estimate;
2088
+
2089
+ if ((a & 0x80000000) == 0) {
2090
+ return 0xffffffff;
2091
+ }
2092
+
2093
+ input = extract32(a, 23, 9);
2094
+ estimate = recip_estimate(input);
2095
+
2096
+ return deposit32(0, (32 - 9), 9, estimate);
2097
+}
2098
+
2099
+uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
2100
+{
2101
+ int estimate;
2102
+
2103
+ if ((a & 0xc0000000) == 0) {
2104
+ return 0xffffffff;
2105
+ }
2106
+
2107
+ estimate = do_recip_sqrt_estimate(extract32(a, 23, 9));
2108
+
2109
+ return deposit32(0, 23, 9, estimate);
2110
+}
2111
+
2112
+/* VFPv4 fused multiply-accumulate */
2113
+float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
2114
+{
2115
+ float_status *fpst = fpstp;
2116
+ return float32_muladd(a, b, c, 0, fpst);
2117
+}
2118
+
2119
+float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
2120
+{
2121
+ float_status *fpst = fpstp;
2122
+ return float64_muladd(a, b, c, 0, fpst);
2123
+}
2124
+
2125
+/* ARMv8 round to integral */
2126
+float32 HELPER(rints_exact)(float32 x, void *fp_status)
2127
+{
2128
+ return float32_round_to_int(x, fp_status);
2129
+}
2130
+
2131
+float64 HELPER(rintd_exact)(float64 x, void *fp_status)
2132
+{
2133
+ return float64_round_to_int(x, fp_status);
2134
+}
2135
+
2136
+float32 HELPER(rints)(float32 x, void *fp_status)
2137
+{
2138
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
2139
+ float32 ret;
2140
+
2141
+ ret = float32_round_to_int(x, fp_status);
2142
+
2143
+ /* Suppress any inexact exceptions the conversion produced */
2144
+ if (!(old_flags & float_flag_inexact)) {
2145
+ new_flags = get_float_exception_flags(fp_status);
2146
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
2147
+ }
2148
+
2149
+ return ret;
2150
+}
2151
+
2152
+float64 HELPER(rintd)(float64 x, void *fp_status)
2153
+{
2154
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
2155
+ float64 ret;
2156
+
2157
+ ret = float64_round_to_int(x, fp_status);
2158
+
2159
+ new_flags = get_float_exception_flags(fp_status);
2160
+
2161
+ /* Suppress any inexact exceptions the conversion produced */
2162
+ if (!(old_flags & float_flag_inexact)) {
2163
+ new_flags = get_float_exception_flags(fp_status);
2164
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
2165
+ }
2166
+
2167
+ return ret;
2168
+}
2169
+
2170
+/* Convert ARM rounding mode to softfloat */
2171
+int arm_rmode_to_sf(int rmode)
2172
+{
2173
+ switch (rmode) {
2174
+ case FPROUNDING_TIEAWAY:
2175
+ rmode = float_round_ties_away;
2176
+ break;
2177
+ case FPROUNDING_ODD:
2178
+ /* FIXME: add support for TIEAWAY and ODD */
2179
+ qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
2180
+ rmode);
2181
+ /* fall through for now */
2182
+ case FPROUNDING_TIEEVEN:
2183
+ default:
2184
+ rmode = float_round_nearest_even;
2185
+ break;
2186
+ case FPROUNDING_POSINF:
2187
+ rmode = float_round_up;
2188
+ break;
2189
+ case FPROUNDING_NEGINF:
2190
+ rmode = float_round_down;
2191
+ break;
2192
+ case FPROUNDING_ZERO:
2193
+ rmode = float_round_to_zero;
2194
+ break;
2195
+ }
2196
+ return rmode;
2197
+}
2198
--
173
--
2199
2.20.1
174
2.20.1
2200
175
2201
176
diff view generated by jsdifflib
New patch
1
From: Guenter Roeck <linux@roeck-us.net>
1
2
3
USB ports on Xilinx Zync must be instantiated as TYPE_CHIPIDEA to work.
4
Linux expects and checks various chipidea registers, which do not exist
5
with the basic ehci emulation. This patch series fixes the problem.
6
7
Without this patch, USB ports fail to instantiate under Linux.
8
9
ci_hdrc ci_hdrc.0: doesn't support host
10
ci_hdrc ci_hdrc.0: no supported roles
11
12
With this patch, USB ports are instantiated, and it is possible
13
to boot from USB drive.
14
15
ci_hdrc ci_hdrc.0: EHCI Host Controller
16
ci_hdrc ci_hdrc.0: new USB bus registered, assigned bus number 1
17
ci_hdrc ci_hdrc.0: USB 2.0 started, EHCI 1.00
18
usb 1-1: new full-speed USB device number 2 using ci_hdrc
19
usb 1-1: not running at top speed; connect to a high speed hub
20
usb 1-1: config 1 interface 0 altsetting 0 endpoint 0x81 has invalid maxpacket 512, setting to 64
21
usb 1-1: config 1 interface 0 altsetting 0 endpoint 0x2 has invalid maxpacket 512, setting to 64
22
usb-storage 1-1:1.0: USB Mass Storage device detected
23
scsi host0: usb-storage 1-1:1.0
24
25
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
26
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
27
Message-id: 20200215122354.13706-2-linux@roeck-us.net
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
---
30
hw/arm/xilinx_zynq.c | 5 +++--
31
1 file changed, 3 insertions(+), 2 deletions(-)
32
33
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/xilinx_zynq.c
36
+++ b/hw/arm/xilinx_zynq.c
37
@@ -XXX,XX +XXX,XX @@
38
#include "hw/loader.h"
39
#include "hw/misc/zynq-xadc.h"
40
#include "hw/ssi/ssi.h"
41
+#include "hw/usb/chipidea.h"
42
#include "qemu/error-report.h"
43
#include "hw/sd/sdhci.h"
44
#include "hw/char/cadence_uart.h"
45
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
46
zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false);
47
zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true);
48
49
- sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]);
50
- sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]);
51
+ sysbus_create_simple(TYPE_CHIPIDEA, 0xE0002000, pic[53 - IRQ_OFFSET]);
52
+ sysbus_create_simple(TYPE_CHIPIDEA, 0xE0003000, pic[76 - IRQ_OFFSET]);
53
54
cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hd(0));
55
cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hd(1));
56
--
57
2.20.1
58
59
diff view generated by jsdifflib
1
The region 0x40010000 .. 0x4001ffff and its secure-only alias
1
From: Guenter Roeck <linux@roeck-us.net>
2
at 0x50010000... are for per-CPU devices. We implement this by
3
giving each CPU its own container memory region, where the
4
per-CPU devices live. Unfortunately, the alias region which
5
makes devices mapped at 0x4... addresses also appear at 0x5...
6
is only implemented in the overall "all CPUs" container. The
7
effect of this bug is that the CPU_IDENTITY register block appears
8
only at 0x4001f000, but not at the 0x5001f000 alias where it should
9
also appear. Guests (like very recent Arm Trusted Firmware-M)
10
which try to access it at 0x5001f000 will crash.
11
2
12
Fix this by moving the handling for this alias from the "all CPUs"
3
Xilinx USB devices are now instantiated through TYPE_CHIPIDEA,
13
container to the per-CPU container. (We leave the aliases for
4
and xlnx support in the EHCI code is no longer needed.
14
0x1... and 0x3... in the overall container, because there are
15
no per-CPU devices there.)
16
5
6
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
7
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
8
Message-id: 20200215122354.13706-3-linux@roeck-us.net
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20190215180500.6906-1-peter.maydell@linaro.org
19
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
20
---
10
---
21
include/hw/arm/armsse.h | 2 +-
11
hw/usb/hcd-ehci-sysbus.c | 17 -----------------
22
hw/arm/armsse.c | 26 ++++++++++++++++----------
12
1 file changed, 17 deletions(-)
23
2 files changed, 17 insertions(+), 11 deletions(-)
24
13
25
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
14
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
26
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/arm/armsse.h
16
--- a/hw/usb/hcd-ehci-sysbus.c
28
+++ b/include/hw/arm/armsse.h
17
+++ b/hw/usb/hcd-ehci-sysbus.c
29
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
18
@@ -XXX,XX +XXX,XX @@ static const TypeInfo ehci_platform_type_info = {
30
MemoryRegion cpu_container[SSE_MAX_CPUS];
19
.class_init = ehci_platform_class_init,
31
MemoryRegion alias1;
32
MemoryRegion alias2;
33
- MemoryRegion alias3;
34
+ MemoryRegion alias3[SSE_MAX_CPUS];
35
MemoryRegion sram[MAX_SRAM_BANKS];
36
37
qemu_irq *exp_irqs[SSE_MAX_CPUS];
38
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/arm/armsse.c
41
+++ b/hw/arm/armsse.c
42
@@ -XXX,XX +XXX,XX @@ static bool irq_is_common[32] = {
43
/* 30, 31: reserved */
44
};
20
};
45
21
46
-/* Create an alias region of @size bytes starting at @base
22
-static void ehci_xlnx_class_init(ObjectClass *oc, void *data)
47
+/*
23
-{
48
+ * Create an alias region in @container of @size bytes starting at @base
24
- SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
49
* which mirrors the memory starting at @orig.
25
- DeviceClass *dc = DEVICE_CLASS(oc);
50
*/
26
-
51
-static void make_alias(ARMSSE *s, MemoryRegion *mr, const char *name,
27
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
52
- hwaddr base, hwaddr size, hwaddr orig)
28
- sec->capsbase = 0x100;
53
+static void make_alias(ARMSSE *s, MemoryRegion *mr, MemoryRegion *container,
29
- sec->opregbase = 0x140;
54
+ const char *name, hwaddr base, hwaddr size, hwaddr orig)
30
-}
31
-
32
-static const TypeInfo ehci_xlnx_type_info = {
33
- .name = "xlnx,ps7-usb",
34
- .parent = TYPE_SYS_BUS_EHCI,
35
- .class_init = ehci_xlnx_class_init,
36
-};
37
-
38
static void ehci_exynos4210_class_init(ObjectClass *oc, void *data)
55
{
39
{
56
- memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
40
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
57
+ memory_region_init_alias(mr, NULL, name, container, orig, size);
41
@@ -XXX,XX +XXX,XX @@ static void ehci_sysbus_register_types(void)
58
/* The alias is even lower priority than unimplemented_device regions */
42
{
59
- memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
43
type_register_static(&ehci_type_info);
60
+ memory_region_add_subregion_overlap(container, base, mr, -1500);
44
type_register_static(&ehci_platform_type_info);
61
}
45
- type_register_static(&ehci_xlnx_type_info);
62
46
type_register_static(&ehci_exynos4210_type_info);
63
static void irq_status_forwarder(void *opaque, int n, int level)
47
type_register_static(&ehci_tegra2_type_info);
64
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
48
type_register_static(&ehci_ppc4xx_type_info);
65
}
66
67
/* Set up the big aliases first */
68
- make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
69
- make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
70
+ make_alias(s, &s->alias1, &s->container, "alias 1",
71
+ 0x10000000, 0x10000000, 0x00000000);
72
+ make_alias(s, &s->alias2, &s->container,
73
+ "alias 2", 0x30000000, 0x10000000, 0x20000000);
74
/* The 0x50000000..0x5fffffff region is not a pure alias: it has
75
* a few extra devices that only appear there (generally the
76
* control interfaces for the protection controllers).
77
* We implement this by mapping those devices over the top of this
78
- * alias MR at a higher priority.
79
+ * alias MR at a higher priority. Some of the devices in this range
80
+ * are per-CPU, so we must put this alias in the per-cpu containers.
81
*/
82
- make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
83
-
84
+ for (i = 0; i < info->num_cpus; i++) {
85
+ make_alias(s, &s->alias3[i], &s->cpu_container[i],
86
+ "alias 3", 0x50000000, 0x10000000, 0x40000000);
87
+ }
88
89
/* Security controller */
90
object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
91
--
49
--
92
2.20.1
50
2.20.1
93
51
94
52
diff view generated by jsdifflib
New patch
1
From: Thomas Huth <thuth@redhat.com>
1
2
3
Old kernels from the Meego project can be used to check that Linux
4
is at least starting on these machines.
5
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20200225172501.29609-2-philmd@redhat.com
12
Message-Id: <20200129131920.22302-1-thuth@redhat.com>
13
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
MAINTAINERS | 1 +
17
tests/acceptance/machine_arm_n8x0.py | 49 ++++++++++++++++++++++++++++
18
2 files changed, 50 insertions(+)
19
create mode 100644 tests/acceptance/machine_arm_n8x0.py
20
21
diff --git a/MAINTAINERS b/MAINTAINERS
22
index XXXXXXX..XXXXXXX 100644
23
--- a/MAINTAINERS
24
+++ b/MAINTAINERS
25
@@ -XXX,XX +XXX,XX @@ F: hw/rtc/twl92230.c
26
F: include/hw/display/blizzard.h
27
F: include/hw/input/tsc2xxx.h
28
F: include/hw/misc/cbus.h
29
+F: tests/acceptance/machine_arm_n8x0.py
30
31
Palm
32
M: Andrzej Zaborowski <balrogg@gmail.com>
33
diff --git a/tests/acceptance/machine_arm_n8x0.py b/tests/acceptance/machine_arm_n8x0.py
34
new file mode 100644
35
index XXXXXXX..XXXXXXX
36
--- /dev/null
37
+++ b/tests/acceptance/machine_arm_n8x0.py
38
@@ -XXX,XX +XXX,XX @@
39
+# Functional test that boots a Linux kernel and checks the console
40
+#
41
+# Copyright (c) 2020 Red Hat, Inc.
42
+#
43
+# Author:
44
+# Thomas Huth <thuth@redhat.com>
45
+#
46
+# This work is licensed under the terms of the GNU GPL, version 2 or
47
+# later. See the COPYING file in the top-level directory.
48
+
49
+import os
50
+
51
+from avocado import skipUnless
52
+from avocado_qemu import Test
53
+from avocado_qemu import wait_for_console_pattern
54
+
55
+class N8x0Machine(Test):
56
+ """Boots the Linux kernel and checks that the console is operational"""
57
+
58
+ timeout = 90
59
+
60
+ def __do_test_n8x0(self):
61
+ kernel_url = ('http://stskeeps.subnetmask.net/meego-n8x0/'
62
+ 'meego-arm-n8x0-1.0.80.20100712.1431-'
63
+ 'vmlinuz-2.6.35~rc4-129.1-n8x0')
64
+ kernel_hash = 'e9d5ab8d7548923a0061b6fbf601465e479ed269'
65
+ kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
66
+
67
+ self.vm.set_console(console_index=1)
68
+ self.vm.add_args('-kernel', kernel_path,
69
+ '-append', 'printk.time=0 console=ttyS1')
70
+ self.vm.launch()
71
+ wait_for_console_pattern(self, 'TSC2005 driver initializing')
72
+
73
+ @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
74
+ def test_n800(self):
75
+ """
76
+ :avocado: tags=arch:arm
77
+ :avocado: tags=machine:n800
78
+ """
79
+ self.__do_test_n8x0()
80
+
81
+ @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
82
+ def test_n810(self):
83
+ """
84
+ :avocado: tags=arch:arm
85
+ :avocado: tags=machine:n810
86
+ """
87
+ self.__do_test_n8x0()
88
--
89
2.20.1
90
91
diff view generated by jsdifflib
1
Create a new include file for the pl031's device struct,
1
From: Thomas Huth <thuth@redhat.com>
2
type macros, etc, so that it can be instantiated using
3
the "embedded struct" coding style.
4
2
3
There is a kernel and initrd available on github which we can use
4
for testing this machine.
5
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20200225172501.29609-3-philmd@redhat.com
12
Message-Id: <20200131170233.14584-1-thuth@redhat.com>
13
[PMD: Renamed test method, moved description from class to method]
14
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
16
---
9
include/hw/timer/pl031.h | 44 ++++++++++++++++++++++++++++++++++++++++
17
MAINTAINERS | 1 +
10
hw/timer/pl031.c | 25 +----------------------
18
tests/acceptance/machine_arm_integratorcp.py | 43 ++++++++++++++++++++
11
MAINTAINERS | 1 +
19
2 files changed, 44 insertions(+)
12
3 files changed, 46 insertions(+), 24 deletions(-)
20
create mode 100644 tests/acceptance/machine_arm_integratorcp.py
13
create mode 100644 include/hw/timer/pl031.h
14
21
15
diff --git a/include/hw/timer/pl031.h b/include/hw/timer/pl031.h
16
new file mode 100644
17
index XXXXXXX..XXXXXXX
18
--- /dev/null
19
+++ b/include/hw/timer/pl031.h
20
@@ -XXX,XX +XXX,XX @@
21
+/*
22
+ * ARM AMBA PrimeCell PL031 RTC
23
+ *
24
+ * Copyright (c) 2007 CodeSourcery
25
+ *
26
+ * This file is free software; you can redistribute it and/or modify
27
+ * it under the terms of the GNU General Public License version 2 as
28
+ * published by the Free Software Foundation.
29
+ *
30
+ * Contributions after 2012-01-13 are licensed under the terms of the
31
+ * GNU GPL, version 2 or (at your option) any later version.
32
+ */
33
+
34
+#ifndef HW_TIMER_PL031
35
+#define HW_TIMER_PL031
36
+
37
+#include "hw/sysbus.h"
38
+
39
+#define TYPE_PL031 "pl031"
40
+#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
41
+
42
+typedef struct PL031State {
43
+ SysBusDevice parent_obj;
44
+
45
+ MemoryRegion iomem;
46
+ QEMUTimer *timer;
47
+ qemu_irq irq;
48
+
49
+ /*
50
+ * Needed to preserve the tick_count across migration, even if the
51
+ * absolute value of the rtc_clock is different on the source and
52
+ * destination.
53
+ */
54
+ uint32_t tick_offset_vmstate;
55
+ uint32_t tick_offset;
56
+
57
+ uint32_t mr;
58
+ uint32_t lr;
59
+ uint32_t cr;
60
+ uint32_t im;
61
+ uint32_t is;
62
+} PL031State;
63
+
64
+#endif
65
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/timer/pl031.c
68
+++ b/hw/timer/pl031.c
69
@@ -XXX,XX +XXX,XX @@
70
*/
71
72
#include "qemu/osdep.h"
73
+#include "hw/timer/pl031.h"
74
#include "hw/sysbus.h"
75
#include "qemu/timer.h"
76
#include "sysemu/sysemu.h"
77
@@ -XXX,XX +XXX,XX @@ do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
78
#define RTC_MIS 0x18 /* Masked interrupt status register */
79
#define RTC_ICR 0x1c /* Interrupt clear register */
80
81
-#define TYPE_PL031 "pl031"
82
-#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
83
-
84
-typedef struct PL031State {
85
- SysBusDevice parent_obj;
86
-
87
- MemoryRegion iomem;
88
- QEMUTimer *timer;
89
- qemu_irq irq;
90
-
91
- /* Needed to preserve the tick_count across migration, even if the
92
- * absolute value of the rtc_clock is different on the source and
93
- * destination.
94
- */
95
- uint32_t tick_offset_vmstate;
96
- uint32_t tick_offset;
97
-
98
- uint32_t mr;
99
- uint32_t lr;
100
- uint32_t cr;
101
- uint32_t im;
102
- uint32_t is;
103
-} PL031State;
104
-
105
static const unsigned char pl031_id[] = {
106
0x31, 0x10, 0x14, 0x00, /* Device ID */
107
0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */
108
diff --git a/MAINTAINERS b/MAINTAINERS
22
diff --git a/MAINTAINERS b/MAINTAINERS
109
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
110
--- a/MAINTAINERS
24
--- a/MAINTAINERS
111
+++ b/MAINTAINERS
25
+++ b/MAINTAINERS
112
@@ -XXX,XX +XXX,XX @@ F: hw/sd/pl181.c
26
@@ -XXX,XX +XXX,XX @@ S: Maintained
113
F: hw/ssi/pl022.c
27
F: hw/arm/integratorcp.c
114
F: include/hw/ssi/pl022.h
28
F: hw/misc/arm_integrator_debug.c
115
F: hw/timer/pl031.c
29
F: include/hw/misc/arm_integrator_debug.h
116
+F: include/hw/timer/pl031.h
30
+F: tests/acceptance/machine_arm_integratorcp.py
117
F: include/hw/arm/primecell.h
31
118
F: hw/timer/cmsdk-apb-timer.c
32
MCIMX6UL EVK / i.MX6ul
119
F: include/hw/timer/cmsdk-apb-timer.h
33
M: Peter Maydell <peter.maydell@linaro.org>
34
diff --git a/tests/acceptance/machine_arm_integratorcp.py b/tests/acceptance/machine_arm_integratorcp.py
35
new file mode 100644
36
index XXXXXXX..XXXXXXX
37
--- /dev/null
38
+++ b/tests/acceptance/machine_arm_integratorcp.py
39
@@ -XXX,XX +XXX,XX @@
40
+# Functional test that boots a Linux kernel and checks the console
41
+#
42
+# Copyright (c) 2020 Red Hat, Inc.
43
+#
44
+# Author:
45
+# Thomas Huth <thuth@redhat.com>
46
+#
47
+# This work is licensed under the terms of the GNU GPL, version 2 or
48
+# later. See the COPYING file in the top-level directory.
49
+
50
+import os
51
+
52
+from avocado import skipUnless
53
+from avocado_qemu import Test
54
+from avocado_qemu import wait_for_console_pattern
55
+
56
+class IntegratorMachine(Test):
57
+
58
+ timeout = 90
59
+
60
+ @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
61
+ def test_integratorcp_console(self):
62
+ """
63
+ Boots the Linux kernel and checks that the console is operational
64
+ :avocado: tags=arch:arm
65
+ :avocado: tags=machine:integratorcp
66
+ """
67
+ kernel_url = ('https://github.com/zayac/qemu-arm/raw/master/'
68
+ 'arm-test/kernel/zImage.integrator')
69
+ kernel_hash = '0d7adba893c503267c946a3cbdc63b4b54f25468'
70
+ kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
71
+
72
+ initrd_url = ('https://github.com/zayac/qemu-arm/raw/master/'
73
+ 'arm-test/kernel/arm_root.img')
74
+ initrd_hash = 'b51e4154285bf784e017a37586428332d8c7bd8b'
75
+ initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
76
+
77
+ self.vm.set_console()
78
+ self.vm.add_args('-kernel', kernel_path,
79
+ '-initrd', initrd_path,
80
+ '-append', 'printk.time=0 console=ttyAMA0')
81
+ self.vm.launch()
82
+ wait_for_console_pattern(self, 'Log in as root')
120
--
83
--
121
2.20.1
84
2.20.1
122
85
123
86
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
As we want to re-use this code, extract it as a new function.
4
Since we are using the PL011 serial console, add a Avocado tag
5
to ease filtering of tests.
6
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
8
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20200225172501.29609-4-philmd@redhat.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
tests/acceptance/machine_arm_integratorcp.py | 18 +++++++++++-------
14
1 file changed, 11 insertions(+), 7 deletions(-)
15
16
diff --git a/tests/acceptance/machine_arm_integratorcp.py b/tests/acceptance/machine_arm_integratorcp.py
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/acceptance/machine_arm_integratorcp.py
19
+++ b/tests/acceptance/machine_arm_integratorcp.py
20
@@ -XXX,XX +XXX,XX @@ class IntegratorMachine(Test):
21
22
timeout = 90
23
24
- @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
25
- def test_integratorcp_console(self):
26
- """
27
- Boots the Linux kernel and checks that the console is operational
28
- :avocado: tags=arch:arm
29
- :avocado: tags=machine:integratorcp
30
- """
31
+ def boot_integratorcp(self):
32
kernel_url = ('https://github.com/zayac/qemu-arm/raw/master/'
33
'arm-test/kernel/zImage.integrator')
34
kernel_hash = '0d7adba893c503267c946a3cbdc63b4b54f25468'
35
@@ -XXX,XX +XXX,XX @@ class IntegratorMachine(Test):
36
'-initrd', initrd_path,
37
'-append', 'printk.time=0 console=ttyAMA0')
38
self.vm.launch()
39
+
40
+ @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
41
+ def test_integratorcp_console(self):
42
+ """
43
+ Boots the Linux kernel and checks that the console is operational
44
+ :avocado: tags=arch:arm
45
+ :avocado: tags=machine:integratorcp
46
+ :avocado: tags=device:pl011
47
+ """
48
+ self.boot_integratorcp()
49
wait_for_console_pattern(self, 'Log in as root')
50
--
51
2.20.1
52
53
diff view generated by jsdifflib
1
In commit 4b635cf7a95e501211 we added a QOM property to the ARMSSE
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
object, but forgot to add it to the documentation comment in the
3
header. Correct the omission.
4
2
5
Fixes: 4b635cf7a95e501211 ("hw/arm/armsse: Make SRAM bank size configurable")
3
Add a test that verifies the Tux logo is displayed on the framebuffer.
4
5
We simply follow the OpenCV "Template Matching with Multiple Objects"
6
tutorial, replacing Lionel Messi by Tux:
7
https://docs.opencv.org/4.2.0/d4/dc6/tutorial_py_template_matching.html
8
9
When OpenCV and NumPy are installed, this test can be run using:
10
11
$ AVOCADO_ALLOW_UNTRUSTED_CODE=hmmm \
12
avocado --show=app,framebuffer run -t device:framebuffer \
13
tests/acceptance/machine_arm_integratorcp.py
14
JOB ID : 8c46b0f8269242e87d738247883ea2a470df949e
15
JOB LOG : avocado/job-results/job-2020-01-31T21.38-8c46b0f/job.log
16
(1/1) tests/acceptance/machine_arm_integratorcp.py:IntegratorMachine.test_framebuffer_tux_logo:
17
framebuffer: found Tux at position [x, y] = (0, 0)
18
PASS (3.96 s)
19
RESULTS : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
20
JOB TIME : 4.23 s
21
22
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
24
Message-id: 20200225172501.29609-5-philmd@redhat.com
25
Message-Id: <20200131211102.29612-3-f4bug@amsat.org>
26
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
28
---
9
include/hw/arm/armsse.h | 2 ++
29
tests/acceptance/machine_arm_integratorcp.py | 52 ++++++++++++++++++++
10
1 file changed, 2 insertions(+)
30
1 file changed, 52 insertions(+)
11
31
12
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
32
diff --git a/tests/acceptance/machine_arm_integratorcp.py b/tests/acceptance/machine_arm_integratorcp.py
13
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armsse.h
34
--- a/tests/acceptance/machine_arm_integratorcp.py
15
+++ b/include/hw/arm/armsse.h
35
+++ b/tests/acceptance/machine_arm_integratorcp.py
16
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@
17
* being the same for both, to avoid having to have separate Property
37
# later. See the COPYING file in the top-level directory.
18
* lists for different variants. This restriction can be relaxed later
38
19
* if necessary.)
39
import os
20
+ * + QOM property "SRAM_ADDR_WIDTH" sets the number of bits used for the
40
+import logging
21
+ * address of each SRAM bank (and thus the total amount of internal SRAM)
41
22
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
42
from avocado import skipUnless
23
* which are wired to its NVIC lines 32 .. n+32
43
from avocado_qemu import Test
24
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
44
from avocado_qemu import wait_for_console_pattern
45
46
+
47
+NUMPY_AVAILABLE = True
48
+try:
49
+ import numpy as np
50
+except ImportError:
51
+ NUMPY_AVAILABLE = False
52
+
53
+CV2_AVAILABLE = True
54
+try:
55
+ import cv2
56
+except ImportError:
57
+ CV2_AVAILABLE = False
58
+
59
+
60
class IntegratorMachine(Test):
61
62
timeout = 90
63
@@ -XXX,XX +XXX,XX @@ class IntegratorMachine(Test):
64
"""
65
self.boot_integratorcp()
66
wait_for_console_pattern(self, 'Log in as root')
67
+
68
+ @skipUnless(NUMPY_AVAILABLE, 'Python NumPy not installed')
69
+ @skipUnless(CV2_AVAILABLE, 'Python OpenCV not installed')
70
+ @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
71
+ def test_framebuffer_tux_logo(self):
72
+ """
73
+ Boot Linux and verify the Tux logo is displayed on the framebuffer.
74
+ :avocado: tags=arch:arm
75
+ :avocado: tags=machine:integratorcp
76
+ :avocado: tags=device:pl110
77
+ :avocado: tags=device:framebuffer
78
+ """
79
+ screendump_path = os.path.join(self.workdir, "screendump.pbm")
80
+ tuxlogo_url = ('https://github.com/torvalds/linux/raw/v2.6.12/'
81
+ 'drivers/video/logo/logo_linux_vga16.ppm')
82
+ tuxlogo_hash = '3991c2ddbd1ddaecda7601f8aafbcf5b02dc86af'
83
+ tuxlogo_path = self.fetch_asset(tuxlogo_url, asset_hash=tuxlogo_hash)
84
+
85
+ self.boot_integratorcp()
86
+ framebuffer_ready = 'Console: switching to colour frame buffer device'
87
+ wait_for_console_pattern(self, framebuffer_ready)
88
+ self.vm.command('human-monitor-command', command_line='stop')
89
+ self.vm.command('human-monitor-command',
90
+ command_line='screendump %s' % screendump_path)
91
+ logger = logging.getLogger('framebuffer')
92
+
93
+ cpu_count = 1
94
+ match_threshold = 0.92
95
+ screendump_bgr = cv2.imread(screendump_path)
96
+ screendump_gray = cv2.cvtColor(screendump_bgr, cv2.COLOR_BGR2GRAY)
97
+ result = cv2.matchTemplate(screendump_gray, cv2.imread(tuxlogo_path, 0),
98
+ cv2.TM_CCOEFF_NORMED)
99
+ loc = np.where(result >= match_threshold)
100
+ tux_count = 0
101
+ for tux_count, pt in enumerate(zip(*loc[::-1]), start=1):
102
+ logger.debug('found Tux at position [x, y] = %s', pt)
103
+ self.assertGreaterEqual(tux_count, cpu_count)
25
--
104
--
26
2.20.1
105
2.20.1
27
106
28
107
diff view generated by jsdifflib
1
The pl011 logs when the guest makes a bad access. It prints
1
We missed an instance of using FIELD_EX32 on a 64-bit ID
2
the address offset in hex but confusingly omits the '0x'
2
register, in isar_feature_aa64_pmu_8_4(). Fix it.
3
prefix; add it.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200224172846.13053-2-peter.maydell@linaro.org
8
---
8
---
9
hw/char/pl011.c | 4 ++--
9
target/arm/cpu.h | 4 ++--
10
1 file changed, 2 insertions(+), 2 deletions(-)
10
1 file changed, 2 insertions(+), 2 deletions(-)
11
11
12
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/char/pl011.c
14
--- a/target/arm/cpu.h
15
+++ b/hw/char/pl011.c
15
+++ b/target/arm/cpu.h
16
@@ -XXX,XX +XXX,XX @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
16
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id)
17
break;
17
18
default:
18
static inline bool isar_feature_aa64_pmu_8_4(const ARMISARegisters *id)
19
qemu_log_mask(LOG_GUEST_ERROR,
19
{
20
- "pl011_read: Bad offset %x\n", (int)offset);
20
- return FIELD_EX32(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 &&
21
+ "pl011_read: Bad offset 0x%x\n", (int)offset);
21
- FIELD_EX32(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
22
r = 0;
22
+ return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 &&
23
break;
23
+ FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
24
}
25
@@ -XXX,XX +XXX,XX @@ static void pl011_write(void *opaque, hwaddr offset,
26
break;
27
default:
28
qemu_log_mask(LOG_GUEST_ERROR,
29
- "pl011_write: Bad offset %x\n", (int)offset);
30
+ "pl011_write: Bad offset 0x%x\n", (int)offset);
31
}
32
}
24
}
33
25
26
/*
34
--
27
--
35
2.20.1
28
2.20.1
36
29
37
30
diff view generated by jsdifflib
1
Wire up the two PL011 UARTs in the Musca board.
1
The v8.3-RCPC extension implements three new load instructions
2
which provide slightly weaker consistency guarantees than the
3
existing load-acquire operations. For QEMU we choose to simply
4
implement them with a full LDAQ barrier.
2
5
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200224172846.13053-3-peter.maydell@linaro.org
5
---
9
---
6
hw/arm/musca.c | 34 +++++++++++++++++++++++++++++-----
10
target/arm/cpu.h | 5 +++++
7
1 file changed, 29 insertions(+), 5 deletions(-)
11
linux-user/elfload.c | 1 +
12
target/arm/cpu64.c | 1 +
13
target/arm/translate-a64.c | 24 ++++++++++++++++++++++++
14
4 files changed, 31 insertions(+)
8
15
9
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
10
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
11
--- a/hw/arm/musca.c
18
--- a/target/arm/cpu.h
12
+++ b/hw/arm/musca.c
19
+++ b/target/arm/cpu.h
13
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_pmu_8_4(const ARMISARegisters *id)
14
#include "qemu/error-report.h"
21
FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
15
#include "qapi/error.h"
16
#include "exec/address-spaces.h"
17
+#include "sysemu/sysemu.h"
18
#include "hw/arm/arm.h"
19
#include "hw/arm/armsse.h"
20
#include "hw/boards.h"
21
+#include "hw/char/pl011.h"
22
#include "hw/core/split-irq.h"
23
#include "hw/misc/tz-mpc.h"
24
#include "hw/misc/tz-ppc.h"
25
@@ -XXX,XX +XXX,XX @@ typedef struct {
26
UnimplementedDeviceState mhu[2];
27
UnimplementedDeviceState pwm[3];
28
UnimplementedDeviceState i2s;
29
- UnimplementedDeviceState uart[2];
30
+ PL011State uart[2];
31
UnimplementedDeviceState i2c[2];
32
UnimplementedDeviceState spi;
33
UnimplementedDeviceState scc;
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque,
35
return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0);
36
}
22
}
37
23
38
+static MemoryRegion *make_uart(MuscaMachineState *mms, void *opaque,
24
+static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id)
39
+ const char *name, hwaddr size)
40
+{
25
+{
41
+ PL011State *uart = opaque;
26
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0;
42
+ int i = uart - &mms->uart[0];
43
+ int irqbase = 7 + i * 6;
44
+ SysBusDevice *s;
45
+
46
+ sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]),
47
+ TYPE_PL011);
48
+ qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
49
+ object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
50
+ s = SYS_BUS_DEVICE(uart);
51
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqbase + 5)); /* combined */
52
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqbase + 0)); /* RX */
53
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqbase + 1)); /* TX */
54
+ sysbus_connect_irq(s, 3, get_sse_irq_in(mms, irqbase + 2)); /* RT */
55
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqbase + 3)); /* MS */
56
+ sysbus_connect_irq(s, 5, get_sse_irq_in(mms, irqbase + 4)); /* E */
57
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
58
+}
27
+}
59
+
28
+
60
static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
29
/*
61
const char *name, hwaddr size)
30
* Feature tests for "does this exist in either 32-bit or 64-bit?"
62
{
31
*/
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
32
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
64
MemoryRegion *container = &mms->container;
33
index XXXXXXX..XXXXXXX 100644
65
34
--- a/linux-user/elfload.c
66
const PPCPortInfo devices[] = {
35
+++ b/linux-user/elfload.c
67
- { "uart0", make_unimp_dev, &mms->uart[0], 0x1000, 0x1000 },
36
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
68
- { "uart1", make_unimp_dev, &mms->uart[1], 0x2000, 0x1000 },
37
GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
69
+ { "uart0", make_uart, &mms->uart[0], 0x1000, 0x1000 },
38
GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
70
+ { "uart1", make_uart, &mms->uart[1], 0x2000, 0x1000 },
39
GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
71
{ "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 },
40
+ GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC);
72
{ "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 },
41
73
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
42
return hwcaps;
74
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
43
}
75
{ "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 },
44
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
76
{ "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 },
45
index XXXXXXX..XXXXXXX 100644
77
{ "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 },
46
--- a/target/arm/cpu64.c
78
- { "uart0", make_unimp_dev, &mms->uart[0], 0x40105000, 0x1000 },
47
+++ b/target/arm/cpu64.c
79
- { "uart1", make_unimp_dev, &mms->uart[1], 0x40106000, 0x1000 },
48
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
80
+ { "uart0", make_uart, &mms->uart[0], 0x40105000, 0x1000 },
49
t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
81
+ { "uart1", make_uart, &mms->uart[1], 0x40106000, 0x1000 },
50
t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
82
{ "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 },
51
t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
83
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 },
52
+ t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 1); /* ARMv8.3-RCPC */
84
{ "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
53
cpu->isar.id_aa64isar1 = t;
54
55
t = cpu->isar.id_aa64pfr0;
56
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/translate-a64.c
59
+++ b/target/arm/translate-a64.c
60
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
61
int rs = extract32(insn, 16, 5);
62
int rn = extract32(insn, 5, 5);
63
int o3_opc = extract32(insn, 12, 4);
64
+ bool r = extract32(insn, 22, 1);
65
+ bool a = extract32(insn, 23, 1);
66
TCGv_i64 tcg_rs, clean_addr;
67
AtomicThreeOpFn *fn;
68
69
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
70
case 010: /* SWP */
71
fn = tcg_gen_atomic_xchg_i64;
72
break;
73
+ case 014: /* LDAPR, LDAPRH, LDAPRB */
74
+ if (!dc_isar_feature(aa64_rcpc_8_3, s) ||
75
+ rs != 31 || a != 1 || r != 0) {
76
+ unallocated_encoding(s);
77
+ return;
78
+ }
79
+ break;
80
default:
81
unallocated_encoding(s);
82
return;
83
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
84
gen_check_sp_alignment(s);
85
}
86
clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
87
+
88
+ if (o3_opc == 014) {
89
+ /*
90
+ * LDAPR* are a special case because they are a simple load, not a
91
+ * fetch-and-do-something op.
92
+ * The architectural consistency requirements here are weaker than
93
+ * full load-acquire (we only need "load-acquire processor consistent"),
94
+ * but we choose to implement them as full LDAQ.
95
+ */
96
+ do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, false, false,
97
+ true, rt, disas_ldst_compute_iss_sf(size, false, 0), true);
98
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
99
+ return;
100
+ }
101
+
102
tcg_rs = read_cpu_reg(s, rs, true);
103
104
if (o3_opc == 1) { /* LDCLR */
85
--
105
--
86
2.20.1
106
2.20.1
87
107
88
108
diff view generated by jsdifflib
1
Many of the devices on the Musca board live behind TrustZone
1
The v8.4-RCPC extension implements some new instructions:
2
Peripheral Protection Controllers (PPCs); add models of the
2
* LDAPUR, LDAPURB, LDAPURH, LDAPRSB, LDAPRSH, LDAPRSW
3
PPCs, using a similar scheme to the MPS2 board models.
3
* STLUR, STLURB, STLURH
4
This commit wires up the PPCs with "unimplemented device"
4
5
stubs behind them in the correct places in the address map.
5
These are all in a new subgroup of encodings that sits below the
6
top-level "Loads and Stores" group in the Arm ARM.
7
8
The STLUR* instructions have standard store-release semantics; the
9
LDAPUR* have Load-AcquirePC semantics, but (as with LDAPR*) we choose
10
to implement them as the slightly stronger Load-Acquire.
6
11
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200224172846.13053-4-peter.maydell@linaro.org
9
---
15
---
10
hw/arm/musca.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++
16
target/arm/cpu.h | 5 +++
11
1 file changed, 289 insertions(+)
17
linux-user/elfload.c | 1 +
18
target/arm/cpu64.c | 2 +-
19
target/arm/translate-a64.c | 90 ++++++++++++++++++++++++++++++++++++++
20
4 files changed, 97 insertions(+), 1 deletion(-)
12
21
13
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/musca.c
24
--- a/target/arm/cpu.h
16
+++ b/hw/arm/musca.c
25
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id)
18
#include "hw/arm/armsse.h"
27
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0;
19
#include "hw/boards.h"
28
}
20
#include "hw/core/split-irq.h"
29
21
+#include "hw/misc/tz-ppc.h"
30
+static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id)
22
+#include "hw/misc/unimp.h"
23
24
#define MUSCA_NUMIRQ_MAX 96
25
+#define MUSCA_PPC_MAX 3
26
27
typedef enum MuscaType {
28
MUSCA_A,
29
@@ -XXX,XX +XXX,XX @@ typedef struct {
30
31
ARMSSE sse;
32
SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
33
+ SplitIRQ sec_resp_splitter;
34
+ TZPPC ppc[MUSCA_PPC_MAX];
35
+ MemoryRegion container;
36
+ UnimplementedDeviceState eflash[2];
37
+ UnimplementedDeviceState qspi;
38
+ UnimplementedDeviceState mpc[5];
39
+ UnimplementedDeviceState mhu[2];
40
+ UnimplementedDeviceState pwm[3];
41
+ UnimplementedDeviceState i2s;
42
+ UnimplementedDeviceState uart[2];
43
+ UnimplementedDeviceState i2c[2];
44
+ UnimplementedDeviceState spi;
45
+ UnimplementedDeviceState scc;
46
+ UnimplementedDeviceState timer;
47
+ UnimplementedDeviceState rtc;
48
+ UnimplementedDeviceState pvt;
49
+ UnimplementedDeviceState sdio;
50
+ UnimplementedDeviceState gpio;
51
} MuscaMachineState;
52
53
#define TYPE_MUSCA_MACHINE "musca"
54
@@ -XXX,XX +XXX,XX @@ typedef struct {
55
*/
56
#define SYSCLK_FRQ 40000000
57
58
+/*
59
+ * Most of the devices in the Musca board sit behind Peripheral Protection
60
+ * Controllers. These data structures define the layout of which devices
61
+ * sit behind which PPCs.
62
+ * The devfn for each port is a function which creates, configures
63
+ * and initializes the device, returning the MemoryRegion which
64
+ * needs to be plugged into the downstream end of the PPC port.
65
+ */
66
+typedef MemoryRegion *MakeDevFn(MuscaMachineState *mms, void *opaque,
67
+ const char *name, hwaddr size);
68
+
69
+typedef struct PPCPortInfo {
70
+ const char *name;
71
+ MakeDevFn *devfn;
72
+ void *opaque;
73
+ hwaddr addr;
74
+ hwaddr size;
75
+} PPCPortInfo;
76
+
77
+typedef struct PPCInfo {
78
+ const char *name;
79
+ PPCPortInfo ports[TZ_NUM_PORTS];
80
+} PPCInfo;
81
+
82
+static MemoryRegion *make_unimp_dev(MuscaMachineState *mms,
83
+ void *opaque, const char *name, hwaddr size)
84
+{
31
+{
85
+ /*
32
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2;
86
+ * Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
87
+ * and return a pointer to its MemoryRegion.
88
+ */
89
+ UnimplementedDeviceState *uds = opaque;
90
+
91
+ sysbus_init_child_obj(OBJECT(mms), name, uds,
92
+ sizeof(UnimplementedDeviceState),
93
+ TYPE_UNIMPLEMENTED_DEVICE);
94
+ qdev_prop_set_string(DEVICE(uds), "name", name);
95
+ qdev_prop_set_uint64(DEVICE(uds), "size", size);
96
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
97
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
98
+}
33
+}
99
+
34
+
100
+static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
35
/*
101
+ const char *name, hwaddr size)
36
* Feature tests for "does this exist in either 32-bit or 64-bit?"
37
*/
38
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/linux-user/elfload.c
41
+++ b/linux-user/elfload.c
42
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
43
GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
44
GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
45
GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC);
46
+ GET_FEATURE_ID(aa64_rcpc_8_4, ARM_HWCAP_A64_ILRCPC);
47
48
return hwcaps;
49
}
50
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/cpu64.c
53
+++ b/target/arm/cpu64.c
54
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
55
t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
56
t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
57
t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
58
- t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 1); /* ARMv8.3-RCPC */
59
+ t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* ARMv8.4-RCPC */
60
cpu->isar.id_aa64isar1 = t;
61
62
t = cpu->isar.id_aa64pfr0;
63
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate-a64.c
66
+++ b/target/arm/translate-a64.c
67
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_pac(DisasContext *s, uint32_t insn,
68
}
69
}
70
71
+/*
72
+ * LDAPR/STLR (unscaled immediate)
73
+ *
74
+ * 31 30 24 22 21 12 10 5 0
75
+ * +------+-------------+-----+---+--------+-----+----+-----+
76
+ * | size | 0 1 1 0 0 1 | opc | 0 | imm9 | 0 0 | Rn | Rt |
77
+ * +------+-------------+-----+---+--------+-----+----+-----+
78
+ *
79
+ * Rt: source or destination register
80
+ * Rn: base register
81
+ * imm9: unscaled immediate offset
82
+ * opc: 00: STLUR*, 01/10/11: various LDAPUR*
83
+ * size: size of load/store
84
+ */
85
+static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
102
+{
86
+{
103
+ /*
87
+ int rt = extract32(insn, 0, 5);
104
+ * Create the container MemoryRegion for all the devices that live
88
+ int rn = extract32(insn, 5, 5);
105
+ * behind the Musca-A PPC's single port. These devices don't have a PPC
89
+ int offset = sextract32(insn, 12, 9);
106
+ * port each, but we use the PPCPortInfo struct as a convenient way
90
+ int opc = extract32(insn, 22, 2);
107
+ * to describe them. Note that addresses here are relative to the base
91
+ int size = extract32(insn, 30, 2);
108
+ * address of the PPC port region: 0x40100000, and devices appear both
92
+ TCGv_i64 clean_addr, dirty_addr;
109
+ * at the 0x4... NS region and the 0x5... S region.
93
+ bool is_store = false;
110
+ */
94
+ bool is_signed = false;
111
+ int i;
95
+ bool extend = false;
112
+ MemoryRegion *container = &mms->container;
96
+ bool iss_sf;
113
+
97
+
114
+ const PPCPortInfo devices[] = {
98
+ if (!dc_isar_feature(aa64_rcpc_8_4, s)) {
115
+ { "uart0", make_unimp_dev, &mms->uart[0], 0x1000, 0x1000 },
99
+ unallocated_encoding(s);
116
+ { "uart1", make_unimp_dev, &mms->uart[1], 0x2000, 0x1000 },
100
+ return;
117
+ { "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 },
118
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 },
119
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
120
+ { "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 },
121
+ { "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 },
122
+ { "rtc", make_unimp_dev, &mms->rtc, 0x8000, 0x1000 },
123
+ { "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 },
124
+ { "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 },
125
+ { "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 },
126
+ { "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 },
127
+ { "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 },
128
+ { "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 },
129
+ { "mpc0", make_unimp_dev, &mms->mpc[0], 0x12000, 0x1000 },
130
+ { "mpc1", make_unimp_dev, &mms->mpc[1], 0x13000, 0x1000 },
131
+ };
132
+
133
+ memory_region_init(container, OBJECT(mms), "musca-device-container", size);
134
+
135
+ for (i = 0; i < ARRAY_SIZE(devices); i++) {
136
+ const PPCPortInfo *pinfo = &devices[i];
137
+ MemoryRegion *mr;
138
+
139
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
140
+ memory_region_add_subregion(container, pinfo->addr, mr);
141
+ }
101
+ }
142
+
102
+
143
+ return &mms->container;
103
+ switch (opc) {
144
+}
104
+ case 0: /* STLURB */
145
+
105
+ is_store = true;
146
static void musca_init(MachineState *machine)
147
{
148
MuscaMachineState *mms = MUSCA_MACHINE(machine);
149
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
150
MachineClass *mc = MACHINE_GET_CLASS(machine);
151
MemoryRegion *system_memory = get_system_memory();
152
DeviceState *ssedev;
153
+ DeviceState *dev_splitter;
154
+ const PPCInfo *ppcs;
155
+ int num_ppcs;
156
int i;
157
158
assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
159
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
160
"EXP_CPU1_IRQ", i));
161
}
162
163
+ /*
164
+ * The sec_resp_cfg output from the SSE-200 must be split into multiple
165
+ * lines, one for each of the PPCs we create here.
166
+ */
167
+ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
168
+ TYPE_SPLIT_IRQ);
169
+ object_property_add_child(OBJECT(machine), "sec-resp-splitter",
170
+ OBJECT(&mms->sec_resp_splitter), &error_fatal);
171
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter),
172
+ ARRAY_SIZE(mms->ppc), "num-lines", &error_fatal);
173
+ object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
174
+ "realized", &error_fatal);
175
+ dev_splitter = DEVICE(&mms->sec_resp_splitter);
176
+ qdev_connect_gpio_out_named(ssedev, "sec_resp_cfg", 0,
177
+ qdev_get_gpio_in(dev_splitter, 0));
178
+
179
+ /*
180
+ * Most of the devices in the board are behind Peripheral Protection
181
+ * Controllers. The required order for initializing things is:
182
+ * + initialize the PPC
183
+ * + initialize, configure and realize downstream devices
184
+ * + connect downstream device MemoryRegions to the PPC
185
+ * + realize the PPC
186
+ * + map the PPC's MemoryRegions to the places in the address map
187
+ * where the downstream devices should appear
188
+ * + wire up the PPC's control lines to the SSE object
189
+ *
190
+ * The PPC mapping differs for the -A and -B1 variants; the -A version
191
+ * is much simpler, using only a single port of a single PPC and putting
192
+ * all the devices behind that.
193
+ */
194
+ const PPCInfo a_ppcs[] = { {
195
+ .name = "ahb_ppcexp0",
196
+ .ports = {
197
+ { "musca-devices", make_musca_a_devs, 0, 0x40100000, 0x100000 },
198
+ },
199
+ },
200
+ };
201
+
202
+ /*
203
+ * Devices listed with an 0x4.. address appear in both the NS 0x4.. region
204
+ * and the 0x5.. S region. Devices listed with an 0x5.. address appear
205
+ * only in the S region.
206
+ */
207
+ const PPCInfo b1_ppcs[] = { {
208
+ .name = "apb_ppcexp0",
209
+ .ports = {
210
+ { "eflash0", make_unimp_dev, &mms->eflash[0],
211
+ 0x52400000, 0x1000 },
212
+ { "eflash1", make_unimp_dev, &mms->eflash[1],
213
+ 0x52500000, 0x1000 },
214
+ { "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 },
215
+ { "mpc0", make_unimp_dev, &mms->mpc[0], 0x52000000, 0x1000 },
216
+ { "mpc1", make_unimp_dev, &mms->mpc[1], 0x52100000, 0x1000 },
217
+ { "mpc2", make_unimp_dev, &mms->mpc[2], 0x52200000, 0x1000 },
218
+ { "mpc3", make_unimp_dev, &mms->mpc[3], 0x52300000, 0x1000 },
219
+ { "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 },
220
+ { "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 },
221
+ { }, /* port 9: unused */
222
+ { }, /* port 10: unused */
223
+ { }, /* port 11: unused */
224
+ { }, /* port 12: unused */
225
+ { }, /* port 13: unused */
226
+ { "mpc4", make_unimp_dev, &mms->mpc[4], 0x52e00000, 0x1000 },
227
+ },
228
+ }, {
229
+ .name = "apb_ppcexp1",
230
+ .ports = {
231
+ { "pwm0", make_unimp_dev, &mms->pwm[0], 0x40101000, 0x1000 },
232
+ { "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 },
233
+ { "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 },
234
+ { "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 },
235
+ { "uart0", make_unimp_dev, &mms->uart[0], 0x40105000, 0x1000 },
236
+ { "uart1", make_unimp_dev, &mms->uart[1], 0x40106000, 0x1000 },
237
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 },
238
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 },
239
+ { "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
240
+ { "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 },
241
+ { "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 },
242
+ { "rtc", make_unimp_dev, &mms->rtc, 0x4010d000, 0x1000 },
243
+ { "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 },
244
+ { "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 },
245
+ },
246
+ }, {
247
+ .name = "ahb_ppcexp0",
248
+ .ports = {
249
+ { }, /* port 0: unused */
250
+ { "gpio", make_unimp_dev, &mms->gpio, 0x41000000, 0x1000 },
251
+ },
252
+ },
253
+ };
254
+
255
+ switch (mmc->type) {
256
+ case MUSCA_A:
257
+ ppcs = a_ppcs;
258
+ num_ppcs = ARRAY_SIZE(a_ppcs);
259
+ break;
106
+ break;
260
+ case MUSCA_B1:
107
+ case 1: /* LDAPUR* */
261
+ ppcs = b1_ppcs;
108
+ break;
262
+ num_ppcs = ARRAY_SIZE(b1_ppcs);
109
+ case 2: /* LDAPURS* 64-bit variant */
110
+ if (size == 3) {
111
+ unallocated_encoding(s);
112
+ return;
113
+ }
114
+ is_signed = true;
115
+ break;
116
+ case 3: /* LDAPURS* 32-bit variant */
117
+ if (size > 1) {
118
+ unallocated_encoding(s);
119
+ return;
120
+ }
121
+ is_signed = true;
122
+ extend = true; /* zero-extend 32->64 after signed load */
263
+ break;
123
+ break;
264
+ default:
124
+ default:
265
+ g_assert_not_reached();
125
+ g_assert_not_reached();
266
+ }
126
+ }
267
+ assert(num_ppcs <= MUSCA_PPC_MAX);
268
+
127
+
269
+ for (i = 0; i < num_ppcs; i++) {
128
+ iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
270
+ const PPCInfo *ppcinfo = &ppcs[i];
271
+ TZPPC *ppc = &mms->ppc[i];
272
+ DeviceState *ppcdev;
273
+ int port;
274
+ char *gpioname;
275
+
129
+
276
+ sysbus_init_child_obj(OBJECT(machine), ppcinfo->name, ppc,
130
+ if (rn == 31) {
277
+ sizeof(TZPPC), TYPE_TZ_PPC);
131
+ gen_check_sp_alignment(s);
278
+ ppcdev = DEVICE(ppc);
279
+
280
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
281
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
282
+ MemoryRegion *mr;
283
+ char *portname;
284
+
285
+ if (!pinfo->devfn) {
286
+ continue;
287
+ }
288
+
289
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
290
+ portname = g_strdup_printf("port[%d]", port);
291
+ object_property_set_link(OBJECT(ppc), OBJECT(mr),
292
+ portname, &error_fatal);
293
+ g_free(portname);
294
+ }
295
+
296
+ object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal);
297
+
298
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
299
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
300
+
301
+ if (!pinfo->devfn) {
302
+ continue;
303
+ }
304
+ sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr);
305
+
306
+ gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name);
307
+ qdev_connect_gpio_out_named(ssedev, gpioname, port,
308
+ qdev_get_gpio_in_named(ppcdev,
309
+ "cfg_nonsec",
310
+ port));
311
+ g_free(gpioname);
312
+ gpioname = g_strdup_printf("%s_ap", ppcinfo->name);
313
+ qdev_connect_gpio_out_named(ssedev, gpioname, port,
314
+ qdev_get_gpio_in_named(ppcdev,
315
+ "cfg_ap", port));
316
+ g_free(gpioname);
317
+ }
318
+
319
+ gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name);
320
+ qdev_connect_gpio_out_named(ssedev, gpioname, 0,
321
+ qdev_get_gpio_in_named(ppcdev,
322
+ "irq_enable", 0));
323
+ g_free(gpioname);
324
+ gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name);
325
+ qdev_connect_gpio_out_named(ssedev, gpioname, 0,
326
+ qdev_get_gpio_in_named(ppcdev,
327
+ "irq_clear", 0));
328
+ g_free(gpioname);
329
+ gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name);
330
+ qdev_connect_gpio_out_named(ppcdev, "irq", 0,
331
+ qdev_get_gpio_in_named(ssedev,
332
+ gpioname, 0));
333
+ g_free(gpioname);
334
+
335
+ qdev_connect_gpio_out(dev_splitter, i,
336
+ qdev_get_gpio_in_named(ppcdev,
337
+ "cfg_sec_resp", 0));
338
+ }
132
+ }
339
+
133
+
340
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
134
+ dirty_addr = read_cpu_reg_sp(s, rn, 1);
341
}
135
+ tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
342
136
+ clean_addr = clean_data_tbi(s, dirty_addr);
137
+
138
+ if (is_store) {
139
+ /* Store-Release semantics */
140
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
141
+ do_gpr_st(s, cpu_reg(s, rt), clean_addr, size, true, rt, iss_sf, true);
142
+ } else {
143
+ /*
144
+ * Load-AcquirePC semantics; we implement as the slightly more
145
+ * restrictive Load-Acquire.
146
+ */
147
+ do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, is_signed, extend,
148
+ true, rt, iss_sf, true);
149
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
150
+ }
151
+}
152
+
153
/* Load/store register (all forms) */
154
static void disas_ldst_reg(DisasContext *s, uint32_t insn)
155
{
156
@@ -XXX,XX +XXX,XX @@ static void disas_ldst(DisasContext *s, uint32_t insn)
157
case 0x0d: /* AdvSIMD load/store single structure */
158
disas_ldst_single_struct(s, insn);
159
break;
160
+ case 0x19: /* LDAPR/STLR (unscaled immediate) */
161
+ if (extract32(insn, 10, 2) != 0 ||
162
+ extract32(insn, 21, 1) != 0) {
163
+ unallocated_encoding(s);
164
+ break;
165
+ }
166
+ disas_ldst_ldapr_stlr(s, insn);
167
+ break;
168
default:
169
unallocated_encoding(s);
170
break;
343
--
171
--
344
2.20.1
172
2.20.1
345
173
346
174
diff view generated by jsdifflib
1
The "background region" for a v8M MPU is a default which will be used
1
The ARMv8.3-CCIDX extension makes the CCSIDR_EL1 system ID registers
2
(if enabled, and if the access is privileged) if the access does
2
have a format that uses the full 64 bit width of the register, and
3
not match any specific MPU region. We were incorrectly using it
3
adds a new CCSIDR2 register so AArch32 can get at the high 32 bits.
4
always (by putting the condition at the wrong nesting level). This
5
meant that we would always return the default background permissions
6
rather than the correct permissions for a specific region, and also
7
that we would not return the right information in response to a
8
TT instruction.
9
4
10
Move the check for the background region to the same place in the
5
QEMU doesn't implement caches, so we just treat these ID registers as
11
logic as the equivalent v8M MPUCheck() pseudocode puts it.
6
opaque values that are set to the correct constant values for each
12
This in turn means we must adjust the condition we use to detect
7
CPU. The only thing we need to do is allow 64-bit values in our
13
matches in multiple regions to avoid false-positives.
8
cssidr[] array and provide the CCSIDR2 accessors.
9
10
We don't set the CCIDX field in our 'max' CPU because the CCSIDR
11
constant values we use are the same as the ones used by the
12
Cortex-A57 and they are in the old 32-bit format. This means
13
that the extra regdef added here is unused currently, but it
14
means that whenever in the future we add a CPU that does need
15
the new 64-bit format it will just work when we set the cssidr
16
values and the ID registers for it.
14
17
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20190214113408.10214-1-peter.maydell@linaro.org
20
Message-id: 20200224182626.29252-1-peter.maydell@linaro.org
18
---
21
---
19
target/arm/helper.c | 8 +++++---
22
target/arm/cpu.h | 17 ++++++++++++++++-
20
1 file changed, 5 insertions(+), 3 deletions(-)
23
target/arm/helper.c | 19 +++++++++++++++++++
24
2 files changed, 35 insertions(+), 1 deletion(-)
21
25
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.h
29
+++ b/target/arm/cpu.h
30
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
31
/* The elements of this array are the CCSIDR values for each cache,
32
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
33
*/
34
- uint32_t ccsidr[16];
35
+ uint64_t ccsidr[16];
36
uint64_t reset_cbar;
37
uint32_t reset_auxcr;
38
bool reset_hivecs;
39
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id)
40
return FIELD_EX32(id->id_mmfr4, ID_MMFR4, AC2) != 0;
41
}
42
43
+static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id)
44
+{
45
+ return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0;
46
+}
47
+
48
/*
49
* 64-bit feature tests via id registers.
50
*/
51
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id)
52
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2;
53
}
54
55
+static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
56
+{
57
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0;
58
+}
59
+
60
/*
61
* Feature tests for "does this exist in either 32-bit or 64-bit?"
62
*/
63
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_any_pmu_8_4(const ARMISARegisters *id)
64
return isar_feature_aa64_pmu_8_4(id) || isar_feature_aa32_pmu_8_4(id);
65
}
66
67
+static inline bool isar_feature_any_ccidx(const ARMISARegisters *id)
68
+{
69
+ return isar_feature_aa64_ccidx(id) || isar_feature_aa32_ccidx(id);
70
+}
71
+
72
/*
73
* Forward to the above feature tests given an ARMCPU pointer.
74
*/
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
75
diff --git a/target/arm/helper.c b/target/arm/helper.c
23
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/helper.c
77
--- a/target/arm/helper.c
25
+++ b/target/arm/helper.c
78
+++ b/target/arm/helper.c
26
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
79
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo predinv_reginfo[] = {
27
hit = true;
80
REGINFO_SENTINEL
28
} else if (m_is_ppb_region(env, address)) {
81
};
29
hit = true;
82
30
- } else if (pmsav7_use_background_region(cpu, mmu_idx, is_user)) {
83
+static uint64_t ccsidr2_read(CPUARMState *env, const ARMCPRegInfo *ri)
31
- hit = true;
84
+{
32
} else {
85
+ /* Read the high 32 bits of the current CCSIDR */
33
+ if (pmsav7_use_background_region(cpu, mmu_idx, is_user)) {
86
+ return extract64(ccsidr_read(env, ri), 32, 32);
34
+ hit = true;
87
+}
35
+ }
36
+
88
+
37
for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
89
+static const ARMCPRegInfo ccsidr2_reginfo[] = {
38
/* region search */
90
+ { .name = "CCSIDR2", .state = ARM_CP_STATE_BOTH,
39
/* Note that the base address is bits [31:5] from the register
91
+ .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 2,
40
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
92
+ .access = PL1_R,
41
*is_subpage = true;
93
+ .accessfn = access_aa64_tid2,
42
}
94
+ .readfn = ccsidr2_read, .type = ARM_CP_NO_RAW },
43
95
+ REGINFO_SENTINEL
44
- if (hit) {
96
+};
45
+ if (matchregion != -1) {
97
+
46
/* Multiple regions match -- always a failure (unlike
98
static CPAccessResult access_aa64_tid3(CPUARMState *env, const ARMCPRegInfo *ri,
47
* PMSAv7 where highest-numbered-region wins)
99
bool isread)
48
*/
100
{
101
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
102
define_arm_cp_regs(cpu, predinv_reginfo);
103
}
104
105
+ if (cpu_isar_feature(any_ccidx, cpu)) {
106
+ define_arm_cp_regs(cpu, ccsidr2_reginfo);
107
+ }
108
+
109
#ifndef CONFIG_USER_ONLY
110
/*
111
* Register redirections and aliases must be done last,
49
--
112
--
50
2.20.1
113
2.20.1
51
114
52
115
diff view generated by jsdifflib
1
Create a new include file for the pl011's device struct,
1
In our KVM GICv2 realize function, we try to cope with old kernels
2
type macros, etc, so that it can be instantiated using
2
that don't provide the device control API (KVM_CAP_DEVICE_CTRL): we
3
the "embedded struct" coding style.
3
try to use the device control, and if that fails we fall back to
4
assuming that the kernel has the old style KVM_CREATE_IRQCHIP and
5
that it will provide a GICv2.
6
7
This doesn't cater for the possibility of a kernel and hardware which
8
only provide a GICv3, which is very common now. On that setup we
9
will abort() later on in kvm_arm_pmu_set_irq() when we try to wire up
10
an interrupt to the GIC we failed to create:
11
12
qemu-system-aarch64: PMU: KVM_SET_DEVICE_ATTR: Invalid argument
13
qemu-system-aarch64: failed to set irq for PMU
14
Aborted
15
16
If the kernel advertises KVM_CAP_DEVICE_CTRL we should trust it if it
17
says it can't create a GICv2, rather than assuming it has one. We
18
can then produce a more helpful error message including a hint about
19
the most probable reason for the failure.
20
21
If the kernel doesn't advertise KVM_CAP_DEVICE_CTRL then it is truly
22
ancient by this point but we might as well still fall back to a
23
KVM_CREATE_IRQCHIP GICv2.
24
25
With this patch then the user misconfiguration which previously
26
caused an abort now prints:
27
qemu-system-aarch64: Initialization of device kvm-arm-gic failed: error creating in-kernel VGIC: No such device
28
Perhaps the host CPU does not support GICv2?
4
29
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
31
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
32
Reviewed-by: Andrew Jones <drjones@redhat.com>
33
Tested-by: Andrew Jones <drjones@redhat.com>
34
Message-id: 20200225182435.1131-1-peter.maydell@linaro.org
8
---
35
---
9
include/hw/char/pl011.h | 34 ++++++++++++++++++++++++++++++++++
36
hw/intc/arm_gic_kvm.c | 9 +++++++++
10
hw/char/pl011.c | 31 ++-----------------------------
37
1 file changed, 9 insertions(+)
11
2 files changed, 36 insertions(+), 29 deletions(-)
12
38
13
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
39
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
14
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/char/pl011.h
41
--- a/hw/intc/arm_gic_kvm.c
16
+++ b/include/hw/char/pl011.h
42
+++ b/hw/intc/arm_gic_kvm.c
17
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
18
#ifndef HW_PL011_H
44
KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true,
19
#define HW_PL011_H
45
&error_abort);
20
46
}
21
+#include "hw/sysbus.h"
47
+ } else if (kvm_check_extension(kvm_state, KVM_CAP_DEVICE_CTRL)) {
22
+#include "chardev/char-fe.h"
48
+ error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
23
+
49
+ error_append_hint(errp,
24
+#define TYPE_PL011 "pl011"
50
+ "Perhaps the host CPU does not support GICv2?\n");
25
+#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
51
} else if (ret != -ENODEV && ret != -ENOTSUP) {
26
+
52
+ /*
27
+/* This shares the same struct (and cast macro) as the base pl011 device */
53
+ * Very ancient kernel without KVM_CAP_DEVICE_CTRL: assume that
28
+#define TYPE_PL011_LUMINARY "pl011_luminary"
54
+ * ENODEV or ENOTSUP mean "can't create GICv2 with KVM_CREATE_DEVICE",
29
+
55
+ * and that we will get a GICv2 via KVM_CREATE_IRQCHIP.
30
+typedef struct PL011State {
56
+ */
31
+ SysBusDevice parent_obj;
57
error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
32
+
58
return;
33
+ MemoryRegion iomem;
59
}
34
+ uint32_t readbuff;
35
+ uint32_t flags;
36
+ uint32_t lcr;
37
+ uint32_t rsr;
38
+ uint32_t cr;
39
+ uint32_t dmacr;
40
+ uint32_t int_enabled;
41
+ uint32_t int_level;
42
+ uint32_t read_fifo[16];
43
+ uint32_t ilpr;
44
+ uint32_t ibrd;
45
+ uint32_t fbrd;
46
+ uint32_t ifl;
47
+ int read_pos;
48
+ int read_count;
49
+ int read_trigger;
50
+ CharBackend chr;
51
+ qemu_irq irq;
52
+ const unsigned char *id;
53
+} PL011State;
54
+
55
static inline DeviceState *pl011_create(hwaddr addr,
56
qemu_irq irq,
57
Chardev *chr)
58
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/char/pl011.c
61
+++ b/hw/char/pl011.c
62
@@ -XXX,XX +XXX,XX @@
63
*/
64
65
#include "qemu/osdep.h"
66
+#include "hw/char/pl011.h"
67
#include "hw/sysbus.h"
68
#include "chardev/char-fe.h"
69
#include "qemu/log.h"
70
#include "trace.h"
71
72
-#define TYPE_PL011 "pl011"
73
-#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
74
-
75
-typedef struct PL011State {
76
- SysBusDevice parent_obj;
77
-
78
- MemoryRegion iomem;
79
- uint32_t readbuff;
80
- uint32_t flags;
81
- uint32_t lcr;
82
- uint32_t rsr;
83
- uint32_t cr;
84
- uint32_t dmacr;
85
- uint32_t int_enabled;
86
- uint32_t int_level;
87
- uint32_t read_fifo[16];
88
- uint32_t ilpr;
89
- uint32_t ibrd;
90
- uint32_t fbrd;
91
- uint32_t ifl;
92
- int read_pos;
93
- int read_count;
94
- int read_trigger;
95
- CharBackend chr;
96
- qemu_irq irq;
97
- const unsigned char *id;
98
-} PL011State;
99
-
100
#define PL011_INT_TX 0x20
101
#define PL011_INT_RX 0x10
102
103
@@ -XXX,XX +XXX,XX @@ static void pl011_luminary_init(Object *obj)
104
}
105
106
static const TypeInfo pl011_luminary_info = {
107
- .name = "pl011_luminary",
108
+ .name = TYPE_PL011_LUMINARY,
109
.parent = TYPE_PL011,
110
.instance_init = pl011_luminary_init,
111
};
112
--
60
--
113
2.20.1
61
2.20.1
114
62
115
63
diff view generated by jsdifflib