[Qemu-devel] [Bug 1585533] Re: cache-miss-rate / Invalid JSON

2019-07-26 Thread Launchpad Bug Tracker
[Expired for QEMU because there has been no activity for 60 days.]

** Changed in: qemu
   Status: Incomplete => Expired

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1585533

Title:
  cache-miss-rate / Invalid JSON

Status in QEMU:
  Expired

Bug description:
  Hi,

  We have VMs which were started with an older version than qemu 2.1
  which added "cache-miss-rate" property for XBZRLECacheStats. While
  trying to migrate the VM to a new host which is running a higher
  version (2.3) of Qemu we got an exception:

  virJSONValueFromString:1642 : internal error: cannot parse json {"return": 
{"expected-downtime": 1, "xbzrle-cache": {"bytes": 0, "cache-size": 67108864, 
"cache-miss-rate": -nan, "pages": 0, "overflow": 0, "cache-miss": 8933}, 
"status": "active", "disk": {"total": 429496729600, "dirty-sync-count": 0, 
"remaining": 193896382464, "mbps": 0, "transferred": 235600347136, "duplicate": 
0, "dirty-pages-rate": 0, "skipped": 0, "normal-bytes": 0, "normal": 0}, 
"setup-time": 13, "total-time": 1543124, "ram": {"total": 8599183360, 
"dirty-sync-count": 4, "remaining": 30695424, "mbps": 830.636997, 
"transferred": 3100448901, "duplicate": 1358341, "dirty-pages-rate": 7, 
"skipped": 0, "normal-bytes": 3082199040, "normal": 752490}}, "id": 
"libvirt-186200"}: lexical error: malformed number, a digit is required after 
the minus sign.
67108864, "cache-miss-rate": -nan, "pages": 0, "overflow": 0
   (right here) --^

  virNetClientStreamRaiseError:191 : stream aborted at client request

  
  Would it be possible to improve the JSON parser to skip the key if the value 
is incorrect instead of throwing an exception? Then hopefully qemu 2.3 or 
higher is able to handle the data without this property, falling back to its 
default.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1585533/+subscriptions



[Qemu-devel] [Bug 1590322] Re: mouse_button 0 takes back to initial position

2019-07-26 Thread Launchpad Bug Tracker
[Expired for QEMU because there has been no activity for 60 days.]

** Changed in: qemu
   Status: Incomplete => Expired

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1590322

Title:
  mouse_button 0 takes back to initial position

Status in QEMU:
  Expired

Bug description:
  i wrote a python script to perform some drag function in the Qemu simulator.
  mouse_move x , y
  mouse_button 1
  mouse_move new_x,new_y
  mouse_move 0

  
  The mouse_move 0 doesn't release the mouse in the position new_x,new_y 
instead it takes  it back to the point x,y and then releases the mouse

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1590322/+subscriptions



Re: [Qemu-devel] [Virtio-fs] [PATCH 1/5] virtiofsd: skip unnecessary vu_queue_get_avail_bytes()

2019-07-26 Thread Liu Bo
On Fri, Jul 26, 2019 at 10:10:59AM +0100, Stefan Hajnoczi wrote:
> When debug output is disabled there is no need to calculate the number
> of in/out bytes available.
> 
> There is also no need to skip a request if there are 0 out bytes.  The
> request parsing code already handles invalid requests.
> 
> Signed-off-by: Stefan Hajnoczi 
> ---
>  contrib/virtiofsd/fuse_virtio.c | 13 +
>  1 file changed, 5 insertions(+), 8 deletions(-)
> 
> diff --git a/contrib/virtiofsd/fuse_virtio.c b/contrib/virtiofsd/fuse_virtio.c
> index 083e4fc317..d543c6d30f 100644
> --- a/contrib/virtiofsd/fuse_virtio.c
> +++ b/contrib/virtiofsd/fuse_virtio.c
> @@ -507,18 +507,16 @@ static void *fv_queue_thread(void *opaque)
> ret = 
> pthread_rwlock_rdlock(>virtio_dev->vu_dispatch_rwlock);
> assert(ret == 0); /* there is no possible error case */
>  
> -   /* out is from guest, in is too guest */
> -   unsigned int in_bytes, out_bytes;
> -   vu_queue_get_avail_bytes(dev, q, _bytes, _bytes, ~0, 
> ~0);
> +   if (se->debug) {
> +   /* out is from guest, in is too guest */
> +   unsigned int in_bytes, out_bytes;
> +   vu_queue_get_avail_bytes(dev, q, _bytes, 
> _bytes, ~0, ~0);
>  
> -   if (se->debug)
> fuse_debug("%s: Queue %d gave evalue: %zx available: 
> in: %u out: %u\n",
> __func__, qi->qidx, (size_t)evalue, in_bytes,
> out_bytes);
> -
> -   if (!out_bytes) {
> -   goto next;
> }
> +
> while (1) {
> bool allocated_bufv = false;
> struct fuse_bufvec bufv;
> @@ -708,7 +706,6 @@ static void *fv_queue_thread(void *opaque)
> elem = NULL;
>  }
>  
> -next:
>  pthread_rwlock_unlock(>virtio_dev->vu_dispatch_rwlock);
>  }
>  pthread_mutex_destroy();
> -- 
> 2.21.0
> 
> ___
> Virtio-fs mailing list
> virtio...@redhat.com
> https://www.redhat.com/mailman/listinfo/virtio-fs

Reviewed-by: Liu Bo 

thanks,
-liubo



Re: [Qemu-devel] [Virtio-fs] [PATCH 2/5] virtiofsd: prevent lo_lookup() NULL pointer dereference

2019-07-26 Thread Liu Bo
On Fri, Jul 26, 2019 at 10:11:00AM +0100, Stefan Hajnoczi wrote:
> Most lo_do_lookup() have already checked that the parent inode exists.
> lo_lookup() hasn't and can therefore hit a NULL pointer dereference when
> lo_inode(req, parent) returns NULL.
>

Sigh...this one has been fixed by 3 different developers...Me, Pengtao and 
Stefan.

The following one on the ML did the exactly same thing.
---
Subject: [Virtio-fs] [PATCH] virtiofsd: fix lo_do_lookup panic

It needs to check for invalid parent dir.

Signed-off-by: Peng Tao 
---

thanks,
-liubo

> Signed-off-by: Stefan Hajnoczi 
> ---
>  contrib/virtiofsd/passthrough_ll.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/contrib/virtiofsd/passthrough_ll.c 
> b/contrib/virtiofsd/passthrough_ll.c
> index 9ae1381618..277a17fc03 100644
> --- a/contrib/virtiofsd/passthrough_ll.c
> +++ b/contrib/virtiofsd/passthrough_ll.c
> @@ -766,6 +766,10 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t 
> parent, const char *name,
>   struct lo_data *lo = lo_data(req);
>   struct lo_inode *inode, *dir = lo_inode(req, parent);
>  
> + if (!dir) {
> + return EBADF;
> + }
> +
>   memset(e, 0, sizeof(*e));
>   e->attr_timeout = lo->timeout;
>   e->entry_timeout = lo->timeout;
> -- 
> 2.21.0
> 
> ___
> Virtio-fs mailing list
> virtio...@redhat.com
> https://www.redhat.com/mailman/listinfo/virtio-fs



[Qemu-devel] [for-4.2 PATCH 2/2] hw/i386: AMD-Vi IVRS DMA alias support

2019-07-26 Thread Alex Williamson
When we account for DMA aliases in the PCI address space, we can no
longer use a single IVHD entry in the IVRS covering all devices.  We
instead need to walk the PCI bus and create alias ranges when we find
a conventional bus.  These alias ranges cannot overlap with a "Select
All" range (as currently implemented), so we also need to enumerate
each device with IVHD entries.

Importantly, the IVHD entries used here include a Device ID, which is
simply the PCI BDF (Bus/Device/Function).  The guest firmware is
responsible for programming bus numbers, so the final revision of this
table depends on the update mechanism (acpi_build_update) to be called
after guest PCI enumeration.

For an example guest configuration of:

-+-[:40]---00.0-[41]00.0  Intel Corporation 82574L Gigabit Network 
Connection
 \-[:00]-+-00.0  Intel Corporation 82G33/G31/P35/P31 Express DRAM Controller
 +-01.0  Device 1234:
 +-02.0-[01]00.0  Intel Corporation 82574L Gigabit Network 
Connection
 +-02.1-[02]00.0  Red Hat, Inc. QEMU XHCI Host Controller
 +-02.2-[03]--
 +-02.3-[04]--
 +-02.4-[05]--
 +-02.5-[06-09]00.0-[07-09]--+-00.0-[08]--
 |   \-01.0-[09]00.0  Intel 
Corporation 82574L Gigabit Network Connection
 +-02.6-[0a-0c]00.0-[0b-0c]--+-01.0-[0c]--
 |   \-03.0  Intel Corporation 82540EM 
Gigabit Ethernet Controller
 +-02.7-[0d]0e.0  Intel Corporation 82540EM Gigabit Ethernet 
Controller
 +-03.0  Red Hat, Inc. QEMU PCIe Expander bridge
 +-04.0  Advanced Micro Devices, Inc. [AMD] Device 0020
 +-1f.0  Intel Corporation 82801IB (ICH9) LPC Interface Controller
 +-1f.2  Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA 
Controller [AHCI mode]
 \-1f.3  Intel Corporation 82801I (ICH9 Family) SMBus Controller

Where we have:

00:02.7 PCI bridge: Intel Corporation 82801 PCI Bridge
 (dmi-to-pci-bridge)
00:03.0 Host bridge: Red Hat, Inc. QEMU PCIe Expander bridge
 (pcie-expander-bus)
06:00.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Upstream)
 (pcie-switch-upstream-port)
07:00.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Downstream)
 (pcie-switch-downstream-port)
07:01.0 PCI bridge: Texas Instruments XIO3130 PCI Express Switch (Downstream)
 (pcie-switch-downstream-port)
0a:00.0 PCI bridge: Red Hat, Inc. Device 000e
 (pcie-to-pci-bridge)

The following IVRS table is produced:

AMD-Vi: Using IVHD type 0x10
AMD-Vi: device: 00:04.0 cap: 0040 seg: 0 flags: d1 info 
AMD-Vi:mmio-addr: fed8
AMD-Vi:   DEV_SELECT devid: 40:00.0 flags: 00
AMD-Vi:   DEV_SELECT_RANGE_START devid: 41:00.0 flags: 00
AMD-Vi:   DEV_RANGE_END  devid: 41:1f.7
AMD-Vi:   DEV_SELECT devid: 00:00.0 flags: 00
AMD-Vi:   DEV_SELECT devid: 00:01.0 flags: 00
AMD-Vi:   DEV_SELECT devid: 00:02.0 flags: 00
AMD-Vi:   DEV_SELECT_RANGE_START devid: 01:00.0 flags: 00
AMD-Vi:   DEV_RANGE_END  devid: 01:1f.7
AMD-Vi:   DEV_SELECT devid: 00:02.1 flags: 00
AMD-Vi:   DEV_SELECT_RANGE_START devid: 02:00.0 flags: 00
AMD-Vi:   DEV_RANGE_END  devid: 02:1f.7
AMD-Vi:   DEV_SELECT devid: 00:02.2 flags: 00
AMD-Vi:   DEV_SELECT_RANGE_START devid: 03:00.0 flags: 00
AMD-Vi:   DEV_RANGE_END  devid: 03:1f.7
AMD-Vi:   DEV_SELECT devid: 00:02.3 flags: 00
AMD-Vi:   DEV_SELECT_RANGE_START devid: 04:00.0 flags: 00
AMD-Vi:   DEV_RANGE_END  devid: 04:1f.7
AMD-Vi:   DEV_SELECT devid: 00:02.4 flags: 00
AMD-Vi:   DEV_SELECT_RANGE_START devid: 05:00.0 flags: 00
AMD-Vi:   DEV_RANGE_END  devid: 05:1f.7
AMD-Vi:   DEV_SELECT devid: 00:02.5 flags: 00
AMD-Vi:   DEV_SELECT devid: 06:00.0 flags: 00
AMD-Vi:   DEV_SELECT devid: 07:00.0 flags: 00
AMD-Vi:   DEV_SELECT_RANGE_START devid: 08:00.0 flags: 00
AMD-Vi:   DEV_RANGE_END  devid: 08:1f.7
AMD-Vi:   DEV_SELECT devid: 07:01.0 flags: 00
AMD-Vi:   DEV_SELECT_RANGE_START devid: 09:00.0 flags: 00
AMD-Vi:   DEV_RANGE_END  devid: 09:1f.7
AMD-Vi:   DEV_SELECT devid: 00:02.6 flags: 00
AMD-Vi:   DEV_SELECT devid: 0a:00.0 flags: 00
AMD-Vi:   DEV_ALIAS_RANGEdevid: 0b:00.0 flags: 00 devid_to: 
0b:00.0
AMD-Vi:   DEV_RANGE_END  devid: 0c:1f.7
AMD-Vi:   DEV_SELECT devid: 00:02.7 flags: 00
AMD-Vi:   DEV_ALIAS_RANGEdevid: 0d:00.0 flags: 00 devid_to: 
00:02.7
AMD-Vi:   DEV_RANGE_END  devid: 0d:1f.7
AMD-Vi:   DEV_SELECT devid: 00:03.0 flags: 00
AMD-Vi:   DEV_SELECT

[Qemu-devel] [for-4.2 PATCH 0/2] PCI DMA alias support

2019-07-26 Thread Alex Williamson
Please see patch 1/ for the motivation and utility of this series.
This v1 submission improves on the previous RFC with revised commit
logs, comments, and more testing, and the missing IVRS support for DMA
alias ranges is now included.  Testing has been done with Linux guests
with both SeaBIOS and OVMF with configurations of intel-iommu and
amd-iommu.  Intel-iommu testing includes device assignment, amd-iommu
is necessarily limited to emulated devices with interrupt remapping
disabled and iommu=pt in the guest (enabling interrupt remapping or
disabling guest passthrough mode fails to work regardless of this
series).  This series is NOT intended for QEMU v4.1.  Thanks,

Alex

---

Alex Williamson (2):
  pci: Use PCI aliases when determining device IOMMU address space
  hw/i386: AMD-Vi IVRS DMA alias support


 hw/i386/acpi-build.c |  127 +++---
 hw/pci/pci.c |   43 -
 2 files changed, 160 insertions(+), 10 deletions(-)



[Qemu-devel] [for-4.2 PATCH 1/2] pci: Use PCI aliases when determining device IOMMU address space

2019-07-26 Thread Alex Williamson
PCIe requester IDs are used by modern IOMMUs to differentiate devices
in order to provide a unique IOVA address space per device.  These
requester IDs are composed of the bus/device/function (BDF) of the
requesting device.  Conventional PCI pre-dates this concept and is
simply a shared parallel bus where transactions are claimed by
decoding target ranges rather than the packetized, point-to-point
mechanisms of PCI-express.  In order to interface conventional PCI
to PCIe, the PCIe-to-PCI bridge creates and accepts packetized
transactions on behalf of all downstream devices, using one of two
potential forms of a requester ID relating to the bridge itself or its
subordinate bus.  All downstream devices are therefore aliased by the
bridge's requester ID and it's not possible for the IOMMU to create
unique IOVA spaces for devices downstream of such buses.

At least that's how it works on bare metal.  Until now point we've
ignored this nuance of vIOMMU support in QEMU, creating a unique
AddressSpace per device regardless of the virtual bus topology.

Aside from simply being true to bare metal behavior, there are aspects
of a shared address space that we can use to our advantage when
designing a VM.  For instance, a PCI device assignment scenario where
we have the following IOMMU group on the host system:

  $ ls  /sys/kernel/iommu_groups/1/devices/
  :00:01.0  :01:00.0  :01:00.1

An IOMMU group is considered the smallest set of devices which are
fully DMA isolated from other devices by the IOMMU.  In this case the
root port at 00:01.0 does not guarantee that it prevents peer to peer
traffic between the endpoints on bus 01: and the devices are therefore
grouped together.  VFIO considers an IOMMU group to be the smallest
unit of device ownership and allows only a single shared IOVA space
per group due to the limitations of the isolation.

Therefore, if we attempt to create the following VM, we get an error:

qemu-system-x86_64 -machine q35... \
  -device intel-iommu,intremap=on \
  -device pcie-root-port,addr=1e.0,id=pcie.1 \
  -device vfio-pci,host=1:00.0,bus=pcie.1,addr=0.0,multifunction=on \
  -device vfio-pci,host=1:00.1,bus=pcie.1,addr=0.1

qemu-system-x86_64: -device vfio-pci,host=1:00.1,bus=pcie.1,addr=0.1: vfio \
:01:00.1: group 1 used in multiple address spaces

VFIO only allows a single IOVA space (AddressSpace) for both devices,
but we've placed them into a topology where the vIOMMU expects a
separate AddressSpace for each device.  On bare metal we know that
a conventional PCI bus would provide the sort of aliasing we need
here, forcing the IOMMU to consider these devices to be part of a
single shared IOVA space.  The support provided here does the same
for QEMU, such that we can create a conventional PCI topology to
expose equivalent AddressSpace sharing requirements to the VM:

qemu-system-x86_64 -machine q35... \
  -device intel-iommu,intremap=on \
  -device pcie-pci-bridge,addr=1e.0,id=pci.1 \
  -device vfio-pci,host=1:00.0,bus=pci.1,addr=1.0,multifunction=on \
  -device vfio-pci,host=1:00.1,bus=pci.1,addr=1.1

There are pros and cons to this configuration; it's not necessarily
recommended, it's simply a tool we can use to create configurations
which may provide additional functionality in spite of host hardware
limitations or as a benefit to the guest configuration or resource
usage.  An incomplete list of pros and cons:

Cons:
 a) Extended PCI configuration space is unavailable to devices
downstream of a conventional PCI bus.  The degree to which this
is a drawback depends on the device and guest drivers.
 b) Applying this topology to devices which are already isolated by
the host IOMMU (singleton IOMMU groups) will result in devices
which appear to be non-isolated to the VM (non-singleton groups).
This can limit configurations within the guest, such as userspace
drivers or nested device assignment.

Pros:
 a) QEMU better emulates bare metal.
 b) Configurations as above are now possible.
 c) Host IOMMU resources and VM locked memory requirements are reduced
in vIOMMU configurations due to shared IOMMU domains on the host
and avoidance of duplicate locked memory accounting.

Signed-off-by: Alex Williamson 
---
 hw/pci/pci.c |   43 ---
 1 file changed, 40 insertions(+), 3 deletions(-)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 8076a80ab3a9..b550741e88a3 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -2610,12 +2610,49 @@ AddressSpace *pci_device_iommu_address_space(PCIDevice 
*dev)
 {
 PCIBus *bus = pci_get_bus(dev);
 PCIBus *iommu_bus = bus;
+uint8_t devfn = dev->devfn;
 
-while(iommu_bus && !iommu_bus->iommu_fn && iommu_bus->parent_dev) {
-iommu_bus = pci_get_bus(iommu_bus->parent_dev);
+while (iommu_bus && !iommu_bus->iommu_fn && iommu_bus->parent_dev) {
+PCIBus *parent_bus = pci_get_bus(iommu_bus->parent_dev);
+
+/*
+ * The requester ID of the provided 

Re: [Qemu-devel] [Qemu-block] [PATCH v3 0/4] virtio/block: handle zoned backing devices

2019-07-26 Thread Dmitry Fomichev
John, please see inline...

Regards,
Dmitry

On Thu, 2019-07-25 at 13:58 -0400, John Snow wrote:
> 
> On 7/23/19 6:19 PM, Dmitry Fomichev wrote:
> > Currently, attaching zoned block devices (i.e., storage devices
> > compliant to ZAC/ZBC standards) using several virtio methods doesn't
> > work properly as zoned devices appear as regular block devices at the
> > guest. This may cause unexpected i/o errors and, potentially, some
> > data corruption.
> > 
> 
> Hi, I'm quite uninitiated here, what's a zoned block device? What are
> the ZAC/ZBC standards?
Zoned block devices (ZBDs) are HDDs that use SMR (shingled magnetic
recording). This type of recording, if applied to the entire drive, would
only allow the drive to be written sequentially. To make such devices more
practical, the entire LBA range of the drive is divided into zones. All
writes within a particular zone must be sequential, but writing different
zones can be done concurrently in random manner. This sounds like a lot of
hassle, but in return SMR can achieve up to 20% better areal data density
compared to the most common PMR recording.

The same zoned model is used in up-and-coming NVMe ZNS standard, even
though the reason for using it in ZNS is different compared to SMR HDDs -
easier flash erase block management.

ZBC is an INCITS T10 (SCSI) standard and ZAC is the corresponding T13 (ATA)
standard.

The lack of limelight for these standards is explained by the fact that
these devices are mostly used by cloud infrastructure providers for "cold"
data storage, a purely enterprise application. Currently, both WDC and
Seagate produce SMR drives in significant quantities and Toshiba has
announced support for ZBDs in their future products.

> > 
> I've found this:
> https://www.snia.org/sites/default/files/SDC/2016/presentations/smr/DamienLeMoal_ZBC-ZAC_Linux.pdf
> 
AFAIK, the most useful collection of public resources about zoned block
devices is this website -
http://zonedstorage.io
The site is maintained by our group at WDC (shameless plug here :) ).
BTW, here is the page containing the links to T10/T13 standards
(the access might be restricted for non-members of T10/T13 committees) -
http://zonedstorage.io/introduction/smr/#governing-standards

> It looks like ZAC/ZBC are new commands -- what happens if we just don't
> use them, exactly?
The standards define three models of zoned block devices: drive-managed,
host-aware and host-managed.

Drive-managed zoned devices behave just like regular SCSI/ATA devices and
don't require any additional support. There is no point for manufacturers
to market such devices as zoned. Host-managed and host-aware devices can
read data exactly the same way as common SCSI/ATA drives, but there are
I/O pattern limitations in the write path that the host must adhere to.

Host-aware drives will work without I/O errors under purely random write
workload, but their performance might be significantly degraded
compared to running them under zone-sequential workload. With
host-managed drives, any non-sequential writes within zones will lead
to an I/O error, most likely, "unaligned write".

It is important to mention that almost all zoned devices that are
currently on the market are host-managed.

ZAC/ZBC standards do add some new commands to the common SCSI/ACS command
sets, but, at least for the host-managed model, it wouldn't be sufficient
just to never issue these commands to be able to utilize these devices.

> 
> > To be more precise, attaching a zoned device via virtio-pci-blk,
> > virtio-scsi-pci/scsi-disk or virtio-scsi-pci/scsi-hd demonstrates the
> > above behavior. The virtio-scsi-pci/scsi-block method works with a
> > recent patch. The virtio-scsi-pci/scsi-generic method also appears to
> > handle zoned devices without problems.
> > 
> 
> What exactly fails, out of curiosity?
The current Linux kernel is able to recognize zoned block devices and
provide some means for the user to see that a particular device is zoned.
For example, lsscsi will show "zbc" instead of "disk" for zoned devices.
Another useful value is the "zoned" sysfs attribute that carries the
zoned model of the drive. Without this patch, the attachment methods
mentioned above present host-managed drives as regular drives at the
guest system. There is no way for the user to figure out that they are
dealing with a ZBD besides starting I/O and getting "unaligned write"
error.

The folks who designed ZAC/ZBC were very careful about this not to
happen and this doesn't happen on bare metal. Host-managed drives have
a distinctive SCSI device type, 0x14, and old kernels without zoned
device support simply are not be able to classify these drives during
the device scan. The kernels with ZBD support are able to recognize
a host-managed drive by its SCSI type and read some additional
protocol-specific info from the drive that is necessary for the kernel
to support it (how? see http://zonedstorage.io/linux/sched/).
In QEMU, this SCSI device type mechanism 

[Qemu-devel] Question regarding tcg trace-events

2019-07-26 Thread sainath grandhi
Hello
I am working with qemu tracing support and combined with tcg.
I read that if tcg property is used for trace-event, it generates a
trace-event once during translation and another trace-event after the
execution.

I made the following change in target/i386/translate.c

-static inline void gen_op_movl_seg_T0_vm(DisasContext *s, int seg_reg)
+static inline void gen_op_movl_seg_T0_vm(DisasContext *s, int
seg_reg, CPUX86State *env)
 {
 tcg_gen_ext16u_tl(s->T0, s->T0);
 tcg_gen_st32_tl(s->T0, cpu_env,
 offsetof(CPUX86State,segs[seg_reg].selector));
+trace_seg_write_tcg(tcg_ctx->cpu, cpu_env, env->eip, seg_reg,
env->segs[seg_reg].selector, s->T0);
 tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4);

I see seg_write_trans and seg_write_exec trace-events.
Question I have is the following:
I expect one seg_write_trans trace-event per seg_write_exec
trace-event. However I notice more than one seg_write_exec
trace-events after a seg_write_trans and in some cases seg_write_exec
trace-events occur without a seg_write_trans.
Why do this happen? Does this have something to do with TCG and TBs?



[Qemu-devel] [PULL] riscv/boot: Fixup the RISC-V firmware warning

2019-07-26 Thread Palmer Dabbelt
From: Alistair Francis 

Fix a typo in the warning message displayed to users, don't print the
message when running inside qtest and don't mention a specific QEMU
version for the deprecation.

Signed-off-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Palmer Dabbelt 
---
 hw/riscv/boot.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 5dee63011b43..6b7d322e857c 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -26,6 +26,7 @@
 #include "hw/riscv/boot.h"
 #include "hw/boards.h"
 #include "elf.h"
+#include "sysemu/qtest.h"
 
 #if defined(TARGET_RISCV32)
 # define KERNEL_BOOT_ADDRESS 0x8040
@@ -46,10 +47,13 @@ void riscv_find_and_load_firmware(MachineState *machine,
  * In the future this defaul will change to loading the prebuilt
  * OpenSBI firmware. Let's warn the user and then continue.
 */
-warn_report("No -bios option specified. Not loading a firmware.");
-warn_report("This default will change in QEMU 4.3. Please use the " \
-"-bios option to aviod breakages when this happens.");
-warn_report("See QEMU's deprecation documentation for details");
+if (!qtest_enabled()) {
+warn_report("No -bios option specified. Not loading a firmware.");
+warn_report("This default will change in a future QEMU release. " \
+"Please use the -bios option to avoid breakages when "\
+"this happens.");
+warn_report("See QEMU's deprecation documentation for details.");
+}
 return;
 }
 
-- 
2.21.0




[Qemu-devel] [PULL] RISC-V Patch for 4.1-rc3

2019-07-26 Thread Palmer Dabbelt
The following changes since commit bf8b024372bf8abf5a9f40bfa65eeefad23ff988:

  Update version for v4.1.0-rc2 release (2019-07-23 18:28:08 +0100)

are available in the Git repository at:

  git://github.com/palmer-dabbelt/qemu.git tags/riscv-for-master-4.1-rc3

for you to fetch changes up to 75ea2529cf09aa4630c5357f9814f04b6697e8b7:

  riscv/boot: Fixup the RISC-V firmware warning (2019-07-26 16:03:48 -0700)


RISC-V Patch for 4.1-rc3

This contains a single patch that fixes the warning introduced as part
of the OpenSBI integration.


Alistair Francis (1):
  riscv/boot: Fixup the RISC-V firmware warning

 hw/riscv/boot.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)




[Qemu-devel] [PATCH 2/2] iotests: use python logging for iotests.log()

2019-07-26 Thread John Snow
We can turn logging on/off globally instead of per-function.

Remove use_log from run_job, and use python logging to turn on
diffable output when we run through a script entry point.

(No, I have no idea why output on 245 changed. I really don't.)

Signed-off-by: John Snow 
---
 tests/qemu-iotests/030|  4 +--
 tests/qemu-iotests/245|  1 +
 tests/qemu-iotests/245.out| 24 +-
 tests/qemu-iotests/iotests.py | 48 ---
 4 files changed, 43 insertions(+), 34 deletions(-)

diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index 1b69f318c6..a382cb430b 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -411,8 +411,8 @@ class TestParallelOps(iotests.QMPTestCase):
 result = self.vm.qmp('block-job-set-speed', device='drive0', speed=0)
 self.assert_qmp(result, 'return', {})
 
-self.vm.run_job(job='drive0', auto_dismiss=True, use_log=False)
-self.vm.run_job(job='node4', auto_dismiss=True, use_log=False)
+self.vm.run_job(job='drive0', auto_dismiss=True)
+self.vm.run_job(job='node4', auto_dismiss=True)
 self.assert_no_active_block_jobs()
 
 # Test a block-stream and a block-commit job in parallel
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
index bc1ceb9792..3bc29acb33 100644
--- a/tests/qemu-iotests/245
+++ b/tests/qemu-iotests/245
@@ -1000,4 +1000,5 @@ class TestBlockdevReopen(iotests.QMPTestCase):
 self.reopen(opts, {'backing': 'hd2'})
 
 if __name__ == '__main__':
+iotests.activate_logging()
 iotests.main(supported_fmts=["qcow2"])
diff --git a/tests/qemu-iotests/245.out b/tests/qemu-iotests/245.out
index a19de5214d..15c3630e92 100644
--- a/tests/qemu-iotests/245.out
+++ b/tests/qemu-iotests/245.out
@@ -1,17 +1,17 @@
+{"execute": "job-finalize", "arguments": {"id": "commit0"}}
+{"return": {}}
+{"data": {"id": "commit0", "type": "commit"}, "event": "BLOCK_JOB_PENDING", 
"timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"device": "commit0", "len": 3145728, "offset": 3145728, "speed": 0, 
"type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": 
{"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "job-finalize", "arguments": {"id": "stream0"}}
+{"return": {}}
+{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", 
"timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, 
"type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": 
{"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "job-finalize", "arguments": {"id": "stream0"}}
+{"return": {}}
+{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", 
"timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, 
"type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": 
{"microseconds": "USECS", "seconds": "SECS"}}
 ..
 --
 Ran 18 tests
 
 OK
-{"execute": "job-finalize", "arguments": {"id": "commit0"}}
-{"return": {}}
-{"data": {"id": "commit0", "type": "commit"}, "event": "BLOCK_JOB_PENDING", 
"timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
-{"data": {"device": "commit0", "len": 3145728, "offset": 3145728, "speed": 0, 
"type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": 
{"microseconds": "USECS", "seconds": "SECS"}}
-{"execute": "job-finalize", "arguments": {"id": "stream0"}}
-{"return": {}}
-{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", 
"timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
-{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, 
"type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": 
{"microseconds": "USECS", "seconds": "SECS"}}
-{"execute": "job-finalize", "arguments": {"id": "stream0"}}
-{"return": {}}
-{"data": {"id": "stream0", "type": "stream"}, "event": "BLOCK_JOB_PENDING", 
"timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
-{"data": {"device": "stream0", "len": 3145728, "offset": 3145728, "speed": 0, 
"type": "stream"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": 
{"microseconds": "USECS", "seconds": "SECS"}}
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 5e9b2989dd..d55ca864eb 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -35,6 +35,13 @@ from collections import OrderedDict
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
 from qemu import qtest
 
+# Use this logger for logging messages directly from the iotests module
+logger = logging.getLogger(__name__)
+logger.addHandler(logging.NullHandler())
+
+# Use this logger for messages that ought to be used for diff output.
+test_logger = logging.getLogger('.'.join((__name__, 'iotest')))

[Qemu-devel] [PATCH 1/2] iotests: add script_initialize

2019-07-26 Thread John Snow
Like script_main, but doesn't require a single point of entry.
Replace all existing initialization sections with this drop-in replacement.

This brings debug support to all existing script-style iotests.

Note: supported_oses=['linux'] was omitted, as it is a default argument.
Signed-off-by: John Snow 
---
 tests/qemu-iotests/149|  3 +--
 tests/qemu-iotests/194|  3 +--
 tests/qemu-iotests/202|  3 +--
 tests/qemu-iotests/203|  3 +--
 tests/qemu-iotests/206|  2 +-
 tests/qemu-iotests/208|  2 +-
 tests/qemu-iotests/216|  3 +--
 tests/qemu-iotests/218|  2 +-
 tests/qemu-iotests/219|  2 +-
 tests/qemu-iotests/222|  5 ++---
 tests/qemu-iotests/224|  3 +--
 tests/qemu-iotests/228|  3 +--
 tests/qemu-iotests/234|  3 +--
 tests/qemu-iotests/235|  4 ++--
 tests/qemu-iotests/236|  2 +-
 tests/qemu-iotests/238|  2 ++
 tests/qemu-iotests/242|  2 +-
 tests/qemu-iotests/246|  2 +-
 tests/qemu-iotests/248|  2 +-
 tests/qemu-iotests/254|  2 +-
 tests/qemu-iotests/255|  2 +-
 tests/qemu-iotests/256|  2 +-
 tests/qemu-iotests/iotests.py | 19 +++
 23 files changed, 40 insertions(+), 36 deletions(-)

diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
index 4f363f295f..9fa97966c5 100755
--- a/tests/qemu-iotests/149
+++ b/tests/qemu-iotests/149
@@ -383,8 +383,7 @@ def test_once(config, qemu_img=False):
 
 
 # Obviously we only work with the luks image format
-iotests.verify_image_format(supported_fmts=['luks'])
-iotests.verify_platform()
+iotests.script_initialize(supported_fmts=['luks'])
 
 # We need sudo in order to run cryptsetup to create
 # dm-crypt devices. This is safe to use on any
diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194
index d746ab1e21..c8aeb6d0e4 100755
--- a/tests/qemu-iotests/194
+++ b/tests/qemu-iotests/194
@@ -21,8 +21,7 @@
 
 import iotests
 
-iotests.verify_image_format(supported_fmts=['qcow2', 'qed', 'raw'])
-iotests.verify_platform(['linux'])
+iotests.script_initialize(supported_fmts=['qcow2', 'qed', 'raw'])
 
 with iotests.FilePath('source.img') as source_img_path, \
  iotests.FilePath('dest.img') as dest_img_path, \
diff --git a/tests/qemu-iotests/202 b/tests/qemu-iotests/202
index 581ca34d79..1271ac9459 100755
--- a/tests/qemu-iotests/202
+++ b/tests/qemu-iotests/202
@@ -24,8 +24,7 @@
 
 import iotests
 
-iotests.verify_image_format(supported_fmts=['qcow2'])
-iotests.verify_platform(['linux'])
+iotests.script_initialize(supported_fmts=['qcow2'])
 
 with iotests.FilePath('disk0.img') as disk0_img_path, \
  iotests.FilePath('disk1.img') as disk1_img_path, \
diff --git a/tests/qemu-iotests/203 b/tests/qemu-iotests/203
index 4874a1a0d8..c40fe231ea 100755
--- a/tests/qemu-iotests/203
+++ b/tests/qemu-iotests/203
@@ -24,8 +24,7 @@
 
 import iotests
 
-iotests.verify_image_format(supported_fmts=['qcow2'])
-iotests.verify_platform(['linux'])
+iotests.script_initialize(supported_fmts=['qcow2'])
 
 with iotests.FilePath('disk0.img') as disk0_img_path, \
  iotests.FilePath('disk1.img') as disk1_img_path, \
diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206
index 5bb738bf23..23ff2f624b 100755
--- a/tests/qemu-iotests/206
+++ b/tests/qemu-iotests/206
@@ -23,7 +23,7 @@
 import iotests
 from iotests import imgfmt
 
-iotests.verify_image_format(supported_fmts=['qcow2'])
+iotests.script_initialize(supported_fmts=['qcow2'])
 
 def blockdev_create(vm, options):
 result = vm.qmp_log('blockdev-create',
diff --git a/tests/qemu-iotests/208 b/tests/qemu-iotests/208
index 1e202388dc..dfce6f9fe4 100755
--- a/tests/qemu-iotests/208
+++ b/tests/qemu-iotests/208
@@ -22,7 +22,7 @@
 
 import iotests
 
-iotests.verify_image_format(supported_fmts=['generic'])
+iotests.script_initialize(supported_fmts=['generic'])
 
 with iotests.FilePath('disk.img') as disk_img_path, \
  iotests.FilePath('disk-snapshot.img') as disk_snapshot_img_path, \
diff --git a/tests/qemu-iotests/216 b/tests/qemu-iotests/216
index 3c0ae54b44..7574bcc09f 100755
--- a/tests/qemu-iotests/216
+++ b/tests/qemu-iotests/216
@@ -23,8 +23,7 @@ import iotests
 from iotests import log, qemu_img, qemu_io_silent
 
 # Need backing file support
-iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'])
-iotests.verify_platform(['linux'])
+iotests.script_initialize(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'])
 
 log('')
 log('=== Copy-on-read across nodes ===')
diff --git a/tests/qemu-iotests/218 b/tests/qemu-iotests/218
index 2554d84581..e18e31076b 100755
--- a/tests/qemu-iotests/218
+++ b/tests/qemu-iotests/218
@@ -29,7 +29,7 @@
 import iotests
 from iotests import log, qemu_img, qemu_io_silent
 
-iotests.verify_image_format(supported_fmts=['qcow2', 'raw'])
+iotests.script_initialize(supported_fmts=['qcow2', 'raw'])
 
 
 # Launches the VM, adds two null-co nodes (source and target), and
diff --git 

[Qemu-devel] [PATCH 0/2] iotests: use python logging

2019-07-26 Thread John Snow
Based-on: https://github.com/jnsnow/qemu/tree/bitmaps

This is a quick hack-em-up of what it might look like to use python
logging to enable output conditionally on iotests.log(). We unify an
initialization call (which also enables debugging output for those tests
with -d) and then make the switch inside of iotests.

It might help with needing to add logged/unlogged versions.

Depends on my bitmaps branch, because of the iotests refactoring I have
done there.

John Snow (2):
  iotests: add script_initialize
  iotests: use python logging for iotests.log()

 tests/qemu-iotests/030|  4 +--
 tests/qemu-iotests/149|  3 +-
 tests/qemu-iotests/194|  3 +-
 tests/qemu-iotests/202|  3 +-
 tests/qemu-iotests/203|  3 +-
 tests/qemu-iotests/206|  2 +-
 tests/qemu-iotests/208|  2 +-
 tests/qemu-iotests/216|  3 +-
 tests/qemu-iotests/218|  2 +-
 tests/qemu-iotests/219|  2 +-
 tests/qemu-iotests/222|  5 ++-
 tests/qemu-iotests/224|  3 +-
 tests/qemu-iotests/228|  3 +-
 tests/qemu-iotests/234|  3 +-
 tests/qemu-iotests/235|  4 +--
 tests/qemu-iotests/236|  2 +-
 tests/qemu-iotests/238|  2 ++
 tests/qemu-iotests/242|  2 +-
 tests/qemu-iotests/245|  1 +
 tests/qemu-iotests/245.out| 24 ++---
 tests/qemu-iotests/246|  2 +-
 tests/qemu-iotests/248|  2 +-
 tests/qemu-iotests/254|  2 +-
 tests/qemu-iotests/255|  2 +-
 tests/qemu-iotests/256|  2 +-
 tests/qemu-iotests/iotests.py | 67 ++-
 26 files changed, 83 insertions(+), 70 deletions(-)

-- 
2.21.0




Re: [Qemu-devel] [Qemu-riscv] [PATCH-4.2 v1 2/6] target/riscv: Remove strict perm checking for CSR R/W

2019-07-26 Thread Alistair Francis
On Fri, Jul 26, 2019 at 2:00 PM Jonathan Behrens  wrote:
>
> The remaining checks are not sufficient. If you look at the bottom of csr.c, 
> you'll see that for most of the M-mode CSRs the predicate is set to "any" 
> which unconditionally allows access regardless of privilege mode. The S-mode 
> CSR predicates similarly only check that supervisor mode exists, but not that 
> the processor is current running in that mode. I do agree with you that using 
> the register address to determine the required privilege mode is a little 
> strange, but RISC-V is designed so that bits 8 and 9 of the CSR address 
> encode that information: 0=U-mode, 1=S-mode, 2=HS-mode, 3=M-mode.

Ah, I didn't realise that was guaranteed. I will drop this patch from
this series and update it in my Hypervisor series.

Alistair

>
> I also tested by booting RVirt with a Linux guest and found that this patch 
> caused it to instantly crash because guest CSR accesses weren't intercepted.
>
> Jonathan
>
> On Fri, Jul 26, 2019 at 4:28 PM Alistair Francis  wrote:
>>
>> On Thu, Jul 25, 2019 at 2:48 PM Jonathan Behrens  wrote:
>> >
>> > Unless I'm missing something, this is the only place that QEMU checks the 
>> > privilege level for read and writes to CSRs. The exact computation used 
>> > here won't work with the hypervisor extension, but we also can't just get 
>> > rid of privilege checking entirely...
>>
>> The csr_ops struct contains a checker function, so there are still
>> some checks occurring. I haven't done negative testing on this patch,
>> but the current check doesn't seem to make any sense so it should be
>> removed. We can separately discuss adding more checks but this current
>> way base don CSR address just seems strange.
>>
>> Alistair
>>
>> >
>> > Jonathan
>> >
>> > On Thu, Jul 25, 2019 at 2:56 PM Alistair Francis 
>> >  wrote:
>> >>
>> >> The privledge check based on the CSR address mask 0x300 doesn't work
>> >> when using Hypervisor extensions so remove the check
>> >>
>> >> Signed-off-by: Alistair Francis 
>> >> ---
>> >>  target/riscv/csr.c | 3 +--
>> >>  1 file changed, 1 insertion(+), 2 deletions(-)
>> >>
>> >> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
>> >> index e0d4586760..af3b762c8b 100644
>> >> --- a/target/riscv/csr.c
>> >> +++ b/target/riscv/csr.c
>> >> @@ -797,9 +797,8 @@ int riscv_csrrw(CPURISCVState *env, int csrno, 
>> >> target_ulong *ret_value,
>> >>
>> >>  /* check privileges and return -1 if check fails */
>> >>  #if !defined(CONFIG_USER_ONLY)
>> >> -int csr_priv = get_field(csrno, 0x300);
>> >>  int read_only = get_field(csrno, 0xC00) == 3;
>> >> -if ((write_mask && read_only) || (env->priv < csr_priv)) {
>> >> +if (write_mask && read_only) {
>> >>  return -1;
>> >>  }
>> >>  #endif
>> >> --
>> >> 2.22.0
>> >>
>> >>



Re: [Qemu-devel] [Qemu-riscv] [PATCH-4.2 v1 2/6] target/riscv: Remove strict perm checking for CSR R/W

2019-07-26 Thread Jonathan Behrens
The remaining checks are not sufficient. If you look at the bottom of
csr.c, you'll see that for most of the M-mode CSRs the predicate is set to
"any" which unconditionally allows access regardless of privilege mode. The
S-mode CSR predicates similarly only check that supervisor mode exists, but
not that the processor is current running in that mode. I do agree with you
that using the register address to determine the required privilege mode is
a little strange, but RISC-V is designed so that bits 8 and 9 of the CSR
address encode that information: 0=U-mode, 1=S-mode, 2=HS-mode, 3=M-mode.

I also tested by booting RVirt  with a
Linux guest and found that this patch caused it to instantly crash because
guest CSR accesses weren't intercepted.

Jonathan

On Fri, Jul 26, 2019 at 4:28 PM Alistair Francis 
wrote:

> On Thu, Jul 25, 2019 at 2:48 PM Jonathan Behrens 
> wrote:
> >
> > Unless I'm missing something, this is the only place that QEMU checks
> the privilege level for read and writes to CSRs. The exact computation used
> here won't work with the hypervisor extension, but we also can't just get
> rid of privilege checking entirely...
>
> The csr_ops struct contains a checker function, so there are still
> some checks occurring. I haven't done negative testing on this patch,
> but the current check doesn't seem to make any sense so it should be
> removed. We can separately discuss adding more checks but this current
> way base don CSR address just seems strange.
>
> Alistair
>
> >
> > Jonathan
> >
> > On Thu, Jul 25, 2019 at 2:56 PM Alistair Francis <
> alistair.fran...@wdc.com> wrote:
> >>
> >> The privledge check based on the CSR address mask 0x300 doesn't work
> >> when using Hypervisor extensions so remove the check
> >>
> >> Signed-off-by: Alistair Francis 
> >> ---
> >>  target/riscv/csr.c | 3 +--
> >>  1 file changed, 1 insertion(+), 2 deletions(-)
> >>
> >> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> >> index e0d4586760..af3b762c8b 100644
> >> --- a/target/riscv/csr.c
> >> +++ b/target/riscv/csr.c
> >> @@ -797,9 +797,8 @@ int riscv_csrrw(CPURISCVState *env, int csrno,
> target_ulong *ret_value,
> >>
> >>  /* check privileges and return -1 if check fails */
> >>  #if !defined(CONFIG_USER_ONLY)
> >> -int csr_priv = get_field(csrno, 0x300);
> >>  int read_only = get_field(csrno, 0xC00) == 3;
> >> -if ((write_mask && read_only) || (env->priv < csr_priv)) {
> >> +if (write_mask && read_only) {
> >>  return -1;
> >>  }
> >>  #endif
> >> --
> >> 2.22.0
> >>
> >>
>


Re: [Qemu-devel] Exploring Sphinx, autodoc, apidoc, and coverage tools for python/qemu

2019-07-26 Thread Eduardo Habkost
CCing Cleber and Gabriel.  Comments at the "conclusions" section
below:

On Wed, Jul 24, 2019 at 05:06:41PM -0400, John Snow wrote:
> Has anyone on this list experimented with these tools?
> 
> I was hoping to use them to document things like the python/machine.py
> and python/qmp.py modules to help demonstrate some of our internal
> tooling API (for test writers, GSoC/Outreachy interns, folks who want to
> script QEMU at a level between writing a CLI driver and using libvirt.)
> 
> What follows below is my process trying to enable this and some of the
> problems I'm still stuck with, summarized below at the end of this more
> exploratory text.
> 
> 
> Enabling autodoc:
> 
> First, it appears as if enabling the "sphinx-autodoc" tool is not
> sufficient for actually generating anything at all when you invoke the
> sphinx-generated "make html" target. It just enables understanding
> certain directives.
> 
> So apparently you need to generate module "stubs" using sphinx-autodoc.
> Sphinx uses the sphinx-autodoc extension to understand how to consume
> the directives in these stubs.
> 
> That strikes me as odd, because these stubs might need to be changed
> frequently as code comes and goes; it seems strange that it isn't
> integrated at the top level. (Do I have the wrong idea on how these
> tools should be used?)
> 
> So you need to run:
> > sphinx-apidoc --separate --module-first -o docs/ python/qemu/
> 
> which generates stubs to docs:
> 
> Creating file docs/qemu.machine.rst.
> Creating file docs/qemu.qmp.rst.
> Creating file docs/qemu.qtest.rst.
> Creating file docs/qemu.rst.
> Creating file docs/modules.rst.
> 
> And then you can edit e.g. the top-level index.rst TOC in docs/index.rst
> to look like this:
> 
> ```
> .. toctree::
>:maxdepth: 2
>:caption: Contents:
> 
>interop/index
>devel/index
>specs/index
>modules
> ```
> 
> And then finally generating the build; manually removing the -W option
> from the Makefile: there are a lot of warnings in here.
> 
> > sphinx-build -n -b html -D version=4.0.92 -D release="4.0.92
> (v4.1.0-rc2-34-g160802eb07-dirty)" -d .doctrees/
> /home/bos/jhuston/src/qemu/docs/ docs/
> 
> Great! that will generate output to docs/index.html which indeed shows
> APIdoc comments generated from our Python files. Good.
> 
> However, where this gets a little strange is if you look at the
> generated stubs. For instance, qemu.machine.rst looks like this:
> 
> ```
> .. automodule:: qemu.machine
> :members:
> :undoc-members:
> :show-inheritance:
> ```
> 
> :undoc-members: says that we want to "document" any members that don't
> have a matching apidoc comment by generating a stub.
> 
> Oops, but the presence of that stub will cause the sphinx coverage tool
> to happily report 100% coverage.
> 
> Further oops, pylint doesn't understand apidoc comments and can't be
> used as the linter in this case, either.
> 
> You can edit the stubs to remove these directives, but these stubs are
> generated -- and it doesn't appear like there's a command line option to
> change this behavior. ...Hmm.
> 
> And either way, the coverage tool only generates a report and not
> something with an error code that I could use to gate the build. Same
> goes for the general build: if I remove the :undoc-members: parameter,
> there's nothing in the autodoc module that appears to throw warnings
> when it encounters undocumented parameters or members.
> 
> That seems disappointing, because it's hard to keep docstrings up to
> date unless they are checked conclusively at build time.
> 
> 
> Conclusions:
> 
> - the autodoc documentation page doesn't seem to document examples of
> how you're expected to write meaningful docstrings for the tool to extract.

I had the same impression when I read sphinx/autodoc
documentation.

> 
> - autodoc fools the coverage tool into reporting 100% coverage.
> 
> - autodoc can be configured to omit non-documented members to allow the
> coverage tool to work, but the configuration is auto-generated and
> defaults to always generating documentation for these entities.
> 
> - coverage tool doesn't appear like it can be used for gating the build
> natively for missing python docs; it only generates a report.
> 
> - Even if we script to block on a non-empty report, the coverage tool
> only works at the function/class level and does not understand the
> concept of missing parameter or return value tags.
> 
> - It would seem that it would be the Autodoc module's job to be
> responsible for understanding incomplete documentation, but doesn't
> appear to. The :param name: syntax is just a ReST "field list" and isn't
> parsed semantically by autodoc, sadly.

I wonder if there are other Python documentation coverage tools
outside Sphinx.  Googling for [python docstring coverage]
resulted in a few different projects, but I don't know which ones
would understand Sphinx-compatible rST docstrings.

> 
> 
> It looks to me, at a glance, that there's nothing in Sphinx 

Re: [Qemu-devel] [RFC 09/19] fuzz: use mtree_info to find mapped addresses

2019-07-26 Thread Paolo Bonzini
On 26/07/19 15:04, Stefan Hajnoczi wrote:
> On Thu, Jul 25, 2019 at 03:23:51AM +, Oleinik, Alexander wrote:
>> Locate mmio and port i/o addresses that are mapped to devices so we can
>> limit the fuzzer to only these addresses. This should be replaced with
>> a sane way of enumaring these memory regions.
>>
>> Signed-off-by: Alexander Oleinik 
>> ---
>>  memory.c | 34 ++
>>  1 file changed, 34 insertions(+)
>>
>> diff --git a/memory.c b/memory.c
>> index 5d8c9a9234..fa6cbe4f1d 100644
>> --- a/memory.c
>> +++ b/memory.c
>> @@ -34,6 +34,11 @@
>>  #include "hw/qdev-properties.h"
>>  #include "hw/boards.h"
>>  #include "migration/vmstate.h"
>> +#ifdef CONFIG_FUZZ
>> +#include "tests/fuzz/fuzz.h"
>> +#include "tests/fuzz/qos_fuzz.h"
>> +#endif
>> +
>>  
>>  //#define DEBUG_UNASSIGNED
>>  
>> @@ -3016,12 +3021,20 @@ static void mtree_print_flatview(gpointer key, 
>> gpointer value,
>>  int n = view->nr;
>>  int i;
>>  AddressSpace *as;
>> +#ifdef CONFIG_FUZZ
>> +bool io=false;
>> +#endif
>> +
>>  
>>  qemu_printf("FlatView #%d\n", fvi->counter);
>>  ++fvi->counter;
>>  
>>  for (i = 0; i < fv_address_spaces->len; ++i) {
>>  as = g_array_index(fv_address_spaces, AddressSpace*, i);
>> +#ifdef CONFIG_FUZZ
>> +if(strcmp("I/O",as->name) == 0)
>> +io = true;
>> +#endif
>>  qemu_printf(" AS \"%s\", root: %s",
>>  as->name, memory_region_name(as->root));
>>  if (as->root->alias) {
>> @@ -3062,6 +3075,27 @@ static void mtree_print_flatview(gpointer key, 
>> gpointer value,
>>  range->readonly ? "rom" : memory_region_type(mr),
>>  memory_region_name(mr));
>>  }
>> +#ifdef CONFIG_FUZZ
>> +if(strcmp("i/o", memory_region_type(mr))==0 && strcmp("io", 
>> memory_region_name(mr))){
>> +fuzz_memory_region *fmr = g_new0(fuzz_memory_region, 1);
>> +if(!fuzz_memory_region_head)
>> +{
>> +fuzz_memory_region_head = fmr;
>> +fuzz_memory_region_tail = fmr;
>> +}
>> +fmr->io = io;
>> +fmr->start = int128_get64(range->addr.start);
>> +fmr->length = MR_SIZE(range->addr.size);
>> +fmr->next = fuzz_memory_region_head;
>> +fuzz_memory_region_tail->next = fmr;
>> +fuzz_memory_region_tail = fmr;
>> +if(io == true){
>> +total_io_mem += MR_SIZE(range->addr.size)+1;
>> +} else {
>> +total_ram_mem += MR_SIZE(range->addr.size)+1;
>> +}
>> +}
>> +#endif
> 
> Why is this patch modifying a print function?  I think the goal is to
> build the fuzz_memory_region list and calculate
> total_io_mem/total_ram_mem.  This should be done by a separate function.

Yeah, this should just cut-and-paste code from mtree_print_flatview,
then you can remove the printing stuff completely from your copy.

Paolo




Re: [Qemu-devel] [QEMU-SECURITY] ide: fix assertion in ide_dma_cb() to prevent qemu DoS from quest

2019-07-26 Thread Alexander Popov



26 июля 2019 г. 2:25:03 GMT+02:00, John Snow  пишет:
>Oh, this is fun.
... 
>I can worry about a proper fix for 4.2+.

Hello John, 

Thanks for your letter. 

I double-checked the git history and mailing list, I'm still sure
that my fix for this assertion is correct.

You know this code very well, of course it would be great if you
prepare the further fixes. 

Feel free to add me to CC, I can review the patches and test
them with fuzzing. 

Best regards, 
Alexander



Re: [Qemu-devel] [RFC 07/19] fuzz: Modify libqtest to directly invoke qtest.c

2019-07-26 Thread Paolo Bonzini
On 26/07/19 14:56, Stefan Hajnoczi wrote:
> This should use indirection: a function pointer to dispatch to either
> the socket or the internal qtest_process_inbuf() call.
> 
> With a bit of refactoring you can eliminate the #ifdefs and treat the
> socket fd as one backend and direct invocation as another backend.

My suggestion was a bit different (two files), but this also works.  In
fact it can also be combined to have three files:

- one defining libqtest's qtest_init and associated struct of function
pointers

- one defining the fuzzer's qtest_init and associated struct of function
pointers

- one with the remaining libqtest code, modified to use the struct of
function pointers for everything that you're #ifdef-ing here, and a
function qtest_client_init that receives the struct of function pointers
and stores them in QTestState.  The two qtest_init implementations in
the other files just call qtest_client_init.

Paolo



Re: [Qemu-devel] [PATCH for-3.1.1 0/2] tpm: Improve on error handling

2019-07-26 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20190726164921.1655115-1-stef...@linux.vnet.ibm.com/



Hi,

This series failed the asan build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#!/bin/bash
make docker-image-fedora V=1 NETWORK=1
time make docker-test-debug@fedora TARGET_LIST=x86_64-softmmu J=14 NETWORK=1
=== TEST SCRIPT END ===

PASS 1 fdc-test /x86_64/fdc/cmos
PASS 2 fdc-test /x86_64/fdc/no_media_on_start
PASS 3 fdc-test /x86_64/fdc/read_without_media
==7963==WARNING: ASan doesn't fully support makecontext/swapcontext functions 
and may produce false positives in some cases!
PASS 4 fdc-test /x86_64/fdc/media_change
PASS 5 fdc-test /x86_64/fdc/sense_interrupt
PASS 6 fdc-test /x86_64/fdc/relative_seek
---
PASS 32 test-opts-visitor /visitor/opts/range/beyond
PASS 33 test-opts-visitor /visitor/opts/dict/unvisited
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  
tests/test-coroutine -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl 
--test-name="test-coroutine" 
==8008==WARNING: ASan doesn't fully support makecontext/swapcontext functions 
and may produce false positives in some cases!
==8008==WARNING: ASan is ignoring requested __asan_handle_no_return: stack top: 
0x7ffdcc21f000; bottom 0x7f9616af8000; size: 0x0067b5727000 (445425807360)
False positive error reports may follow
For details see https://github.com/google/sanitizers/issues/189
PASS 1 test-coroutine /basic/no-dangling-access
---
PASS 13 test-aio /aio/event/wait/no-flush-cb
PASS 11 fdc-test /x86_64/fdc/read_no_dma_18
PASS 14 test-aio /aio/timer/schedule
==8027==WARNING: ASan doesn't fully support makecontext/swapcontext functions 
and may produce false positives in some cases!
PASS 15 test-aio /aio/coroutine/queue-chaining
PASS 16 test-aio /aio-gsource/flush
PASS 17 test-aio /aio-gsource/bh/schedule
---
PASS 27 test-aio /aio-gsource/event/wait/no-flush-cb
PASS 28 test-aio /aio-gsource/timer/schedule
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  
tests/test-aio-multithread -m=quick -k --tap < /dev/null | 
./scripts/tap-driver.pl --test-name="test-aio-multithread" 
==8033==WARNING: ASan doesn't fully support makecontext/swapcontext functions 
and may produce false positives in some cases!
PASS 1 test-aio-multithread /aio/multi/lifecycle
PASS 2 test-aio-multithread /aio/multi/schedule
PASS 12 fdc-test /x86_64/fdc/read_no_dma_19
PASS 3 test-aio-multithread /aio/multi/mutex/contended
PASS 13 fdc-test /x86_64/fdc/fuzz-registers
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  
QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64 QTEST_QEMU_IMG=qemu-img 
tests/ide-test -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl 
--test-name="ide-test" 
==8061==WARNING: ASan doesn't fully support makecontext/swapcontext functions 
and may produce false positives in some cases!
PASS 1 ide-test /x86_64/ide/identify
==8067==WARNING: ASan doesn't fully support makecontext/swapcontext functions 
and may produce false positives in some cases!
PASS 4 test-aio-multithread /aio/multi/mutex/handoff
PASS 2 ide-test /x86_64/ide/flush
==8078==WARNING: ASan doesn't fully support makecontext/swapcontext functions 
and may produce false positives in some cases!
PASS 5 test-aio-multithread /aio/multi/mutex/mcs
PASS 3 ide-test /x86_64/ide/bmdma/simple_rw
==8089==WARNING: ASan doesn't fully support makecontext/swapcontext functions 
and may produce false positives in some cases!
PASS 6 test-aio-multithread /aio/multi/mutex/pthread
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  
tests/test-throttle -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl 
--test-name="test-throttle" 
PASS 4 ide-test /x86_64/ide/bmdma/trim
---
PASS 5 test-throttle /throttle/have_timer
PASS 6 test-throttle /throttle/detach_attach
PASS 7 test-throttle /throttle/config_functions
==8097==WARNING: ASan doesn't fully support makecontext/swapcontext functions 
and may produce false positives in some cases!
PASS 8 test-throttle /throttle/accounting
PASS 9 test-throttle /throttle/groups
PASS 10 test-throttle /throttle/config/enabled
---
PASS 14 test-throttle /throttle/config/max
PASS 15 test-throttle /throttle/config/iops_size
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  
tests/test-thread-pool -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl 
--test-name="test-thread-pool" 
==8103==WARNING: ASan doesn't fully support makecontext/swapcontext functions 
and may produce false positives in some cases!
PASS 1 test-thread-pool /thread-pool/submit
PASS 2 test-thread-pool /thread-pool/submit-aio
PASS 3 test-thread-pool /thread-pool/submit-co
PASS 4 test-thread-pool /thread-pool/submit-many
==8099==WARNING: ASan doesn't fully support makecontext/swapcontext functions 
and may produce false positives in some cases!
PASS 5 ide-test /x86_64/ide/bmdma/short_prdt
==8175==WARNING: ASan doesn't fully 

Re: [Qemu-devel] [PATCH 22/28] Include hw/boards.h a bit less

2019-07-26 Thread Alistair Francis
On Fri, Jul 26, 2019 at 5:10 AM Markus Armbruster  wrote:
>
> hw/boards.h pulls in almost 60 headers.  The less we include it into
> headers, the better.  As a first step, drop superfluous inclusions,
> and downgrade some more to what's actually needed.  Gets rid of just
> one inclusion into a header.
>
> Cc: Eduardo Habkost 
> Cc: Marcel Apfelbaum 
> Signed-off-by: Markus Armbruster 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  backends/cryptodev-builtin.c| 1 -
>  backends/cryptodev-vhost-user.c | 1 -
>  backends/cryptodev.c| 1 -
>  exec.c  | 1 -
>  hw/acpi/cpu.c   | 1 -
>  hw/acpi/ich9.c  | 1 +
>  hw/acpi/memory_hotplug.c| 1 -
>  hw/alpha/dp264.c| 1 -
>  hw/alpha/typhoon.c  | 1 +
>  hw/arm/boot.c   | 1 -
>  hw/arm/exynos4210.c | 2 +-
>  hw/arm/fsl-imx25.c  | 1 -
>  hw/arm/fsl-imx31.c  | 1 -
>  hw/arm/msf2-soc.c   | 1 -
>  hw/arm/nrf51_soc.c  | 1 -
>  hw/arm/omap1.c  | 1 +
>  hw/arm/omap2.c  | 1 +
>  hw/arm/smmuv3.c | 1 -
>  hw/arm/virt.c   | 1 +
>  hw/core/machine-qmp-cmds.c  | 1 -
>  hw/core/machine.c   | 1 -
>  hw/core/numa.c  | 2 ++
>  hw/i386/intel_iommu.c   | 1 -
>  hw/i386/pc_piix.c   | 1 -
>  hw/i386/pc_q35.c| 1 -
>  hw/i386/pc_sysfw.c  | 1 -
>  hw/i386/x86-iommu.c | 1 -
>  hw/ppc/e500plat.c   | 1 -
>  hw/ppc/mpc8544ds.c  | 1 -
>  hw/ppc/pnv.c| 1 +
>  hw/ppc/ppc405_uc.c  | 1 -
>  hw/ppc/spapr_cpu_core.c | 1 -
>  hw/ppc/spapr_rtas.c | 1 -
>  hw/ppc/spapr_vio.c  | 1 -
>  hw/riscv/boot.c | 2 +-
>  hw/s390x/s390-stattrib-kvm.c| 1 -
>  hw/s390x/s390-stattrib.c| 1 -
>  hw/xtensa/xtensa_memory.c   | 1 -
>  include/hw/mem/pc-dimm.h| 1 -
>  monitor/qmp-cmds.c  | 1 -
>  target/alpha/machine.c  | 1 -
>  target/arm/kvm.c| 1 -
>  target/arm/machine.c| 1 -
>  target/arm/monitor.c| 1 -
>  target/hppa/machine.c   | 1 -
>  target/i386/hax-all.c   | 1 -
>  target/i386/hvf/hvf.c   | 1 -
>  target/i386/hvf/x86_task.c  | 1 -
>  target/i386/machine.c   | 1 -
>  target/i386/whpx-all.c  | 1 -
>  target/lm32/machine.c   | 1 -
>  target/moxie/machine.c  | 1 -
>  target/openrisc/machine.c   | 1 -
>  target/ppc/machine.c| 1 -
>  target/sparc/machine.c  | 1 -
>  55 files changed, 10 insertions(+), 48 deletions(-)
>
> diff --git a/backends/cryptodev-builtin.c b/backends/cryptodev-builtin.c
> index 9fb0bd57a6..c8ae3b9742 100644
> --- a/backends/cryptodev-builtin.c
> +++ b/backends/cryptodev-builtin.c
> @@ -23,7 +23,6 @@
>
>  #include "qemu/osdep.h"
>  #include "sysemu/cryptodev.h"
> -#include "hw/boards.h"
>  #include "qapi/error.h"
>  #include "standard-headers/linux/virtio_crypto.h"
>  #include "crypto/cipher.h"
> diff --git a/backends/cryptodev-vhost-user.c b/backends/cryptodev-vhost-user.c
> index 1052a5d0e9..b344283940 100644
> --- a/backends/cryptodev-vhost-user.c
> +++ b/backends/cryptodev-vhost-user.c
> @@ -22,7 +22,6 @@
>   */
>
>  #include "qemu/osdep.h"
> -#include "hw/boards.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/error-report.h"
> diff --git a/backends/cryptodev.c b/backends/cryptodev.c
> index f35be377ef..3c071eab95 100644
> --- a/backends/cryptodev.c
> +++ b/backends/cryptodev.c
> @@ -23,7 +23,6 @@
>
>  #include "qemu/osdep.h"
>  #include "sysemu/cryptodev.h"
> -#include "hw/boards.h"
>  #include "qapi/error.h"
>  #include "qapi/visitor.h"
>  #include "qemu/config-file.h"
> diff --git a/exec.c b/exec.c
> index 78f849de99..6d60fdfb1f 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -29,7 +29,6 @@
>  #include "hw/qdev-core.h"
>  #include "hw/qdev-properties.h"
>  #if !defined(CONFIG_USER_ONLY)
> -#include "hw/boards.h"
>  #include "hw/xen/xen.h"
>  #endif
>  #include "sysemu/kvm.h"
> diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
> index 87f30a31d7..d8e531ad64 100644
> --- a/hw/acpi/cpu.c
> +++ b/hw/acpi/cpu.c
> @@ -1,5 +1,4 @@
>  #include "qemu/osdep.h"
> -#include "hw/boards.h"
>  #include "migration/vmstate.h"
>  #include "hw/acpi/cpu.h"
>  #include "qapi/error.h"
> diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
> index 39649cbe6a..c1aaa07d43 100644
> --- a/hw/acpi/ich9.c
> +++ b/hw/acpi/ich9.c
> @@ -31,6 +31,7 @@
>  #include "hw/pci/pci.h"
>  #include "migration/vmstate.h"
>  #include "qemu/timer.h"
> +#include "qom/cpu.h"
>  #include "sysemu/reset.h"
>  #include "sysemu/sysemu.h"
>  #include "hw/acpi/acpi.h"
> diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
> index 9483d66e86..b413f491ee 100644
> --- a/hw/acpi/memory_hotplug.c
> +++ b/hw/acpi/memory_hotplug.c

Re: [Qemu-devel] [PATCH-4.2 v1 5/6] target/riscv: Update the Hypervisor CSRs to v0.4

2019-07-26 Thread Alistair Francis
On Fri, Jul 26, 2019 at 10:41 AM Chih-Min Chao  wrote:
>
>
>
> On Fri, Jul 26, 2019 at 2:55 AM Alistair Francis  
> wrote:
>>
>> Update the Hypervisor CSR addresses to match the v0.4 spec.
>>
>> Signed-off-by: Alistair Francis 
>> ---
>>  target/riscv/cpu_bits.h | 35 ++-
>>  1 file changed, 18 insertions(+), 17 deletions(-)
>>
>> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
>> index 11f971ad5d..97b96c4e19 100644
>> --- a/target/riscv/cpu_bits.h
>> +++ b/target/riscv/cpu_bits.h
>> @@ -173,6 +173,24 @@
>>  #define CSR_SPTBR   0x180
>>  #define CSR_SATP0x180
>>
>> +/* Hpervisor CSRs */
>> +#define CSR_HSTATUS 0x600
>> +#define CSR_HEDELEG 0x602
>> +#define CSR_HIDELEG 0x603
>> +#define CSR_HCOUNTERNEN 0x606
>> +#define CSR_HGATP   0x680
>> +
>> +#if defined(TARGET_RISCV32)
>> +#define HGATP_MODE   SATP32_MODE
>> +#define HGATP_ASID   SATP32_ASID
>> +#define HGATP_PPNSATP32_PPN
>> +#endif
>> +#if defined(TARGET_RISCV64)
>> +#define HGATP_MODE   SATP64_MODE
>> +#define HGATP_ASID   SATP64_ASID
>> +#define HGATP_PPNSATP64_PPN
>> +#endif
>> +
>
>
> Basd on spec, is HGATP_VMID  preferable ?

Yep, updated.

Alistair

>
> chihmin
>>
>>  /* Physical Memory Protection */
>>  #define CSR_PMPCFG0 0x3a0
>>  #define CSR_PMPCFG1 0x3a1
>> @@ -206,23 +224,6 @@
>>  #define CSR_DPC 0x7b1
>>  #define CSR_DSCRATCH0x7b2
>>
>> -/* Hpervisor CSRs */
>> -#define CSR_HSTATUS 0xa00
>> -#define CSR_HEDELEG 0xa02
>> -#define CSR_HIDELEG 0xa03
>> -#define CSR_HGATP   0xa80
>> -
>> -#if defined(TARGET_RISCV32)
>> -#define HGATP_MODE   SATP32_MODE
>> -#define HGATP_ASID   SATP32_ASID
>> -#define HGATP_PPNSATP32_PPN
>> -#endif
>> -#if defined(TARGET_RISCV64)
>> -#define HGATP_MODE   SATP64_MODE
>> -#define HGATP_ASID   SATP64_ASID
>> -#define HGATP_PPNSATP64_PPN
>> -#endif
>> -
>>  /* Performance Counters */
>>  #define CSR_MHPMCOUNTER30xb03
>>  #define CSR_MHPMCOUNTER40xb04
>> --
>> 2.22.0
>>
>>



Re: [Qemu-devel] [PATCH 2/3] riscv: sivive_u: Add dummy serial clock and aliases entry for uart

2019-07-26 Thread Alistair Francis
On Fri, Jul 19, 2019 at 6:41 AM Guenter Roeck  wrote:
>
> The riscv uart needs valid clocks. This requires a refereence
> to the clock node. Since the SOC clock is not emulated by qemu,
> add a reference to a fixed clock instead. The clock-frequency
> entry in the uart node does not seem to be necessary, so drop it.
>
> In addition to a reference to the clock, the driver also needs
> an aliases entry for the serial node. Add it as well.
>
> Without this patch, the serial driver fails to instantiate with
> the following error message.
>
> sifive-serial 10013000.uart: unable to find controller clock
> sifive-serial: probe of 10013000.uart failed with error -2
>
> when trying to boot Linux.
>
> Signed-off-by: Guenter Roeck 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/riscv/sifive_u.c | 19 +--
>  1 file changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index 0657046..5a221c6 100644
> --- a/hw/riscv/sifive_u.c
> +++ b/hw/riscv/sifive_u.c
> @@ -76,6 +76,7 @@ static void *create_fdt(SiFiveUState *s, const struct 
> MemmapEntry *memmap,
>  char *nodename;
>  char ethclk_names[] = "pclk\0hclk\0tx_clk";
>  uint32_t plic_phandle, ethclk_phandle, phandle = 1;
> +uint32_t uartclk_phandle;
>
>  fdt = s->fdt = create_device_tree(>fdt_size);
>  if (!fdt) {
> @@ -226,6 +227,17 @@ static void *create_fdt(SiFiveUState *s, const struct 
> MemmapEntry *memmap,
>  qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0);
>  g_free(nodename);
>
> +uartclk_phandle = phandle++;
> +nodename = g_strdup_printf("/soc/uartclk");
> +qemu_fdt_add_subnode(fdt, nodename);
> +qemu_fdt_setprop_string(fdt, nodename, "compatible", "fixed-clock");
> +qemu_fdt_setprop_cell(fdt, nodename, "#clock-cells", 0x0);
> +qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", 3686400);
> +qemu_fdt_setprop_cell(fdt, nodename, "phandle", uartclk_phandle);
> +qemu_fdt_setprop_cell(fdt, nodename, "linux,phandle", uartclk_phandle);
> +uartclk_phandle = qemu_fdt_get_phandle(fdt, nodename);
> +g_free(nodename);
> +
>  nodename = g_strdup_printf("/soc/uart@%lx",
>  (long)memmap[SIFIVE_U_UART0].base);
>  qemu_fdt_add_subnode(fdt, nodename);
> @@ -233,8 +245,7 @@ static void *create_fdt(SiFiveUState *s, const struct 
> MemmapEntry *memmap,
>  qemu_fdt_setprop_cells(fdt, nodename, "reg",
>  0x0, memmap[SIFIVE_U_UART0].base,
>  0x0, memmap[SIFIVE_U_UART0].size);
> -qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
> -  SIFIVE_U_CLOCK_FREQ / 2);
> +qemu_fdt_setprop_cells(fdt, nodename, "clocks", uartclk_phandle);
>  qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle);
>  qemu_fdt_setprop_cells(fdt, nodename, "interrupts", SIFIVE_U_UART0_IRQ);
>
> @@ -243,6 +254,10 @@ static void *create_fdt(SiFiveUState *s, const struct 
> MemmapEntry *memmap,
>  if (cmdline) {
>  qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
>  }
> +
> +qemu_fdt_add_subnode(fdt, "/aliases");
> +qemu_fdt_setprop_string(fdt, "/aliases", "serial0", nodename);
> +
>  g_free(nodename);
>
>  return fdt;
> --
> 2.7.4
>
>



Re: [Qemu-devel] [PATCH v3] tests/boot_linux_console: add a test for riscv64 + virt

2019-07-26 Thread Alistair Francis
On Fri, Jul 26, 2019 at 10:12 AM Chih-Min Chao  wrote:
>
>
>
> On Thu, Jul 25, 2019 at 8:12 AM Alistair Francis  wrote:
>>
>> On Tue, Jul 23, 2019 at 11:46 PM Chih-Min Chao  
>> wrote:
>> >
>> > Similar to the mips + malta test, it boots a Linux kernel on a virt
>> > board and verify the serial is working.  Also, it relies on the serial
>> > device set by the machine itself.
>> >
>> > If riscv64 is a target being built, "make check-acceptance" will
>> > automatically include this test by the use of the "arch:riscv64" tags.
>> >
>> > Alternatively, this test can be run using:
>> >
>> >   $ avocado run -t arch:riscv64 tests/acceptance
>> >
>> > packages
>> >   debian official
>> > binutils-riscv64-linux-gnu_2.32-8
>> > opensbi_0.4-1_all
>> > linux-image-5.0.0-trunk-riscv64 5.0.2-1~exp1
>> >   third-party
>> > 
>> > https://github.com/groeck/linux-build-test/rootfs/riscv64/rootfs.cpio.gz
>> > (the repo is also used in mips target acceptance)
>> >
>> > Signed-off-by: Chih-Min Chao 
>> > ---
>> >  .travis.yml|  2 +-
>> >  tests/acceptance/boot_linux_console.py | 67 
>> > ++
>> >  2 files changed, 68 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/.travis.yml b/.travis.yml
>> > index caf0a1f..7ba9952 100644
>> > --- a/.travis.yml
>> > +++ b/.travis.yml
>> > @@ -232,7 +232,7 @@ matrix:
>> >
>> >  # Acceptance (Functional) tests
>> >  - env:
>> > -- CONFIG="--python=/usr/bin/python3 
>> > --target-list=x86_64-softmmu,mips-softmmu,mips64el-softmmu,aarch64-softmmu,arm-softmmu,s390x-softmmu,alpha-softmmu"
>> > +- CONFIG="--python=/usr/bin/python3 
>> > --target-list=x86_64-softmmu,mips-softmmu,mips64el-softmmu,aarch64-softmmu,arm-softmmu,s390x-softmmu,alpha-softmmu,riscv64-softmmu"
>> >  - TEST_CMD="make check-acceptance"
>> >after_failure:
>> >  - cat tests/results/latest/job.log
>> > diff --git a/tests/acceptance/boot_linux_console.py 
>> > b/tests/acceptance/boot_linux_console.py
>> > index 3215950..b0569b9 100644
>> > --- a/tests/acceptance/boot_linux_console.py
>> > +++ b/tests/acceptance/boot_linux_console.py
>> > @@ -354,3 +354,70 @@ class BootLinuxConsole(Test):
>> >  self.vm.launch()
>> >  console_pattern = 'Kernel command line: %s' % kernel_command_line
>> >  self.wait_for_console_pattern(console_pattern)
>> > +
>> > +def test_riscv64_virt(self):
>> > +"""
>> > +:avocado: tags=arch:riscv64
>> > +:avocado: tags=machine:virt
>> > +"""
>> > +deb_url = ('https://snapshot.debian.org/archive/debian/'
>> > + '20190424T171759Z/pool/main/b/binutils/'
>> > + 'binutils-riscv64-linux-gnu_2.32-8_amd64.deb')
>> > +deb_hash = ('7fe376fd4452696c03acd508d6d613ca553ea15e')
>> > +deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
>> > +objcopy_path = '/usr/bin/riscv64-linux-gnu-objcopy'
>> > +objcopy_path = self.extract_from_deb(deb_path, objcopy_path)
>> > +libbfd_path = '/usr/lib/x86_64-linux-gnu/libbfd-2.32-riscv64.so'
>> > +libbfd_path = self.extract_from_deb(deb_path, libbfd_path)
>> > +process.run('ls -al %s' % (objcopy_path))
>>
>> Why do we need objcopy? Won't this not work on non x86 architectures?
>>
>> > +
>> > +deb_url = ('https://snapshot.debian.org/archive/debian/'
>> > +   '20190708T032337Z/pool/main/o/opensbi/'
>> > +   'opensbi_0.4-1_all.deb')
>> > +deb_hash = ('2319dcd702958291d323acf5649fd98a11d90112')
>> > +deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
>> > +opensbi_path = ('/usr/lib/riscv64-linux-gnu/opensbi/'
>> > +'qemu/virt/fw_jump.elf')
>> > +opensbi_path = self.extract_from_deb(deb_path, opensbi_path)
>> > +
>> > +deb_url = ('https://snapshot.debian.org/archive/debian-ports/'
>> > +   '20190319T205124Z/pool-riscv64/main/l/linux/'
>> > +   
>> > 'linux-image-5.0.0-trunk-riscv64_5.0.2-1~exp1_riscv64.deb')
>> > +deb_hash = ('90155ed4b36673cbf7746a37cf3159c8f0b2857a')
>> > +deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
>> > +kernel_path = '/boot/vmlinux-5.0.0-trunk-riscv64'
>>
>> I thought we were swapping to using an Image file?
>>
>> Alistair
>>
>
>   For objcopy,
>  Philippe had the same question in PATCH v2 thread.  Debian 
> linux-kernel package only has vmlinux and riscv vmlinux  ELF header doesn't 
> contain the correct physical loading address 0x8020_.
>   What I think is to extract the Image from vmlinux by objcopy.  This 
> is what kernel do when generating  arch/riscv/boot/Image.

That is a real pain. I've never used Debian on RISC-V but that seems
strange that they don't build Image files. I think you should use a
Fedora kernel instead then.

>
>   For swapping to using an image file,
> 

Re: [Qemu-devel] [Qemu-riscv] [PATCH-4.2 v1 2/6] target/riscv: Remove strict perm checking for CSR R/W

2019-07-26 Thread Alistair Francis
On Thu, Jul 25, 2019 at 2:48 PM Jonathan Behrens  wrote:
>
> Unless I'm missing something, this is the only place that QEMU checks the 
> privilege level for read and writes to CSRs. The exact computation used here 
> won't work with the hypervisor extension, but we also can't just get rid of 
> privilege checking entirely...

The csr_ops struct contains a checker function, so there are still
some checks occurring. I haven't done negative testing on this patch,
but the current check doesn't seem to make any sense so it should be
removed. We can separately discuss adding more checks but this current
way base don CSR address just seems strange.

Alistair

>
> Jonathan
>
> On Thu, Jul 25, 2019 at 2:56 PM Alistair Francis  
> wrote:
>>
>> The privledge check based on the CSR address mask 0x300 doesn't work
>> when using Hypervisor extensions so remove the check
>>
>> Signed-off-by: Alistair Francis 
>> ---
>>  target/riscv/csr.c | 3 +--
>>  1 file changed, 1 insertion(+), 2 deletions(-)
>>
>> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
>> index e0d4586760..af3b762c8b 100644
>> --- a/target/riscv/csr.c
>> +++ b/target/riscv/csr.c
>> @@ -797,9 +797,8 @@ int riscv_csrrw(CPURISCVState *env, int csrno, 
>> target_ulong *ret_value,
>>
>>  /* check privileges and return -1 if check fails */
>>  #if !defined(CONFIG_USER_ONLY)
>> -int csr_priv = get_field(csrno, 0x300);
>>  int read_only = get_field(csrno, 0xC00) == 3;
>> -if ((write_mask && read_only) || (env->priv < csr_priv)) {
>> +if (write_mask && read_only) {
>>  return -1;
>>  }
>>  #endif
>> --
>> 2.22.0
>>
>>



Re: [Qemu-devel] [PATCH] Fix Guest VM crash due to iSCSI Sense Key error

2019-07-26 Thread John Snow
Paolo, Stefan and Kevin: can I loop you in here? I'm quite uncertain
about this and I'd like to clear this up quickly if it's possible:

On 7/25/19 8:58 PM, John Snow wrote:
> 
> 
> On 7/7/19 10:55 PM, shaju.abra...@nutanix.com wrote:
>> From: Shaju Abraham 
>>
>> During the  IDE DMA transfer for a ISCSI target,when libiscsi encounters
>> a SENSE KEY error, it sets the task->sense to  the value "COMMAND ABORTED".
>> The function iscsi_translate_sense() later translaters this error to 
>> -ECANCELED
>> and this value is passed to the callback function. In the case of  IDE DMA 
>> read
>> or write, the callback function returns immediately if the value of the ret
>> argument is -ECANCELED.
>> Later when ide_cancel_dma_sync() function is invoked  the assertion
>> "s->bus->dma->aiocb == ((void *)0)" fails and the qemu process gets 
>> terminated.
>> Fix the issue by making the value of s->bus->dma->aiocb = NULL when
>> -ECANCELED is passed to the callback.
>>
>> Signed-off-by: Shaju Abraham 
>> ---
>>  hw/ide/core.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/hw/ide/core.c b/hw/ide/core.c
>> index 6afadf8..78ea357 100644
>> --- a/hw/ide/core.c
>> +++ b/hw/ide/core.c
>> @@ -841,6 +841,7 @@ static void ide_dma_cb(void *opaque, int ret)
>>  bool stay_active = false;
>>  
>>  if (ret == -ECANCELED) {
>> +s->bus->dma->aiocb = NULL;
>>  return;
>>  }
>>  
>>
> 
> The part that makes me nervous here is that I can't remember why we do
> NO cleanup whatsoever for the ECANCELED case.
> 
> commit 0d910cfeaf2076b116b4517166d5deb0fea76394
> Author: Fam Zheng 
> Date:   Thu Sep 11 13:41:07 2014 +0800
> 
> ide/ahci: Check for -ECANCELED in aio callbacks
> 
> 
> ... This looks like we never expected the aio callbacks to ever get
> called with ECANCELED, so we treat this as a QEMU-internal signal.
> 
> It looks like we expect these callbacks to do NOTHING in this case; but
> I'm not sure where the IDE state machine does its cleanup otherwise.
> (The DMA might have been canceled, but the DMA and IDE state machines
> still need to exit their loop.)
> 
> If you take a look at this patch from 2014 though, there are many other
> spots where we have littered ECANCELED checks that might also cause
> problems if we're receiving error codes we thought we couldn't get normally.
> 
> I am worried this patch papers over something worse.
> 
I'm not clear why Fam's patch adds a do-nothing return to the ide_dma_cb
if it's invoked with ECANCELED: shouldn't it be the case that the IDE
state machine needs to know that a transfer it was relying on to service
an ATA command was canceled and treat it like an error?

Why was it ever correct to ignore these? Is it because we only ever
canceled DMA during reset/shutdown/etc?

It appears as if iscsi requests can actually genuinely return an
ECANCELED errno, so there are likely several places in the IDE code that
need to accommodate this from happening.

The easiest fix LOOKS like just deleting the special-casing of ECANCELED
altogether and letting the error pathways handle things as normal.

Am I mistaken?

--js



Re: [Qemu-devel] [RFC 06/19] fuzz: Add ramfile for fast vmstate/vmload

2019-07-26 Thread Paolo Bonzini
On 26/07/19 21:36, Oleinik, Alexander wrote:
>>
>> Please add the ram file to qemu-file.c instead of duplicating QEMUFile.
>>
> I think we should be able to replace all of this simply by using 
> memfd_create. Since it acts as a regular file, it will work with the 
> existing code (likely with performance gains).

That wouldn't be portable to non-Linux, so having RAMFile is better.

Paolo



Re: [Qemu-devel] [RFC 06/19] fuzz: Add ramfile for fast vmstate/vmload

2019-07-26 Thread Oleinik, Alexander
On 7/26/19 8:47 AM, Stefan Hajnoczi wrote:
> On Thu, Jul 25, 2019 at 03:23:49AM +, Oleinik, Alexander wrote:
>> The ramfile allows vmstate to be saved and restored directly onto the
>> heap.
>>
>> Signed-off-by: Alexander Oleinik 
>> ---
>>   tests/fuzz/ramfile.c | 127 +++
>>   tests/fuzz/ramfile.h |  20 +++
>>   2 files changed, 147 insertions(+)
>>   create mode 100644 tests/fuzz/ramfile.c
>>   create mode 100644 tests/fuzz/ramfile.h
>>
>> diff --git a/tests/fuzz/ramfile.c b/tests/fuzz/ramfile.c
>> new file mode 100644
>> index 00..8da242e9ee
>> --- /dev/null
>> +++ b/tests/fuzz/ramfile.c
> 
> Please put this in migration/.  This code doesn't do fuzzing and is
> general-purpose enough to be used by other parts of QEMU dealing with
> live migration.
> 
>> @@ -0,0 +1,127 @@
>> +/*
>> + * 
>> =
>> + *
>> + *   Filename:  ramfile.c
>> + *
>> + *Description:  QEMUFile stored in dynamically allocated RAM for fast 
>> VMRestore
>> + *
>> + * Author:  Alexander Oleinik (), alx...@bu.edu
>> + *   Organization:
>> + *
>> + * 
>> =
>> + */
> 
> Please use license headers with all new files that are created.
> Fine-grained filename and authorship information is already kept by git
> so it's not necessary to duplicate it here.
> 
>> +#include 
>> +#include "qemu/osdep.h"
> 
> osdep.h already includes stdlib.h.
> 
>> +#include "qemu-common.h"
>> +#include "exec/memory.h"
>> +#include "migration/qemu-file.h"
>> +#include "migration/migration.h"
>> +#include "migration/savevm.h"
>> +#include "ramfile.h"
>> +
>> +#define INCREMENT 10240
>> +#define IO_BUF_SIZE 32768
>> +#define MAX_IOV_SIZE MIN(IOV_MAX, 64)
>> +
>> +struct QEMUFile {
>> +const QEMUFileOps *ops;
>> +const QEMUFileHooks *hooks;
>> +void *opaque;
>> +
>> +int64_t bytes_xfer;
>> +int64_t xfer_limit;
>> +
>> +int64_t pos; /* start of buffer when writing, end of buffer
>> +when reading */
>> +int buf_index;
>> +int buf_size; /* 0 when writing */
>> +uint8_t buf[IO_BUF_SIZE];
>> +
>> +DECLARE_BITMAP(may_free, MAX_IOV_SIZE);
>> +struct iovec iov[MAX_IOV_SIZE];
>> +unsigned int iovcnt;
>> +
>> +int last_error;
>> +};
> 
> Wait, what?! :)
> 
> Please add the ram file to qemu-file.c instead of duplicating QEMUFile.
> 
I think we should be able to replace all of this simply by using 
memfd_create. Since it acts as a regular file, it will work with the 
existing code (likely with performance gains).



Re: [Qemu-devel] [PATCH 66/67] target/arm: Move singlestep check from gen_jmp to gen_goto_tb

2019-07-26 Thread Richard Henderson
On 7/26/19 11:13 AM, Peter Maydell wrote:
> On Fri, 26 Jul 2019 at 18:51, Richard Henderson
>  wrote:
>>
>> We miss quite a number of single-step events by having
>> the check in the wrong place.
>>
>> Signed-off-by: Richard Henderson 
>> ---
>>  target/arm/translate.c | 16 ++--
>>  1 file changed, 6 insertions(+), 10 deletions(-)
>>
>> diff --git a/target/arm/translate.c b/target/arm/translate.c
>> index c2b8b86fd2..9ae9b23823 100644
>> --- a/target/arm/translate.c
>> +++ b/target/arm/translate.c
>> @@ -2740,7 +2740,10 @@ static void gen_goto_ptr(void)
>>   */
>>  static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
>>  {
>> -if (use_goto_tb(s, dest)) {
>> +if (unlikely(is_singlestepping(s))) {
>> +gen_set_pc_im(s, dest);
>> +gen_singlestep_exception(s);
>> +} else if (use_goto_tb(s, dest)) {
>>  tcg_gen_goto_tb(n);
>>  gen_set_pc_im(s, dest);
>>  tcg_gen_exit_tb(s->base.tb, n);
>> @@ -2751,16 +2754,9 @@ static void gen_goto_tb(DisasContext *s, int n, 
>> target_ulong dest)
>>  s->base.is_jmp = DISAS_NORETURN;
>>  }
>>
>> -static inline void gen_jmp (DisasContext *s, uint32_t dest)
>> +static inline void gen_jmp(DisasContext *s, uint32_t dest)
>>  {
>> -if (unlikely(is_singlestepping(s))) {
>> -/* An indirect jump so that we still trigger the debug exception.  
>> */
>> -if (s->thumb)
>> -dest |= 1;
>> -gen_bx_im(s, dest);
>> -} else {
>> -gen_goto_tb(s, 0, dest);
>> -}
>> +gen_goto_tb(s, 0, dest);
>>  }
>>
>>  static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
> 
> I haven't tested but I'm not sure this change is right.
> The idea of the current code is that we handle generating
> the actual singlestep exception in arm_tr_tb_stop() at the
> end, rather than in the process of generating code for the
> insn. This change means we now do a gen_singlestep_exception()
> in the gen_jmp()/gen_goto_tb() part of the code, but we haven't
> removed the handling of it in arm_tr_tb_stop(), so we're now
> doing this in two places. Why doesn't the current design work?

Note that the existing gen_goto_tb does not test for single-step, and always
emits NORETURN code, either via tcg_gen_goto_tb() or
tcg_gen_lookup_and_goto_ptr().  The singlestep exception is neither generated
nor would it be reachable.

Another way to do handle this would be to test single-step but set DISAS_JUMP
instead of actually generate the singlestep exception in gen_goto_tb.  Do you
prefer that method?

> And if we need to do something different for the route to
> "change the PC via gen_jmp()" why don't we need to do it
> also when we change the PC via eg gen_bx_im() ?

See patch 67.

>  * four places for barrier insns where we use a
>gen_goto_tb to end the TB -- this isn't consistent
>with how we end the TB for other situations...)

Fixing this sounds like a good cleanup.


r~



Re: [Qemu-devel] [PATCH 00/67] target/arm: Convert aa32 base isa to decodetree

2019-07-26 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20190726175032.6769-1-richard.hender...@linaro.org/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Subject: [Qemu-devel] [PATCH 00/67] target/arm: Convert aa32 base isa to 
decodetree
Message-id: 20190726175032.6769-1-richard.hender...@linaro.org

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag] patchew/20190726175032.6769-1-richard.hender...@linaro.org 
-> patchew/20190726175032.6769-1-richard.hender...@linaro.org
Submodule 'capstone' (https://git.qemu.org/git/capstone.git) registered for 
path 'capstone'
Submodule 'dtc' (https://git.qemu.org/git/dtc.git) registered for path 'dtc'
Submodule 'roms/QemuMacDrivers' (https://git.qemu.org/git/QemuMacDrivers.git) 
registered for path 'roms/QemuMacDrivers'
Submodule 'roms/SLOF' (https://git.qemu.org/git/SLOF.git) registered for path 
'roms/SLOF'
Submodule 'roms/edk2' (https://git.qemu.org/git/edk2.git) registered for path 
'roms/edk2'
Submodule 'roms/ipxe' (https://git.qemu.org/git/ipxe.git) registered for path 
'roms/ipxe'
Submodule 'roms/openbios' (https://git.qemu.org/git/openbios.git) registered 
for path 'roms/openbios'
Submodule 'roms/openhackware' (https://git.qemu.org/git/openhackware.git) 
registered for path 'roms/openhackware'
Submodule 'roms/opensbi' (https://git.qemu.org/git/opensbi.git) registered for 
path 'roms/opensbi'
Submodule 'roms/qemu-palcode' (https://git.qemu.org/git/qemu-palcode.git) 
registered for path 'roms/qemu-palcode'
Submodule 'roms/seabios' (https://git.qemu.org/git/seabios.git/) registered for 
path 'roms/seabios'
Submodule 'roms/seabios-hppa' (https://git.qemu.org/git/seabios-hppa.git) 
registered for path 'roms/seabios-hppa'
Submodule 'roms/sgabios' (https://git.qemu.org/git/sgabios.git) registered for 
path 'roms/sgabios'
Submodule 'roms/skiboot' (https://git.qemu.org/git/skiboot.git) registered for 
path 'roms/skiboot'
Submodule 'roms/u-boot' (https://git.qemu.org/git/u-boot.git) registered for 
path 'roms/u-boot'
Submodule 'roms/u-boot-sam460ex' (https://git.qemu.org/git/u-boot-sam460ex.git) 
registered for path 'roms/u-boot-sam460ex'
Submodule 'slirp' (https://git.qemu.org/git/libslirp.git) registered for path 
'slirp'
Submodule 'tests/fp/berkeley-softfloat-3' 
(https://git.qemu.org/git/berkeley-softfloat-3.git) registered for path 
'tests/fp/berkeley-softfloat-3'
Submodule 'tests/fp/berkeley-testfloat-3' 
(https://git.qemu.org/git/berkeley-testfloat-3.git) registered for path 
'tests/fp/berkeley-testfloat-3'
Submodule 'ui/keycodemapdb' (https://git.qemu.org/git/keycodemapdb.git) 
registered for path 'ui/keycodemapdb'
Cloning into 'capstone'...
Submodule path 'capstone': checked out 
'22ead3e0bfdb87516656453336160e0a37b066bf'
Cloning into 'dtc'...
Submodule path 'dtc': checked out '88f18909db731a627456f26d779445f84e449536'
Cloning into 'roms/QemuMacDrivers'...
Submodule path 'roms/QemuMacDrivers': checked out 
'90c488d5f4a407342247b9ea869df1c2d9c8e266'
Cloning into 'roms/SLOF'...
Submodule path 'roms/SLOF': checked out 
'ba1ab360eebe6338bb8d7d83a9220ccf7e213af3'
Cloning into 'roms/edk2'...
Submodule path 'roms/edk2': checked out 
'20d2e5a125e34fc8501026613a71549b2a1a3e54'
Submodule 'SoftFloat' (https://github.com/ucb-bar/berkeley-softfloat-3.git) 
registered for path 'ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3'
Submodule 'CryptoPkg/Library/OpensslLib/openssl' 
(https://github.com/openssl/openssl) registered for path 
'CryptoPkg/Library/OpensslLib/openssl'
Cloning into 'ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3'...
Submodule path 'roms/edk2/ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3': 
checked out 'b64af41c3276f97f0e181920400ee056b9c88037'
Cloning into 'CryptoPkg/Library/OpensslLib/openssl'...
Submodule path 'roms/edk2/CryptoPkg/Library/OpensslLib/openssl': checked out 
'50eaac9f3337667259de725451f201e784599687'
Submodule 'boringssl' (https://boringssl.googlesource.com/boringssl) registered 
for path 'boringssl'
Submodule 'krb5' (https://github.com/krb5/krb5) registered for path 'krb5'
Submodule 'pyca.cryptography' (https://github.com/pyca/cryptography.git) 
registered for path 'pyca-cryptography'
Cloning into 'boringssl'...
Submodule path 'roms/edk2/CryptoPkg/Library/OpensslLib/openssl/boringssl': 
checked out '2070f8ad9151dc8f3a73bffaa146b5e6937a583f'
Cloning into 'krb5'...
Submodule path 'roms/edk2/CryptoPkg/Library/OpensslLib/openssl/krb5': checked 
out 'b9ad6c49505c96a088326b62a52568e3484f2168'
Cloning into 'pyca-cryptography'...
Submodule path 
'roms/edk2/CryptoPkg/Library/OpensslLib/openssl/pyca-cryptography': checked out 

[Qemu-devel] [PATCH 42/67] target/arm: Simplify disas_arm_insn

2019-07-26 Thread Richard Henderson
Fold away all of the cases that now just goto illegal_op,
because all of their internal bits are now in decodetree.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 69 ++
 1 file changed, 16 insertions(+), 53 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 836b3752f7..65a74a963b 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10257,7 +10257,7 @@ static bool trans_PLI(DisasContext *s, arg_PLD *a)
 
 static void disas_arm_insn(DisasContext *s, unsigned int insn)
 {
-unsigned int cond, op1;
+unsigned int cond = insn >> 28;
 
 /* M variants do not implement ARM mode; this must raise the INVSTATE
  * UsageFault exception.
@@ -10267,7 +10267,6 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
default_exception_el(s));
 return;
 }
-cond = insn >> 28;
 
 if (cond == 0xf) {
 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
@@ -10332,11 +10331,6 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 goto illegal_op;
 }
 return;
-} else if ((insn & 0x0fe0) == 0x0c40) {
-/* Coprocessor double register transfer.  */
-ARCH(5TE);
-} else if ((insn & 0x0f10) == 0x0e10) {
-/* Additional coprocessor register transfer.  */
 }
 goto illegal_op;
 }
@@ -10348,55 +10342,24 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 }
 /* fall back to legacy decoder */
 
-if ((insn & 0x0f90) == 0x0300) {
-/* All done in decodetree.  Illegal ops reach here.  */
-goto illegal_op;
-} else if ((insn & 0x0f90) == 0x0100
-   && (insn & 0x0090) != 0x0090) {
-/* miscellaneous instructions */
-/* All done in decodetree.  Illegal ops reach here.  */
-goto illegal_op;
-} else if (((insn & 0x0e00) == 0 &&
-(insn & 0x0090) != 0x90) ||
-   ((insn & 0x0e00) == (1 << 25))) {
-/* Data-processing (reg, reg-shift-reg, imm).  */
-/* All done in decodetree.  Reach here for illegal ops.  */
-goto illegal_op;
-} else {
-/* other instructions */
-op1 = (insn >> 24) & 0xf;
-switch(op1) {
-case 0x0:
-case 0x1:
-case 0x4:
-case 0x5:
-case 0x6:
-case 0x7:
-case 0x08:
-case 0x09:
-case 0xa:
-case 0xb:
-case 0xf:
-/* All done in decodetree.  Reach here for illegal ops.  */
-goto illegal_op;
-case 0xc:
-case 0xd:
-case 0xe:
-if (((insn >> 8) & 0xe) == 10) {
-/* VFP.  */
-if (disas_vfp_insn(s, insn)) {
-goto illegal_op;
-}
-} else if (disas_coproc_insn(s, insn)) {
-/* Coprocessor.  */
+switch ((insn >> 24) & 0xf) {
+case 0xc:
+case 0xd:
+case 0xe:
+if (((insn >> 8) & 0xe) == 10) {
+/* VFP.  */
+if (disas_vfp_insn(s, insn)) {
 goto illegal_op;
 }
-break;
-default:
-illegal_op:
-gen_illegal_op(s);
-break;
+} else if (disas_coproc_insn(s, insn)) {
+/* Coprocessor.  */
+goto illegal_op;
 }
+break;
+default:
+illegal_op:
+gen_illegal_op(s);
+break;
 }
 }
 
-- 
2.17.1




Re: [Qemu-devel] [PATCH v4 7/7] monitor: adding info tbs, tb, and coverset

2019-07-26 Thread Alex Bennée


vandersonmr  writes:

> Adding info [tbs|tb|coverset] commands to HMP.
> These commands allow the exploration of TBs
> generated by the TCG. Understand which one
> hotter, with more guest/host instructions...
> and examine their guest, host and IR code.
>
> The goal of this command is to allow the dynamic exploration
> of TCG behavior and code quality. Therefore, for now, a
> corresponding QMP command is not worthwhile.
>
> Signed-off-by: vandersonmr 
> ---
>  accel/tcg/tb-stats.c | 275 +++
>  hmp-commands-info.hx |  23 +++
>  include/exec/tb-stats.h  |  37 +
>  include/qemu/log-for-trace.h |   2 +
>  include/qemu/log.h   |   1 +
>  linux-user/exit.c|   4 +
>  monitor/misc.c   |  71 +
>  util/log.c   |  26 +++-
>  8 files changed, 431 insertions(+), 8 deletions(-)
>
> diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c
> index 6c330e1b02..85a16cd563 100644
> --- a/accel/tcg/tb-stats.c
> +++ b/accel/tcg/tb-stats.c
> @@ -212,3 +212,278 @@ void do_hmp_tbstats_safe(CPUState *cpu, run_on_cpu_data 
> icmd)
>  g_free(cmdinfo);
>  }
>  
> +static void collect_tb_stats(void *p, uint32_t hash, void *userp)
> +{
> +last_search = g_list_prepend(last_search, p);
> +}
> +
> +static void dump_tb_header(TBStatistics *tbs)
> +{
> +unsigned g = tbs->translations.total ?
> +tbs->code.num_guest_inst / tbs->translations.total : 0;
> +unsigned ops = tbs->translations.total ?
> +tbs->code.num_tcg_ops / tbs->translations.total : 0;
> +unsigned ops_opt = tbs->translations.total ?
> +tbs->code.num_tcg_ops_opt / tbs->translations.total : 0;
> +unsigned h = tbs->translations.total ?
> +tbs->code.num_host_inst / tbs->translations.total : 0;
> +unsigned spills = tbs->translations.total ?
> +tbs->code.spills / tbs->translations.total : 0;

A helper like:

  #define stat_per_translation(stat, name) \
  stat->translations.total ? stat->name / stat->translations.total : 0

could be helpful here (and useful for later re-use).

> +
> +float guest_host_prop = g ? ((float) h / g) : 0;
> +
> +qemu_log("TB%d: phys:0x"TB_PAGE_ADDR_FMT" virt:0x"TARGET_FMT_lx
> + " flags:%#08x (trans:%lu uncached:%lu exec:%lu ints: g:%u op:%u 
> op_opt:%u h:%u h/g:%.2f spills:%d)\n",
> + tbs->display_id,
> + tbs->phys_pc, tbs->pc, tbs->flags,
> + tbs->translations.total, tbs->translations.uncached,
> + tbs->executions.total, g, ops, ops_opt, h, guest_host_prop,
> + spills);
> +}
> +
> +static gint
> +inverse_sort_tbs(gconstpointer p1, gconstpointer p2, gpointer psort_by)
> +{
> +const TBStatistics *tbs1 = (TBStatistics *) p1;
> +const TBStatistics *tbs2 = (TBStatistics *) p2;
> +int sort_by = *((int *) psort_by);
> +unsigned long c1 = 0;
> +unsigned long c2 = 0;

Like here. As we aggregate our spill and instruction stats by the number
of translations on display we will want the same for the sort. Otherwise
heavily translated blocks will distort the figures.

> +
> +if (likely(sort_by == SORT_BY_SPILLS)) {
> +c1 = tbs1->code.spills;
> +c2 = tbs2->code.spills;
> +} else if (likely(sort_by == SORT_BY_HOTNESS)) {
> +c1 = tbs1->executions.total;
> +c2 = tbs2->executions.total;
> +} else if (likely(sort_by == SORT_BY_HG)) {
> +if (tbs1->code.num_guest_inst == 0) {
> +return -1;
> +}
> +if (tbs2->code.num_guest_inst == 0) {
> +return 1;
> +}
> +
> +float a = (float) tbs1->code.num_host_inst / 
> tbs1->code.num_guest_inst;
> +float b = (float) tbs2->code.num_host_inst / 
> tbs2->code.num_guest_inst;
> +c1 = a <= b ? 0 : 1;
> +c2 = a <= b ? 1 : 0;
> +}
> +
> +return c1 < c2 ? 1 : c1 == c2 ? 0 : -1;
> +}
> +
> +static void do_dump_coverset_info(int percentage)
> +{
> +uint64_t total_exec_count = 0;
> +uint64_t covered_exec_count = 0;
> +unsigned coverset_size = 0;
> +int id = 1;
> +GList *i;
> +
> +g_list_free(last_search);
> +last_search = NULL;
> +
> +qht_iter(_ctx.tb_stats, collect_tb_stats, NULL);
> +
> +int sort_by = SORT_BY_HOTNESS;
> +last_search = g_list_sort_with_data(last_search, inverse_sort_tbs, 
> _by);
> +
> +if (!last_search) {
> +qemu_log("No data collected yet\n");
> +return;
> +}
> +
> +/* Compute total execution count for all tbs */
> +for (i = last_search; i; i = i->next) {
> +TBStatistics *tbs = (TBStatistics *) i->data;
> +total_exec_count += tbs->executions.total * tbs->code.num_guest_inst;
> +}
> +
> +for (i = last_search; i; i = i->next) {
> +TBStatistics *tbs = (TBStatistics *) i->data;
> +covered_exec_count += tbs->executions.total * 
> tbs->code.num_guest_inst;
> +tbs->display_id = id++;
> +

Re: [Qemu-devel] [PATCH 66/67] target/arm: Move singlestep check from gen_jmp to gen_goto_tb

2019-07-26 Thread Peter Maydell
On Fri, 26 Jul 2019 at 18:51, Richard Henderson
 wrote:
>
> We miss quite a number of single-step events by having
> the check in the wrong place.
>
> Signed-off-by: Richard Henderson 
> ---
>  target/arm/translate.c | 16 ++--
>  1 file changed, 6 insertions(+), 10 deletions(-)
>
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index c2b8b86fd2..9ae9b23823 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -2740,7 +2740,10 @@ static void gen_goto_ptr(void)
>   */
>  static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
>  {
> -if (use_goto_tb(s, dest)) {
> +if (unlikely(is_singlestepping(s))) {
> +gen_set_pc_im(s, dest);
> +gen_singlestep_exception(s);
> +} else if (use_goto_tb(s, dest)) {
>  tcg_gen_goto_tb(n);
>  gen_set_pc_im(s, dest);
>  tcg_gen_exit_tb(s->base.tb, n);
> @@ -2751,16 +2754,9 @@ static void gen_goto_tb(DisasContext *s, int n, 
> target_ulong dest)
>  s->base.is_jmp = DISAS_NORETURN;
>  }
>
> -static inline void gen_jmp (DisasContext *s, uint32_t dest)
> +static inline void gen_jmp(DisasContext *s, uint32_t dest)
>  {
> -if (unlikely(is_singlestepping(s))) {
> -/* An indirect jump so that we still trigger the debug exception.  */
> -if (s->thumb)
> -dest |= 1;
> -gen_bx_im(s, dest);
> -} else {
> -gen_goto_tb(s, 0, dest);
> -}
> +gen_goto_tb(s, 0, dest);
>  }
>
>  static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)

I haven't tested but I'm not sure this change is right.
The idea of the current code is that we handle generating
the actual singlestep exception in arm_tr_tb_stop() at the
end, rather than in the process of generating code for the
insn. This change means we now do a gen_singlestep_exception()
in the gen_jmp()/gen_goto_tb() part of the code, but we haven't
removed the handling of it in arm_tr_tb_stop(), so we're now
doing this in two places. Why doesn't the current design work?
And if we need to do something different for the route to
"change the PC via gen_jmp()" why don't we need to do it
also when we change the PC via eg gen_bx_im() ?

(Incidentally, the only places other than gen_jmp()
which call gen_goto_tb() are:
 * the end-of-TB handling of DISAS_NEXT/DISAS_TOO_MANY
 * four places for barrier insns where we use a
   gen_goto_tb to end the TB -- this isn't consistent
   with how we end the TB for other situations...)

thanks
-- PMM



[Qemu-devel] [PATCH 44/67] target/arm: Convert T16 data-processing (two low regs)

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 152 ++---
 target/arm/t16.decode  |  36 ++
 2 files changed, 43 insertions(+), 145 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index db93b12608..17a0eea425 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -486,13 +486,6 @@ static inline void gen_logic_CC(TCGv_i32 var)
 tcg_gen_mov_i32(cpu_ZF, var);
 }
 
-/* T0 += T1 + CF.  */
-static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
-{
-tcg_gen_add_i32(t0, t0, t1);
-tcg_gen_add_i32(t0, t0, cpu_CF);
-}
-
 /* dest = T0 + T1 + CF. */
 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
 {
@@ -7590,6 +7583,11 @@ static int t32_branch24(DisasContext *s, int x)
 return x << 1;
 }
 
+static int t16_setflags(DisasContext *s, int x)
+{
+return s->condexec_mask == 0;
+}
+
 /*
  * Include the generated decoders.
  * Note that the T32 decoder reuses some of the trans_* functions
@@ -10751,145 +10749,9 @@ static void disas_thumb_insn(DisasContext *s, 
uint32_t insn)
 
 /*
  * 0b0100_00xx__
- *  - Data-processing (two low registers)
+ *  - Data-processing (two low registers), in decodetree
  */
-rd = insn & 7;
-rm = (insn >> 3) & 7;
-op = (insn >> 6) & 0xf;
-if (op == 2 || op == 3 || op == 4 || op == 7) {
-/* the shift/rotate ops want the operands backwards */
-val = rm;
-rm = rd;
-rd = val;
-val = 1;
-} else {
-val = 0;
-}
-
-if (op == 9) { /* neg */
-tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, 0);
-} else if (op != 0xf) { /* mvn doesn't read its first operand */
-tmp = load_reg(s, rd);
-} else {
-tmp = NULL;
-}
-
-tmp2 = load_reg(s, rm);
-switch (op) {
-case 0x0: /* and */
-tcg_gen_and_i32(tmp, tmp, tmp2);
-if (!s->condexec_mask)
-gen_logic_CC(tmp);
-break;
-case 0x1: /* eor */
-tcg_gen_xor_i32(tmp, tmp, tmp2);
-if (!s->condexec_mask)
-gen_logic_CC(tmp);
-break;
-case 0x2: /* lsl */
-if (s->condexec_mask) {
-gen_shl(tmp2, tmp2, tmp);
-} else {
-gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
-gen_logic_CC(tmp2);
-}
-break;
-case 0x3: /* lsr */
-if (s->condexec_mask) {
-gen_shr(tmp2, tmp2, tmp);
-} else {
-gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
-gen_logic_CC(tmp2);
-}
-break;
-case 0x4: /* asr */
-if (s->condexec_mask) {
-gen_sar(tmp2, tmp2, tmp);
-} else {
-gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
-gen_logic_CC(tmp2);
-}
-break;
-case 0x5: /* adc */
-if (s->condexec_mask) {
-gen_adc(tmp, tmp2);
-} else {
-gen_adc_CC(tmp, tmp, tmp2);
-}
-break;
-case 0x6: /* sbc */
-if (s->condexec_mask) {
-gen_sub_carry(tmp, tmp, tmp2);
-} else {
-gen_sbc_CC(tmp, tmp, tmp2);
-}
-break;
-case 0x7: /* ror */
-if (s->condexec_mask) {
-tcg_gen_andi_i32(tmp, tmp, 0x1f);
-tcg_gen_rotr_i32(tmp2, tmp2, tmp);
-} else {
-gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
-gen_logic_CC(tmp2);
-}
-break;
-case 0x8: /* tst */
-tcg_gen_and_i32(tmp, tmp, tmp2);
-gen_logic_CC(tmp);
-rd = 16;
-break;
-case 0x9: /* neg */
-if (s->condexec_mask)
-tcg_gen_neg_i32(tmp, tmp2);
-else
-gen_sub_CC(tmp, tmp, tmp2);
-break;
-case 0xa: /* cmp */
-gen_sub_CC(tmp, tmp, tmp2);
-rd = 16;
-break;
-case 0xb: /* cmn */
-gen_add_CC(tmp, tmp, tmp2);
-rd = 16;
-break;
-case 0xc: /* orr */
-tcg_gen_or_i32(tmp, tmp, tmp2);
-if (!s->condexec_mask)
-gen_logic_CC(tmp);
-break;
-case 0xd: /* mul */
-tcg_gen_mul_i32(tmp, tmp, tmp2);
-if (!s->condexec_mask)
-gen_logic_CC(tmp);
-break;
-case 0xe: /* bic */
-tcg_gen_andc_i32(tmp, tmp, tmp2);
-if (!s->condexec_mask)
-gen_logic_CC(tmp);
-break;
-case 0xf: /* mvn */
-tcg_gen_not_i32(tmp2, tmp2);
-if 

[Qemu-devel] [PATCH 57/67] target/arm: Convert T16, nop hints

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c |  3 +--
 target/arm/t16.decode  | 17 +
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index c9386ceefb..55404414a2 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10779,8 +10779,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 
 case 15: /* IT, nop-hint.  */
 if ((insn & 0xf) == 0) {
-gen_nop_hint(s, (insn >> 4) & 0xf);
-break;
+goto illegal_op; /* nop hint, in decodetree */
 }
 /*
  * IT (If-Then)
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 8864f89a81..90a4b71a45 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -19,6 +19,7 @@
 # This file is processed by scripts/decodetree.py
 #
 
+   !extern
 _rrr_shi   !extern s rd rn rm shim shty
 _rrr_shr   !extern s rn rd rm rs shty
 _rri_rot   !extern s rn rd imm rot
@@ -204,3 +205,19 @@ SETEND  1011 0110 010 1 E:1 000 
 REV 1011 1010 00 ... ...@rdm
 REV16   1011 1010 01 ... ...@rdm
 REVSH   1011 1010 11 ... ...@rdm
+
+# Hints
+
+{
+  YIELD 1011  0001 
+  WFE   1011  0010 
+  WFI   1011  0011 
+
+  # TODO: Implement SEV, SEVL; may help SMP performance.
+  # SEV 1011  0100 
+  # SEVL1011  0101 
+
+  # The canonical nop has the second nibble as , but the whole of the
+  # rest of the space is a reserved hint, behaves as nop.
+  NOP   1011   
+}
-- 
2.17.1




[Qemu-devel] [PATCH 54/67] target/arm: Convert T16, extract

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 14 +-
 target/arm/t16.decode  | 10 ++
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 8dd88419fe..9c8e11bd3a 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10649,21 +10649,9 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 op = (insn >> 8) & 0xf;
 switch (op) {
 case 0: /* add/sub (sp, immediate), in decodetree */
+case 2: /* sign/zero extend, in decodetree */
 goto illegal_op;
 
-case 2: /* sign/zero extend.  */
-ARCH(6);
-rd = insn & 7;
-rm = (insn >> 3) & 7;
-tmp = load_reg(s, rm);
-switch ((insn >> 6) & 3) {
-case 0: gen_sxth(tmp); break;
-case 1: gen_sxtb(tmp); break;
-case 2: gen_uxth(tmp); break;
-case 3: gen_uxtb(tmp); break;
-}
-store_reg(s, rd, tmp);
-break;
 case 4: case 5: case 0xc: case 0xd:
 /*
  * 0b1011_x10x__
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index ddf12ada11..1b47e804bf 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -23,6 +23,7 @@
 _rrr_shr   !extern s rn rd rm rs shty
 _rri_rot   !extern s rn rd imm rot
 _  !extern s rd rn rm ra
+_rot !extern rd rn rm rot
   !extern rd imm
!extern rm
 _rr !extern p w u rn rt rm shimm shtype
@@ -173,3 +174,12 @@ BX  0100 0111 0  000@branchr
 BLX_r   0100 0111 1  000@branchr
 BXNS0100 0111 0  100@branchr
 BLXNS   0100 0111 1  100@branchr
+
+# Extend
+
+@extend   .. rm:3 rd:3  _rot rn=15 rot=0
+
+SXTAH   1011 0010 00 ... ...@extend
+SXTAB   1011 0010 01 ... ...@extend
+UXTAH   1011 0010 10 ... ...@extend
+UXTAB   1011 0010 11 ... ...@extend
-- 
2.17.1




[Qemu-devel] [PATCH 66/67] target/arm: Move singlestep check from gen_jmp to gen_goto_tb

2019-07-26 Thread Richard Henderson
We miss quite a number of single-step events by having
the check in the wrong place.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 16 ++--
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index c2b8b86fd2..9ae9b23823 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -2740,7 +2740,10 @@ static void gen_goto_ptr(void)
  */
 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
 {
-if (use_goto_tb(s, dest)) {
+if (unlikely(is_singlestepping(s))) {
+gen_set_pc_im(s, dest);
+gen_singlestep_exception(s);
+} else if (use_goto_tb(s, dest)) {
 tcg_gen_goto_tb(n);
 gen_set_pc_im(s, dest);
 tcg_gen_exit_tb(s->base.tb, n);
@@ -2751,16 +2754,9 @@ static void gen_goto_tb(DisasContext *s, int n, 
target_ulong dest)
 s->base.is_jmp = DISAS_NORETURN;
 }
 
-static inline void gen_jmp (DisasContext *s, uint32_t dest)
+static inline void gen_jmp(DisasContext *s, uint32_t dest)
 {
-if (unlikely(is_singlestepping(s))) {
-/* An indirect jump so that we still trigger the debug exception.  */
-if (s->thumb)
-dest |= 1;
-gen_bx_im(s, dest);
-} else {
-gen_goto_tb(s, 0, dest);
-}
+gen_goto_tb(s, 0, dest);
 }
 
 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
-- 
2.17.1




[Qemu-devel] [PATCH 64/67] target/arm: Convert T16, long branches

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 89 +++---
 target/arm/t16.decode  |  3 ++
 2 files changed, 43 insertions(+), 49 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 480515a0a9..a8db6e9280 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10055,6 +10055,44 @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
 return true;
 }
 
+static bool trans_BL_BLX_prefix(DisasContext *s, arg_BL_BLX_prefix *a)
+{
+/*
+ * thumb_insn_is_16bit() ensures we can't get here for
+ * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
+ */
+assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
+tcg_gen_movi_i32(cpu_R[14], s->pc_read + (a->imm << 12));
+return true;
+}
+
+static bool trans_BL_suffix(DisasContext *s, arg_BL_suffix *a)
+{
+TCGv_i32 tmp = tcg_temp_new_i32();
+
+assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
+tcg_gen_addi_i32(tmp, cpu_R[14], (a->imm << 1) | 1);
+tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
+gen_bx(s, tmp);
+return true;
+}
+
+static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
+{
+TCGv_i32 tmp;
+
+assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
+if (!ENABLE_ARCH_5) {
+return false;
+}
+tmp = tcg_temp_new_i32();
+tcg_gen_addi_i32(tmp, cpu_R[14], a->imm << 1);
+tcg_gen_andi_i32(tmp, tmp, -4);
+tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
+gen_bx(s, tmp);
+return true;
+}
+
 static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
 {
 TCGv_i32 addr, tmp;
@@ -10639,10 +10677,6 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 
 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
 {
-int32_t offset;
-TCGv_i32 tmp;
-TCGv_i32 tmp2;
-
 if (disas_t16(s, insn)) {
 return;
 }
@@ -10661,53 +10695,10 @@ static void disas_thumb_insn(DisasContext *s, 
uint32_t insn)
 case 11: /* misc, in decodetree */
 case 12: /* load/store multiple, in decodetree */
 case 13: /* conditional branch or swi, in decodetree */
-goto illegal_op;
-
 case 14:
-if (insn & (1 << 11)) {
-/* thumb_insn_is_16bit() ensures we can't get here for
- * a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
- * 0b1110_1xxx__ : BLX suffix (or UNDEF)
- */
-assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
-ARCH(5);
-offset = ((insn & 0x7ff) << 1);
-tmp = load_reg(s, 14);
-tcg_gen_addi_i32(tmp, tmp, offset);
-tcg_gen_andi_i32(tmp, tmp, 0xfffc);
-
-tmp2 = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp2, s->pc | 1);
-store_reg(s, 14, tmp2);
-gen_bx(s, tmp);
-break;
-}
-/* unconditional branch, in decodetree */
-goto illegal_op;
-
 case 15:
-/* thumb_insn_is_16bit() ensures we can't get here for
- * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
- */
-assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
-
-if (insn & (1 << 11)) {
-/* 0b_1xxx__ : BL suffix */
-offset = ((insn & 0x7ff) << 1) | 1;
-tmp = load_reg(s, 14);
-tcg_gen_addi_i32(tmp, tmp, offset);
-
-tmp2 = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp2, s->pc | 1);
-store_reg(s, 14, tmp2);
-gen_bx(s, tmp);
-} else {
-/* 0b_0xxx__ : BL/BLX prefix */
-uint32_t uoffset = ((int32_t)insn << 21) >> 9;
-
-tcg_gen_movi_i32(cpu_R[14], s->pc_read + uoffset);
-}
-break;
+/* branches, in decodetree */
+goto illegal_op;
 }
 return;
 illegal_op:
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 457f2f4178..105218882a 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -274,3 +274,6 @@ LDM 1011 110 . \
 %imm11_0x2  0:s11 !function=times_2
 
 B   11100 ...imm=%imm11_0x2
+BLX_suffix  11101 imm:11
+BL_BLX_prefix   0 imm:s11   
+BL_suffix   1 imm:11
-- 
2.17.1




[Qemu-devel] [PATCH 61/67] target/arm: Convert T16, shift immediate

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 26 ++
 target/arm/t16.decode  |  8 
 2 files changed, 10 insertions(+), 24 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index f3a946d8c9..f9022fe65c 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10657,7 +10657,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 
 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
 {
-uint32_t val, op, rm, rd, shift;
+uint32_t val, rd;
 int32_t offset;
 TCGv_i32 tmp;
 TCGv_i32 tmp2;
@@ -10669,29 +10669,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 /* fall back to legacy decoder */
 
 switch (insn >> 12) {
-case 0: case 1:
-
-rd = insn & 7;
-op = (insn >> 11) & 3;
-if (op == 3) {
-/*
- * 0b0001_1xxx__
- *  - Add, subtract (three low registers)
- *  - Add, subtract (two low registers and immediate)
- * In decodetree.
- */
-goto illegal_op;
-} else {
-/* shift immediate */
-rm = (insn >> 3) & 7;
-shift = (insn >> 6) & 0x1f;
-tmp = load_reg(s, rm);
-gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
-if (!s->condexec_mask)
-gen_logic_CC(tmp);
-store_reg(s, rd, tmp);
-}
-break;
+case 0: case 1: /* add/sub (3reg, 2reg imm), shift imm; in decodetree */
 case 2: case 3: /* add, sub, cmp, mov (reg, imm), in decodetree */
 goto illegal_op;
 case 4:
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 17297a3032..ddffd073a2 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -126,6 +126,14 @@ ADD_rri 10101 rd:3  \
 STM 11000 ...   @ldstm
 LDM_t16 11001 ...   @ldstm
 
+# Shift (immediate)
+
+@shift_i. shim:5 rm:3 rd:3  _rrr_shi %s rn=%reg_0
+
+MOV_rrri000 00 . ... ...@shift_i shty=0  # LSL
+MOV_rrri000 01 . ... ...@shift_i shty=1  # LSR
+MOV_rrri000 10 . ... ...@shift_i shty=2  # ASR
+
 # Add/subtract (three low registers)
 
 @addsub_3   ... rm:3 rn:3 rd:3 \
-- 
2.17.1




[Qemu-devel] [PATCH 11/67] target/arm: Add stubs for aa32 decodetree

2019-07-26 Thread Richard Henderson
Add the infrastructure that will become the new decoder.
No instructions adjusted so far.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c   | 45 +++-
 target/arm/Makefile.objs | 18 +++
 target/arm/a32-uncond.decode | 23 ++
 target/arm/a32.decode| 23 ++
 target/arm/t32.decode| 20 
 5 files changed, 128 insertions(+), 1 deletion(-)
 create mode 100644 target/arm/a32-uncond.decode
 create mode 100644 target/arm/a32.decode
 create mode 100644 target/arm/t32.decode

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 36419025db..4738b91957 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7715,6 +7715,33 @@ static void arm_skip_unless(DisasContext *s, uint32_t 
cond)
 }
 }
 
+/*
+ * Include the generated decoders.
+ * Note that the T32 decoder reuses some of the trans_* functions
+ * initially declared by the A32 decoder, which results in duplicate
+ * declaration warnings.  Suppress them.
+ */
+
+#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wredundant-decls"
+# ifdef __clang__
+#  pragma GCC diagnostic ignored "-Wtypedef-redefinition"
+# endif
+#endif
+
+#include "decode-a32.inc.c"
+#include "decode-a32-uncond.inc.c"
+#include "decode-t32.inc.c"
+
+#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
+# pragma GCC diagnostic pop
+#endif
+
+/*
+ * Legacy decoder.
+ */
+
 static void disas_arm_insn(DisasContext *s, unsigned int insn)
 {
 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
@@ -7733,7 +7760,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 return;
 }
 cond = insn >> 28;
-if (cond == 0xf){
+
+if (cond == 0xf) {
 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
  * choose to UNDEF. In ARMv5 and above the space is used
  * for miscellaneous unconditional instructions.
@@ -7741,6 +7769,11 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 ARCH(5);
 
 /* Unconditional instructions.  */
+if (disas_a32_uncond(s, insn)) {
+return;
+}
+/* fall back to legacy decoder */
+
 if (((insn >> 25) & 7) == 1) {
 /* NEON Data processing.  */
 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
@@ -7953,6 +7986,11 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 
 arm_skip_unless(s, cond);
 
+if (disas_a32(s, insn)) {
+return;
+}
+/* fall back to legacy decoder */
+
 if ((insn & 0x0f90) == 0x0300) {
 if ((insn & (1 << 21)) == 0) {
 ARCH(6T2);
@@ -9440,6 +9478,11 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 ARCH(6T2);
 }
 
+if (disas_t32(s, insn)) {
+return;
+}
+/* fall back to legacy decoder */
+
 rn = (insn >> 16) & 0xf;
 rs = (insn >> 12) & 0xf;
 rd = (insn >> 8) & 0xf;
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
index 5cafc1eb6c..7806b4dac0 100644
--- a/target/arm/Makefile.objs
+++ b/target/arm/Makefile.objs
@@ -28,9 +28,27 @@ target/arm/decode-vfp-uncond.inc.c: 
$(SRC_PATH)/target/arm/vfp-uncond.decode $(D
  $(PYTHON) $(DECODETREE) --static-decode disas_vfp_uncond -o $@ $<,\
  "GEN", $(TARGET_DIR)$@)
 
+target/arm/decode-a32.inc.c: $(SRC_PATH)/target/arm/a32.decode $(DECODETREE)
+   $(call quiet-command,\
+ $(PYTHON) $(DECODETREE) --static-decode disas_a32 -o $@ $<,\
+ "GEN", $(TARGET_DIR)$@)
+
+target/arm/decode-a32-uncond.inc.c: $(SRC_PATH)/target/arm/a32-uncond.decode 
$(DECODETREE)
+   $(call quiet-command,\
+ $(PYTHON) $(DECODETREE) --static-decode disas_a32_uncond -o $@ $<,\
+ "GEN", $(TARGET_DIR)$@)
+
+target/arm/decode-t32.inc.c: $(SRC_PATH)/target/arm/t32.decode $(DECODETREE)
+   $(call quiet-command,\
+ $(PYTHON) $(DECODETREE) --static-decode disas_t32 -o $@ $<,\
+ "GEN", $(TARGET_DIR)$@)
+
 target/arm/translate-sve.o: target/arm/decode-sve.inc.c
 target/arm/translate.o: target/arm/decode-vfp.inc.c
 target/arm/translate.o: target/arm/decode-vfp-uncond.inc.c
+target/arm/translate.o: target/arm/decode-a32.inc.c
+target/arm/translate.o: target/arm/decode-a32-uncond.inc.c
+target/arm/translate.o: target/arm/decode-t32.inc.c
 
 obj-y += tlb_helper.o debug_helper.o
 obj-y += translate.o op_helper.o
diff --git a/target/arm/a32-uncond.decode b/target/arm/a32-uncond.decode
new file mode 100644
index 00..8dee26d3b6
--- /dev/null
+++ b/target/arm/a32-uncond.decode
@@ -0,0 +1,23 @@
+# A32 unconditional instructions
+#
+#  Copyright (c) 2019 Linaro, Ltd
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at 

[Qemu-devel] [PATCH 67/67] target/arm: Merge gen_bx_im into trans_BLX_i

2019-07-26 Thread Richard Henderson
This is the only remaining use of gen_bx_im.  Simplify, since we know
the destination mode is changing.  Use gen_jmp for the actual branch.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 23 +++
 1 file changed, 7 insertions(+), 16 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 9ae9b23823..dc51e1e622 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -813,21 +813,6 @@ static inline void gen_set_pc_im(DisasContext *s, 
target_ulong val)
 tcg_gen_movi_i32(cpu_R[15], val);
 }
 
-/* Set PC and Thumb state from an immediate address.  */
-static inline void gen_bx_im(DisasContext *s, uint32_t addr)
-{
-TCGv_i32 tmp;
-
-s->base.is_jmp = DISAS_JUMP;
-if (s->thumb != (addr & 1)) {
-tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, addr & 1);
-tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
-tcg_temp_free_i32(tmp);
-}
-tcg_gen_movi_i32(cpu_R[15], addr & ~1);
-}
-
 /* Set PC and Thumb state from var.  var is marked as dead.  */
 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
 {
@@ -10042,12 +10027,18 @@ static bool trans_BL(DisasContext *s, arg_i *a)
 
 static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
 {
+TCGv_i32 tmp;
+
 /* For A32, ARCH(5) is checked near the start of the uncond block. */
 if (s->thumb && (a->imm & 2)) {
 return false;
 }
 tcg_gen_movi_i32(cpu_R[14], s->pc | s->thumb);
-gen_bx_im(s, (s->pc_read & ~3) + a->imm + !s->thumb);
+tmp = tcg_temp_new_i32();
+tcg_gen_movi_i32(tmp, !s->thumb);
+tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
+tcg_temp_free_i32(tmp);
+gen_jmp(s, (s->pc_read & ~3) + a->imm);
 return true;
 }
 
-- 
2.17.1




[Qemu-devel] [PATCH 58/67] target/arm: Convert T16, push and pop

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 83 ++
 target/arm/t16.decode  | 10 +
 2 files changed, 22 insertions(+), 71 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 55404414a2..5d0d0779c8 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7593,6 +7593,16 @@ static int t16_setflags(DisasContext *s, int x)
 return s->condexec_mask == 0;
 }
 
+static int t16_push_list(DisasContext *s, int x)
+{
+return (x & 0xff) | (x & 0x100) << (14 - 8);
+}
+
+static int t16_pop_list(DisasContext *s, int x)
+{
+return (x & 0xff) | (x & 0x100) << (15 - 8);
+}
+
 /*
  * Include the generated decoders.
  * Note that the T32 decoder reuses some of the trans_* functions
@@ -10618,7 +10628,6 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 {
 uint32_t val, op, rm, rd, shift, cond;
 int32_t offset;
-int i;
 TCGv_i32 tmp;
 TCGv_i32 tmp2;
 TCGv_i32 addr;
@@ -10691,76 +10700,8 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 goto illegal_op;
 
 case 4: case 5: case 0xc: case 0xd:
-/*
- * 0b1011_x10x__
- *  - push/pop
- */
-addr = load_reg(s, 13);
-if (insn & (1 << 8))
-offset = 4;
-else
-offset = 0;
-for (i = 0; i < 8; i++) {
-if (insn & (1 << i))
-offset += 4;
-}
-if ((insn & (1 << 11)) == 0) {
-tcg_gen_addi_i32(addr, addr, -offset);
-}
-
-if (s->v8m_stackcheck) {
-/*
- * Here 'addr' is the lower of "old SP" and "new SP";
- * if this is a pop that starts below the limit and ends
- * above it, it is UNKNOWN whether the limit check triggers;
- * we choose to trigger.
- */
-gen_helper_v8m_stackcheck(cpu_env, addr);
-}
-
-for (i = 0; i < 8; i++) {
-if (insn & (1 << i)) {
-if (insn & (1 << 11)) {
-/* pop */
-tmp = tcg_temp_new_i32();
-gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
-store_reg(s, i, tmp);
-} else {
-/* push */
-tmp = load_reg(s, i);
-gen_aa32_st32(s, tmp, addr, get_mem_index(s));
-tcg_temp_free_i32(tmp);
-}
-/* advance to the next address.  */
-tcg_gen_addi_i32(addr, addr, 4);
-}
-}
-tmp = NULL;
-if (insn & (1 << 8)) {
-if (insn & (1 << 11)) {
-/* pop pc */
-tmp = tcg_temp_new_i32();
-gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
-/* don't set the pc until the rest of the instruction
-   has completed */
-} else {
-/* push lr */
-tmp = load_reg(s, 14);
-gen_aa32_st32(s, tmp, addr, get_mem_index(s));
-tcg_temp_free_i32(tmp);
-}
-tcg_gen_addi_i32(addr, addr, 4);
-}
-if ((insn & (1 << 11)) == 0) {
-tcg_gen_addi_i32(addr, addr, -offset);
-}
-/* write back the new stack pointer */
-store_reg(s, 13, addr);
-/* set the new PC value */
-if ((insn & 0x0900) == 0x0900) {
-store_reg_from_load(s, 15, tmp);
-}
-break;
+/* push/pop, in decodetree */
+goto illegal_op;
 
 case 1: case 3: case 9: case 11: /* czb */
 rm = insn & 7;
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 90a4b71a45..10cdca1fbb 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -221,3 +221,13 @@ REVSH   1011 1010 11 ... ...@rdm
   # rest of the space is a reserved hint, behaves as nop.
   NOP   1011   
 }
+
+# Push and Pop
+
+%push_list  0:9 !function=t16_push_list
+%pop_list   0:9 !function=t16_pop_list
+
+STM 1011 010 . \
+_block i=0 b=1 u=0 w=1 rn=13 list=%push_list
+LDM 1011 110 . \
+_block i=1 b=0 u=0 w=1 rn=13 list=%pop_list
-- 
2.17.1




[Qemu-devel] [PATCH 41/67] target/arm: Simplify disas_thumb2_insn

2019-07-26 Thread Richard Henderson
Fold away all of the cases that now just goto illegal_op,
because all of their internal bits are now in decodetree.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 78 ++
 1 file changed, 3 insertions(+), 75 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index a750a2c092..836b3752f7 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10442,9 +10442,6 @@ static bool thumb_insn_is_16bit(DisasContext *s, 
uint32_t insn)
 /* Translate a 32-bit thumb instruction. */
 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
 {
-uint32_t rn;
-int op;
-
 /*
  * ARMv6-M supports a limited subset of Thumb2 instructions.
  * Other Thumb1 architectures allow only 32-bit
@@ -10485,34 +10482,10 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 }
 /* fall back to legacy decoder */
 
-rn = (insn >> 16) & 0xf;
 switch ((insn >> 25) & 0xf) {
 case 0: case 1: case 2: case 3:
 /* 16-bit instructions.  Should never happen.  */
 abort();
-case 4:
-/* All in decodetree */
-goto illegal_op;
-case 5:
-/* All in decodetree */
-goto illegal_op;
-case 13: /* Misc data processing.  */
-op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
-if (op < 4 && (insn & 0xf000) != 0xf000)
-goto illegal_op;
-switch (op) {
-case 0: /* Register controlled shift, in decodetree */
-case 1: /* Sign/zero extend, in decodetree */
-case 2: /* SIMD add/subtract, in decodetree */
-case 3: /* Other data processing, in decodetree */
-goto illegal_op;
-case 4: case 5:
-/* 32-bit multiply.  Sum of absolute differences, in decodetree */
-goto illegal_op;
-case 6: case 7: /* 64-bit multiply, Divide, in decodetree */
-goto illegal_op;
-}
-break;
 case 6: case 7: case 14: case 15:
 /* Coprocessor.  */
 if (arm_dc_feature(s, ARM_FEATURE_M)) {
@@ -10541,6 +10514,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 }
 
 if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
+uint32_t rn = (insn >> 16) & 0xf;
 TCGv_i32 fptr = load_reg(s, rn);
 
 if (extract32(insn, 20, 1)) {
@@ -10599,49 +10573,6 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 }
 }
 break;
-case 8: case 9: case 10: case 11:
-if (insn & (1 << 15)) {
-/* Branches, misc control.  */
-if (insn & 0x5000) {
-/* Unconditional branch, in decodetree */
-goto illegal_op;
-} else if (((insn >> 23) & 7) == 7) {
-/* Misc control */
-if (insn & (1 << 13))
-goto illegal_op;
-
-if (insn & (1 << 26)) {
-/* hvc, smc, in decodetree */
-goto illegal_op;
-} else {
-op = (insn >> 20) & 7;
-switch (op) {
-case 0: /* msr cpsr, in decodetree  */
-case 1: /* msr spsr, in decodetree  */
-goto illegal_op;
-case 2: /* cps, nop-hint, in decodetree */
-goto illegal_op;
-case 3: /* Special control operations, in decodetree */
-case 4: /* bxj, in decodetree */
-case 5: /* eret, in decodetree */
-case 6: /* MRS, in decodetree */
-case 7: /* MSR, in decodetree */
-goto illegal_op;
-}
-}
-} else {
-/* Conditional branch, in decodetree */
-goto illegal_op;
-}
-} else {
-/*
- * 0b_0xxx__0xxx__
- *  - Data-processing (modified immediate, plain binary immediate)
- * All in decodetree.
- */
-goto illegal_op;
-}
-break;
 case 12:
 if ((insn & 0x0110) == 0x0100) {
 if (disas_neon_ls_insn(s, insn)) {
@@ -10649,14 +10580,11 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 }
 break;
 }
-/* Load/store single data item, in decodetree */
 goto illegal_op;
 default:
-goto illegal_op;
+illegal_op:
+gen_illegal_op(s);
 }
-return;
-illegal_op:
-gen_illegal_op(s);
 }
 
 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
-- 
2.17.1




[Qemu-devel] [PATCH 65/67] target/arm: Clean up disas_thumb_insn

2019-07-26 Thread Richard Henderson
Now that everything is converted, remove the rest of
the legacy decode.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 27 ++-
 1 file changed, 2 insertions(+), 25 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index a8db6e9280..c2b8b86fd2 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10677,32 +10677,9 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 
 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
 {
-if (disas_t16(s, insn)) {
-return;
+if (!disas_t16(s, insn)) {
+gen_illegal_op(s);
 }
-/* fall back to legacy decoder */
-
-switch (insn >> 12) {
-case 0: case 1: /* add/sub (3reg, 2reg imm), shift imm; in decodetree */
-case 2: case 3: /* add, sub, cmp, mov (reg, imm), in decodetree */
-case 4: /* ldr lit, data proc (2reg), data proc ext, bx; in decodetree */
-case 5: /* load/store register offset, in decodetree */
-case 6: /* load/store word immediate offset, in decodetree */
-case 7: /* load/store byte immediate offset, in decodetree */
-case 8: /* load/store halfword immediate offset, in decodetree */
-case 9: /* load/store from stack, in decodetree */
-case 10: /* add PC/SP (immediate), in decodetree */
-case 11: /* misc, in decodetree */
-case 12: /* load/store multiple, in decodetree */
-case 13: /* conditional branch or swi, in decodetree */
-case 14:
-case 15:
-/* branches, in decodetree */
-goto illegal_op;
-}
-return;
-illegal_op:
-gen_illegal_op(s);
 }
 
 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
-- 
2.17.1




[Qemu-devel] [PATCH 51/67] target/arm: Convert T16 branch and exchange

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 64 +++---
 target/arm/t16.decode  | 10 +++
 2 files changed, 33 insertions(+), 41 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 9bdcb91537..e2183eb543 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8406,7 +8406,7 @@ static bool trans_BX(DisasContext *s, arg_BX *a)
 if (!ENABLE_ARCH_4T) {
 return false;
 }
-gen_bx(s, load_reg(s, a->rm));
+gen_bx_excret(s, load_reg(s, a->rm));
 return true;
 }
 
@@ -8433,6 +8433,26 @@ static bool trans_BLX_r(DisasContext *s, arg_BLX_r *a)
 return true;
 }
 
+static bool trans_BXNS(DisasContext *s, arg_BXNS *a)
+{
+if (!s->v8m_secure || IS_USER_ONLY) {
+gen_illegal_op(s);
+} else {
+gen_bxns(s, a->rm);
+}
+return true;
+}
+
+static bool trans_BLXNS(DisasContext *s, arg_BLXNS *a)
+{
+if (!s->v8m_secure || IS_USER_ONLY) {
+gen_illegal_op(s);
+} else {
+gen_blxns(s, a->rm);
+}
+return true;
+}
+
 static bool trans_CLZ(DisasContext *s, arg_CLZ *a)
 {
 TCGv_i32 tmp;
@@ -10645,49 +10665,11 @@ static void disas_thumb_insn(DisasContext *s, 
uint32_t insn)
 }
 break;
 case 3:
-{
 /* 0b0100_0111__
  * - branch [and link] exchange thumb register
+ * In decodetree
  */
-bool link = insn & (1 << 7);
-
-if (insn & 3) {
-goto undef;
-}
-if (link) {
-ARCH(5);
-}
-if ((insn & 4)) {
-/* BXNS/BLXNS: only exists for v8M with the
- * security extensions, and always UNDEF if NonSecure.
- * We don't implement these in the user-only mode
- * either (in theory you can use them from Secure User
- * mode but they are too tied in to system emulation.)
- */
-if (!s->v8m_secure || IS_USER_ONLY) {
-goto undef;
-}
-if (link) {
-gen_blxns(s, rm);
-} else {
-gen_bxns(s, rm);
-}
-break;
-}
-/* BLX/BX */
-tmp = load_reg(s, rm);
-if (link) {
-val = (uint32_t)s->pc | 1;
-tmp2 = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp2, val);
-store_reg(s, 14, tmp2);
-gen_bx(s, tmp);
-} else {
-/* Only BX works as exception-return, not BLX */
-gen_bx_excret(s, tmp);
-}
-break;
-}
+goto illegal_op;
 }
 break;
 }
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index edb67a3896..4701f72357 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -24,6 +24,7 @@
 _rri_rot   !extern s rn rd imm rot
 _  !extern s rd rn rm ra
   !extern rd imm
+   !extern rm
 _rr !extern p w u rn rt rm shimm shtype
 _ri !extern p w u rn rt imm
 _block  !extern rn i b u w list
@@ -144,3 +145,12 @@ MOV_rri 00100 ...   @arith_1i 
%s
 CMP_rri 00101 ...   @arith_1i s=1
 ADD_rri 00110 ...   @arith_1i %s
 SUB_rri 00111 ...   @arith_1i %s
+
+# Branch and exchange
+
+@branchr  . rm:4 ...
+
+BX  0100 0111 0  000@branchr
+BLX_r   0100 0111 1  000@branchr
+BXNS0100 0111 0  100@branchr
+BLXNS   0100 0111 1  100@branchr
-- 
2.17.1




[Qemu-devel] [PATCH 55/67] target/arm: Convert T16, Change processor state

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 85 --
 target/arm/t16.decode  | 12 ++
 2 files changed, 52 insertions(+), 45 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 9c8e11bd3a..8f2adbbc7d 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7531,6 +7531,11 @@ static int negate(DisasContext *s, int x)
 return -x;
 }
 
+static int plus_2(DisasContext *s, int x)
+{
+return x + 2;
+}
+
 static int times_2(DisasContext *s, int x)
 {
 return x * 2;
@@ -10163,6 +10168,9 @@ static bool trans_CPS(DisasContext *s, arg_CPS *a)
 {
 uint32_t mask, val;
 
+if (ENABLE_ARCH_6 && arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
 if (IS_USER(s)) {
 /* Implemented as NOP in user mode.  */
 return true;
@@ -10193,6 +10201,36 @@ static bool trans_CPS(DisasContext *s, arg_CPS *a)
 return true;
 }
 
+static bool trans_CPS_v6m(DisasContext *s, arg_CPS_v6m *a)
+{
+TCGv_i32 tmp, addr;
+
+if (!(ENABLE_ARCH_6 && arm_dc_feature(s, ARM_FEATURE_M))) {
+return false;
+}
+if (IS_USER(s)) {
+/* Implemented as NOP in user mode.  */
+return true;
+}
+
+tmp = tcg_const_i32(a->im);
+/* FAULTMASK */
+if (a->F) {
+addr = tcg_const_i32(19);
+gen_helper_v7m_msr(cpu_env, addr, tmp);
+tcg_temp_free_i32(addr);
+}
+/* PRIMASK */
+if (a->I) {
+addr = tcg_const_i32(16);
+gen_helper_v7m_msr(cpu_env, addr, tmp);
+tcg_temp_free_i32(addr);
+}
+tcg_temp_free_i32(tmp);
+gen_lookup_tb(s);
+return true;
+}
+
 /*
  * Clear-Exclusive, Barriers
  */
@@ -10793,51 +10831,8 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 break;
 }
 
-case 6:
-switch ((insn >> 5) & 7) {
-case 2:
-/* setend */
-ARCH(6);
-if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
-gen_helper_setend(cpu_env);
-s->base.is_jmp = DISAS_UPDATE;
-}
-break;
-case 3:
-/* cps */
-ARCH(6);
-if (IS_USER(s)) {
-break;
-}
-if (arm_dc_feature(s, ARM_FEATURE_M)) {
-tmp = tcg_const_i32((insn & (1 << 4)) != 0);
-/* FAULTMASK */
-if (insn & 1) {
-addr = tcg_const_i32(19);
-gen_helper_v7m_msr(cpu_env, addr, tmp);
-tcg_temp_free_i32(addr);
-}
-/* PRIMASK */
-if (insn & 2) {
-addr = tcg_const_i32(16);
-gen_helper_v7m_msr(cpu_env, addr, tmp);
-tcg_temp_free_i32(addr);
-}
-tcg_temp_free_i32(tmp);
-gen_lookup_tb(s);
-} else {
-if (insn & (1 << 4)) {
-shift = CPSR_A | CPSR_I | CPSR_F;
-} else {
-shift = 0;
-}
-gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
-}
-break;
-default:
-goto undef;
-}
-break;
+case 6: /* setend, cps; in decodetree */
+goto illegal_op;
 
 default:
 goto undef;
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 1b47e804bf..f43ea6ce20 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -29,6 +29,8 @@
 _rr !extern p w u rn rt rm shimm shtype
 _ri !extern p w u rn rt imm
 _block  !extern rn i b u w list
+  !extern E
+ !extern mode imod M A I F
 
 # Set S if the instruction is outside of an IT block.
 %s   !function=t16_setflags
@@ -183,3 +185,13 @@ SXTAH   1011 0010 00 ... ...@extend
 SXTAB   1011 0010 01 ... ...@extend
 UXTAH   1011 0010 10 ... ...@extend
 UXTAB   1011 0010 11 ... ...@extend
+
+# Change processor state
+
+%imod   4:1 !function=plus_2
+
+SETEND  1011 0110 010 1 E:1 000 
+{
+  CPS_v6m   1011 0110 011 im:1 00 I:1 F:1
+  CPS   1011 0110 011 . 0 A:1 I:1 F:1mode=0 M=0 %imod
+}
-- 
2.17.1




[Qemu-devel] [PATCH 56/67] target/arm: Convert T16, Reverse bytes

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 18 +++---
 target/arm/t16.decode  |  9 +
 2 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 8f2adbbc7d..c9386ceefb 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10616,7 +10616,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 
 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
 {
-uint32_t val, op, rm, rn, rd, shift, cond;
+uint32_t val, op, rm, rd, shift, cond;
 int32_t offset;
 int i;
 TCGv_i32 tmp;
@@ -10815,20 +10815,8 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 break;
 }
 
-/* Otherwise this is rev */
-ARCH(6);
-rn = (insn >> 3) & 0x7;
-rd = insn & 0x7;
-tmp = load_reg(s, rn);
-switch (op1) {
-case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
-case 1: gen_rev16(tmp, tmp); break;
-case 3: gen_revsh(tmp, tmp); break;
-default:
-g_assert_not_reached();
-}
-store_reg(s, rd, tmp);
-break;
+/* Otherwise this is rev, in decodetree */
+goto illegal_op;
 }
 
 case 6: /* setend, cps; in decodetree */
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index f43ea6ce20..8864f89a81 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -24,6 +24,7 @@
 _rri_rot   !extern s rn rd imm rot
 _  !extern s rd rn rm ra
 _rot !extern rd rn rm rot
+  !extern rd rm
   !extern rd imm
!extern rm
 _rr !extern p w u rn rt rm shimm shtype
@@ -195,3 +196,11 @@ SETEND  1011 0110 010 1 E:1 000 
   CPS_v6m   1011 0110 011 im:1 00 I:1 F:1
   CPS   1011 0110 011 . 0 A:1 I:1 F:1mode=0 M=0 %imod
 }
+
+# Reverse bytes
+
+@rdm  .. rm:3 rd:3  
+
+REV 1011 1010 00 ... ...@rdm
+REV16   1011 1010 01 ... ...@rdm
+REVSH   1011 1010 11 ... ...@rdm
-- 
2.17.1




[Qemu-devel] [PATCH 60/67] target/arm: Convert T16, Miscellaneous 16-bit instructions

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 111 -
 target/arm/t16.decode  |  31 
 2 files changed, 54 insertions(+), 88 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 97c472c8f7..f3a946d8c9 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10104,6 +10104,18 @@ static bool trans_TBH(DisasContext *s, arg_tbranch *a)
 return op_tbranch(s, a, true);
 }
 
+static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
+{
+TCGv_i32 tmp = load_reg(s, a->rn);
+
+arm_gen_condlabel(s);
+tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
+tmp, 0, s->condlabel);
+tcg_temp_free_i32(tmp);
+gen_jmp(s, s->pc_read + a->imm);
+return true;
+}
+
 /*
  * Supervisor call
  */
@@ -10325,6 +10337,25 @@ static bool trans_PLI(DisasContext *s, arg_PLD *a)
 return ENABLE_ARCH_7;
 }
 
+/*
+ * If-then
+ */
+
+static bool trans_IT(DisasContext *s, arg_IT *a)
+{
+/*
+ * No actual code generated for this insn, just setup state.
+ *
+ * Combinations of firstcond and mask which set up an 0b
+ * condition are UNPREDICTABLE; we take the CONSTRAINED
+ * UNPREDICTABLE choice to treat 0b the same as 0b1110,
+ * i.e. both meaning "execute always".
+ */
+s->condexec_cond = a->cond;
+s->condexec_mask = a->imm;
+return true;
+}
+
 /*
  * Legacy decoder.
  */
@@ -10688,85 +10719,8 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 case 8: /* load/store halfword immediate offset, in decodetree */
 case 9: /* load/store from stack, in decodetree */
 case 10: /* add PC/SP (immediate), in decodetree */
+case 11: /* misc, in decodetree */
 case 12: /* load/store multiple, in decodetree */
-goto illegal_op;
-
-case 11:
-/* misc */
-op = (insn >> 8) & 0xf;
-switch (op) {
-case 0: /* add/sub (sp, immediate), in decodetree */
-case 2: /* sign/zero extend, in decodetree */
-goto illegal_op;
-
-case 4: case 5: case 0xc: case 0xd:
-/* push/pop, in decodetree */
-goto illegal_op;
-
-case 1: case 3: case 9: case 11: /* czb */
-rm = insn & 7;
-tmp = load_reg(s, rm);
-arm_gen_condlabel(s);
-if (insn & (1 << 11))
-tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
-else
-tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
-tcg_temp_free_i32(tmp);
-offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
-val = s->pc_read;
-val += offset;
-gen_jmp(s, val);
-break;
-
-case 15: /* IT, nop-hint.  */
-if ((insn & 0xf) == 0) {
-goto illegal_op; /* nop hint, in decodetree */
-}
-/*
- * IT (If-Then)
- *
- * Combinations of firstcond and mask which set up an 0b
- * condition are UNPREDICTABLE; we take the CONSTRAINED
- * UNPREDICTABLE choice to treat 0b the same as 0b1110,
- * i.e. both meaning "execute always".
- */
-s->condexec_cond = (insn >> 4) & 0xe;
-s->condexec_mask = insn & 0x1f;
-/* No actual code generated for this insn, just setup state.  */
-break;
-
-case 0xe: /* bkpt */
-{
-int imm8 = extract32(insn, 0, 8);
-ARCH(5);
-gen_exception_bkpt_insn(s, syn_aa32_bkpt(imm8, true));
-break;
-}
-
-case 0xa: /* rev, and hlt */
-{
-int op1 = extract32(insn, 6, 2);
-
-if (op1 == 2) {
-/* HLT */
-int imm6 = extract32(insn, 0, 6);
-
-gen_hlt(s, imm6);
-break;
-}
-
-/* Otherwise this is rev, in decodetree */
-goto illegal_op;
-}
-
-case 6: /* setend, cps; in decodetree */
-goto illegal_op;
-
-default:
-goto undef;
-}
-break;
-
 case 13: /* conditional branch or swi, in decodetree */
 goto illegal_op;
 
@@ -10822,7 +10776,6 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 }
 return;
 illegal_op:
-undef:
 gen_illegal_op(s);
 }
 
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index f4091c812d..17297a3032 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -210,20 +210,33 @@ REVSH   1011 1010 11 ... ...@rdm
 
 # Hints
 
+%it_cond5:3 !function=times_2
+
 {
-  YIELD 1011  0001 
-  WFE   1011  0010 
-  WFI   1011  0011 
+  {
+YIELD   1011  0001 
+WFE 1011  0010 
+WFI 1011  0011 
 
-  # TODO: 

[Qemu-devel] [PATCH 52/67] target/arm: Convert T16 add, compare, move (two high registers)

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 49 ++
 target/arm/t16.decode  | 10 +
 2 files changed, 12 insertions(+), 47 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index e2183eb543..23f5f982f5 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10628,55 +10628,10 @@ static void disas_thumb_insn(DisasContext *s, 
uint32_t insn)
 store_reg(s, rd, tmp);
 break;
 }
-if (insn & (1 << 10)) {
-/* 0b0100_01xx__
- * - data processing extended, branch and exchange
- */
-rd = (insn & 7) | ((insn >> 4) & 8);
-rm = (insn >> 3) & 0xf;
-op = (insn >> 8) & 3;
-switch (op) {
-case 0: /* add */
-tmp = load_reg(s, rd);
-tmp2 = load_reg(s, rm);
-tcg_gen_add_i32(tmp, tmp, tmp2);
-tcg_temp_free_i32(tmp2);
-if (rd == 13) {
-/* ADD SP, SP, reg */
-store_sp_checked(s, tmp);
-} else {
-store_reg(s, rd, tmp);
-}
-break;
-case 1: /* cmp */
-tmp = load_reg(s, rd);
-tmp2 = load_reg(s, rm);
-gen_sub_CC(tmp, tmp, tmp2);
-tcg_temp_free_i32(tmp2);
-tcg_temp_free_i32(tmp);
-break;
-case 2: /* mov/cpy */
-tmp = load_reg(s, rm);
-if (rd == 13) {
-/* MOV SP, reg */
-store_sp_checked(s, tmp);
-} else {
-store_reg(s, rd, tmp);
-}
-break;
-case 3:
-/* 0b0100_0111__
- * - branch [and link] exchange thumb register
- * In decodetree
- */
-goto illegal_op;
-}
-break;
-}
 
 /*
- * 0b0100_00xx__
- *  - Data-processing (two low registers), in decodetree
+ * - Data-processing (two low registers), in decodetree
+ * - data processing extended, branch and exchange, in decodetree
  */
 goto illegal_op;
 
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 4701f72357..69d3894ba7 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -146,6 +146,16 @@ CMP_rri 00101 ...   @arith_1i 
s=1
 ADD_rri 00110 ...   @arith_1i %s
 SUB_rri 00111 ...   @arith_1i %s
 
+# Add, compare, move (two high registers)
+
+%reg_0_77:1 0:3
+@addsub_2h    . rm:4 ... \
+_rrr_shi rd=%reg_0_7 rn=%reg_0_7 shim=0 shty=0
+
+ADD_rrri0100 0100 .  ...@addsub_2h s=0
+CMP_rrri0100 0101 .  ...@addsub_2h s=1
+MOV_rrri0100 0110 .  ...@addsub_2h s=0
+
 # Branch and exchange
 
 @branchr  . rm:4 ...
-- 
2.17.1




[Qemu-devel] [PATCH 63/67] target/arm: Convert T16, Unconditional branch

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 9 ++---
 target/arm/t16.decode  | 6 ++
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index f1cab437e0..480515a0a9 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10639,7 +10639,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 
 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
 {
-uint32_t val;
 int32_t offset;
 TCGv_i32 tmp;
 TCGv_i32 tmp2;
@@ -10683,12 +10682,8 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 gen_bx(s, tmp);
 break;
 }
-/* unconditional branch */
-val = s->pc_read;
-offset = ((int32_t)insn << 21) >> 21;
-val += offset << 1;
-gen_jmp(s, val);
-break;
+/* unconditional branch, in decodetree */
+goto illegal_op;
 
 case 15:
 /* thumb_insn_is_16bit() ensures we can't get here for
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index c18d146a84..457f2f4178 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -268,3 +268,9 @@ LDM 1011 110 . \
   SVC   1101  imm:8 
   B_cond_thumb  1101 cond:4  imm=%imm8_0x2
 }
+
+# Unconditional Branch
+
+%imm11_0x2  0:s11 !function=times_2
+
+B   11100 ...imm=%imm11_0x2
-- 
2.17.1




[Qemu-devel] [PATCH 62/67] target/arm: Convert T16, load (literal)

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 42 ++
 target/arm/t16.decode  |  4 
 2 files changed, 6 insertions(+), 40 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index f9022fe65c..f1cab437e0 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1011,14 +1011,6 @@ static inline void gen_aa32_ld##SUFF(DisasContext *s, 
TCGv_i32 val,  \
  TCGv_i32 a32, int index)\
 {\
 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data);   \
-}\
-static inline void gen_aa32_ld##SUFF##_iss(DisasContext *s,  \
-   TCGv_i32 val, \
-   TCGv_i32 a32, int index,  \
-   ISSInfo issinfo)  \
-{\
-gen_aa32_ld##SUFF(s, val, a32, index);   \
-disas_set_da_iss(s, OPC, issinfo);   \
 }
 
 #define DO_GEN_ST(SUFF, OPC) \
@@ -1026,14 +1018,6 @@ static inline void gen_aa32_st##SUFF(DisasContext *s, 
TCGv_i32 val,  \
  TCGv_i32 a32, int index)\
 {\
 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data);   \
-}\
-static inline void gen_aa32_st##SUFF##_iss(DisasContext *s,  \
-   TCGv_i32 val, \
-   TCGv_i32 a32, int index,  \
-   ISSInfo issinfo)  \
-{\
-gen_aa32_st##SUFF(s, val, a32, index);   \
-disas_set_da_iss(s, OPC, issinfo | ISSIsWrite);  \
 }
 
 static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
@@ -1082,9 +1066,7 @@ static inline void gen_aa32_st64(DisasContext *s, 
TCGv_i64 val,
 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
 }
 
-DO_GEN_LD(8s, MO_SB)
 DO_GEN_LD(8u, MO_UB)
-DO_GEN_LD(16s, MO_SW)
 DO_GEN_LD(16u, MO_UW)
 DO_GEN_LD(32u, MO_UL)
 DO_GEN_ST(8, MO_UB)
@@ -10657,11 +10639,10 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 
 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
 {
-uint32_t val, rd;
+uint32_t val;
 int32_t offset;
 TCGv_i32 tmp;
 TCGv_i32 tmp2;
-TCGv_i32 addr;
 
 if (disas_t16(s, insn)) {
 return;
@@ -10671,26 +10652,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 switch (insn >> 12) {
 case 0: case 1: /* add/sub (3reg, 2reg imm), shift imm; in decodetree */
 case 2: case 3: /* add, sub, cmp, mov (reg, imm), in decodetree */
-goto illegal_op;
-case 4:
-if (insn & (1 << 11)) {
-rd = (insn >> 8) & 7;
-/* load pc-relative.  Bit 1 of PC is ignored.  */
-addr = add_reg_for_lit(s, 15, (insn & 0xff) * 4);
-tmp = tcg_temp_new_i32();
-gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
-   rd | ISSIs16Bit);
-tcg_temp_free_i32(addr);
-store_reg(s, rd, tmp);
-break;
-}
-
-/*
- * - Data-processing (two low registers), in decodetree
- * - data processing extended, branch and exchange, in decodetree
- */
-goto illegal_op;
-
+case 4: /* ldr lit, data proc (2reg), data proc ext, bx; in decodetree */
 case 5: /* load/store register offset, in decodetree */
 case 6: /* load/store word immediate offset, in decodetree */
 case 7: /* load/store byte immediate offset, in decodetree */
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index ddffd073a2..c18d146a84 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -113,6 +113,10 @@ LDRH_ri 10001 . ... ... @ldst_ri_2
 STR_ri  10010 ...   @ldst_spec_i rn=13
 LDR_ri  10011 ...   @ldst_spec_i rn=13
 
+# Load (PC-relative)
+
+LDR_ri  01001 ...   @ldst_spec_i rn=15
+
 # Add PC/SP (immediate)
 
 ADR 10100 rd:3  imm=%imm8_0x4
-- 
2.17.1




[Qemu-devel] [PATCH 59/67] target/arm: Convert T16, Conditional branches, Supervisor call

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 26 +++---
 target/arm/t16.decode  | 12 
 2 files changed, 15 insertions(+), 23 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 5d0d0779c8..97c472c8f7 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10626,7 +10626,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 
 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
 {
-uint32_t val, op, rm, rd, shift, cond;
+uint32_t val, op, rm, rd, shift;
 int32_t offset;
 TCGv_i32 tmp;
 TCGv_i32 tmp2;
@@ -10767,28 +10767,8 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 }
 break;
 
-case 13:
-/* conditional branch or swi */
-cond = (insn >> 8) & 0xf;
-if (cond == 0xe)
-goto undef;
-
-if (cond == 0xf) {
-/* swi */
-gen_set_pc_im(s, s->pc);
-s->svc_imm = extract32(insn, 0, 8);
-s->base.is_jmp = DISAS_SWI;
-break;
-}
-/* generate a conditional jump to next instruction */
-arm_skip_unless(s, cond);
-
-/* jump to the offset */
-val = s->pc_read;
-offset = ((int32_t)insn << 24) >> 24;
-val += offset << 1;
-gen_jmp(s, val);
-break;
+case 13: /* conditional branch or swi, in decodetree */
+goto illegal_op;
 
 case 14:
 if (insn & (1 << 11)) {
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 10cdca1fbb..f4091c812d 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -28,11 +28,13 @@
   !extern rd rm
   !extern rd imm
!extern rm
+   !extern imm
 _rr !extern p w u rn rt rm shimm shtype
 _ri !extern p w u rn rt imm
 _block  !extern rn i b u w list
   !extern E
  !extern mode imod M A I F
+  !extern cond imm
 
 # Set S if the instruction is outside of an IT block.
 %s   !function=t16_setflags
@@ -231,3 +233,13 @@ STM 1011 010 . \
 _block i=0 b=1 u=0 w=1 rn=13 list=%push_list
 LDM 1011 110 . \
 _block i=1 b=0 u=0 w=1 rn=13 list=%pop_list
+
+# Conditional branches, Supervisor call
+
+%imm8_0x2   0:s8 !function=times_2
+
+{
+  UDF   1101 1110  
+  SVC   1101  imm:8 
+  B_cond_thumb  1101 cond:4  imm=%imm8_0x2
+}
-- 
2.17.1




[Qemu-devel] [PATCH 53/67] target/arm: Convert T16 adjust sp (immediate)

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 15 ++-
 target/arm/t16.decode  |  9 +
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 23f5f982f5..8dd88419fe 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10648,19 +10648,8 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 /* misc */
 op = (insn >> 8) & 0xf;
 switch (op) {
-case 0:
-/*
- * 0b1011___
- *  - ADD (SP plus immediate)
- *  - SUB (SP minus immediate)
- */
-tmp = load_reg(s, 13);
-val = (insn & 0x7f) * 4;
-if (insn & (1 << 7))
-val = -(int32_t)val;
-tcg_gen_addi_i32(tmp, tmp, val);
-store_sp_checked(s, tmp);
-break;
+case 0: /* add/sub (sp, immediate), in decodetree */
+goto illegal_op;
 
 case 2: /* sign/zero extend.  */
 ARCH(6);
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 69d3894ba7..ddf12ada11 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -156,6 +156,15 @@ ADD_rrri0100 0100 .  ...@addsub_2h 
s=0
 CMP_rrri0100 0101 .  ...@addsub_2h s=1
 MOV_rrri0100 0110 .  ...@addsub_2h s=0
 
+# Adjust SP (immediate)
+
+%imm7_0x4   0:7 !function=times_4
+@addsub_sp_i  . ... \
+_rri_rot s=0 rd=13 rn=13 rot=0 imm=%imm7_0x4
+
+ADD_rri 1011  0 ... @addsub_sp_i
+SUB_rri 1011  1 ... @addsub_sp_i
+
 # Branch and exchange
 
 @branchr  . rm:4 ...
-- 
2.17.1




[Qemu-devel] [PATCH 43/67] target/arm: Add skeleton for T16 decodetree

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c   |  6 ++
 target/arm/Makefile.objs |  6 ++
 target/arm/t16.decode| 20 
 3 files changed, 32 insertions(+)
 create mode 100644 target/arm/t16.decode

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 65a74a963b..db93b12608 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7608,6 +7608,7 @@ static int t32_branch24(DisasContext *s, int x)
 #include "decode-a32.inc.c"
 #include "decode-a32-uncond.inc.c"
 #include "decode-t32.inc.c"
+#include "decode-t16.inc.c"
 
 #ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
 # pragma GCC diagnostic pop
@@ -10559,6 +10560,11 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 TCGv_i32 tmp2;
 TCGv_i32 addr;
 
+if (disas_t16(s, insn)) {
+return;
+}
+/* fall back to legacy decoder */
+
 switch (insn >> 12) {
 case 0: case 1:
 
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
index 7806b4dac0..cf26c16f5f 100644
--- a/target/arm/Makefile.objs
+++ b/target/arm/Makefile.objs
@@ -43,12 +43,18 @@ target/arm/decode-t32.inc.c: 
$(SRC_PATH)/target/arm/t32.decode $(DECODETREE)
  $(PYTHON) $(DECODETREE) --static-decode disas_t32 -o $@ $<,\
  "GEN", $(TARGET_DIR)$@)
 
+target/arm/decode-t16.inc.c: $(SRC_PATH)/target/arm/t16.decode $(DECODETREE)
+   $(call quiet-command,\
+ $(PYTHON) $(DECODETREE) -w 16 --static-decode disas_t16 -o $@ $<,\
+ "GEN", $(TARGET_DIR)$@)
+
 target/arm/translate-sve.o: target/arm/decode-sve.inc.c
 target/arm/translate.o: target/arm/decode-vfp.inc.c
 target/arm/translate.o: target/arm/decode-vfp-uncond.inc.c
 target/arm/translate.o: target/arm/decode-a32.inc.c
 target/arm/translate.o: target/arm/decode-a32-uncond.inc.c
 target/arm/translate.o: target/arm/decode-t32.inc.c
+target/arm/translate.o: target/arm/decode-t16.inc.c
 
 obj-y += tlb_helper.o debug_helper.o
 obj-y += translate.o op_helper.o
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
new file mode 100644
index 00..e954f61fe4
--- /dev/null
+++ b/target/arm/t16.decode
@@ -0,0 +1,20 @@
+# Thumb1 instructions
+#
+#  Copyright (c) 2019 Linaro, Ltd
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see .
+
+#
+# This file is processed by scripts/decodetree.py
+#
-- 
2.17.1




[Qemu-devel] [PATCH 38/67] target/arm: Convert Table Branch

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 62 +++---
 target/arm/t32.decode  |  8 +-
 2 files changed, 41 insertions(+), 29 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 87cbadc6cb..9c6623fb6b 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9979,6 +9979,37 @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
 return true;
 }
 
+static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
+{
+TCGv_i32 addr, tmp;
+
+tmp = load_reg(s, a->rm);
+if (half) {
+tcg_gen_add_i32(tmp, tmp, tmp);
+}
+addr = load_reg(s, a->rn);
+tcg_gen_add_i32(addr, addr, tmp);
+
+gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
+half ? MO_UW | s->be_data : MO_UB);
+tcg_temp_free_i32(addr);
+
+tcg_gen_add_i32(tmp, tmp, tmp);
+tcg_gen_addi_i32(tmp, tmp, s->pc_read);
+store_reg(s, 15, tmp);
+return true;
+}
+
+static bool trans_TBB(DisasContext *s, arg_tbranch *a)
+{
+return op_tbranch(s, a, false);
+}
+
+static bool trans_TBH(DisasContext *s, arg_tbranch *a)
+{
+return op_tbranch(s, a, true);
+}
+
 /*
  * Supervisor call
  */
@@ -10358,9 +10389,7 @@ static bool thumb_insn_is_16bit(DisasContext *s, 
uint32_t insn)
 /* Translate a 32-bit thumb instruction. */
 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
 {
-uint32_t rd, rn, rm, rs;
-TCGv_i32 tmp;
-TCGv_i32 addr;
+uint32_t rd, rn, rs;
 int op;
 
 /*
@@ -10406,7 +10435,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 rn = (insn >> 16) & 0xf;
 rs = (insn >> 12) & 0xf;
 rd = (insn >> 8) & 0xf;
-rm = insn & 0xf;
 switch ((insn >> 25) & 0xf) {
 case 0: case 1: case 2: case 3:
 /* 16-bit instructions.  Should never happen.  */
@@ -10479,30 +10507,8 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 /* Load/store exclusive, in decodetree */
 goto illegal_op;
 } else if ((insn & (7 << 5)) == 0) {
-/* Table Branch.  */
-if (rn == 15) {
-addr = tcg_temp_new_i32();
-tcg_gen_movi_i32(addr, s->pc_read);
-} else {
-addr = load_reg(s, rn);
-}
-tmp = load_reg(s, rm);
-tcg_gen_add_i32(addr, addr, tmp);
-if (insn & (1 << 4)) {
-/* tbh */
-tcg_gen_add_i32(addr, addr, tmp);
-tcg_temp_free_i32(tmp);
-tmp = tcg_temp_new_i32();
-gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
-} else { /* tbb */
-tcg_temp_free_i32(tmp);
-tmp = tcg_temp_new_i32();
-gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
-}
-tcg_temp_free_i32(addr);
-tcg_gen_shli_i32(tmp, tmp, 1);
-tcg_gen_addi_i32(tmp, tmp, s->pc_read);
-store_reg(s, 15, tmp);
+/* Table Branch, in decodetree */
+goto illegal_op;
 } else {
 /* Load/store exclusive, load-acq/store-rel, in decodetree */
 goto illegal_op;
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
index f8d8660466..17e6dae688 100644
--- a/target/arm/t32.decode
+++ b/target/arm/t32.decode
@@ -487,7 +487,7 @@ LDRD_ri_t32  1110 1001 .101    
@ldstd_ri8 w=0 p=1
 STRD_ri_t32  1110 1001 .110    @ldstd_ri8 w=1 p=1
 LDRD_ri_t32  1110 1001 .111    @ldstd_ri8 w=1 p=1
 
-# Load/Store Exclusive and Load-Acquire/Store-Release
+# Load/Store Exclusive, Load-Acquire/Store-Release, and Table Branch
 
 @strex_i    rn:4 rt:4 rd:4   \
   rt2=15 imm=%imm8x4
@@ -531,6 +531,12 @@ LDA  1110 1000 1101    1010    
   @ldrex_0
 LDAB 1110 1000 1101    1000   @ldrex_0
 LDAH 1110 1000 1101    1001   @ldrex_0
 
+ rn rm
+@tbranch    rn:4    rm:4  
+
+TBB  1110 1000 1101       @tbranch
+TBH  1110 1000 1101    0001   @tbranch
+
 # Parallel addition and subtraction
 
 SADD8 1010 1000       @rndm
-- 
2.17.1




[Qemu-devel] [PATCH 47/67] target/arm: Convert T16 add pc/sp (immediate)

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 12 +---
 target/arm/t16.decode  |  7 +++
 2 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 28f274ca7c..525276ed13 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10758,19 +10758,9 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 case 7: /* load/store byte immediate offset, in decodetree */
 case 8: /* load/store halfword immediate offset, in decodetree */
 case 9: /* load/store from stack, in decodetree */
+case 10: /* add PC/SP (immediate), in decodetree */
 goto illegal_op;
 
-case 10:
-/*
- * 0b1010___
- *  - Add PC/SP (immediate)
- */
-rd = (insn >> 8) & 7;
-val = (insn & 0xff) * 4;
-tmp = add_reg_for_lit(s, insn & (1 << 11) ? 13 : 15, val);
-store_reg(s, rd, tmp);
-break;
-
 case 11:
 /* misc */
 op = (insn >> 8) & 0xf;
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 797e4e7068..568656ecd6 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -23,6 +23,7 @@
 _rrr_shr   !extern s rn rd rm rs shty
 _rri_rot   !extern s rn rd imm rot
 _  !extern s rd rn rm ra
+  !extern rd imm
 _rr !extern p w u rn rt rm shimm shtype
 _ri !extern p w u rn rt imm
 
@@ -102,3 +103,9 @@ LDRH_ri 10001 . ... ... @ldst_ri_2
 
 STR_ri  10010 ...   @ldst_spec_i rn=13
 LDR_ri  10011 ...   @ldst_spec_i rn=13
+
+# Add PC/SP (immediate)
+
+ADR 10100 rd:3  imm=%imm8_0x4
+ADD_rri 10101 rd:3  \
+_rri_rot rn=13 s=0 rot=0 imm=%imm8_0x4  # SP
-- 
2.17.1




[Qemu-devel] [PATCH 49/67] target/arm: Convert T16 add/sub (3 low, 2 low and imm)

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 26 ++
 target/arm/t16.decode  | 16 
 2 files changed, 18 insertions(+), 24 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index f551fde3db..692891dbe0 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10580,31 +10580,9 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
  * 0b0001_1xxx__
  *  - Add, subtract (three low registers)
  *  - Add, subtract (two low registers and immediate)
+ * In decodetree.
  */
-rn = (insn >> 3) & 7;
-tmp = load_reg(s, rn);
-if (insn & (1 << 10)) {
-/* immediate */
-tmp2 = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
-} else {
-/* reg */
-rm = (insn >> 6) & 7;
-tmp2 = load_reg(s, rm);
-}
-if (insn & (1 << 9)) {
-if (s->condexec_mask)
-tcg_gen_sub_i32(tmp, tmp, tmp2);
-else
-gen_sub_CC(tmp, tmp, tmp2);
-} else {
-if (s->condexec_mask)
-tcg_gen_add_i32(tmp, tmp, tmp2);
-else
-gen_add_CC(tmp, tmp, tmp2);
-}
-tcg_temp_free_i32(tmp2);
-store_reg(s, rd, tmp);
+goto illegal_op;
 } else {
 /* shift immediate */
 rm = (insn >> 3) & 7;
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 67476b30dc..965fb1bf6e 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -117,3 +117,19 @@ ADD_rri 10101 rd:3  \
 
 STM 11000 ...   @ldstm
 LDM_t16 11001 ...   @ldstm
+
+# Add/subtract (three low registers)
+
+@addsub_3   ... rm:3 rn:3 rd:3 \
+_rrr_shi %s shim=0 shty=0
+
+ADD_rrri0001100 ... ... ... @addsub_3
+SUB_rrri0001101 ... ... ... @addsub_3
+
+# Add/subtract (two low registers and immediate)
+
+@addsub_2i  ... imm:3 rn:3 rd:3 \
+_rri_rot %s rot=0
+
+ADD_rri 0001 110 ... ... ...@addsub_2i
+SUB_rri 0001 111 ... ... ...@addsub_2i
-- 
2.17.1




[Qemu-devel] [PATCH 31/67] target/arm: Convert SVC

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 19 +--
 target/arm/a32.decode  |  4 
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 3f14e5c7f3..7ea118a795 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9979,6 +9979,18 @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
 return true;
 }
 
+/*
+ * Supervisor call
+ */
+
+static bool trans_SVC(DisasContext *s, arg_SVC *a)
+{
+gen_set_pc_im(s, s->pc);
+s->svc_imm = a->imm;
+s->base.is_jmp = DISAS_SWI;
+return true;
+}
+
 /*
  * Legacy decoder.
  */
@@ -10243,6 +10255,7 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 case 0x09:
 case 0xa:
 case 0xb:
+case 0xf:
 /* All done in decodetree.  Reach here for illegal ops.  */
 goto illegal_op;
 case 0xc:
@@ -10258,12 +10271,6 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 goto illegal_op;
 }
 break;
-case 0xf:
-/* swi */
-gen_set_pc_im(s, s->pc);
-s->svc_imm = extract32(insn, 0, 24);
-s->base.is_jmp = DISAS_SWI;
-break;
 default:
 illegal_op:
 gen_illegal_op(s);
diff --git a/target/arm/a32.decode b/target/arm/a32.decode
index f0f0f50c4e..c2fb28f235 100644
--- a/target/arm/a32.decode
+++ b/target/arm/a32.decode
@@ -528,3 +528,7 @@ LDM   100 b:1 i:1 u:1 w:1 1 rn:4 list:16   
_block
 
 B 1010    @branch
 BL    1011    @branch
+
+# Supervisor call
+
+SVC    imm:24 
-- 
2.17.1




[Qemu-devel] [PATCH 40/67] target/arm: Convert TT

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 88 ++
 target/arm/t32.decode  |  5 ++-
 2 files changed, 32 insertions(+), 61 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index df515e9341..a750a2c092 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8525,6 +8525,31 @@ static bool trans_SG(DisasContext *s, arg_SG *a)
 return true;
 }
 
+static bool trans_TT(DisasContext *s, arg_TT *a)
+{
+TCGv_i32 addr, tmp;
+
+if (!arm_dc_feature(s, ARM_FEATURE_M) ||
+!arm_dc_feature(s, ARM_FEATURE_V8)) {
+return false;
+}
+if (a->rd == 13 || a->rd == 15 || a->rn == 15) {
+/* We UNDEF for these UNPREDICTABLE cases */
+return false;
+}
+if (a->A && !s->v8m_secure) {
+gen_illegal_op(s);
+return true;
+}
+
+addr = load_reg(s, a->rn);
+tmp = tcg_const_i32((a->A << 1) | a->T);
+gen_helper_v7m_tt(tmp, cpu_env, addr, tmp);
+tcg_temp_free_i32(addr);
+store_reg(s, a->rd, tmp);
+return true;
+}
+
 /*
  * Load/store register index
  */
@@ -10417,7 +10442,7 @@ static bool thumb_insn_is_16bit(DisasContext *s, 
uint32_t insn)
 /* Translate a 32-bit thumb instruction. */
 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
 {
-uint32_t rd, rn, rs;
+uint32_t rn;
 int op;
 
 /*
@@ -10461,70 +10486,13 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 /* fall back to legacy decoder */
 
 rn = (insn >> 16) & 0xf;
-rs = (insn >> 12) & 0xf;
-rd = (insn >> 8) & 0xf;
 switch ((insn >> 25) & 0xf) {
 case 0: case 1: case 2: case 3:
 /* 16-bit instructions.  Should never happen.  */
 abort();
 case 4:
-if (insn & (1 << 22)) {
-/* 0b1110_100x_x1xx_____
- * - load/store doubleword, load/store exclusive, ldacq/strel,
- *   table branch, TT.
- */
-if (insn & 0x0120) {
-/* load/store dual, in decodetree */
-goto illegal_op;
-} else if ((insn & (1 << 23)) == 0) {
-/* 0b1110_1000_010x_____
- * - load/store exclusive word
- * - TT (v8M only)
- */
-if (rs == 15) {
-if (!(insn & (1 << 20)) &&
-arm_dc_feature(s, ARM_FEATURE_M) &&
-arm_dc_feature(s, ARM_FEATURE_V8)) {
-/* 0b1110_1000_0100_____
- *  - TT (v8M only)
- */
-bool alt = insn & (1 << 7);
-TCGv_i32 addr, op, ttresp;
-
-if ((insn & 0x3f) || rd == 13 || rd == 15 || rn == 15) 
{
-/* we UNDEF for these UNPREDICTABLE cases */
-goto illegal_op;
-}
-
-if (alt && !s->v8m_secure) {
-goto illegal_op;
-}
-
-addr = load_reg(s, rn);
-op = tcg_const_i32(extract32(insn, 6, 2));
-ttresp = tcg_temp_new_i32();
-gen_helper_v7m_tt(ttresp, cpu_env, addr, op);
-tcg_temp_free_i32(addr);
-tcg_temp_free_i32(op);
-store_reg(s, rd, ttresp);
-break;
-}
-goto illegal_op;
-}
-/* Load/store exclusive, in decodetree */
-goto illegal_op;
-} else if ((insn & (7 << 5)) == 0) {
-/* Table Branch, in decodetree */
-goto illegal_op;
-} else {
-/* Load/store exclusive, load-acq/store-rel, in decodetree */
-goto illegal_op;
-}
-} else {
-/* Load/store multiple, RFE, SRS, in decodetree */
-goto illegal_op;
-}
-break;
+/* All in decodetree */
+goto illegal_op;
 case 5:
 /* All in decodetree */
 goto illegal_op;
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
index c0b962479b..90db05dab6 100644
--- a/target/arm/t32.decode
+++ b/target/arm/t32.decode
@@ -506,7 +506,10 @@ STRD_ri_t32  1110 1001 .110    
@ldstd_ri8 w=1 p=1
 @ldrex_d    rn:4 rt:4 rt2:4   \
   imm=0
 
-STREX1110 1000 0100       @strex_i
+{
+  TT 1110 1000 0100 rn:4  rd:4 A:1 T:1 00
+  STREX  1110 1000 0100       @strex_i
+}
 STREXB   1110 1000 1100    0100   @strex_0
 STREXH   1110 1000 1100    0101   

[Qemu-devel] [PATCH 34/67] target/arm: Convert CPS (privileged)

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c   | 87 +++-
 target/arm/a32-uncond.decode |  3 ++
 target/arm/t32.decode|  3 ++
 3 files changed, 42 insertions(+), 51 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 797e8f7344..8dbe189df7 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10049,6 +10049,40 @@ static bool trans_SRS(DisasContext *s, arg_SRS *a)
 return true;
 }
 
+static bool trans_CPS(DisasContext *s, arg_CPS *a)
+{
+uint32_t mask, val;
+
+if (IS_USER(s)) {
+/* Implemented as NOP in user mode.  */
+return true;
+}
+
+mask = val = 0;
+if (a->imod & 2) {
+if (a->A) {
+mask |= CPSR_A;
+}
+if (a->I) {
+mask |= CPSR_I;
+}
+if (a->F) {
+mask |= CPSR_F;
+}
+if (a->imod & 1) {
+val |= mask;
+}
+}
+if (a->M) {
+mask |= CPSR_M;
+val |= a->mode;
+}
+if (mask) {
+gen_set_psr_im(s, mask, 0, val);
+}
+return true;
+}
+
 /*
  * Clear-Exclusive, Barriers
  */
@@ -10220,31 +10254,6 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 ARCH(5TE);
 } else if ((insn & 0x0f10) == 0x0e10) {
 /* Additional coprocessor register transfer.  */
-} else if ((insn & 0x0ff10020) == 0x0100) {
-uint32_t mask;
-uint32_t val;
-/* cps (privileged) */
-if (IS_USER(s))
-return;
-mask = val = 0;
-if (insn & (1 << 19)) {
-if (insn & (1 << 8))
-mask |= CPSR_A;
-if (insn & (1 << 7))
-mask |= CPSR_I;
-if (insn & (1 << 6))
-mask |= CPSR_F;
-if (insn & (1 << 18))
-val |= mask;
-}
-if (insn & (1 << 17)) {
-mask |= CPSR_M;
-val |= (insn & 0x1f);
-}
-if (mask) {
-gen_set_psr_im(s, mask, 0, val);
-}
-return;
 }
 goto illegal_op;
 }
@@ -10350,7 +10359,6 @@ static bool thumb_insn_is_16bit(DisasContext *s, 
uint32_t insn)
 /* Translate a 32-bit thumb instruction. */
 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
 {
-uint32_t imm, offset;
 uint32_t rd, rn, rm, rs;
 TCGv_i32 tmp;
 TCGv_i32 addr;
@@ -10631,31 +10639,8 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 case 0: /* msr cpsr, in decodetree  */
 case 1: /* msr spsr, in decodetree  */
 goto illegal_op;
-case 2: /* cps, nop-hint.  */
-/* nop hints in decodetree */
-/* Implemented as NOP in user mode.  */
-if (IS_USER(s))
-break;
-offset = 0;
-imm = 0;
-if (insn & (1 << 10)) {
-if (insn & (1 << 7))
-offset |= CPSR_A;
-if (insn & (1 << 6))
-offset |= CPSR_I;
-if (insn & (1 << 5))
-offset |= CPSR_F;
-if (insn & (1 << 9))
-imm = CPSR_A | CPSR_I | CPSR_F;
-}
-if (insn & (1 << 8)) {
-offset |= 0x1f;
-imm |= (insn & 0x1f);
-}
-if (offset) {
-gen_set_psr_im(s, offset, 0, imm);
-}
-break;
+case 2: /* cps, nop-hint, in decodetree */
+goto illegal_op;
 case 3: /* Special control operations, in decodetree */
 case 4: /* bxj, in decodetree */
 case 5: /* eret, in decodetree */
diff --git a/target/arm/a32-uncond.decode b/target/arm/a32-uncond.decode
index b077958cec..eb1c55b330 100644
--- a/target/arm/a32-uncond.decode
+++ b/target/arm/a32-uncond.decode
@@ -35,9 +35,12 @@ BLX_i 101 .  
  imm=%imm24h
 
  rn w pu
  mode w pu
+ mode imod M A I F
 
 RFE   100 pu:2 0 w:1 1 rn:4  1010     
 SRS   110 pu:2 1 w:1 0 1101  0101 000 mode:5  
+CPS   0001  imod:2 M:1 0  000 A:1 I:1 F:1 0 mode:5 \
+ 
 
 # Clear-Exclusive, Barriers
 
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
index 9fe1500fe0..f8d8660466 100644
--- 

[Qemu-devel] [PATCH 33/67] target/arm: Convert Clear-Exclusive, Barriers

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c   | 122 +++
 target/arm/a32-uncond.decode |  10 +++
 target/arm/t32.decode|  10 +++
 3 files changed, 73 insertions(+), 69 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index b43b344f96..797e8f7344 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10049,6 +10049,58 @@ static bool trans_SRS(DisasContext *s, arg_SRS *a)
 return true;
 }
 
+/*
+ * Clear-Exclusive, Barriers
+ */
+
+static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
+{
+if (!ENABLE_ARCH_6K) {
+return false;
+}
+gen_clrex(s);
+return true;
+}
+
+static bool trans_DSB(DisasContext *s, arg_DSB *a)
+{
+if (!s->thumb && !ENABLE_ARCH_7) {
+return false;
+}
+tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
+return true;
+}
+
+static bool trans_DMB(DisasContext *s, arg_DMB *a)
+{
+return trans_DSB(s, NULL);
+}
+
+static bool trans_ISB(DisasContext *s, arg_ISB *a)
+{
+/*
+ * We need to break the TB after this insn to execute
+ * self-modifying code correctly and also to take
+ * any pending interrupts immediately.
+ */
+gen_goto_tb(s, 0, s->pc & ~1);
+return true;
+}
+
+static bool trans_SB(DisasContext *s, arg_SB *a)
+{
+if (!dc_isar_feature(aa32_sb, s)) {
+return false;
+}
+/*
+ * TODO: There is no speculation barrier opcode
+ * for TCG; MB and end the TB instead.
+ */
+tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
+gen_goto_tb(s, 0, s->pc & ~1);
+return true;
+}
+
 /*
  * Legacy decoder.
  */
@@ -10142,38 +10194,6 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 s->base.is_jmp = DISAS_UPDATE;
 }
 return;
-} else if ((insn & 0x0f00) == 0x057ff000) {
-switch ((insn >> 4) & 0xf) {
-case 1: /* clrex */
-ARCH(6K);
-gen_clrex(s);
-return;
-case 4: /* dsb */
-case 5: /* dmb */
-ARCH(7);
-tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
-return;
-case 6: /* isb */
-/* We need to break the TB after this insn to execute
- * self-modifying code correctly and also to take
- * any pending interrupts immediately.
- */
-gen_goto_tb(s, 0, s->pc & ~1);
-return;
-case 7: /* sb */
-if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
-goto illegal_op;
-}
-/*
- * TODO: There is no speculation barrier opcode
- * for TCG; MB and end the TB instead.
- */
-tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
-gen_goto_tb(s, 0, s->pc & ~1);
-return;
-default:
-goto illegal_op;
-}
 } else if ((insn & 0x0e000f00) == 0x0c000100) {
 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
 /* iWMMXt register transfer.  */
@@ -10636,43 +10656,7 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 gen_set_psr_im(s, offset, 0, imm);
 }
 break;
-case 3: /* Special control operations.  */
-if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
-!arm_dc_feature(s, ARM_FEATURE_M)) {
-goto illegal_op;
-}
-op = (insn >> 4) & 0xf;
-switch (op) {
-case 2: /* clrex */
-gen_clrex(s);
-break;
-case 4: /* dsb */
-case 5: /* dmb */
-tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
-break;
-case 6: /* isb */
-/* We need to break the TB after this insn
- * to execute self-modifying code correctly
- * and also to take any pending interrupts
- * immediately.
- */
-gen_goto_tb(s, 0, s->pc & ~1);
-break;
-case 7: /* sb */
-if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
-goto illegal_op;
-}
-/*
- * TODO: There is no speculation barrier opcode
- * for TCG; MB and end the TB instead.
- */
-tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
-

[Qemu-devel] [PATCH 39/67] target/arm: Convert SG

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 51 --
 target/arm/t32.decode  |  5 -
 2 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 9c6623fb6b..df515e9341 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8497,6 +8497,34 @@ static bool trans_SMC(DisasContext *s, arg_SMC *a)
 return true;
 }
 
+static bool trans_SG(DisasContext *s, arg_SG *a)
+{
+if (!arm_dc_feature(s, ARM_FEATURE_M) ||
+!arm_dc_feature(s, ARM_FEATURE_V8)) {
+return false;
+}
+/*
+ * SG (v8M only)
+ * The bulk of the behaviour for this instruction is implemented
+ * in v7m_handle_execute_nsc(), which deals with the insn when
+ * it is executed by a CPU in non-secure state from memory
+ * which is Secure & NonSecure-Callable.
+ * Here we only need to handle the remaining cases:
+ *  * in NS memory (including the "security extension not
+ *implemented" case) : NOP
+ *  * in S memory but CPU already secure (clear IT bits)
+ * We know that the attribute for the memory this insn is
+ * in must match the current CPU state, because otherwise
+ * get_phys_addr_pmsav8 would have generated an exception.
+ */
+if (s->v8m_secure) {
+/* Like the IT insn, we don't need to generate any code */
+s->condexec_cond = 0;
+s->condexec_mask = 0;
+}
+return true;
+}
+
 /*
  * Load/store register index
  */
@@ -10445,28 +10473,7 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
  * - load/store doubleword, load/store exclusive, ldacq/strel,
  *   table branch, TT.
  */
-if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_M) &&
-arm_dc_feature(s, ARM_FEATURE_V8)) {
-/* 0b1110_1001_0111__1110_1001_0111_111
- *  - SG (v8M only)
- * The bulk of the behaviour for this instruction is 
implemented
- * in v7m_handle_execute_nsc(), which deals with the insn when
- * it is executed by a CPU in non-secure state from memory
- * which is Secure & NonSecure-Callable.
- * Here we only need to handle the remaining cases:
- *  * in NS memory (including the "security extension not
- *implemented" case) : NOP
- *  * in S memory but CPU already secure (clear IT bits)
- * We know that the attribute for the memory this insn is
- * in must match the current CPU state, because otherwise
- * get_phys_addr_pmsav8 would have generated an exception.
- */
-if (s->v8m_secure) {
-/* Like the IT insn, we don't need to generate any code */
-s->condexec_cond = 0;
-s->condexec_mask = 0;
-}
-} else if (insn & 0x0120) {
+if (insn & 0x0120) {
 /* load/store dual, in decodetree */
 goto illegal_op;
 } else if ((insn & (1 << 23)) == 0) {
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
index 17e6dae688..c0b962479b 100644
--- a/target/arm/t32.decode
+++ b/target/arm/t32.decode
@@ -485,7 +485,10 @@ STRD_ri_t32  1110 1001 .100    
@ldstd_ri8 w=0 p=1
 LDRD_ri_t32  1110 1001 .101    @ldstd_ri8 w=0 p=1
 
 STRD_ri_t32  1110 1001 .110    @ldstd_ri8 w=1 p=1
-LDRD_ri_t32  1110 1001 .111    @ldstd_ri8 w=1 p=1
+{
+  SG 1110 1001 0111  1110 1001 0111
+  LDRD_ri_t321110 1001 .111    @ldstd_ri8 w=1 p=1
+}
 
 # Load/Store Exclusive, Load-Acquire/Store-Release, and Table Branch
 
-- 
2.17.1




[Qemu-devel] [PATCH 32/67] target/arm: Convert RFE and SRS

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c   | 150 ++-
 target/arm/a32-uncond.decode |   8 ++
 target/arm/t32.decode|  12 +++
 3 files changed, 81 insertions(+), 89 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 7ea118a795..b43b344f96 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9991,16 +9991,71 @@ static bool trans_SVC(DisasContext *s, arg_SVC *a)
 return true;
 }
 
+/*
+ * Unconditional system instructions
+ */
+
+static bool trans_RFE(DisasContext *s, arg_RFE *a)
+{
+int32_t offset;
+TCGv_i32 addr, t1, t2;
+
+if (IS_USER(s) || !ENABLE_ARCH_6) {
+return false;
+}
+
+addr = load_reg(s, a->rn);
+
+switch (a->pu) {
+case 0: offset = -4; break; /* DA */
+case 1: offset =  0; break; /* IA */
+case 2: offset = -8; break; /* DB */
+case 3: offset =  4; break; /* IB */
+default:
+g_assert_not_reached();
+}
+tcg_gen_addi_i32(addr, addr, offset);
+
+/* Load PC into tmp and CPSR into tmp2.  */
+t1 = tcg_temp_new_i32();
+gen_aa32_ld32u(s, t1, addr, get_mem_index(s));
+tcg_gen_addi_i32(addr, addr, 4);
+t2 = tcg_temp_new_i32();
+gen_aa32_ld32u(s, t2, addr, get_mem_index(s));
+
+if (a->w) {
+/* Base writeback.  */
+switch (a->pu) {
+case 0: offset = -8; break;
+case 1: offset =  4; break;
+case 2: offset = -4; break;
+case 3: offset =  0; break;
+}
+tcg_gen_addi_i32(addr, addr, offset);
+store_reg(s, a->rn, addr);
+} else {
+tcg_temp_free_i32(addr);
+}
+gen_rfe(s, t1, t2);
+return true;
+}
+
+static bool trans_SRS(DisasContext *s, arg_SRS *a)
+{
+if (!ENABLE_ARCH_6) {
+return false;
+}
+gen_srs(s, a->mode, a->pu, a->w);
+return true;
+}
+
 /*
  * Legacy decoder.
  */
 
 static void disas_arm_insn(DisasContext *s, unsigned int insn)
 {
-unsigned int cond, op1, i, rn;
-TCGv_i32 tmp;
-TCGv_i32 tmp2;
-TCGv_i32 addr;
+unsigned int cond, op1;
 
 /* M variants do not implement ARM mode; this must raise the INVSTATE
  * UsageFault exception.
@@ -10119,52 +10174,6 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 default:
 goto illegal_op;
 }
-} else if ((insn & 0x0e5fffe0) == 0x084d0500) {
-/* srs */
-ARCH(6);
-gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
-return;
-} else if ((insn & 0x0e50ffe0) == 0x08100a00) {
-/* rfe */
-int32_t offset;
-if (IS_USER(s))
-goto illegal_op;
-ARCH(6);
-rn = (insn >> 16) & 0xf;
-addr = load_reg(s, rn);
-i = (insn >> 23) & 3;
-switch (i) {
-case 0: offset = -4; break; /* DA */
-case 1: offset = 0; break; /* IA */
-case 2: offset = -8; break; /* DB */
-case 3: offset = 4; break; /* IB */
-default: abort();
-}
-if (offset)
-tcg_gen_addi_i32(addr, addr, offset);
-/* Load PC into tmp and CPSR into tmp2.  */
-tmp = tcg_temp_new_i32();
-gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
-tcg_gen_addi_i32(addr, addr, 4);
-tmp2 = tcg_temp_new_i32();
-gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
-if (insn & (1 << 21)) {
-/* Base writeback.  */
-switch (i) {
-case 0: offset = -8; break;
-case 1: offset = 4; break;
-case 2: offset = -4; break;
-case 3: offset = 0; break;
-default: abort();
-}
-if (offset)
-tcg_gen_addi_i32(addr, addr, offset);
-store_reg(s, rn, addr);
-} else {
-tcg_temp_free_i32(addr);
-}
-gen_rfe(s, tmp, tmp2);
-return;
 } else if ((insn & 0x0e000f00) == 0x0c000100) {
 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
 /* iWMMXt register transfer.  */
@@ -10324,7 +10333,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 uint32_t imm, offset;
 uint32_t rd, rn, rm, rs;
 TCGv_i32 tmp;
-TCGv_i32 tmp2;
 TCGv_i32 addr;
 int op;
 
@@ -10473,44 +10481,8 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 goto illegal_op;
 }
 } else {
-/* Load/store multiple, RFE, SRS.  */
-if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
-/* RFE, SRS: not available in user mode or on M profile */
-if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
-goto illegal_op;
-}

[Qemu-devel] [PATCH 30/67] target/arm: Convert B, BL, BLX (immediate)

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c   | 134 +++
 target/arm/a32-uncond.decode |   8 +++
 target/arm/a32.decode|   8 +++
 target/arm/t32.decode|  79 +
 4 files changed, 122 insertions(+), 107 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 33daf70d5d..3f14e5c7f3 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7582,6 +7582,14 @@ static int t32_expandimm_imm(DisasContext *s, int x)
 return imm;
 }
 
+static int t32_branch24(DisasContext *s, int x)
+{
+/* Convert J1:J2 at x[22:21] to I2:I1, which involves I=J^~S.  */
+x ^= !(x < 0) * (3 << 21);
+/* Append the final zero.  */
+return x << 1;
+}
+
 /*
  * Include the generated decoders.
  * Note that the T32 decoder reuses some of the trans_* functions
@@ -9928,13 +9936,56 @@ static bool trans_LDM(DisasContext *s, arg_ldst_block 
*a)
 return true;
 }
 
+/*
+ * Branch, branch with link
+ */
+
+static bool trans_B(DisasContext *s, arg_i *a)
+{
+gen_jmp(s, s->pc_read + a->imm);
+return true;
+}
+
+static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
+{
+/* This has cond from encoding, required to be outside IT block.  */
+if (a->cond >= 0xe) {
+return false;
+}
+if (s->condexec_mask) {
+gen_illegal_op(s);
+return true;
+}
+arm_skip_unless(s, a->cond);
+gen_jmp(s, s->pc_read + a->imm);
+return true;
+}
+
+static bool trans_BL(DisasContext *s, arg_i *a)
+{
+tcg_gen_movi_i32(cpu_R[14], s->pc | s->thumb);
+gen_jmp(s, s->pc_read + a->imm);
+return true;
+}
+
+static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
+{
+/* For A32, ARCH(5) is checked near the start of the uncond block. */
+if (s->thumb && (a->imm & 2)) {
+return false;
+}
+tcg_gen_movi_i32(cpu_R[14], s->pc | s->thumb);
+gen_bx_im(s, (s->pc_read & ~3) + a->imm + !s->thumb);
+return true;
+}
+
 /*
  * Legacy decoder.
  */
 
 static void disas_arm_insn(DisasContext *s, unsigned int insn)
 {
-unsigned int cond, val, op1, i, rn;
+unsigned int cond, op1, i, rn;
 TCGv_i32 tmp;
 TCGv_i32 tmp2;
 TCGv_i32 addr;
@@ -10102,21 +10153,6 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 }
 gen_rfe(s, tmp, tmp2);
 return;
-} else if ((insn & 0x0e00) == 0x0a00) {
-/* branch link and change to thumb (blx ) */
-int32_t offset;
-
-tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, s->pc);
-store_reg(s, 14, tmp);
-/* Sign-extend the 24-bit offset */
-offset = (((int32_t)insn) << 8) >> 8;
-val = s->pc_read;
-/* offset * 4 + bit24 * 2 + (thumb bit) */
-val += (offset << 2) | ((insn >> 23) & 2) | 1;
-/* protected by ARCH(5); above, near the start of uncond block */
-gen_bx_im(s, val);
-return;
 } else if ((insn & 0x0e000f00) == 0x0c000100) {
 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
 /* iWMMXt register transfer.  */
@@ -10205,24 +10241,10 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 case 0x7:
 case 0x08:
 case 0x09:
-/* All done in decodetree.  Reach here for illegal ops.  */
-goto illegal_op;
 case 0xa:
 case 0xb:
-{
-int32_t offset;
-
-/* branch (and link) */
-if (insn & (1 << 24)) {
-tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, s->pc);
-store_reg(s, 14, tmp);
-}
-offset = sextract32(insn << 2, 0, 26);
-val = s->pc_read + offset;
-gen_jmp(s, val);
-}
-break;
+/* All done in decodetree.  Reach here for illegal ops.  */
+goto illegal_op;
 case 0xc:
 case 0xd:
 case 0xe:
@@ -10594,32 +10616,8 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 if (insn & (1 << 15)) {
 /* Branches, misc control.  */
 if (insn & 0x5000) {
-/* Unconditional branch.  */
-/* signextend(hw1[10:0]) -> offset[:12].  */
-offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
-/* hw1[10:0] -> offset[11:1].  */
-offset |= (insn & 0x7ff) << 1;
-/* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
-   offset[24:22] already have the same value because of the
-   sign extension above.  */
-offset ^= ((~insn) & (1 << 13)) << 10;
-offset ^= ((~insn) & (1 << 11)) << 11;
-
-if (insn & (1 << 14)) {
-/* Branch and link.  */
-   

[Qemu-devel] [PATCH 48/67] target/arm: Convert T16 load/store multiple

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 47 +++---
 target/arm/t16.decode  |  8 +++
 2 files changed, 16 insertions(+), 39 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 525276ed13..f551fde3db 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9988,6 +9988,13 @@ static bool trans_LDM(DisasContext *s, arg_ldst_block *a)
 return true;
 }
 
+static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
+{
+/* Writeback is conditional on the base register not being loaded.  */
+a->w = !(a->list & (1 << a->rn));
+return trans_LDM(s, a);
+}
+
 /*
  * Branch, branch with link
  */
@@ -10759,6 +10766,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 case 8: /* load/store halfword immediate offset, in decodetree */
 case 9: /* load/store from stack, in decodetree */
 case 10: /* add PC/SP (immediate), in decodetree */
+case 12: /* load/store multiple, in decodetree */
 goto illegal_op;
 
 case 11:
@@ -10984,45 +10992,6 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 }
 break;
 
-case 12:
-{
-/* load/store multiple */
-TCGv_i32 loaded_var = NULL;
-rn = (insn >> 8) & 0x7;
-addr = load_reg(s, rn);
-for (i = 0; i < 8; i++) {
-if (insn & (1 << i)) {
-if (insn & (1 << 11)) {
-/* load */
-tmp = tcg_temp_new_i32();
-gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
-if (i == rn) {
-loaded_var = tmp;
-} else {
-store_reg(s, i, tmp);
-}
-} else {
-/* store */
-tmp = load_reg(s, i);
-gen_aa32_st32(s, tmp, addr, get_mem_index(s));
-tcg_temp_free_i32(tmp);
-}
-/* advance to the next address */
-tcg_gen_addi_i32(addr, addr, 4);
-}
-}
-if ((insn & (1 << rn)) == 0) {
-/* base reg not in list: base register writeback */
-store_reg(s, rn, addr);
-} else {
-/* base reg in list: if load, complete it now */
-if (insn & (1 << 11)) {
-store_reg(s, rn, loaded_var);
-}
-tcg_temp_free_i32(addr);
-}
-break;
-}
 case 13:
 /* conditional branch or swi */
 cond = (insn >> 8) & 0xf;
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 568656ecd6..67476b30dc 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -26,6 +26,7 @@
   !extern rd imm
 _rr !extern p w u rn rt rm shimm shtype
 _ri !extern p w u rn rt imm
+_block  !extern rn i b u w list
 
 # Set S if the instruction is outside of an IT block.
 %s   !function=t16_setflags
@@ -109,3 +110,10 @@ LDR_ri  10011 ...   
@ldst_spec_i rn=13
 ADR 10100 rd:3  imm=%imm8_0x4
 ADD_rri 10101 rd:3  \
 _rri_rot rn=13 s=0 rot=0 imm=%imm8_0x4  # SP
+
+# Load/store multiple
+
+@ldstm  . rn:3 list:8   _block i=1 b=0 u=0 w=1
+
+STM 11000 ...   @ldstm
+LDM_t16 11001 ...   @ldstm
-- 
2.17.1




[Qemu-devel] [PATCH 25/67] target/arm: Convert Parallel addition and subtraction

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 229 -
 target/arm/a32.decode  |  44 
 target/arm/t32.decode  |  44 
 3 files changed, 200 insertions(+), 117 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index bcc890c458..8f2b5dcb02 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -696,99 +696,6 @@ static inline void gen_arm_shift_reg(TCGv_i32 var, int 
shiftop,
 tcg_temp_free_i32(shift);
 }
 
-#define PAS_OP(pfx) \
-switch (op2) {  \
-case 0: gen_pas_helper(glue(pfx,add16)); break; \
-case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
-case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
-case 3: gen_pas_helper(glue(pfx,sub16)); break; \
-case 4: gen_pas_helper(glue(pfx,add8)); break; \
-case 7: gen_pas_helper(glue(pfx,sub8)); break; \
-}
-static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
-{
-TCGv_ptr tmp;
-
-switch (op1) {
-#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
-case 1:
-tmp = tcg_temp_new_ptr();
-tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
-PAS_OP(s)
-tcg_temp_free_ptr(tmp);
-break;
-case 5:
-tmp = tcg_temp_new_ptr();
-tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
-PAS_OP(u)
-tcg_temp_free_ptr(tmp);
-break;
-#undef gen_pas_helper
-#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
-case 2:
-PAS_OP(q);
-break;
-case 3:
-PAS_OP(sh);
-break;
-case 6:
-PAS_OP(uq);
-break;
-case 7:
-PAS_OP(uh);
-break;
-#undef gen_pas_helper
-}
-}
-#undef PAS_OP
-
-/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */
-#define PAS_OP(pfx) \
-switch (op1) {  \
-case 0: gen_pas_helper(glue(pfx,add8)); break; \
-case 1: gen_pas_helper(glue(pfx,add16)); break; \
-case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
-case 4: gen_pas_helper(glue(pfx,sub8)); break; \
-case 5: gen_pas_helper(glue(pfx,sub16)); break; \
-case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
-}
-static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 
b)
-{
-TCGv_ptr tmp;
-
-switch (op2) {
-#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
-case 0:
-tmp = tcg_temp_new_ptr();
-tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
-PAS_OP(s)
-tcg_temp_free_ptr(tmp);
-break;
-case 4:
-tmp = tcg_temp_new_ptr();
-tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
-PAS_OP(u)
-tcg_temp_free_ptr(tmp);
-break;
-#undef gen_pas_helper
-#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
-case 1:
-PAS_OP(q);
-break;
-case 2:
-PAS_OP(sh);
-break;
-case 5:
-PAS_OP(uq);
-break;
-case 6:
-PAS_OP(uh);
-break;
-#undef gen_pas_helper
-}
-}
-#undef PAS_OP
-
 /*
  * Generate a conditional based on ARM condition code cc.
  * This is common between ARM and Aarch64 targets.
@@ -9284,6 +9191,114 @@ static bool trans_UDF(DisasContext *s, arg_UDF *a)
 return true;
 }
 
+/*
+ * Parallel addition and subtraction
+ */
+
+static bool op_par_addsub(DisasContext *s, arg_rrr *a,
+  void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
+{
+TCGv_i32 t0, t1;
+
+if (s->thumb
+? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
+: !ENABLE_ARCH_6) {
+return false;
+}
+
+t0 = load_reg(s, a->rn);
+t1 = load_reg(s, a->rm);
+
+gen(t0, t0, t1);
+
+tcg_temp_free_i32(t1);
+store_reg(s, a->rd, t0);
+return true;
+}
+
+static bool op_par_addsub_ge(DisasContext *s, arg_rrr *a,
+ void (*gen)(TCGv_i32, TCGv_i32,
+ TCGv_i32, TCGv_ptr))
+{
+TCGv_i32 t0, t1;
+TCGv_ptr ge;
+
+if (s->thumb
+? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
+: !ENABLE_ARCH_6) {
+return false;
+}
+
+t0 = load_reg(s, a->rn);
+t1 = load_reg(s, a->rm);
+
+ge = tcg_temp_new_ptr();
+tcg_gen_addi_ptr(ge, cpu_env, offsetof(CPUARMState, GE));
+gen(t0, t0, t1, ge);
+
+tcg_temp_free_ptr(ge);
+tcg_temp_free_i32(t1);
+store_reg(s, a->rd, t0);
+return true;
+}
+
+#define DO_PAR_ADDSUB(NAME, helper) \
+static bool trans_##NAME(DisasContext *s, arg_rrr *a)   \
+{   \
+return op_par_addsub(s, a, helper); \
+}
+
+#define DO_PAR_ADDSUB_GE(NAME, helper) \
+static bool trans_##NAME(DisasContext *s, arg_rrr *a)   \
+{   \
+return op_par_addsub_ge(s, a, helper);  \
+}
+
+DO_PAR_ADDSUB_GE(SADD16, 

[Qemu-devel] [PATCH 16/67] target/arm: Convert Halfword multiply and multiply accumulate

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 216 ++---
 target/arm/a32.decode  |  20 
 target/arm/t32.decode  |  29 ++
 3 files changed, 167 insertions(+), 98 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 85f829c1bb..2140671eb2 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8216,6 +8216,114 @@ DO_QADDSUB(QDSUB, false, true)
 
 #undef DO_QADDSUB
 
+/*
+ * Halfword multiply and multiply accumulate
+ */
+
+static bool op_smlaxxx(DisasContext *s, arg_ *a,
+   int add_long, bool nt, bool mt)
+{
+TCGv_i32 t0, t1, tl, th;
+
+if (s->thumb
+? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
+: !ENABLE_ARCH_5TE) {
+return false;
+}
+
+t0 = load_reg(s, a->rn);
+t1 = load_reg(s, a->rm);
+gen_mulxy(t0, t1, nt, mt);
+tcg_temp_free_i32(t1);
+
+switch (add_long) {
+case 0:
+store_reg(s, a->rd, t0);
+break;
+case 1:
+t1 = load_reg(s, a->ra);
+gen_helper_add_setq(t0, cpu_env, t0, t1);
+tcg_temp_free_i32(t1);
+store_reg(s, a->rd, t0);
+break;
+case 2:
+tl = load_reg(s, a->ra);
+th = load_reg(s, a->rd);
+tcg_gen_add2_i32(tl, th, tl, th, t0, t1);
+tcg_temp_free_i32(t0);
+tcg_temp_free_i32(t1);
+store_reg(s, a->ra, tl);
+store_reg(s, a->rd, th);
+}
+return true;
+}
+
+#define DO_SMLAX(NAME, add, nt, mt) \
+static bool trans_##NAME(DisasContext *s, arg_ *a) \
+{  \
+return op_smlaxxx(s, a, add, nt, mt);  \
+}
+
+DO_SMLAX(SMULBB, 0, 0, 0)
+DO_SMLAX(SMULBT, 0, 0, 1)
+DO_SMLAX(SMULTB, 0, 1, 0)
+DO_SMLAX(SMULTT, 0, 1, 1)
+
+DO_SMLAX(SMLABB, 1, 0, 0)
+DO_SMLAX(SMLABT, 1, 0, 1)
+DO_SMLAX(SMLATB, 1, 1, 0)
+DO_SMLAX(SMLATT, 1, 1, 1)
+
+DO_SMLAX(SMLALBB, 2, 0, 0)
+DO_SMLAX(SMLALBT, 2, 0, 1)
+DO_SMLAX(SMLALTB, 2, 1, 0)
+DO_SMLAX(SMLALTT, 2, 1, 1)
+
+#undef DO_SMLAX
+
+static bool op_smlawx(DisasContext *s, arg_ *a, bool add, bool mt)
+{
+TCGv_i32 t0, t1;
+
+if (!ENABLE_ARCH_5TE) {
+return false;
+}
+
+t0 = load_reg(s, a->rn);
+t1 = load_reg(s, a->rm);
+/*
+ * Since the nominal result is product<47:16>, shift the 16-bit
+ * input up by 16 bits, so that the result is at product<63:32>.
+ */
+if (mt) {
+tcg_gen_andi_i32(t1, t1, 0x);
+} else {
+tcg_gen_shli_i32(t1, t1, 16);
+}
+tcg_gen_muls2_i32(t0, t1, t0, t1);
+tcg_temp_free_i32(t0);
+if (add) {
+t0 = load_reg(s, a->ra);
+gen_helper_add_setq(t1, cpu_env, t1, t0);
+tcg_temp_free_i32(t0);
+}
+store_reg(s, a->rd, t1);
+return true;
+}
+
+#define DO_SMLAWX(NAME, add, mt) \
+static bool trans_##NAME(DisasContext *s, arg_ *a) \
+{  \
+return op_smlawx(s, a, add, mt);   \
+}
+
+DO_SMLAWX(SMULWB, 0, 0)
+DO_SMLAWX(SMULWT, 0, 1)
+DO_SMLAWX(SMLAWB, 1, 0)
+DO_SMLAWX(SMLAWT, 1, 1)
+
+#undef DO_SMLAWX
+
 /*
  * Legacy decoder.
  */
@@ -8680,56 +8788,13 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 }
 break;
 }
-case 0x8: /* signed multiply */
+case 0x8:
 case 0xa:
 case 0xc:
 case 0xe:
-ARCH(5TE);
-rs = (insn >> 8) & 0xf;
-rn = (insn >> 12) & 0xf;
-rd = (insn >> 16) & 0xf;
-if (op1 == 1) {
-/* (32 * 16) >> 16 */
-tmp = load_reg(s, rm);
-tmp2 = load_reg(s, rs);
-if (sh & 4)
-tcg_gen_sari_i32(tmp2, tmp2, 16);
-else
-gen_sxth(tmp2);
-tmp64 = gen_muls_i64_i32(tmp, tmp2);
-tcg_gen_shri_i64(tmp64, tmp64, 16);
-tmp = tcg_temp_new_i32();
-tcg_gen_extrl_i64_i32(tmp, tmp64);
-tcg_temp_free_i64(tmp64);
-if ((sh & 2) == 0) {
-tmp2 = load_reg(s, rn);
-gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
-tcg_temp_free_i32(tmp2);
-}
-store_reg(s, rd, tmp);
-} else {
-/* 16 * 16 */
-tmp = load_reg(s, rm);
-tmp2 = load_reg(s, rs);
-gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
-tcg_temp_free_i32(tmp2);
-if (op1 == 2) {
-tmp64 = tcg_temp_new_i64();
-tcg_gen_ext_i32_i64(tmp64, tmp);
-tcg_temp_free_i32(tmp);
-gen_addq(s, tmp64, rn, rd);
-gen_storeq_reg(s, rn, rd, tmp64);
-tcg_temp_free_i64(tmp64);
-} else {
-

[Qemu-devel] [PATCH 19/67] target/arm: Convert Cyclic Redundancy Check

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 121 +++--
 target/arm/a32.decode  |   9 +++
 target/arm/t32.decode  |   7 +++
 3 files changed, 72 insertions(+), 65 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index fa0c048b38..ed7041d0e4 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8362,6 +8362,57 @@ static bool trans_MSR_imm(DisasContext *s, arg_MSR_imm 
*a)
 return true;
 }
 
+/*
+ * Cyclic Redundancy Check
+ */
+
+static bool op_crc32(DisasContext *s, arg_rrr *a, bool c, TCGMemOp sz)
+{
+TCGv_i32 t1, t2, t3;
+
+if (!dc_isar_feature(aa32_crc32, s)) {
+return false;
+}
+
+t1 = load_reg(s, a->rn);
+t2 = load_reg(s, a->rm);
+switch (sz) {
+case MO_8:
+gen_uxtb(t2);
+break;
+case MO_16:
+gen_uxth(t2);
+break;
+case MO_32:
+break;
+default:
+g_assert_not_reached();
+}
+t3 = tcg_const_i32(1 << sz);
+if (c) {
+gen_helper_crc32c(t1, t1, t2, t3);
+} else {
+gen_helper_crc32(t1, t1, t2, t3);
+}
+tcg_temp_free_i32(t2);
+tcg_temp_free_i32(t3);
+store_reg(s, a->rd, t1);
+return true;
+}
+
+#define DO_CRC32(NAME, c, sz) \
+static bool trans_##NAME(DisasContext *s, arg_rrr *a)  \
+{ return op_crc32(s, a, c, sz); }
+
+DO_CRC32(CRC32B, false, MO_8)
+DO_CRC32(CRC32H, false, MO_16)
+DO_CRC32(CRC32W, false, MO_32)
+DO_CRC32(CRC32CB, true, MO_8)
+DO_CRC32(CRC32CH, true, MO_16)
+DO_CRC32(CRC32CW, true, MO_32)
+
+#undef DO_CRC32
+
 /*
  * Miscellaneous instructions
  */
@@ -8774,39 +8825,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 gen_bx(s, tmp);
 break;
 case 0x4:
-{
-/* crc32/crc32c */
-uint32_t c = extract32(insn, 8, 4);
-
-/* Check this CPU supports ARMv8 CRC instructions.
- * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
- * Bits 8, 10 and 11 should be zero.
- */
-if (!dc_isar_feature(aa32_crc32, s) || op1 == 0x3 || (c & 0xd) != 
0) {
-goto illegal_op;
-}
-
-rn = extract32(insn, 16, 4);
-rd = extract32(insn, 12, 4);
-
-tmp = load_reg(s, rn);
-tmp2 = load_reg(s, rm);
-if (op1 == 0) {
-tcg_gen_andi_i32(tmp2, tmp2, 0xff);
-} else if (op1 == 1) {
-tcg_gen_andi_i32(tmp2, tmp2, 0x);
-}
-tmp3 = tcg_const_i32(1 << op1);
-if (c & 0x2) {
-gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
-} else {
-gen_helper_crc32(tmp, tmp, tmp2, tmp3);
-}
-tcg_temp_free_i32(tmp2);
-tcg_temp_free_i32(tmp3);
-store_reg(s, rd, tmp);
-break;
-}
+/* crc32 */
+/* All done in decodetree.  Illegal ops reach here.  */
+goto illegal_op;
 case 0x5:
 /* Saturating addition and subtraction.  */
 /* All done in decodetree.  Reach here for illegal ops.  */
@@ -10256,16 +10277,13 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 goto illegal_op;
 }
 break;
-case 0x20: /* crc32/crc32c */
+case 0x20: /* crc32/crc32c, in decodetree */
 case 0x21:
 case 0x22:
 case 0x28:
 case 0x29:
 case 0x2a:
-if (!dc_isar_feature(aa32_crc32, s)) {
-goto illegal_op;
-}
-break;
+goto illegal_op;
 default:
 goto illegal_op;
 }
@@ -10294,33 +10312,6 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 case 0x18: /* clz */
 tcg_gen_clzi_i32(tmp, tmp, 32);
 break;
-case 0x20:
-case 0x21:
-case 0x22:
-case 0x28:
-case 0x29:
-case 0x2a:
-{
-/* crc32/crc32c */
-uint32_t sz = op & 0x3;
-uint32_t c = op & 0x8;
-
-tmp2 = load_reg(s, rm);
-if (sz == 0) {
-tcg_gen_andi_i32(tmp2, tmp2, 0xff);
-} else if (sz == 1) {
-tcg_gen_andi_i32(tmp2, tmp2, 0x);
-}
-tmp3 = tcg_const_i32(1 << sz);
-if (c) {
-gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
-} else {
-gen_helper_crc32(tmp, tmp, tmp2, tmp3);
-}
-

[Qemu-devel] [PATCH 27/67] target/arm: Convert Signed multiply, signed and unsigned divide

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 471 ++---
 target/arm/a32.decode  |  22 ++
 target/arm/t32.decode  |  18 ++
 3 files changed, 248 insertions(+), 263 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 11e74135fd..5bdec27265 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9512,17 +9512,218 @@ static bool trans_RBIT(DisasContext *s, arg_rr *a)
 return op_rr(s, a, gen_helper_rbit);
 }
 
+/*
+ * Signed multiply, signed and unsigned divide
+ */
+
+static bool op_smlad(DisasContext *s, arg_ *a, bool m_swap, bool sub)
+{
+TCGv_i32 t1, t2;
+
+if (!ENABLE_ARCH_6) {
+return false;
+}
+
+t1 = load_reg(s, a->rn);
+t2 = load_reg(s, a->rm);
+if (m_swap) {
+gen_swap_half(t2);
+}
+gen_smul_dual(t1, t2);
+
+if (sub) {
+/* This subtraction cannot overflow. */
+tcg_gen_sub_i32(t1, t1, t2);
+} else {
+/*
+ * This addition cannot overflow 32 bits; however it may
+ * overflow considered as a signed operation, in which case
+ * we must set the Q flag.
+ */
+gen_helper_add_setq(t1, cpu_env, t1, t2);
+}
+tcg_temp_free_i32(t2);
+
+if (a->ra != 15) {
+t2 = load_reg(s, a->ra);
+gen_helper_add_setq(t1, cpu_env, t1, t2);
+tcg_temp_free_i32(t2);
+}
+store_reg(s, a->rd, t1);
+return true;
+}
+
+static bool trans_SMLAD(DisasContext *s, arg_ *a)
+{
+return op_smlad(s, a, false, false);
+}
+
+static bool trans_SMLADX(DisasContext *s, arg_ *a)
+{
+return op_smlad(s, a, true, false);
+}
+
+static bool trans_SMLSD(DisasContext *s, arg_ *a)
+{
+return op_smlad(s, a, false, true);
+}
+
+static bool trans_SMLSDX(DisasContext *s, arg_ *a)
+{
+return op_smlad(s, a, true, true);
+}
+
+static bool op_smlald(DisasContext *s, arg_ *a, bool m_swap, bool sub)
+{
+TCGv_i32 t1, t2;
+TCGv_i64 l1, l2;
+
+if (!ENABLE_ARCH_6) {
+return false;
+}
+
+t1 = load_reg(s, a->rn);
+t2 = load_reg(s, a->rm);
+if (m_swap) {
+gen_swap_half(t2);
+}
+gen_smul_dual(t1, t2);
+
+l1 = tcg_temp_new_i64();
+l2 = tcg_temp_new_i64();
+tcg_gen_ext_i32_i64(l1, t1);
+tcg_gen_ext_i32_i64(l2, t2);
+tcg_temp_free_i32(t1);
+tcg_temp_free_i32(t2);
+
+if (sub) {
+tcg_gen_sub_i64(l1, l1, l2);
+} else {
+tcg_gen_add_i64(l1, l1, l2);
+}
+tcg_temp_free_i64(l2);
+
+gen_addq(s, l1, a->ra, a->rd);
+gen_storeq_reg(s, a->ra, a->rd, l1);
+tcg_temp_free_i64(l1);
+return true;
+}
+
+static bool trans_SMLALD(DisasContext *s, arg_ *a)
+{
+return op_smlald(s, a, false, false);
+}
+
+static bool trans_SMLALDX(DisasContext *s, arg_ *a)
+{
+return op_smlald(s, a, true, false);
+}
+
+static bool trans_SMLSLD(DisasContext *s, arg_ *a)
+{
+return op_smlald(s, a, false, true);
+}
+
+static bool trans_SMLSLDX(DisasContext *s, arg_ *a)
+{
+return op_smlald(s, a, true, true);
+}
+
+static bool op_smmla(DisasContext *s, arg_ *a, bool round, bool sub)
+{
+TCGv_i32 t1, t2;
+TCGv_i64 tmp64;
+
+if (s->thumb
+? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
+: !ENABLE_ARCH_6) {
+return false;
+}
+
+t1 = load_reg(s, a->rn);
+t2 = load_reg(s, a->rm);
+tmp64 = gen_muls_i64_i32(t1, t2);
+
+if (a->ra != 15) {
+t1 = load_reg(s, a->ra);
+if (sub) {
+tmp64 = gen_subq_msw(tmp64, t1);
+} else {
+tmp64 = gen_addq_msw(tmp64, t1);
+}
+}
+if (round) {
+tcg_gen_addi_i64(tmp64, tmp64, 0x8000u);
+}
+t1 = tcg_temp_new_i32();
+tcg_gen_extrh_i64_i32(t1, tmp64);
+tcg_temp_free_i64(tmp64);
+store_reg(s, a->rd, t1);
+return true;
+}
+
+static bool trans_SMMLA(DisasContext *s, arg_ *a)
+{
+return op_smmla(s, a, false, false);
+}
+
+static bool trans_SMMLAR(DisasContext *s, arg_ *a)
+{
+return op_smmla(s, a, true, false);
+}
+
+static bool trans_SMMLS(DisasContext *s, arg_ *a)
+{
+return op_smmla(s, a, false, true);
+}
+
+static bool trans_SMMLSR(DisasContext *s, arg_ *a)
+{
+return op_smmla(s, a, true, true);
+}
+
+static bool op_div(DisasContext *s, arg_rrr *a, bool u)
+{
+TCGv_i32 t1, t2;
+
+if (s->thumb
+? !dc_isar_feature(thumb_div, s)
+: !dc_isar_feature(arm_div, s)) {
+return false;
+}
+
+t1 = load_reg(s, a->rn);
+t2 = load_reg(s, a->rm);
+if (u) {
+gen_helper_udiv(t1, t1, t2);
+} else {
+gen_helper_sdiv(t1, t1, t2);
+}
+tcg_temp_free_i32(t2);
+store_reg(s, a->rd, t1);
+return true;
+}
+
+static bool trans_SDIV(DisasContext *s, arg_rrr *a)
+{
+return op_div(s, a, false);
+}
+
+static bool trans_UDIV(DisasContext *s, arg_rrr *a)
+{
+return op_div(s, a, true);
+}
+
 /*
  * Legacy decoder.
 

[Qemu-devel] [PATCH 45/67] target/arm: Convert T16 load/store (register offset)

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 51 ++
 target/arm/t16.decode  | 15 +
 2 files changed, 17 insertions(+), 49 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 17a0eea425..7b87621315 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10754,55 +10754,8 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 goto illegal_op;
 
 case 5:
-/* load/store register offset.  */
-rd = insn & 7;
-rn = (insn >> 3) & 7;
-rm = (insn >> 6) & 7;
-op = (insn >> 9) & 7;
-addr = load_reg(s, rn);
-tmp = load_reg(s, rm);
-tcg_gen_add_i32(addr, addr, tmp);
-tcg_temp_free_i32(tmp);
-
-if (op < 3) { /* store */
-tmp = load_reg(s, rd);
-} else {
-tmp = tcg_temp_new_i32();
-}
-
-switch (op) {
-case 0: /* str */
-gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
-break;
-case 1: /* strh */
-gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
-break;
-case 2: /* strb */
-gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
-break;
-case 3: /* ldrsb */
-gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
-break;
-case 4: /* ldr */
-gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | 
ISSIs16Bit);
-break;
-case 5: /* ldrh */
-gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | 
ISSIs16Bit);
-break;
-case 6: /* ldrb */
-gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
-break;
-case 7: /* ldrsh */
-gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | 
ISSIs16Bit);
-break;
-}
-if (op >= 3) { /* load */
-store_reg(s, rd, tmp);
-} else {
-tcg_temp_free_i32(tmp);
-}
-tcg_temp_free_i32(addr);
-break;
+/* load/store register offset, in decodetree */
+goto illegal_op;
 
 case 6:
 /* load/store word immediate offset */
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 9833fc97e7..567c5005d6 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -23,6 +23,7 @@
 _rrr_shr   !extern s rn rd rm rs shty
 _rri_rot   !extern s rn rd imm rot
 _  !extern s rd rn rm ra
+_rr !extern p w u rn rt rm shimm shtype
 
 # Set S if the instruction is outside of an IT block.
 %s   !function=t16_setflags
@@ -54,3 +55,17 @@ ORR_rrri 01 1100 ... ...@lll_noshr
 MUL  01 1101 rn:3 rd:3  _ %s rm=%reg_0 ra=0
 BIC_rrri 01 1110 ... ...@lll_noshr
 MVN_rrri 01  ... ...@lll_noshr
+
+# Load/store (register offset)
+
+@ldst_rr ... rm:3 rn:3 rt:3 \
+ _rr p=1 w=0 u=1 shimm=0 shtype=0
+
+STR_rr   0101 000 ... ... ...   @ldst_rr
+STRH_rr  0101 001 ... ... ...   @ldst_rr
+STRB_rr  0101 010 ... ... ...   @ldst_rr
+LDRSB_rr 0101 011 ... ... ...   @ldst_rr
+LDR_rr   0101 100 ... ... ...   @ldst_rr
+LDRH_rr  0101 101 ... ... ...   @ldst_rr
+LDRB_rr  0101 110 ... ... ...   @ldst_rr
+LDRSH_rr 0101 111 ... ... ...   @ldst_rr
-- 
2.17.1




[Qemu-devel] [PATCH 24/67] target/arm: Convert USAD8, USADA8, SBFX, UBFX, BFC, BFI, UDF

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 201 +
 target/arm/a32.decode  |  20 
 target/arm/t32.decode  |  19 
 3 files changed, 144 insertions(+), 96 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 74e54b7efb..bcc890c458 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9186,6 +9186,104 @@ static bool trans_LDAH(DisasContext *s, arg_LDA *a)
 return op_lda(s, a, MO_UW);
 }
 
+/*
+ * Media instructions
+ */
+
+static bool trans_USADA8(DisasContext *s, arg_USADA8 *a)
+{
+TCGv_i32 t1, t2;
+
+if (!ENABLE_ARCH_6) {
+return false;
+}
+
+t1 = load_reg(s, a->rn);
+t2 = load_reg(s, a->rm);
+gen_helper_usad8(t1, t1, t2);
+tcg_temp_free_i32(t2);
+if (a->ra != 15) {
+t2 = load_reg(s, a->ra);
+tcg_gen_add_i32(t1, t1, t2);
+tcg_temp_free_i32(t2);
+}
+store_reg(s, a->rd, t1);
+return true;
+}
+
+static bool op_bfx(DisasContext *s, arg_UBFX *a, bool u)
+{
+TCGv_i32 tmp;
+int width = a->widthm1 + 1;
+int shift = a->lsb;
+
+if (!ENABLE_ARCH_6T2) {
+return false;
+}
+
+tmp = load_reg(s, a->rn);
+if (shift + width > 32) {
+gen_illegal_op(s);
+} else if (width < 32) {
+if (u) {
+tcg_gen_extract_i32(tmp, tmp, shift, width);
+} else {
+tcg_gen_sextract_i32(tmp, tmp, shift, width);
+}
+}
+store_reg(s, a->rd, tmp);
+return true;
+}
+
+static bool trans_SBFX(DisasContext *s, arg_SBFX *a)
+{
+return op_bfx(s, a, false);
+}
+
+static bool trans_UBFX(DisasContext *s, arg_UBFX *a)
+{
+return op_bfx(s, a, true);
+}
+
+static bool trans_BFCI(DisasContext *s, arg_BFCI *a)
+{
+TCGv_i32 tmp;
+int msb = a->msb, lsb = a->lsb;
+int width;
+
+if (!ENABLE_ARCH_6T2) {
+return false;
+}
+
+if (msb < lsb) {
+/* UNPREDICTABLE; we choose to UNDEF */
+gen_illegal_op(s);
+return true;
+}
+
+width = msb + 1 - lsb;
+if (a->rn == 15) {
+/* BFC */
+tmp = tcg_const_i32(0);
+} else {
+/* BFI */
+tmp = load_reg(s, a->rn);
+}
+if (width != 32) {
+TCGv_i32 tmp2 = load_reg(s, a->rd);
+tcg_gen_deposit_i32(tmp, tmp2, tmp, lsb, width);
+tcg_temp_free_i32(tmp2);
+}
+store_reg(s, a->rd, tmp);
+return true;
+}
+
+static bool trans_UDF(DisasContext *s, arg_UDF *a)
+{
+gen_illegal_op(s);
+return true;
+}
+
 /*
  * Legacy decoder.
  */
@@ -9723,65 +9821,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 }
 break;
 case 3:
-op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
-switch (op1) {
-case 0: /* Unsigned sum of absolute differences.  */
-ARCH(6);
-tmp = load_reg(s, rm);
-tmp2 = load_reg(s, rs);
-gen_helper_usad8(tmp, tmp, tmp2);
-tcg_temp_free_i32(tmp2);
-if (rd != 15) {
-tmp2 = load_reg(s, rd);
-tcg_gen_add_i32(tmp, tmp, tmp2);
-tcg_temp_free_i32(tmp2);
-}
-store_reg(s, rn, tmp);
-break;
-case 0x20: case 0x24: case 0x28: case 0x2c:
-/* Bitfield insert/clear.  */
-ARCH(6T2);
-shift = (insn >> 7) & 0x1f;
-i = (insn >> 16) & 0x1f;
-if (i < shift) {
-/* UNPREDICTABLE; we choose to UNDEF */
-goto illegal_op;
-}
-i = i + 1 - shift;
-if (rm == 15) {
-tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, 0);
-} else {
-tmp = load_reg(s, rm);
-}
-if (i != 32) {
-tmp2 = load_reg(s, rd);
-tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
-tcg_temp_free_i32(tmp2);
-}
-store_reg(s, rd, tmp);
-break;
-case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
-case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
-ARCH(6T2);
-tmp = load_reg(s, rm);
-shift = (insn >> 7) & 0x1f;
-i = ((insn >> 16) & 0x1f) + 1;
-if (shift + i > 32)
-goto illegal_op;

[Qemu-devel] [PATCH 37/67] target/arm: Convert Unallocated memory hint

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c   | 8 
 target/arm/a32-uncond.decode | 8 
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 5366741d7b..87cbadc6cb 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10227,14 +10227,6 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 }
 return;
 }
-if (((insn & 0x0f70) == 0x0410) ||
-((insn & 0x0f700010) == 0x0610)) {
-if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
-goto illegal_op;
-}
-return; /* v7MP: Unallocated memory hint: must NOP */
-}
-
 if ((insn & 0x0e000f00) == 0x0c000100) {
 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
 /* iWMMXt register transfer.  */
diff --git a/target/arm/a32-uncond.decode b/target/arm/a32-uncond.decode
index aed381cb8e..afa95bf7aa 100644
--- a/target/arm/a32-uncond.decode
+++ b/target/arm/a32-uncond.decode
@@ -64,3 +64,11 @@ PLI   0100 -101     
# (imm, lit) 7
 PLD   0111 -101   - -- 0    # (register) 5te
 PLDW  0111 -001   - -- 0    # (register) 7mp
 PLI   0110 -101   - -- 0    # (register) 7
+
+# Unallocated memory hints
+#
+# Since these are v7MP nops, and PLDW is v7MP and implemented as nop,
+# (ab)use the PLDW helper.
+
+PLDW  0100 -001     
+PLDW  0110 -001    ---0 
-- 
2.17.1




[Qemu-devel] [PATCH 36/67] target/arm: Convert PLI, PLD, PLDW

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c   | 37 +++-
 target/arm/a32-uncond.decode | 10 ++
 2 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 1d07caa62a..5366741d7b 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10147,6 +10147,26 @@ static bool trans_SETEND(DisasContext *s, arg_SETEND 
*a)
 return true;
 }
 
+/*
+ * Preload instructions
+ * All are nops, contingent on the appropriate arch level.
+ */
+
+static bool trans_PLD(DisasContext *s, arg_PLD *a)
+{
+return ENABLE_ARCH_5TE;
+}
+
+static bool trans_PLDW(DisasContext *s, arg_PLD *a)
+{
+return arm_dc_feature(s, ARM_FEATURE_V7MP);
+}
+
+static bool trans_PLI(DisasContext *s, arg_PLD *a)
+{
+return ENABLE_ARCH_7;
+}
+
 /*
  * Legacy decoder.
  */
@@ -10207,23 +10227,6 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 }
 return;
 }
-if (((insn & 0x0f30f000) == 0x0510f000) ||
-((insn & 0x0f30f010) == 0x0710f000)) {
-if ((insn & (1 << 22)) == 0) {
-/* PLDW; v7MP */
-if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
-goto illegal_op;
-}
-}
-/* Otherwise PLD; v5TE+ */
-ARCH(5TE);
-return;
-}
-if (((insn & 0x0f70f000) == 0x0450f000) ||
-((insn & 0x0f70f010) == 0x0650f000)) {
-ARCH(7);
-return; /* PLI; V7 */
-}
 if (((insn & 0x0f70) == 0x0410) ||
 ((insn & 0x0f700010) == 0x0610)) {
 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
diff --git a/target/arm/a32-uncond.decode b/target/arm/a32-uncond.decode
index d5ed48f0fd..aed381cb8e 100644
--- a/target/arm/a32-uncond.decode
+++ b/target/arm/a32-uncond.decode
@@ -54,3 +54,13 @@ SB    0101 0111    0111 
 
 # Set Endianness
 SETEND    0001  0001  00 E:1 0    
+
+# Preload instructions
+
+PLD   0101 -101     # (imm, lit) 5te
+PLDW  0101 -001     # (imm, lit) 7mp
+PLI   0100 -101     # (imm, lit) 7
+
+PLD   0111 -101   - -- 0    # (register) 5te
+PLDW  0111 -001   - -- 0    # (register) 7mp
+PLI   0110 -101   - -- 0    # (register) 7
-- 
2.17.1




[Qemu-devel] [PATCH 22/67] target/arm: Convert load/store (register, immediate, literal)

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 793 ++---
 target/arm/a32.decode  | 120 +++
 target/arm/t32.decode  | 141 
 3 files changed, 611 insertions(+), 443 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index d19131d594..73cb624ebd 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1293,62 +1293,6 @@ static inline void gen_hlt(DisasContext *s, int imm)
 gen_illegal_op(s);
 }
 
-static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
-   TCGv_i32 var)
-{
-int val, rm, shift, shiftop;
-TCGv_i32 offset;
-
-if (!(insn & (1 << 25))) {
-/* immediate */
-val = insn & 0xfff;
-if (!(insn & (1 << 23)))
-val = -val;
-if (val != 0)
-tcg_gen_addi_i32(var, var, val);
-} else {
-/* shift/register */
-rm = (insn) & 0xf;
-shift = (insn >> 7) & 0x1f;
-shiftop = (insn >> 5) & 3;
-offset = load_reg(s, rm);
-gen_arm_shift_im(offset, shiftop, shift, 0);
-if (!(insn & (1 << 23)))
-tcg_gen_sub_i32(var, var, offset);
-else
-tcg_gen_add_i32(var, var, offset);
-tcg_temp_free_i32(offset);
-}
-}
-
-static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
-int extra, TCGv_i32 var)
-{
-int val, rm;
-TCGv_i32 offset;
-
-if (insn & (1 << 22)) {
-/* immediate */
-val = (insn & 0xf) | ((insn >> 4) & 0xf0);
-if (!(insn & (1 << 23)))
-val = -val;
-val += extra;
-if (val != 0)
-tcg_gen_addi_i32(var, var, val);
-} else {
-/* register */
-if (extra)
-tcg_gen_addi_i32(var, var, extra);
-rm = (insn) & 0xf;
-offset = load_reg(s, rm);
-if (!(insn & (1 << 23)))
-tcg_gen_sub_i32(var, var, offset);
-else
-tcg_gen_add_i32(var, var, offset);
-tcg_temp_free_i32(offset);
-}
-}
-
 static TCGv_ptr get_fpstatus_ptr(int neon)
 {
 TCGv_ptr statusptr = tcg_temp_new_ptr();
@@ -7693,6 +7637,11 @@ static int times_2(DisasContext *s, int x)
 return x * 2;
 }
 
+static int times_4(DisasContext *s, int x)
+{
+return x * 4;
+}
+
 /* Return only the rotation part of T32ExpandImm.  */
 static int t32_expandimm_rot(DisasContext *s, int x)
 {
@@ -8606,6 +8555,341 @@ static bool trans_SMC(DisasContext *s, arg_SMC *a)
 return true;
 }
 
+/*
+ * Load/store register index
+ */
+
+static ISSInfo make_issinfo(DisasContext *s, int rd, bool p, bool w)
+{
+ISSInfo ret;
+
+/* ISS not valid if writeback */
+if (p & !w) {
+ret = rd;
+} else {
+ret = ISSInvalid;
+}
+return ret;
+}
+
+static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
+{
+TCGv_i32 addr = load_reg(s, a->rn);
+
+if (s->v8m_stackcheck && a->rn == 13 && a->w) {
+gen_helper_v8m_stackcheck(cpu_env, addr);
+}
+
+if (a->p) {
+TCGv_i32 ofs = load_reg(s, a->rm);
+gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
+if (a->u) {
+tcg_gen_add_i32(addr, addr, ofs);
+} else {
+tcg_gen_sub_i32(addr, addr, ofs);
+}
+tcg_temp_free_i32(ofs);
+}
+return addr;
+}
+
+static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
+TCGv_i32 addr, int address_offset)
+{
+if (!a->p) {
+TCGv_i32 ofs = load_reg(s, a->rm);
+gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
+if (a->u) {
+tcg_gen_add_i32(addr, addr, ofs);
+} else {
+tcg_gen_sub_i32(addr, addr, ofs);
+}
+tcg_temp_free_i32(ofs);
+} else if (!a->w) {
+tcg_temp_free_i32(addr);
+return;
+}
+tcg_gen_addi_i32(addr, addr, address_offset);
+store_reg(s, a->rn, addr);
+}
+
+static bool op_load_rr(DisasContext *s, arg_ldst_rr *a,
+   TCGMemOp mop, int mem_idx)
+{
+ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
+TCGv_i32 addr, tmp;
+
+addr = op_addr_rr_pre(s, a);
+
+tmp = tcg_temp_new_i32();
+gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop | s->be_data);
+disas_set_da_iss(s, mop, issinfo);
+
+/*
+ * Perform base writeback before the loaded value to
+ * ensure correct behavior with overlapping index registers.
+ */
+op_addr_rr_post(s, a, addr, 0);
+store_reg_from_load(s, a->rt, tmp);
+return true;
+}
+
+static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
+TCGMemOp mop, int mem_idx)
+{
+ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
+TCGv_i32 addr, tmp;
+
+addr = op_addr_rr_pre(s, a);
+
+tmp = load_reg(s, a->rt);
+gen_aa32_st_i32(s, tmp, addr, mem_idx, mop | s->be_data);
+

[Qemu-devel] [PATCH 29/67] target/arm: Convert LDM, STM

2019-07-26 Thread Richard Henderson
While unifying all of these paths, remove the constrained unpredictable
test for "wback && registers == 1" from the T2 encoding that isn't
constrained unpredictable for the A1 encoding.  The A1 behaviour is
allowed for the T2 behaviour.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 388 -
 target/arm/a32.decode  |   6 +
 target/arm/t32.decode  |  10 ++
 3 files changed, 206 insertions(+), 198 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index ee97a0ccdd..33daf70d5d 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9742,6 +9742,192 @@ static bool trans_UDIV(DisasContext *s, arg_rrr *a)
 return op_div(s, a, true);
 }
 
+/*
+ * Block data transfer
+ */
+
+static TCGv_i32 op_addr_block_pre(DisasContext *s, arg_ldst_block *a, int n)
+{
+TCGv_i32 addr = load_reg(s, a->rn);
+
+if (a->b) {
+if (a->i) {
+/* pre increment */
+tcg_gen_addi_i32(addr, addr, 4);
+} else {
+/* pre decrement */
+tcg_gen_addi_i32(addr, addr, -(n * 4));
+}
+} else if (!a->i && n != 1) {
+/* post decrement */
+tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
+}
+
+if (s->v8m_stackcheck && a->rn == 13 && a->w) {
+/*
+ * If the writeback is incrementing SP rather than
+ * decrementing it, and the initial SP is below the
+ * stack limit but the final written-back SP would
+ * be above, then then we must not perform any memory
+ * accesses, but it is IMPDEF whether we generate
+ * an exception. We choose to do so in this case.
+ * At this point 'addr' is the lowest address, so
+ * either the original SP (if incrementing) or our
+ * final SP (if decrementing), so that's what we check.
+ */
+gen_helper_v8m_stackcheck(cpu_env, addr);
+}
+
+return addr;
+}
+
+static void op_addr_block_post(DisasContext *s, arg_ldst_block *a,
+   TCGv_i32 addr, int n)
+{
+if (a->w) {
+/* write back */
+if (!a->b) {
+if (a->i) {
+/* post increment */
+tcg_gen_addi_i32(addr, addr, 4);
+} else {
+/* post decrement */
+tcg_gen_addi_i32(addr, addr, -(n * 4));
+}
+} else if (!a->i && n != 1) {
+/* pre decrement */
+tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
+}
+store_reg(s, a->rn, addr);
+} else {
+tcg_temp_free_i32(addr);
+}
+}
+
+static bool trans_STM(DisasContext *s, arg_ldst_block *a)
+{
+int i, j, n, list, mem_idx;
+TCGv_i32 addr, tmp, tmp2;
+bool user = a->u;
+
+if (user) {
+/* STM (user) */
+if (IS_USER(s)) {
+/* Only usable in supervisor mode.  */
+return false;
+}
+}
+
+/* compute total size */
+list = a->list;
+n = ctpop16(list);
+mem_idx = get_mem_index(s);
+
+addr = op_addr_block_pre(s, a, n);
+for (i = j = 0; i < 16; i++) {
+if (((list >> i) & 1) == 0) {
+continue;
+}
+if (user && i != 15) {
+tmp = tcg_temp_new_i32();
+tmp2 = tcg_const_i32(i);
+gen_helper_get_user_reg(tmp, cpu_env, tmp2);
+tcg_temp_free_i32(tmp2);
+} else {
+tmp = load_reg(s, i);
+}
+gen_aa32_st32(s, tmp, addr, mem_idx);
+tcg_temp_free_i32(tmp);
+/* No need to add after the last transfer.  */
+if (++j != n) {
+tcg_gen_addi_i32(addr, addr, 4);
+}
+}
+
+op_addr_block_post(s, a, addr, n);
+return true;
+}
+
+static bool trans_LDM(DisasContext *s, arg_ldst_block *a)
+{
+int i, j, n, mem_idx, loaded_base;
+int list = a->list;
+bool user = a->u;
+bool exc_return = false;
+TCGv_i32 addr, tmp, tmp2, loaded_var;
+
+if (user) {
+/* LDM (user), LDM (exception return) */
+if (IS_USER(s)) {
+/* Only usable in supervisor mode.  */
+return false;
+}
+if (extract32(a->list, 15, 1)) {
+exc_return = true;
+user = false;
+} else {
+/* LDM (User) does not allow W set.  */
+if (a->w) {
+return false;
+}
+}
+}
+
+/* compute total size */
+loaded_base = 0;
+loaded_var = NULL;
+n = ctpop16(list);
+mem_idx = get_mem_index(s);
+
+addr = op_addr_block_pre(s, a, n);
+for (i = j = 0; i < 16; i++) {
+if (((list >> i) & 1) == 0) {
+continue;
+}
+tmp = tcg_temp_new_i32();
+gen_aa32_ld32u(s, tmp, addr, mem_idx);
+if (user) {
+tmp2 = tcg_const_i32(i);
+gen_helper_set_user_reg(cpu_env, tmp2, tmp);
+tcg_temp_free_i32(tmp2);
+

[Qemu-devel] [PATCH 50/67] target/arm: Convert T16 one low register and immediate

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 44 ++
 target/arm/t16.decode  | 11 +++
 2 files changed, 13 insertions(+), 42 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 692891dbe0..9bdcb91537 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10594,48 +10594,8 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 store_reg(s, rd, tmp);
 }
 break;
-case 2: case 3:
-/*
- * 0b001x___
- *  - Add, subtract, compare, move (one low register and immediate)
- */
-op = (insn >> 11) & 3;
-rd = (insn >> 8) & 0x7;
-if (op == 0) { /* mov */
-tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, insn & 0xff);
-if (!s->condexec_mask)
-gen_logic_CC(tmp);
-store_reg(s, rd, tmp);
-} else {
-tmp = load_reg(s, rd);
-tmp2 = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp2, insn & 0xff);
-switch (op) {
-case 1: /* cmp */
-gen_sub_CC(tmp, tmp, tmp2);
-tcg_temp_free_i32(tmp);
-tcg_temp_free_i32(tmp2);
-break;
-case 2: /* add */
-if (s->condexec_mask)
-tcg_gen_add_i32(tmp, tmp, tmp2);
-else
-gen_add_CC(tmp, tmp, tmp2);
-tcg_temp_free_i32(tmp2);
-store_reg(s, rd, tmp);
-break;
-case 3: /* sub */
-if (s->condexec_mask)
-tcg_gen_sub_i32(tmp, tmp, tmp2);
-else
-gen_sub_CC(tmp, tmp, tmp2);
-tcg_temp_free_i32(tmp2);
-store_reg(s, rd, tmp);
-break;
-}
-}
-break;
+case 2: case 3: /* add, sub, cmp, mov (reg, imm), in decodetree */
+goto illegal_op;
 case 4:
 if (insn & (1 << 11)) {
 rd = (insn >> 8) & 7;
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 965fb1bf6e..edb67a3896 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -133,3 +133,14 @@ SUB_rrri0001101 ... ... ... @addsub_3
 
 ADD_rri 0001 110 ... ... ...@addsub_2i
 SUB_rri 0001 111 ... ... ...@addsub_2i
+
+# Add, subtract, compare, move (one low register and immediate)
+
+%reg_8  8:3
+@arith_1i   . rd:3 imm:8 \
+_rri_rot rot=0 rn=%reg_8
+
+MOV_rri 00100 ...   @arith_1i %s
+CMP_rri 00101 ...   @arith_1i s=1
+ADD_rri 00110 ...   @arith_1i %s
+SUB_rri 00111 ...   @arith_1i %s
-- 
2.17.1




[Qemu-devel] [PATCH 28/67] target/arm: Convert MOVW, MOVT

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 89 --
 target/arm/a32.decode  |  6 +++
 target/arm/t32.decode  |  9 +
 3 files changed, 48 insertions(+), 56 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 5bdec27265..ee97a0ccdd 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7919,6 +7919,34 @@ static bool trans_ADR(DisasContext *s, arg_ri *a)
 return true;
 }
 
+static bool trans_MOVW(DisasContext *s, arg_MOVW *a)
+{
+TCGv_i32 tmp;
+
+if (!ENABLE_ARCH_6T2) {
+return false;
+}
+
+tmp = tcg_const_i32(a->imm);
+store_reg(s, a->rd, tmp);
+return true;
+}
+
+static bool trans_MOVT(DisasContext *s, arg_MOVW *a)
+{
+TCGv_i32 tmp;
+
+if (!ENABLE_ARCH_6T2) {
+return false;
+}
+
+tmp = load_reg(s, a->rd);
+tcg_gen_ext16u_i32(tmp, tmp);
+tcg_gen_ori_i32(tmp, tmp, a->imm << 16);
+store_reg(s, a->rd, tmp);
+return true;
+}
+
 /*
  * Multiply and multiply accumulate
  */
@@ -9720,7 +9748,7 @@ static bool trans_UDIV(DisasContext *s, arg_rrr *a)
 
 static void disas_arm_insn(DisasContext *s, unsigned int insn)
 {
-unsigned int cond, val, op1, i, rn, rd;
+unsigned int cond, val, op1, i, rn;
 TCGv_i32 tmp;
 TCGv_i32 tmp2;
 TCGv_i32 addr;
@@ -9966,26 +9994,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 /* fall back to legacy decoder */
 
 if ((insn & 0x0f90) == 0x0300) {
-if ((insn & (1 << 21)) == 0) {
-ARCH(6T2);
-rd = (insn >> 12) & 0xf;
-val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
-if ((insn & (1 << 22)) == 0) {
-/* MOVW */
-tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, val);
-} else {
-/* MOVT */
-tmp = load_reg(s, rd);
-tcg_gen_ext16u_i32(tmp, tmp);
-tcg_gen_ori_i32(tmp, tmp, val << 16);
-}
-store_reg(s, rd, tmp);
-} else {
-/* MSR (immediate) and hints */
-/* All done in decodetree.  Illegal ops already signalled.  */
-g_assert_not_reached();
-}
+/* All done in decodetree.  Illegal ops reach here.  */
+goto illegal_op;
 } else if ((insn & 0x0f90) == 0x0100
&& (insn & 0x0090) != 0x0090) {
 /* miscellaneous instructions */
@@ -10725,42 +10735,9 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 /*
  * 0b_0xxx__0xxx__
  *  - Data-processing (modified immediate, plain binary immediate)
+ * All in decodetree.
  */
-if (insn & (1 << 25)) {
-/*
- * 0b_0x1x__0xxx__
- *  - Data-processing (plain binary immediate)
- */
-if (insn & (1 << 24)) {
-/* Bitfield/Saturate, in decodetree */
-goto illegal_op;
-} else {
-imm = ((insn & 0x0400) >> 15)
-  | ((insn & 0x7000) >> 4) | (insn & 0xff);
-if (insn & (1 << 22)) {
-/* 16-bit immediate.  */
-imm |= (insn >> 4) & 0xf000;
-if (insn & (1 << 23)) {
-/* movt */
-tmp = load_reg(s, rd);
-tcg_gen_ext16u_i32(tmp, tmp);
-tcg_gen_ori_i32(tmp, tmp, imm << 16);
-} else {
-/* movw */
-tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, imm);
-}
-store_reg(s, rd, tmp);
-} else {
-/* Add/sub 12-bit immediate, in decodetree */
-goto illegal_op;
-}
-}
-} else {
-/* Data-processing (modified immediate) */
-/* All done in decodetree.  Reach here for illegal ops.  */
-goto illegal_op;
-}
+goto illegal_op;
 }
 break;
 case 12:
diff --git a/target/arm/a32.decode b/target/arm/a32.decode
index c5af685585..02d7e5b202 100644
--- a/target/arm/a32.decode
+++ b/target/arm/a32.decode
@@ -73,6 +73,12 @@ MOV_rrri  000 1101 .   . .. 0    
 @s_rxr_shi
 BIC_rrri  000 1110 .   . .. 0 @s_rrr_shi
 MVN_rrri  000  .   . .. 0 @s_rxr_shi
 
+%imm16   16:4 0:12
+@mov16       rd:4  imm=%imm16
+
+MOVW  0011    @mov16
+MOVT

[Qemu-devel] [PATCH 46/67] target/arm: Convert T16 load/store (immediate offset)

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 94 +++---
 target/arm/t16.decode  | 33 +++
 2 files changed, 38 insertions(+), 89 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 7b87621315..28f274ca7c 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10753,97 +10753,13 @@ static void disas_thumb_insn(DisasContext *s, 
uint32_t insn)
  */
 goto illegal_op;
 
-case 5:
-/* load/store register offset, in decodetree */
+case 5: /* load/store register offset, in decodetree */
+case 6: /* load/store word immediate offset, in decodetree */
+case 7: /* load/store byte immediate offset, in decodetree */
+case 8: /* load/store halfword immediate offset, in decodetree */
+case 9: /* load/store from stack, in decodetree */
 goto illegal_op;
 
-case 6:
-/* load/store word immediate offset */
-rd = insn & 7;
-rn = (insn >> 3) & 7;
-addr = load_reg(s, rn);
-val = (insn >> 4) & 0x7c;
-tcg_gen_addi_i32(addr, addr, val);
-
-if (insn & (1 << 11)) {
-/* load */
-tmp = tcg_temp_new_i32();
-gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
-store_reg(s, rd, tmp);
-} else {
-/* store */
-tmp = load_reg(s, rd);
-gen_aa32_st32(s, tmp, addr, get_mem_index(s));
-tcg_temp_free_i32(tmp);
-}
-tcg_temp_free_i32(addr);
-break;
-
-case 7:
-/* load/store byte immediate offset */
-rd = insn & 7;
-rn = (insn >> 3) & 7;
-addr = load_reg(s, rn);
-val = (insn >> 6) & 0x1f;
-tcg_gen_addi_i32(addr, addr, val);
-
-if (insn & (1 << 11)) {
-/* load */
-tmp = tcg_temp_new_i32();
-gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
-store_reg(s, rd, tmp);
-} else {
-/* store */
-tmp = load_reg(s, rd);
-gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
-tcg_temp_free_i32(tmp);
-}
-tcg_temp_free_i32(addr);
-break;
-
-case 8:
-/* load/store halfword immediate offset */
-rd = insn & 7;
-rn = (insn >> 3) & 7;
-addr = load_reg(s, rn);
-val = (insn >> 5) & 0x3e;
-tcg_gen_addi_i32(addr, addr, val);
-
-if (insn & (1 << 11)) {
-/* load */
-tmp = tcg_temp_new_i32();
-gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | 
ISSIs16Bit);
-store_reg(s, rd, tmp);
-} else {
-/* store */
-tmp = load_reg(s, rd);
-gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
-tcg_temp_free_i32(tmp);
-}
-tcg_temp_free_i32(addr);
-break;
-
-case 9:
-/* load/store from stack */
-rd = (insn >> 8) & 7;
-addr = load_reg(s, 13);
-val = (insn & 0xff) * 4;
-tcg_gen_addi_i32(addr, addr, val);
-
-if (insn & (1 << 11)) {
-/* load */
-tmp = tcg_temp_new_i32();
-gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | 
ISSIs16Bit);
-store_reg(s, rd, tmp);
-} else {
-/* store */
-tmp = load_reg(s, rd);
-gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
-tcg_temp_free_i32(tmp);
-}
-tcg_temp_free_i32(addr);
-break;
-
 case 10:
 /*
  * 0b1010___
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index 567c5005d6..797e4e7068 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -24,6 +24,7 @@
 _rri_rot   !extern s rn rd imm rot
 _  !extern s rd rn rm ra
 _rr !extern p w u rn rt rm shimm shtype
+_ri !extern p w u rn rt imm
 
 # Set S if the instruction is outside of an IT block.
 %s   !function=t16_setflags
@@ -69,3 +70,35 @@ LDR_rr   0101 100 ... ... ...   @ldst_rr
 LDRH_rr  0101 101 ... ... ...   @ldst_rr
 LDRB_rr  0101 110 ... ... ...   @ldst_rr
 LDRSH_rr 0101 111 ... ... ...   @ldst_rr
+
+# Load/store word/byte (immediate offset)
+
+%imm5_6x4   6:5 !function=times_4
+
+@ldst_ri_1  . imm:5 rn:3 rt:3 \
+_ri p=1 w=0 u=1
+@ldst_ri_4  . . rn:3 rt:3 \
+_ri p=1 w=0 u=1 imm=%imm5_6x4
+
+STR_ri  01100 . ... ... @ldst_ri_4
+LDR_ri  01101 . ... ... @ldst_ri_4
+STRB_ri 01110 . ... ... @ldst_ri_1
+LDRB_ri 0 . ... ... @ldst_ri_1
+
+# Load/store halfword (immediate offset)
+
+%imm5_6x2   6:5 !function=times_2
+@ldst_ri_2  . 

[Qemu-devel] [PATCH 26/67] target/arm: Convert Packing, unpacking, saturation, and reversal

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 554 +
 target/arm/a32.decode  |  32 +++
 target/arm/t32.decode  |  37 ++-
 3 files changed, 302 insertions(+), 321 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 8f2b5dcb02..11e74135fd 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -364,7 +364,7 @@ static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
 }
 
 /* Byteswap each halfword.  */
-static void gen_rev16(TCGv_i32 var)
+static void gen_rev16(TCGv_i32 dest, TCGv_i32 var)
 {
 TCGv_i32 tmp = tcg_temp_new_i32();
 TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
@@ -372,17 +372,17 @@ static void gen_rev16(TCGv_i32 var)
 tcg_gen_and_i32(tmp, tmp, mask);
 tcg_gen_and_i32(var, var, mask);
 tcg_gen_shli_i32(var, var, 8);
-tcg_gen_or_i32(var, var, tmp);
+tcg_gen_or_i32(dest, var, tmp);
 tcg_temp_free_i32(mask);
 tcg_temp_free_i32(tmp);
 }
 
 /* Byteswap low halfword and sign extend.  */
-static void gen_revsh(TCGv_i32 var)
+static void gen_revsh(TCGv_i32 dest, TCGv_i32 var)
 {
 tcg_gen_ext16u_i32(var, var);
 tcg_gen_bswap16_i32(var, var);
-tcg_gen_ext16s_i32(var, var);
+tcg_gen_ext16s_i32(dest, var);
 }
 
 /* Return (b << 32) + a. Mark inputs as dead */
@@ -467,7 +467,7 @@ static void gen_swap_half(TCGv_i32 var)
 t0 = (t0 + t1) ^ tmp;
  */
 
-static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
+static void gen_add16(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
 {
 TCGv_i32 tmp = tcg_temp_new_i32();
 tcg_gen_xor_i32(tmp, t0, t1);
@@ -475,9 +475,8 @@ static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
 tcg_gen_andi_i32(t0, t0, ~0x8000);
 tcg_gen_andi_i32(t1, t1, ~0x8000);
 tcg_gen_add_i32(t0, t0, t1);
-tcg_gen_xor_i32(t0, t0, tmp);
+tcg_gen_xor_i32(dest, t0, tmp);
 tcg_temp_free_i32(tmp);
-tcg_temp_free_i32(t1);
 }
 
 /* Set N and Z flags from var.  */
@@ -6390,7 +6389,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t 
insn)
 }
 break;
 case NEON_2RM_VREV16:
-gen_rev16(tmp);
+gen_rev16(tmp, tmp);
 break;
 case NEON_2RM_VCLS:
 switch (size) {
@@ -9299,16 +9298,229 @@ DO_PAR_ADDSUB(UHSUB8, gen_helper_uhsub8)
 #undef DO_PAR_ADDSUB
 #undef DO_PAR_ADDSUB_GE
 
+/*
+ * Packing, unpacking, saturation, and reversal
+ */
+
+static bool trans_PKH(DisasContext *s, arg_PKH *a)
+{
+TCGv_i32 tn, tm;
+int shift = a->imm;
+
+if (s->thumb
+? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
+: !ENABLE_ARCH_6) {
+return false;
+}
+
+tn = load_reg(s, a->rn);
+tm = load_reg(s, a->rm);
+if (a->tb) {
+/* PKHTB */
+if (shift == 0) {
+shift = 31;
+}
+tcg_gen_sari_i32(tm, tm, shift);
+tcg_gen_deposit_i32(tn, tn, tm, 0, 16);
+} else {
+/* PKHBT */
+tcg_gen_shli_i32(tm, tm, shift);
+tcg_gen_deposit_i32(tn, tm, tn, 0, 16);
+}
+tcg_temp_free_i32(tm);
+store_reg(s, a->rd, tn);
+return true;
+}
+
+static bool op_sat(DisasContext *s, arg_sat *a,
+   void (*gen)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
+{
+TCGv_i32 tmp, satimm;
+int shift = a->imm;
+
+if (!ENABLE_ARCH_6) {
+return false;
+}
+
+tmp = load_reg(s, a->rn);
+if (a->sh) {
+tcg_gen_sari_i32(tmp, tmp, shift ? shift : 31);
+} else {
+tcg_gen_shli_i32(tmp, tmp, shift);
+}
+
+satimm = tcg_const_i32(a->satimm);
+gen(tmp, cpu_env, tmp, satimm);
+tcg_temp_free_i32(satimm);
+
+store_reg(s, a->rd, tmp);
+return true;
+}
+
+static bool trans_SSAT(DisasContext *s, arg_sat *a)
+{
+return op_sat(s, a, gen_helper_ssat);
+}
+
+static bool trans_USAT(DisasContext *s, arg_sat *a)
+{
+return op_sat(s, a, gen_helper_usat);
+}
+
+static bool trans_SSAT16(DisasContext *s, arg_sat *a)
+{
+if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
+return false;
+}
+return op_sat(s, a, gen_helper_ssat16);
+}
+
+static bool trans_USAT16(DisasContext *s, arg_sat *a)
+{
+if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
+return false;
+}
+return op_sat(s, a, gen_helper_usat16);
+}
+
+static bool op_xta(DisasContext *s, arg_rrr_rot *a,
+   void (*gen_extract)(TCGv_i32, TCGv_i32),
+   void (*gen_add)(TCGv_i32, TCGv_i32, TCGv_i32))
+{
+TCGv_i32 tmp;
+
+if (!ENABLE_ARCH_6) {
+return false;
+}
+
+tmp = load_reg(s, a->rm);
+/*
+ * TODO: In many cases we could do a shift instead of a rotate.
+ * Combined with a simple extend, that becomes an extract.
+ */
+if (a->rot != 0) {
+tcg_gen_rotri_i32(tmp, tmp, a->rot * 8);
+}
+gen_extract(tmp, 

[Qemu-devel] [PATCH 23/67] target/arm: Convert Synchronization primitives

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 560 ++---
 target/arm/a32.decode  |  48 
 target/arm/t32.decode  |  46 
 3 files changed, 396 insertions(+), 258 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 73cb624ebd..74e54b7efb 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8890,6 +8890,302 @@ DO_LDST(STRH, store, MO_UW)
 
 #undef DO_LDST
 
+/*
+ * Synchronization primitives
+ */
+
+static bool op_swp(DisasContext *s, arg_SWP *a, TCGMemOp opc)
+{
+TCGv_i32 addr, tmp;
+TCGv taddr;
+
+opc |= s->be_data;
+addr = load_reg(s, a->rn);
+taddr = gen_aa32_addr(s, addr, opc);
+tcg_temp_free_i32(addr);
+
+tmp = load_reg(s, a->rt2);
+tcg_gen_atomic_xchg_i32(tmp, taddr, tmp, get_mem_index(s), opc);
+tcg_temp_free(taddr);
+
+store_reg(s, a->rt, tmp);
+return true;
+}
+
+static bool trans_SWP(DisasContext *s, arg_SWP *a)
+{
+return op_swp(s, a, MO_UL | MO_ALIGN);
+}
+
+static bool trans_SWPB(DisasContext *s, arg_SWP *a)
+{
+return op_swp(s, a, MO_UB);
+}
+
+/*
+ * Load/Store Exclusive and Load-Acquire/Store-Release
+ */
+
+static bool op_strex(DisasContext *s, arg_STREX *a, TCGMemOp mop, bool rel)
+{
+TCGv_i32 addr;
+
+if (rel) {
+tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
+}
+
+addr = tcg_temp_local_new_i32();
+load_reg_var(s, addr, a->rn);
+tcg_gen_addi_i32(addr, addr, a->imm);
+
+gen_store_exclusive(s, a->rd, a->rt, a->rt2, addr, mop);
+tcg_temp_free_i32(addr);
+return true;
+}
+
+static bool trans_STREX(DisasContext *s, arg_STREX *a)
+{
+if (!ENABLE_ARCH_6) {
+return false;
+}
+return op_strex(s, a, MO_32, false);
+}
+
+static bool trans_STREXD_a32(DisasContext *s, arg_STREX *a)
+{
+if (!ENABLE_ARCH_6K || (a->rt & 1)) {
+return false;
+}
+a->rt2 = a->rt + 1;
+return op_strex(s, a, MO_64, false);
+}
+
+static bool trans_STREXD_t32(DisasContext *s, arg_STREX *a)
+{
+return op_strex(s, a, MO_64, false);
+}
+
+static bool trans_STREXB(DisasContext *s, arg_STREX *a)
+{
+if (!ENABLE_ARCH_6K) {
+return false;
+}
+return op_strex(s, a, MO_8, false);
+}
+
+static bool trans_STREXH(DisasContext *s, arg_STREX *a)
+{
+if (!ENABLE_ARCH_6K) {
+return false;
+}
+return op_strex(s, a, MO_16, false);
+}
+
+static bool trans_STLEX(DisasContext *s, arg_STREX *a)
+{
+if (!ENABLE_ARCH_8) {
+return false;
+}
+return op_strex(s, a, MO_32, true);
+}
+
+static bool trans_STLEXD_a32(DisasContext *s, arg_STREX *a)
+{
+if (!ENABLE_ARCH_8 || (a->rt & 1)) {
+return false;
+}
+a->rt2 = a->rt + 1;
+return op_strex(s, a, MO_64, true);
+}
+
+static bool trans_STLEXD_t32(DisasContext *s, arg_STREX *a)
+{
+if (!ENABLE_ARCH_8) {
+return false;
+}
+return op_strex(s, a, MO_64, true);
+}
+
+static bool trans_STLEXB(DisasContext *s, arg_STREX *a)
+{
+if (!ENABLE_ARCH_8) {
+return false;
+}
+return op_strex(s, a, MO_8, true);
+}
+
+static bool trans_STLEXH(DisasContext *s, arg_STREX *a)
+{
+if (!ENABLE_ARCH_8) {
+return false;
+}
+return op_strex(s, a, MO_16, true);
+}
+
+static bool op_stl(DisasContext *s, arg_STL *a, TCGMemOp mop)
+{
+TCGv_i32 addr, tmp;
+
+if (!ENABLE_ARCH_8) {
+return false;
+}
+addr = load_reg(s, a->rn);
+
+tmp = load_reg(s, a->rt);
+tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
+gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), mop | s->be_data);
+disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel | ISSIsWrite);
+
+tcg_temp_free_i32(tmp);
+tcg_temp_free_i32(addr);
+return true;
+}
+
+static bool trans_STL(DisasContext *s, arg_STL *a)
+{
+return op_stl(s, a, MO_UL);
+}
+
+static bool trans_STLB(DisasContext *s, arg_STL *a)
+{
+return op_stl(s, a, MO_UB);
+}
+
+static bool trans_STLH(DisasContext *s, arg_STL *a)
+{
+return op_stl(s, a, MO_UW);
+}
+
+static bool op_ldrex(DisasContext *s, arg_LDREX *a, TCGMemOp mop, bool acq)
+{
+TCGv_i32 addr;
+
+addr = tcg_temp_local_new_i32();
+load_reg_var(s, addr, a->rn);
+tcg_gen_addi_i32(addr, addr, a->imm);
+
+gen_load_exclusive(s, a->rt, a->rt2, addr, mop);
+tcg_temp_free_i32(addr);
+
+if (acq) {
+tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
+}
+return true;
+}
+
+static bool trans_LDREX(DisasContext *s, arg_LDREX *a)
+{
+if (!ENABLE_ARCH_6) {
+return false;
+}
+return op_ldrex(s, a, MO_32, false);
+}
+
+static bool trans_LDREXD_a32(DisasContext *s, arg_LDREX *a)
+{
+if (!ENABLE_ARCH_6K || (a->rt & 1)) {
+return false;
+}
+a->rt2 = a->rt + 1;
+return op_ldrex(s, a, MO_64, false);
+}
+
+static bool trans_LDREXD_t32(DisasContext *s, arg_LDREX *a)
+{
+return op_ldrex(s, a, MO_64, false);
+}
+
+static bool trans_LDREXB(DisasContext *s, arg_LDREX *a)
+{
+if 

[Qemu-devel] [PATCH 15/67] target/arm: Convert Saturating addition and subtraction

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/helper.h|  1 -
 target/arm/op_helper.c | 15 -
 target/arm/translate.c | 74 +++---
 target/arm/a32.decode  | 10 ++
 target/arm/t32.decode  |  9 +
 5 files changed, 66 insertions(+), 43 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index 132aa1682e..1fb2cb5a77 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -6,7 +6,6 @@ DEF_HELPER_3(add_saturate, i32, env, i32, i32)
 DEF_HELPER_3(sub_saturate, i32, env, i32, i32)
 DEF_HELPER_3(add_usaturate, i32, env, i32, i32)
 DEF_HELPER_3(sub_usaturate, i32, env, i32, i32)
-DEF_HELPER_2(double_saturate, i32, env, s32)
 DEF_HELPER_FLAGS_2(sdiv, TCG_CALL_NO_RWG_SE, s32, s32, s32)
 DEF_HELPER_FLAGS_2(udiv, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_FLAGS_1(rbit, TCG_CALL_NO_RWG_SE, i32, i32)
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 1ab91f915e..142239b03a 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -135,21 +135,6 @@ uint32_t HELPER(sub_saturate)(CPUARMState *env, uint32_t 
a, uint32_t b)
 return res;
 }
 
-uint32_t HELPER(double_saturate)(CPUARMState *env, int32_t val)
-{
-uint32_t res;
-if (val >= 0x4000) {
-res = ~SIGNBIT;
-env->QF = 1;
-} else if (val <= (int32_t)0xc000) {
-res = SIGNBIT;
-env->QF = 1;
-} else {
-res = val << 1;
-}
-return res;
-}
-
 uint32_t HELPER(add_usaturate)(CPUARMState *env, uint32_t a, uint32_t b)
 {
 uint32_t res = a + b;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 354a52d36c..85f829c1bb 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8174,6 +8174,47 @@ static bool trans_UMAAL(DisasContext *s, arg_UMAAL *a)
 return true;
 }
 
+/*
+ * Saturating addition and subtraction
+ */
+
+static bool op_qaddsub(DisasContext *s, arg_rrr *a, bool add, bool doub)
+{
+TCGv_i32 t0, t1;
+
+if (s->thumb
+? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
+: !ENABLE_ARCH_5TE) {
+return false;
+}
+
+t0 = load_reg(s, a->rm);
+t1 = load_reg(s, a->rn);
+if (doub) {
+gen_helper_add_saturate(t1, cpu_env, t1, t1);
+}
+if (add) {
+gen_helper_add_saturate(t0, cpu_env, t0, t1);
+} else {
+gen_helper_sub_saturate(t0, cpu_env, t0, t1);
+}
+tcg_temp_free_i32(t1);
+store_reg(s, a->rd, t0);
+return true;
+}
+
+#define DO_QADDSUB(NAME, ADD, DOUB) \
+static bool trans_##NAME(DisasContext *s, arg_rrr *a)\
+{\
+return op_qaddsub(s, a, ADD, DOUB);  \
+}
+
+DO_QADDSUB(QADD, true, false)
+DO_QADDSUB(QSUB, false, false)
+DO_QADDSUB(QDADD, true, true)
+DO_QADDSUB(QDSUB, false, true)
+
+#undef DO_QADDSUB
 
 /*
  * Legacy decoder.
@@ -8582,21 +8623,10 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 store_reg(s, rd, tmp);
 break;
 }
-case 0x5: /* saturating add/subtract */
-ARCH(5TE);
-rd = (insn >> 12) & 0xf;
-rn = (insn >> 16) & 0xf;
-tmp = load_reg(s, rm);
-tmp2 = load_reg(s, rn);
-if (op1 & 2)
-gen_helper_double_saturate(tmp2, cpu_env, tmp2);
-if (op1 & 1)
-gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
-else
-gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
-tcg_temp_free_i32(tmp2);
-store_reg(s, rd, tmp);
-break;
+case 0x5:
+/* Saturating addition and subtraction.  */
+/* All done in decodetree.  Reach here for illegal ops.  */
+goto illegal_op;
 case 0x6: /* ERET */
 if (op1 != 3) {
 goto illegal_op;
@@ -10070,18 +10100,8 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
 if (op < 4) {
 /* Saturating add/subtract.  */
-if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
-goto illegal_op;
-}
-tmp = load_reg(s, rn);
-tmp2 = load_reg(s, rm);
-if (op & 1)
-gen_helper_double_saturate(tmp, cpu_env, tmp);
-if (op & 2)
-gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
-else
-gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
-tcg_temp_free_i32(tmp2);
+/* All done in decodetree.  Reach here for illegal ops.  */
+goto illegal_op;
 } else {
 switch (op) {
 case 0x0a: /* rbit */
diff --git a/target/arm/a32.decode b/target/arm/a32.decode
index 71846b79fd..af6712a9e8 100644
--- a/target/arm/a32.decode
+++ 

[Qemu-devel] [PATCH 09/67] target/arm: Fold a pc load into load_reg

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index e316eeb312..53c46fcdc4 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9161,11 +9161,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 }
 } else {
 /* store */
-if (i == 15) {
-/* special case: r15 = PC + 8 */
-tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, s->pc_read);
-} else if (user) {
+if (user && i != 15) {
 tmp = tcg_temp_new_i32();
 tmp2 = tcg_const_i32(i);
 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
-- 
2.17.1




[Qemu-devel] [PATCH 13/67] target/arm: Convert Data Processing (reg, reg-shifted-reg, imm)

2019-07-26 Thread Richard Henderson
Do these all in one lump because these are all logically intertwined.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 747 -
 target/arm/a32.decode  |  84 +
 target/arm/t32.decode  |  91 +
 3 files changed, 536 insertions(+), 386 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 0f21ee9ce7..ee7d53dfa5 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -480,12 +480,6 @@ static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
 tcg_temp_free_i32(t1);
 }
 
-/* Set CF to the top bit of var.  */
-static void gen_set_CF_bit31(TCGv_i32 var)
-{
-tcg_gen_shri_i32(cpu_CF, var, 31);
-}
-
 /* Set N and Z flags from var.  */
 static inline void gen_logic_CC(TCGv_i32 var)
 {
@@ -905,25 +899,6 @@ void arm_gen_test_cc(int cc, TCGLabel *label)
 arm_free_cc();
 }
 
-static const uint8_t table_logic_cc[16] = {
-1, /* and */
-1, /* xor */
-0, /* sub */
-0, /* rsb */
-0, /* add */
-0, /* adc */
-0, /* sbc */
-0, /* rsc */
-1, /* andl */
-1, /* xorl */
-0, /* cmp */
-0, /* cmn */
-1, /* orr */
-1, /* mov */
-1, /* bic */
-1, /* mvn */
-};
-
 static inline void gen_set_condexec(DisasContext *s)
 {
 if (s->condexec_mask) {
@@ -7719,6 +7694,49 @@ static void arm_skip_unless(DisasContext *s, uint32_t 
cond)
 }
 }
 
+/*
+ * Constant expanders for the decoders.
+ */
+
+static int times_2(DisasContext *s, int x)
+{
+return x * 2;
+}
+
+/* Return only the rotation part of T32ExpandImm.  */
+static int t32_expandimm_rot(DisasContext *s, int x)
+{
+return x & 0xc00 ? extract32(x, 7, 5) : 0;
+}
+
+/* Return the unrotated immediate from T32ExpandImm.  */
+static int t32_expandimm_imm(DisasContext *s, int x)
+{
+int imm = extract32(x, 0, 8);
+
+switch (extract32(x, 8, 4)) {
+case 0: /* XY */
+/* Nothing to do.  */
+break;
+case 1: /* 00XY00XY */
+imm |= imm << 16;
+break;
+case 2: /* XY00XY00 */
+imm |= imm << 16;
+imm <<= 8;
+break;
+case 3: /* XYXYXYXY */
+imm |= imm << 8;
+imm |= imm << 16;
+break;
+default:
+/* Rotated constant.  */
+imm |= 0x80;
+break;
+}
+return imm;
+}
+
 /*
  * Include the generated decoders.
  * Note that the T32 decoder reuses some of the trans_* functions
@@ -7742,6 +7760,314 @@ static void arm_skip_unless(DisasContext *s, uint32_t 
cond)
 # pragma GCC diagnostic pop
 #endif
 
+/* Helpers to swap operands for reverse-subtract.  */
+static void gen_rsb(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
+{
+tcg_gen_sub_i32(dst, b, a);
+}
+
+static void gen_rsb_CC(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
+{
+gen_sub_CC(dst, b, a);
+}
+
+static void gen_rsc(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
+{
+gen_sub_carry(dest, b, a);
+}
+
+static void gen_rsc_CC(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
+{
+gen_sbc_CC(dest, b, a);
+}
+
+/*
+ * Helper for the data processing routines.
+ * After the computation store the results back.
+ * This may be suppressed altogether (STREG_NONE), require a runtime
+ * check against the stack limits (STREG_SP_CHECK), or generate an
+ * exception return.  Oh, or store into a register.
+ */
+typedef enum {
+   STREG_NORMAL,
+   STREG_NONE,
+   STREG_SP_CHECK,
+   STREG_EXC_RET,
+} StoreRegKind;
+
+static bool store_reg_flags(DisasContext *s, int rd,
+TCGv_i32 val, StoreRegKind kind)
+{
+switch (kind) {
+case STREG_NORMAL:
+break;
+case STREG_NONE:
+tcg_temp_free_i32(val);
+return true;
+case STREG_SP_CHECK:
+if (rd == 13) {
+store_sp_checked(s, val);
+return true;
+}
+break;
+case STREG_EXC_RET:
+gen_exception_return(s, val);
+return true;
+default:
+g_assert_not_reached();
+}
+/* ALUWritePC: Interworking only from a32 mode. */
+if (s->thumb) {
+store_reg(s, rd, val);
+} else {
+store_reg_bx(s, rd, val);
+}
+return true;
+}
+
+/*
+ * Data Processing (register)
+ *
+ * Operate, with set flags, one register source,
+ * one immediate shifted register source, and a destination.
+ * Here, we return the result without storing into a destination.
+ */
+static TCGv_i32 op_s_rrr_shi(DisasContext *s, arg_s_rrr_shi *a,
+ void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
+ int logic_cc)
+{
+TCGv_i32 tmp1, tmp2;
+
+tmp2 = load_reg(s, a->rm);
+gen_arm_shift_im(tmp2, a->shty, a->shim, logic_cc);
+tmp1 = load_reg(s, a->rn);
+
+gen(tmp1, tmp1, tmp2);
+tcg_temp_free_i32(tmp2);
+
+if (logic_cc) {
+gen_logic_CC(tmp1);
+}
+return tmp1;
+}
+
+static TCGv_i32 op_s_rxr_shi(DisasContext *s, arg_s_rrr_shi *a,
+ void (*gen)(TCGv_i32, TCGv_i32),
+ int 

[Qemu-devel] [PATCH 35/67] target/arm: Convert SETEND

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c   | 22 +-
 target/arm/a32-uncond.decode |  4 
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 8dbe189df7..1d07caa62a 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10135,6 +10135,18 @@ static bool trans_SB(DisasContext *s, arg_SB *a)
 return true;
 }
 
+static bool trans_SETEND(DisasContext *s, arg_SETEND *a)
+{
+if (!ENABLE_ARCH_6) {
+return false;
+}
+if (a->E != (s->be_data == MO_BE)) {
+gen_helper_setend(cpu_env);
+s->base.is_jmp = DISAS_UPDATE;
+}
+return true;
+}
+
 /*
  * Legacy decoder.
  */
@@ -10220,15 +10232,7 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 return; /* v7MP: Unallocated memory hint: must NOP */
 }
 
-if ((insn & 0x0dff) == 0x0101) {
-ARCH(6);
-/* setend */
-if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
-gen_helper_setend(cpu_env);
-s->base.is_jmp = DISAS_UPDATE;
-}
-return;
-} else if ((insn & 0x0e000f00) == 0x0c000100) {
+if ((insn & 0x0e000f00) == 0x0c000100) {
 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
 /* iWMMXt register transfer.  */
 if (extract32(s->c15_cpar, 1, 1)) {
diff --git a/target/arm/a32-uncond.decode b/target/arm/a32-uncond.decode
index eb1c55b330..d5ed48f0fd 100644
--- a/target/arm/a32-uncond.decode
+++ b/target/arm/a32-uncond.decode
@@ -24,6 +24,7 @@
 
!extern
!extern imm
+  E
 
 # Branch with Link and Exchange
 
@@ -50,3 +51,6 @@ DSB   0101 0111    0100 
 DMB   0101 0111    0101 
 ISB   0101 0111    0110 
 SB    0101 0111    0111 
+
+# Set Endianness
+SETEND    0001  0001  00 E:1 0    
-- 
2.17.1




[Qemu-devel] [PATCH 20/67] target/arm: Convert the rest of A32 Miscelaneous instructions

2019-07-26 Thread Richard Henderson
This fixes an exiting bug with the T5 encoding of SUBS PC, LR, #IMM,
in that it may be executed from user mode as with any other encoding
of SUBS, not as ERET.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 273 +++--
 target/arm/a32.decode  |  21 
 target/arm/t32.decode  |  20 +++
 3 files changed, 143 insertions(+), 171 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index ed7041d0e4..09310b1c3a 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8500,6 +8500,101 @@ static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m 
*a)
 return true;
 }
 
+static bool trans_BX(DisasContext *s, arg_BX *a)
+{
+if (!ENABLE_ARCH_4T) {
+return false;
+}
+gen_bx(s, load_reg(s, a->rm));
+return true;
+}
+
+static bool trans_BXJ(DisasContext *s, arg_BXJ *a)
+{
+if (!ENABLE_ARCH_5J || arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+/* Trivial implementation equivalent to bx.  */
+gen_bx(s, load_reg(s, a->rm));
+return true;
+}
+
+static bool trans_BLX_r(DisasContext *s, arg_BLX_r *a)
+{
+TCGv_i32 tmp;
+
+if (!ENABLE_ARCH_5) {
+return false;
+}
+tmp = load_reg(s, a->rm);
+tcg_gen_movi_i32(cpu_R[14], s->pc | s->thumb);
+gen_bx(s, tmp);
+return true;
+}
+
+static bool trans_CLZ(DisasContext *s, arg_CLZ *a)
+{
+TCGv_i32 tmp;
+
+if (!ENABLE_ARCH_5) {
+return false;
+}
+tmp = load_reg(s, a->rm);
+tcg_gen_clzi_i32(tmp, tmp, 32);
+store_reg(s, a->rd, tmp);
+return true;
+}
+
+static bool trans_ERET(DisasContext *s, arg_ERET *a)
+{
+TCGv_i32 tmp;
+
+if (IS_USER(s) || !arm_dc_feature(s, ARM_FEATURE_V7VE)) {
+return false;
+}
+if (s->current_el == 2) {
+/* ERET from Hyp uses ELR_Hyp, not LR */
+tmp = load_cpu_field(elr_el[2]);
+} else {
+tmp = load_reg(s, 14);
+}
+gen_exception_return(s, tmp);
+return true;
+}
+
+static bool trans_HLT(DisasContext *s, arg_HLT *a)
+{
+gen_hlt(s, a->imm);
+return true;
+}
+
+static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
+{
+if (!ENABLE_ARCH_5) {
+return false;
+}
+gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
+return true;
+}
+
+static bool trans_HVC(DisasContext *s, arg_HVC *a)
+{
+if (!ENABLE_ARCH_7 || IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+gen_hvc(s, a->imm);
+return true;
+}
+
+static bool trans_SMC(DisasContext *s, arg_SMC *a)
+{
+if (!ENABLE_ARCH_6K || IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+gen_smc(s);
+return true;
+}
+
 /*
  * Legacy decoder.
  */
@@ -8777,124 +8872,8 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 } else if ((insn & 0x0f90) == 0x0100
&& (insn & 0x0090) != 0x0090) {
 /* miscellaneous instructions */
-op1 = (insn >> 21) & 3;
-sh = (insn >> 4) & 0xf;
-rm = insn & 0xf;
-switch (sh) {
-case 0x0:
-/* MSR/MRS (banked/register) */
-/* All done in decodetree.  Illegal ops already signalled.  */
-g_assert_not_reached();
-case 0x1:
-if (op1 == 1) {
-/* branch/exchange thumb (bx).  */
-ARCH(4T);
-tmp = load_reg(s, rm);
-gen_bx(s, tmp);
-} else if (op1 == 3) {
-/* clz */
-ARCH(5);
-rd = (insn >> 12) & 0xf;
-tmp = load_reg(s, rm);
-tcg_gen_clzi_i32(tmp, tmp, 32);
-store_reg(s, rd, tmp);
-} else {
-goto illegal_op;
-}
-break;
-case 0x2:
-if (op1 == 1) {
-ARCH(5J); /* bxj */
-/* Trivial implementation equivalent to bx.  */
-tmp = load_reg(s, rm);
-gen_bx(s, tmp);
-} else {
-goto illegal_op;
-}
-break;
-case 0x3:
-if (op1 != 1)
-  goto illegal_op;
-
-ARCH(5);
-/* branch link/exchange thumb (blx) */
-tmp = load_reg(s, rm);
-tmp2 = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp2, s->pc);
-store_reg(s, 14, tmp2);
-gen_bx(s, tmp);
-break;
-case 0x4:
-/* crc32 */
-/* All done in decodetree.  Illegal ops reach here.  */
-goto illegal_op;
-case 0x5:
-/* Saturating addition and subtraction.  */
-/* All done in decodetree.  Reach here for illegal ops.  */
-goto illegal_op;
-case 0x6: /* ERET */
-if (op1 != 3) {
-goto illegal_op;
-}
-if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
- 

[Qemu-devel] [PATCH 10/67] target/arm: Move test for AL into arm_skip_unless

2019-07-26 Thread Richard Henderson
We will shortly be calling this function much more often.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 28 
 1 file changed, 12 insertions(+), 16 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 53c46fcdc4..36419025db 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7705,8 +7705,14 @@ static void arm_gen_condlabel(DisasContext *s)
 /* Skip this instruction if the ARM condition is false */
 static void arm_skip_unless(DisasContext *s, uint32_t cond)
 {
-arm_gen_condlabel(s);
-arm_gen_test_cc(cond ^ 1, s->condlabel);
+/*
+ * Conditionally skip the insn. Note that both 0xe and 0xf mean
+ * "always"; 0xf is not "never".
+ */
+if (cond < 0xe) {
+arm_gen_condlabel(s);
+arm_gen_test_cc(cond ^ 1, s->condlabel);
+}
 }
 
 static void disas_arm_insn(DisasContext *s, unsigned int insn)
@@ -7944,11 +7950,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 }
 goto illegal_op;
 }
-if (cond != 0xe) {
-/* if not always execute, we generate a conditional jump to
-   next instruction */
-arm_skip_unless(s, cond);
-}
+
+arm_skip_unless(s, cond);
+
 if ((insn & 0x0f90) == 0x0300) {
 if ((insn & (1 << 21)) == 0) {
 ARCH(6T2);
@@ -12095,15 +12099,7 @@ static void thumb_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cpu)
 dc->insn = insn;
 
 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
-uint32_t cond = dc->condexec_cond;
-
-/*
- * Conditionally skip the insn. Note that both 0xe and 0xf mean
- * "always"; 0xf is not "never".
- */
-if (cond < 0x0e) {
-arm_skip_unless(dc, cond);
-}
+arm_skip_unless(dc, dc->condexec_cond);
 }
 
 if (is_16bit) {
-- 
2.17.1




[Qemu-devel] [PATCH 18/67] target/arm: Convert MRS/MSR (banked, register)

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 226 ++---
 target/arm/a32.decode  |  14 +++
 target/arm/t32.decode  |  40 ++--
 3 files changed, 142 insertions(+), 138 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 36c815caf3..fa0c048b38 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8362,6 +8362,93 @@ static bool trans_MSR_imm(DisasContext *s, arg_MSR_imm 
*a)
 return true;
 }
 
+/*
+ * Miscellaneous instructions
+ */
+
+static bool trans_MRS_bank(DisasContext *s, arg_MRS_bank *a)
+{
+if (arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+gen_mrs_banked(s, a->r, a->sysm, a->rd);
+return true;
+}
+
+static bool trans_MSR_bank(DisasContext *s, arg_MSR_bank *a)
+{
+if (arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+gen_msr_banked(s, a->r, a->sysm, a->rn);
+return true;
+}
+
+static bool trans_MRS_reg(DisasContext *s, arg_MRS_reg *a)
+{
+TCGv_i32 tmp;
+
+if (arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+if (a->r) {
+if (IS_USER(s)) {
+gen_illegal_op(s);
+return true;
+}
+tmp = load_cpu_field(spsr);
+} else {
+tmp = tcg_temp_new_i32();
+gen_helper_cpsr_read(tmp, cpu_env);
+}
+store_reg(s, a->rd, tmp);
+return true;
+}
+
+static bool trans_MSR_reg(DisasContext *s, arg_MSR_reg *a)
+{
+TCGv_i32 tmp;
+uint32_t mask = msr_mask(s, a->mask, a->r);
+
+if (arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+tmp = load_reg(s, a->rn);
+if (gen_set_psr(s, mask, a->r, tmp)) {
+gen_illegal_op(s);
+}
+return true;
+}
+
+static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
+{
+TCGv_i32 tmp;
+
+if (!arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+tmp = tcg_const_i32(a->sysm);
+gen_helper_v7m_mrs(tmp, cpu_env, tmp);
+store_reg(s, a->rd, tmp);
+return true;
+}
+
+static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
+{
+TCGv_i32 addr, reg;
+
+if (!arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+addr = tcg_const_i32((a->mask << 10) | a->sysm);
+reg = load_reg(s, a->rn);
+gen_helper_v7m_msr(cpu_env, addr, reg);
+tcg_temp_free_i32(addr);
+tcg_temp_free_i32(reg);
+gen_lookup_tb(s);
+return true;
+}
+
 /*
  * Legacy decoder.
  */
@@ -8643,46 +8730,10 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 sh = (insn >> 4) & 0xf;
 rm = insn & 0xf;
 switch (sh) {
-case 0x0: /* MSR, MRS */
-if (insn & (1 << 9)) {
-/* MSR (banked) and MRS (banked) */
-int sysm = extract32(insn, 16, 4) |
-(extract32(insn, 8, 1) << 4);
-int r = extract32(insn, 22, 1);
-
-if (op1 & 1) {
-/* MSR (banked) */
-gen_msr_banked(s, r, sysm, rm);
-} else {
-/* MRS (banked) */
-int rd = extract32(insn, 12, 4);
-
-gen_mrs_banked(s, r, sysm, rd);
-}
-break;
-}
-
-/* MSR, MRS (for PSRs) */
-if (op1 & 1) {
-/* PSR = reg */
-tmp = load_reg(s, rm);
-i = ((op1 & 2) != 0);
-if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
-goto illegal_op;
-} else {
-/* reg = PSR */
-rd = (insn >> 12) & 0xf;
-if (op1 & 2) {
-if (IS_USER(s))
-goto illegal_op;
-tmp = load_cpu_field(spsr);
-} else {
-tmp = tcg_temp_new_i32();
-gen_helper_cpsr_read(tmp, cpu_env);
-}
-store_reg(s, rd, tmp);
-}
-break;
+case 0x0:
+/* MSR/MRS (banked/register) */
+/* All done in decodetree.  Illegal ops already signalled.  */
+g_assert_not_reached();
 case 0x1:
 if (op1 == 1) {
 /* branch/exchange thumb (bx).  */
@@ -10559,40 +10610,9 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 } else {
 op = (insn >> 20) & 7;
 switch (op) {
-case 0: /* msr cpsr.  */
-if (arm_dc_feature(s, ARM_FEATURE_M)) {
-tmp = load_reg(s, rn);
-/* the constant is the mask and SYSm fields */
-addr = tcg_const_i32(insn & 0xfff);
-gen_helper_v7m_msr(cpu_env, addr, tmp);
-tcg_temp_free_i32(addr);
-   

[Qemu-devel] [PATCH 21/67] target/arm: Convert T32 ADDW/SUBW

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 24 +---
 target/arm/a32.decode  |  1 +
 target/arm/t32.decode  | 19 +++
 3 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 09310b1c3a..d19131d594 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7683,6 +7683,11 @@ static void arm_skip_unless(DisasContext *s, uint32_t 
cond)
  * Constant expanders for the decoders.
  */
 
+static int negate(DisasContext *s, int x)
+{
+return -x;
+}
+
 static int times_2(DisasContext *s, int x)
 {
 return x * 2;
@@ -8053,6 +8058,12 @@ static bool trans_ORN_rri(DisasContext *s, arg_s_rri_rot 
*a)
 #undef DO_ANY
 #undef DO_LOGIC
 
+static bool trans_ADR(DisasContext *s, arg_ri *a)
+{
+store_reg_bx(s, a->rd, add_reg_for_lit(s, 15, a->imm));
+return true;
+}
+
 /*
  * Multiply and multiply accumulate
  */
@@ -10758,17 +10769,8 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 }
 store_reg(s, rd, tmp);
 } else {
-/* Add/sub 12-bit immediate.  */
-if (insn & (1 << 23)) {
-imm = -imm;
-}
-tmp = add_reg_for_lit(s, rn, imm);
-if (rn == 13 && rd == 13) {
-/* ADD SP, SP, imm or SUB SP, SP, imm */
-store_sp_checked(s, tmp);
-} else {
-store_reg(s, rd, tmp);
-}
+/* Add/sub 12-bit immediate, in decodetree */
+goto illegal_op;
 }
 }
 } else {
diff --git a/target/arm/a32.decode b/target/arm/a32.decode
index 32d1833037..baae62dea9 100644
--- a/target/arm/a32.decode
+++ b/target/arm/a32.decode
@@ -30,6 +30,7 @@
 rd rn rm ra
  rd rn rm
   rd rm
+  rd imm
rm
imm
 _reg rn r mask
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
index abd233180d..69e81ef71a 100644
--- a/target/arm/t32.decode
+++ b/target/arm/t32.decode
@@ -27,6 +27,7 @@
 !extern rd rn rm ra
  !extern rd rn rm
   !extern rd rm
+  !extern rd imm
!extern rm
!extern imm
 _reg !extern rn r mask
@@ -121,6 +122,24 @@ SBC_rri   0.0 1011 .  0 ...    
   @s_rri_rot
 }
 RSB_rri   0.0 1110 .  0 ...   @s_rri_rot
 
+# Data processing (plain binary immediate)
+
+%imm12_26_12_0   26:1 12:3 0:8
+%neg12_26_12_0   26:1 12:3 0:8 !function=negate
+@s0_rri_12    ...  . rn:4 . ... rd:4  \
+ _rri_rot imm=%imm12_26_12_0 rot=0 s=0
+
+{
+  ADR 0.1  0  0 ... rd:4  \
+  imm=%imm12_26_12_0
+  ADD_rri 0.1  0  0 ...   @s0_rri_12
+}
+{
+  ADR 0.1 0101 0  0 ... rd:4  \
+  imm=%neg12_26_12_0
+  SUB_rri 0.1 0101 0  0 ...   @s0_rri_12
+}
+
 # Multiply and multiply accumulate
 
 @s0_rnadm   rn:4 ra:4 rd:4  rm:4  _ s=0
-- 
2.17.1




[Qemu-devel] [PATCH 08/67] target/arm: Use store_reg_from_load in thumb2 code

2019-07-26 Thread Richard Henderson
There is an extra always-true ARMv5 test, but this will
become more obvious once we start unifying the
implementation of A32+T32.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 12 +++-
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 5e2dd8bb16..e316eeb312 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9773,13 +9773,11 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 /* Load.  */
 tmp = tcg_temp_new_i32();
 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
-if (i == 15) {
-gen_bx_excret(s, tmp);
-} else if (i == rn) {
+if (i == rn) {
 loaded_var = tmp;
 loaded_base = 1;
 } else {
-store_reg(s, i, tmp);
+store_reg_from_load(s, i, tmp);
 }
 } else {
 /* Store.  */
@@ -10914,11 +10912,7 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 tcg_temp_free_i32(addr);
 goto illegal_op;
 }
-if (rs == 15) {
-gen_bx_excret(s, tmp);
-} else {
-store_reg(s, rs, tmp);
-}
+store_reg_from_load(s, rs, tmp);
 } else {
 /* Store.  */
 tmp = load_reg(s, rs);
-- 
2.17.1




[Qemu-devel] [PATCH 06/67] target/arm: Introduce pc_read

2019-07-26 Thread Richard Henderson
We currently have 3 different ways of computing the architectural
value of "PC" as seen in the ARM ARM.

The value of s->pc has been incremented past the current insn,
but that is all.  Thus for a32, PC = s->pc + 4; for t32, PC = s->pc;
for t16, PC = s->pc + 2.  These differing computations make it
impossible at present to unify the various code paths.

Let s->pc_read hold the architectural value of PC for all cases.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.h | 10 
 target/arm/translate.c | 53 ++
 2 files changed, 32 insertions(+), 31 deletions(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index a20f6e2056..2dfdd8ca66 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -9,7 +9,17 @@ typedef struct DisasContext {
 DisasContextBase base;
 const ARMISARegisters *isar;
 
+/*
+ * Summary of the various values for "PC":
+ * base.pc_next -- the start of the current insn
+ * pc   -- the start of the next insn
+ * pc_read  -- the value for "PC" in the ARM ARM;
+ * in arm mode, the current insn + 8;
+ * in thumb mode, the current insn + 4;
+ * in aa64 mode, unused.
+ */
 target_ulong pc;
+target_ulong pc_read;
 target_ulong page_start;
 uint32_t insn;
 /* Nonzero if this instruction has been conditionally skipped.  */
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 595385e1b1..a48e9a90f8 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -200,13 +200,7 @@ static inline void store_cpu_offset(TCGv_i32 var, int 
offset)
 static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
 {
 if (reg == 15) {
-uint32_t addr;
-/* normally, since we updated PC, we need only to add one insn */
-if (s->thumb)
-addr = (long)s->pc + 2;
-else
-addr = (long)s->pc + 4;
-tcg_gen_movi_i32(var, addr);
+tcg_gen_movi_i32(var, s->pc_read);
 } else {
 tcg_gen_mov_i32(var, cpu_R[reg]);
 }
@@ -7868,16 +7862,14 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 /* branch link and change to thumb (blx ) */
 int32_t offset;
 
-val = (uint32_t)s->pc;
 tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, val);
+tcg_gen_movi_i32(tmp, s->pc);
 store_reg(s, 14, tmp);
 /* Sign-extend the 24-bit offset */
 offset = (((int32_t)insn) << 8) >> 8;
+val = s->pc_read;
 /* offset * 4 + bit24 * 2 + (thumb bit) */
 val += (offset << 2) | ((insn >> 23) & 2) | 1;
-/* pipeline offset */
-val += 4;
 /* protected by ARCH(5); above, near the start of uncond block */
 gen_bx_im(s, val);
 return;
@@ -9154,9 +9146,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 /* store */
 if (i == 15) {
 /* special case: r15 = PC + 8 */
-val = (long)s->pc + 4;
 tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, val);
+tcg_gen_movi_i32(tmp, s->pc_read);
 } else if (user) {
 tmp = tcg_temp_new_i32();
 tmp2 = tcg_const_i32(i);
@@ -9222,14 +9213,13 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 int32_t offset;
 
 /* branch (and link) */
-val = (int32_t)s->pc;
 if (insn & (1 << 24)) {
 tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, val);
+tcg_gen_movi_i32(tmp, s->pc);
 store_reg(s, 14, tmp);
 }
 offset = sextract32(insn << 2, 0, 26);
-val += offset + 4;
+val = s->pc_read + offset;
 gen_jmp(s, val);
 }
 break;
@@ -9484,7 +9474,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 goto illegal_op;
 }
 addr = tcg_temp_new_i32();
-tcg_gen_movi_i32(addr, s->pc & ~3);
+tcg_gen_movi_i32(addr, s->pc_read & ~3);
 } else {
 addr = load_reg(s, rn);
 }
@@ -9590,7 +9580,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 /* Table Branch.  */
 if (rn == 15) {
 addr = tcg_temp_new_i32();
-tcg_gen_movi_i32(addr, s->pc);
+tcg_gen_movi_i32(addr, s->pc_read);
 } else 

[Qemu-devel] [PATCH 17/67] target/arm: Convert MSR (immediate) and hints

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 61 +-
 target/arm/a32.decode  | 25 +
 target/arm/t32.decode  | 17 
 3 files changed, 84 insertions(+), 19 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 2140671eb2..36c815caf3 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8324,6 +8324,44 @@ DO_SMLAWX(SMLAWT, 1, 1)
 
 #undef DO_SMLAWX
 
+/*
+ * MSR (immediate) and hints
+ */
+
+static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
+{
+gen_nop_hint(s, 1);
+return true;
+}
+
+static bool trans_WFE(DisasContext *s, arg_WFE *a)
+{
+gen_nop_hint(s, 2);
+return true;
+}
+
+static bool trans_WFI(DisasContext *s, arg_WFI *a)
+{
+gen_nop_hint(s, 2);
+return true;
+}
+
+static bool trans_NOP(DisasContext *s, arg_NOP *a)
+{
+return true;
+}
+
+static bool trans_MSR_imm(DisasContext *s, arg_MSR_imm *a)
+{
+uint32_t val = ror32(a->imm, a->rot * 2);
+uint32_t mask = msr_mask(s, a->mask, a->r);
+
+if (gen_set_psr_im(s, mask, a->r, val)) {
+gen_illegal_op(s);
+}
+return true;
+}
+
 /*
  * Legacy decoder.
  */
@@ -8594,22 +8632,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 }
 store_reg(s, rd, tmp);
 } else {
-if (((insn >> 12) & 0xf) != 0xf)
-goto illegal_op;
-if (((insn >> 16) & 0xf) == 0) {
-gen_nop_hint(s, insn & 0xff);
-} else {
-/* CPSR = immediate */
-val = insn & 0xff;
-shift = ((insn >> 8) & 0xf) * 2;
-if (shift)
-val = (val >> shift) | (val << (32 - shift));
-i = ((insn & (1 << 22)) != 0);
-if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
-   i, val)) {
-goto illegal_op;
-}
-}
+/* MSR (immediate) and hints */
+/* All done in decodetree.  Illegal ops already signalled.  */
+g_assert_not_reached();
 }
 } else if ((insn & 0x0f90) == 0x0100
&& (insn & 0x0090) != 0x0090) {
@@ -10569,9 +10594,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 goto illegal_op;
 break;
 case 2: /* cps, nop-hint.  */
-if (((insn >> 8) & 7) == 0) {
-gen_nop_hint(s, insn & 0xff);
-}
+/* nop hints in decodetree */
 /* Implemented as NOP in user mode.  */
 if (IS_USER(s))
 break;
diff --git a/target/arm/a32.decode b/target/arm/a32.decode
index 8dc74dfdb8..4cefba6f0e 100644
--- a/target/arm/a32.decode
+++ b/target/arm/a32.decode
@@ -22,6 +22,7 @@
 # All insns that have 0xf in insn[31:28] are in a32u.decode.
 #
 
+
 _rrr_shi   s rd rn rm shim shty
 _rrr_shr   s rn rd rm rs shty
 _rri_rot   s rn rd imm rot
@@ -152,3 +153,27 @@ SMULBB    0001 0110    1000    
   @rd0mn
 SMULBT    0001 0110    1100   @rd0mn
 SMULTB    0001 0110    1010   @rd0mn
 SMULTT    0001 0110    1110   @rd0mn
+
+# MSR (immediate) and hints
+
+_i   r mask rot imm
+@msr_i      mask:4  rot:4 imm:8   _i
+
+{
+  {
+YIELD 0011 0010     0001
+WFE   0011 0010     0010
+WFI   0011 0010     0011
+
+# TODO: Implement SEV, SEVL; may help SMP performance.
+# SEV 0011 0010     0100
+# SEVL    0011 0010     0101
+
+# The canonical nop ends in , but the whole of the
+# rest of the space executes as nop if otherwise unsupported.
+NOP   0011 0010     
+  }
+  # Note mask = 0 is covered by NOP
+  MSR_imm 0011 0010       @msr_i r=0
+}
+MSR_imm   0011 0110       @msr_i r=1
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
index e611ac4969..b4f0a9632d 100644
--- a/target/arm/t32.decode
+++ b/target/arm/t32.decode
@@ -19,6 +19,7 @@
 # This file is processed by scripts/decodetree.py
 #
 
+   !extern
 _rrr_shi   !extern s rd rn rm shim shty
 _rrr_shr   !extern s rn rd rm rs shty
 _rri_rot   !extern s rn rd imm rot
@@ -166,3 +167,19 @@ QADD  1010 1000    1000    
   @rndm
 QSUB  1010 1000    1010   @rndm
 QDADD 1010 1000    1001   @rndm
 QDSUB 1010 1000 

[Qemu-devel] [PATCH 14/67] target/arm: Convert multiply and multiply accumulate

2019-07-26 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 214 -
 target/arm/a32.decode  |  17 
 target/arm/t32.decode  |  19 
 3 files changed, 163 insertions(+), 87 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index ee7d53dfa5..354a52d36c 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7376,21 +7376,6 @@ static void gen_storeq_reg(DisasContext *s, int rlow, 
int rhigh, TCGv_i64 val)
 store_reg(s, rhigh, tmp);
 }
 
-/* load a 32-bit value from a register and perform a 64-bit accumulate.  */
-static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
-{
-TCGv_i64 tmp;
-TCGv_i32 tmp2;
-
-/* Load value and extend to 64 bits.  */
-tmp = tcg_temp_new_i64();
-tmp2 = load_reg(s, rlow);
-tcg_gen_extu_i32_i64(tmp, tmp2);
-tcg_temp_free_i32(tmp2);
-tcg_gen_add_i64(val, val, tmp);
-tcg_temp_free_i64(tmp);
-}
-
 /* load and add a 64-bit value from a register pair.  */
 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
 {
@@ -8068,6 +8053,128 @@ static bool trans_ORN_rri(DisasContext *s, 
arg_s_rri_rot *a)
 #undef DO_ANY
 #undef DO_LOGIC
 
+/*
+ * Multiply and multiply accumulate
+ */
+
+static bool op_mla(DisasContext *s, arg_s_ *a, bool add)
+{
+TCGv_i32 t1, t2;
+
+t1 = load_reg(s, a->rn);
+t2 = load_reg(s, a->rm);
+tcg_gen_mul_i32(t1, t1, t2);
+tcg_temp_free_i32(t2);
+if (add) {
+t2 = load_reg(s, a->ra);
+tcg_gen_add_i32(t1, t1, t2);
+tcg_temp_free_i32(t2);
+}
+if (a->s) {
+gen_logic_CC(t1);
+}
+store_reg(s, a->rd, t1);
+return true;
+}
+
+static bool trans_MUL(DisasContext *s, arg_MUL *a)
+{
+return op_mla(s, a, false);
+}
+
+static bool trans_MLA(DisasContext *s, arg_MLA *a)
+{
+return op_mla(s, a, true);
+}
+
+static bool trans_MLS(DisasContext *s, arg_MLS *a)
+{
+TCGv_i32 t1, t2;
+
+t1 = load_reg(s, a->rn);
+t2 = load_reg(s, a->rm);
+tcg_gen_mul_i32(t1, t1, t2);
+tcg_temp_free_i32(t2);
+t2 = load_reg(s, a->ra);
+tcg_gen_sub_i32(t1, t2, t1);
+tcg_temp_free_i32(t2);
+store_reg(s, a->rd, t1);
+return true;
+}
+
+static bool op_mlal(DisasContext *s, arg_s_ *a, bool uns, bool add)
+{
+TCGv_i32 t0, t1, t2, t3;
+
+t0 = load_reg(s, a->rm);
+t1 = load_reg(s, a->rn);
+if (uns) {
+tcg_gen_mulu2_i32(t0, t1, t0, t1);
+} else {
+tcg_gen_muls2_i32(t0, t1, t0, t1);
+}
+if (add) {
+t2 = load_reg(s, a->ra);
+t3 = load_reg(s, a->rd);
+tcg_gen_add2_i32(t0, t1, t0, t1, t2, t3);
+tcg_temp_free_i32(t2);
+tcg_temp_free_i32(t3);
+}
+store_reg(s, a->ra, t0);
+store_reg(s, a->rd, t1);
+if (a->s) {
+gen_logicq_cc(t0, t1);
+}
+return true;
+}
+
+static bool trans_UMULL(DisasContext *s, arg_UMULL *a)
+{
+return op_mlal(s, a, true, false);
+}
+
+static bool trans_SMULL(DisasContext *s, arg_SMULL *a)
+{
+return op_mlal(s, a, false, false);
+}
+
+static bool trans_UMLAL(DisasContext *s, arg_UMLAL *a)
+{
+return op_mlal(s, a, true, true);
+}
+
+static bool trans_SMLAL(DisasContext *s, arg_SMLAL *a)
+{
+return op_mlal(s, a, false, true);
+}
+
+static bool trans_UMAAL(DisasContext *s, arg_UMAAL *a)
+{
+TCGv_i32 t0, t1, t2, zero;
+
+if (s->thumb
+? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
+: !ENABLE_ARCH_6) {
+return false;
+}
+
+t0 = load_reg(s, a->rm);
+t1 = load_reg(s, a->rn);
+tcg_gen_mulu2_i32(t0, t1, t0, t1);
+zero = tcg_const_i32(0);
+t2 = load_reg(s, a->ra);
+tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
+tcg_temp_free_i32(t2);
+t2 = load_reg(s, a->rd);
+tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
+tcg_temp_free_i32(t2);
+tcg_temp_free_i32(zero);
+store_reg(s, a->ra, t0);
+store_reg(s, a->rd, t1);
+return true;
+}
+
+
 /*
  * Legacy decoder.
  */
@@ -8612,71 +8719,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 sh = (insn >> 5) & 3;
 if (sh == 0) {
 if (op1 == 0x0) {
-rd = (insn >> 16) & 0xf;
-rn = (insn >> 12) & 0xf;
-rs = (insn >> 8) & 0xf;
-rm = (insn) & 0xf;
-op1 = (insn >> 20) & 0xf;
-switch (op1) {
-case 0: case 1: case 2: case 3: case 6:
-/* 32 bit mul */
-tmp = load_reg(s, rs);
-tmp2 = load_reg(s, rm);
-tcg_gen_mul_i32(tmp, tmp, tmp2);
-tcg_temp_free_i32(tmp2);
-if (insn & (1 << 22)) {
-/* Subtract (mls) */
-ARCH(6T2);
-tmp2 = load_reg(s, rn);
-

[Qemu-devel] [PATCH 07/67] target/arm: Introduce add_reg_for_lit

2019-07-26 Thread Richard Henderson
Used only on the thumb side so far, but will be more obvious
once we start unifying the implementation of A32+T32.

Signed-off-by: Richard Henderson 
---
 target/arm/translate-vfp.inc.c |  34 +--
 target/arm/translate.c | 163 +++--
 2 files changed, 76 insertions(+), 121 deletions(-)

diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
index e7389bc057..4066b2febf 100644
--- a/target/arm/translate-vfp.inc.c
+++ b/target/arm/translate-vfp.inc.c
@@ -941,14 +941,7 @@ static bool trans_VLDR_VSTR_sp(DisasContext *s, 
arg_VLDR_VSTR_sp *a)
 offset = -offset;
 }
 
-if (s->thumb && a->rn == 15) {
-/* This is actually UNPREDICTABLE */
-addr = tcg_temp_new_i32();
-tcg_gen_movi_i32(addr, s->pc & ~2);
-} else {
-addr = load_reg(s, a->rn);
-}
-tcg_gen_addi_i32(addr, addr, offset);
+addr = add_reg_for_lit(s, a->rn, offset);
 tmp = tcg_temp_new_i32();
 if (a->l) {
 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
@@ -983,14 +976,7 @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, 
arg_VLDR_VSTR_dp *a)
 offset = -offset;
 }
 
-if (s->thumb && a->rn == 15) {
-/* This is actually UNPREDICTABLE */
-addr = tcg_temp_new_i32();
-tcg_gen_movi_i32(addr, s->pc & ~2);
-} else {
-addr = load_reg(s, a->rn);
-}
-tcg_gen_addi_i32(addr, addr, offset);
+addr = add_reg_for_lit(s, a->rn, offset);
 tmp = tcg_temp_new_i64();
 if (a->l) {
 gen_aa32_ld64(s, tmp, addr, get_mem_index(s));
@@ -1029,13 +1015,7 @@ static bool trans_VLDM_VSTM_sp(DisasContext *s, 
arg_VLDM_VSTM_sp *a)
 return true;
 }
 
-if (s->thumb && a->rn == 15) {
-/* This is actually UNPREDICTABLE */
-addr = tcg_temp_new_i32();
-tcg_gen_movi_i32(addr, s->pc & ~2);
-} else {
-addr = load_reg(s, a->rn);
-}
+addr = add_reg_for_lit(s, a->rn, 0);
 if (a->p) {
 /* pre-decrement */
 tcg_gen_addi_i32(addr, addr, -(a->imm << 2));
@@ -1112,13 +1092,7 @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, 
arg_VLDM_VSTM_dp *a)
 return true;
 }
 
-if (s->thumb && a->rn == 15) {
-/* This is actually UNPREDICTABLE */
-addr = tcg_temp_new_i32();
-tcg_gen_movi_i32(addr, s->pc & ~2);
-} else {
-addr = load_reg(s, a->rn);
-}
+addr = add_reg_for_lit(s, a->rn, 0);
 if (a->p) {
 /* pre-decrement */
 tcg_gen_addi_i32(addr, addr, -(a->imm << 2));
diff --git a/target/arm/translate.c b/target/arm/translate.c
index a48e9a90f8..5e2dd8bb16 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -214,6 +214,23 @@ static inline TCGv_i32 load_reg(DisasContext *s, int reg)
 return tmp;
 }
 
+/*
+ * Create a new temp, incremented by OFS, except PC is aligned but not
+ * incremented for thumb.  This is used for load/store for which use of
+ * PC implies (literal), or ADD that implies ADR.
+ */
+static TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
+{
+TCGv_i32 tmp = tcg_temp_new_i32();
+
+if (reg == 15) {
+tcg_gen_movi_i32(tmp, (s->pc_read & ~3) + ofs);
+} else {
+tcg_gen_addi_i32(tmp, cpu_R[reg], ofs);
+}
+return tmp;
+}
+
 /* Set a CPU register.  The source must be a temporary and will be
marked as dead.  */
 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
@@ -9468,16 +9485,12 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
  */
 bool wback = extract32(insn, 21, 1);
 
-if (rn == 15) {
-if (insn & (1 << 21)) {
-/* UNPREDICTABLE */
-goto illegal_op;
-}
-addr = tcg_temp_new_i32();
-tcg_gen_movi_i32(addr, s->pc_read & ~3);
-} else {
-addr = load_reg(s, rn);
+if (rn == 15 && (insn & (1 << 21))) {
+/* UNPREDICTABLE */
+goto illegal_op;
 }
+
+addr = add_reg_for_lit(s, rn, 0);
 offset = (insn & 0xff) * 4;
 if ((insn & (1 << 23)) == 0) {
 offset = -offset;
@@ -10683,27 +10696,15 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 store_reg(s, rd, tmp);
 } else {
 /* Add/sub 12-bit immediate.  */
-if (rn == 15) {
-offset = s->pc_read & ~(uint32_t)3;
-if (insn & (1 << 23))
-offset -= imm;
-else
-offset += imm;
-tmp = tcg_temp_new_i32();
-tcg_gen_movi_i32(tmp, offset);
-

[Qemu-devel] [PATCH 12/67] target/arm: Introduce gen_illegal_op

2019-07-26 Thread Richard Henderson
Unify the code sequence for generating an illegal opcode exception.

Signed-off-by: Richard Henderson 
---
 target/arm/translate-vfp.inc.c |  3 +--
 target/arm/translate.c | 21 +++--
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
index 4066b2febf..1b08930649 100644
--- a/target/arm/translate-vfp.inc.c
+++ b/target/arm/translate-vfp.inc.c
@@ -108,8 +108,7 @@ static bool full_vfp_access_check(DisasContext *s, bool 
ignore_vfp_enabled)
 
 if (!s->vfp_enabled && !ignore_vfp_enabled) {
 assert(!arm_dc_feature(s, ARM_FEATURE_M));
-gen_exception_insn(s, EXCP_UDEF, syn_uncategorized(),
-   default_exception_el(s));
+gen_illegal_op(s);
 return false;
 }
 
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 4738b91957..0f21ee9ce7 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1279,6 +1279,12 @@ static void gen_exception_bkpt_insn(DisasContext *s, 
uint32_t syn)
 s->base.is_jmp = DISAS_NORETURN;
 }
 
+static void gen_illegal_op(DisasContext *s)
+{
+gen_exception_insn(s, EXCP_UDEF, syn_uncategorized(),
+   default_exception_el(s));
+}
+
 /* Force a TB lookup after an instruction that changes the CPU state.  */
 static inline void gen_lookup_tb(DisasContext *s)
 {
@@ -1309,8 +1315,7 @@ static inline void gen_hlt(DisasContext *s, int imm)
 return;
 }
 
-gen_exception_insn(s, EXCP_UDEF, syn_uncategorized(),
-   default_exception_el(s));
+gen_illegal_op(s);
 }
 
 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
@@ -7631,8 +7636,7 @@ static void gen_srs(DisasContext *s,
 }
 
 if (undef) {
-gen_exception_insn(s, EXCP_UDEF, syn_uncategorized(),
-   default_exception_el(s));
+gen_illegal_op(s);
 return;
 }
 
@@ -9299,8 +9303,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 break;
 default:
 illegal_op:
-gen_exception_insn(s, EXCP_UDEF, syn_uncategorized(),
-   default_exception_el(s));
+gen_illegal_op(s);
 break;
 }
 }
@@ -10990,8 +10993,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t 
insn)
 }
 return;
 illegal_op:
-gen_exception_insn(s, EXCP_UDEF, syn_uncategorized(),
-   default_exception_el(s));
+gen_illegal_op(s);
 }
 
 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
@@ -11816,8 +11818,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 return;
 illegal_op:
 undef:
-gen_exception_insn(s, EXCP_UDEF, syn_uncategorized(),
-   default_exception_el(s));
+gen_illegal_op(s);
 }
 
 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
-- 
2.17.1




[Qemu-devel] [PATCH 04/67] target/arm: Remove offset argument to gen_exception_internal_insn

2019-07-26 Thread Richard Henderson
The actual argument is 0 for all callers.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 19b126d4f3..0848fb933a 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1239,10 +1239,10 @@ static inline void gen_smc(DisasContext *s)
 s->base.is_jmp = DISAS_SMC;
 }
 
-static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
+static void gen_exception_internal_insn(DisasContext *s, int excp)
 {
 gen_set_condexec(s);
-gen_set_pc_im(s, s->pc - offset);
+gen_set_pc_im(s, s->pc);
 gen_exception_internal(excp);
 s->base.is_jmp = DISAS_NORETURN;
 }
@@ -1294,7 +1294,7 @@ static inline void gen_hlt(DisasContext *s, int imm)
 s->current_el != 0 &&
 #endif
 (imm == (s->thumb ? 0x3c : 0xf000))) {
-gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
+gen_exception_internal_insn(s, EXCP_SEMIHOST);
 return;
 }
 
@@ -11984,7 +11984,7 @@ static bool arm_tr_breakpoint_check(DisasContextBase 
*dcbase, CPUState *cpu,
 /* End the TB early; it's likely not going to be executed */
 dc->base.is_jmp = DISAS_TOO_MANY;
 } else {
-gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
+gen_exception_internal_insn(dc, EXCP_DEBUG);
 /* The address covered by the breakpoint must be
included in [tb->pc, tb->pc + tb->size) in order
to for it to be properly cleared -- thus we
-- 
2.17.1




[Qemu-devel] [PATCH 05/67] target/arm: Use the saved value of the insn address

2019-07-26 Thread Richard Henderson
The address of the current insn is still available in s->base.pc_next,
and need not be recomputed from s->pc - 4.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 0848fb933a..595385e1b1 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1212,7 +1212,7 @@ static inline void gen_hvc(DisasContext *s, int imm16)
  * as an undefined insn by runtime configuration (ie before
  * the insn really executes).
  */
-gen_set_pc_im(s, s->pc - 4);
+gen_set_pc_im(s, s->base.pc_next);
 gen_helper_pre_hvc(cpu_env);
 /* Otherwise we will treat this as a real exception which
  * happens after execution of the insn. (The distinction matters
@@ -1231,7 +1231,7 @@ static inline void gen_smc(DisasContext *s)
  */
 TCGv_i32 tmp;
 
-gen_set_pc_im(s, s->pc - 4);
+gen_set_pc_im(s, s->base.pc_next);
 tmp = tcg_const_i32(syn_aa32_smc());
 gen_helper_pre_smc(cpu_env, tmp);
 tcg_temp_free_i32(tmp);
@@ -3190,7 +3190,7 @@ static void gen_msr_banked(DisasContext *s, int r, int 
sysm, int rn)
 
 /* Sync state because msr_banked() can raise exceptions */
 gen_set_condexec(s);
-gen_set_pc_im(s, s->pc - 4);
+gen_set_pc_im(s, s->base.pc_next);
 tcg_reg = load_reg(s, rn);
 tcg_tgtmode = tcg_const_i32(tgtmode);
 tcg_regno = tcg_const_i32(regno);
@@ -3212,7 +3212,7 @@ static void gen_mrs_banked(DisasContext *s, int r, int 
sysm, int rn)
 
 /* Sync state because mrs_banked() can raise exceptions */
 gen_set_condexec(s);
-gen_set_pc_im(s, s->pc - 4);
+gen_set_pc_im(s, s->base.pc_next);
 tcg_reg = tcg_temp_new_i32();
 tcg_tgtmode = tcg_const_i32(tgtmode);
 tcg_regno = tcg_const_i32(regno);
@@ -7219,7 +7219,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t 
insn)
 }
 
 gen_set_condexec(s);
-gen_set_pc_im(s, s->pc - 4);
+gen_set_pc_im(s, s->base.pc_next);
 tmpptr = tcg_const_ptr(ri);
 tcg_syn = tcg_const_i32(syndrome);
 tcg_isread = tcg_const_i32(isread);
@@ -7629,7 +7629,7 @@ static void gen_srs(DisasContext *s,
 tmp = tcg_const_i32(mode);
 /* get_r13_banked() will raise an exception if called from System mode */
 gen_set_condexec(s);
-gen_set_pc_im(s, s->pc - 4);
+gen_set_pc_im(s, s->base.pc_next);
 gen_helper_get_r13_banked(addr, cpu_env, tmp);
 tcg_temp_free_i32(tmp);
 switch (amode) {
-- 
2.17.1




[Qemu-devel] [PATCH 00/67] target/arm: Convert aa32 base isa to decodetree

2019-07-26 Thread Richard Henderson
This unifies the implementation of the actual instructions
for a32, t32, and t16.  In order to make this happen, we
need several preliminary cleanups.  Most importantly to how
we handle the architectural representation of PC.

I attempt to convert single groups of instructions at once,
as they are grouped in the sections of the encoding sections
of the manual.

This has been tested by running the debian 9 armhf installer,
which does a far amount of switching between arm and thumb modes.
I've also run Peter's ARM TFM image, and all of the existing
RISU tests that we have.  (Our RISU test cases are nowhere near
complete for 32-bit mode, but it did find 3 bugs, so not useless.)

What's left is converting NEON and iwmmxt, then we could start
merging some of the decoders and tidying the top-level interface
further.

We will need to convert NEON in order to have a good chance at
finishing the ARMv8.2-FHP extension.


r~


Richard Henderson (67):
  decodetree: Allow !function with no input bits
  target/arm: Remove offset argument to gen_exception_insn
  target/arm: Remove offset argument to gen_exception_bkpt_insn
  target/arm: Remove offset argument to gen_exception_internal_insn
  target/arm: Use the saved value of the insn address
  target/arm: Introduce pc_read
  target/arm: Introduce add_reg_for_lit
  target/arm: Use store_reg_from_load in thumb2 code
  target/arm: Fold a pc load into load_reg
  target/arm: Move test for AL into arm_skip_unless
  target/arm: Add stubs for aa32 decodetree
  target/arm: Introduce gen_illegal_op
  target/arm: Convert Data Processing (reg, reg-shifted-reg, imm)
  target/arm: Convert multiply and multiply accumulate
  target/arm: Convert Saturating addition and subtraction
  target/arm: Convert Halfword multiply and multiply accumulate
  target/arm: Convert MSR (immediate) and hints
  target/arm: Convert MRS/MSR (banked, register)
  target/arm: Convert Cyclic Redundancy Check
  target/arm: Convert the rest of A32 Miscelaneous instructions
  target/arm: Convert T32 ADDW/SUBW
  target/arm: Convert load/store (register, immediate, literal)
  target/arm: Convert Synchronization primitives
  target/arm: Convert USAD8, USADA8, SBFX, UBFX, BFC, BFI, UDF
  target/arm: Convert Parallel addition and subtraction
  target/arm: Convert Packing, unpacking, saturation, and reversal
  target/arm: Convert Signed multiply, signed and unsigned divide
  target/arm: Convert MOVW, MOVT
  target/arm: Convert LDM, STM
  target/arm: Convert B, BL, BLX (immediate)
  target/arm: Convert SVC
  target/arm: Convert RFE and SRS
  target/arm: Convert Clear-Exclusive, Barriers
  target/arm: Convert CPS (privileged)
  target/arm: Convert SETEND
  target/arm: Convert PLI, PLD, PLDW
  target/arm: Convert Unallocated memory hint
  target/arm: Convert Table Branch
  target/arm: Convert SG
  target/arm: Convert TT
  target/arm: Simplify disas_thumb2_insn
  target/arm: Simplify disas_arm_insn
  target/arm: Add skeleton for T16 decodetree
  target/arm: Convert T16 data-processing (two low regs)
  target/arm: Convert T16 load/store (register offset)
  target/arm: Convert T16 load/store (immediate offset)
  target/arm: Convert T16 add pc/sp (immediate)
  target/arm: Convert T16 load/store multiple
  target/arm: Convert T16 add/sub (3 low, 2 low and imm)
  target/arm: Convert T16 one low register and immediate
  target/arm: Convert T16 branch and exchange
  target/arm: Convert T16 add, compare, move (two high registers)
  target/arm: Convert T16 adjust sp (immediate)
  target/arm: Convert T16, extract
  target/arm: Convert T16, Change processor state
  target/arm: Convert T16, Reverse bytes
  target/arm: Convert T16, nop hints
  target/arm: Convert T16, push and pop
  target/arm: Convert T16, Conditional branches, Supervisor call
  target/arm: Convert T16, Miscellaneous 16-bit instructions
  target/arm: Convert T16, shift immediate
  target/arm: Convert T16, load (literal)
  target/arm: Convert T16, Unconditional branch
  target/arm: Convert T16, long branches
  target/arm: Clean up disas_thumb_insn
  target/arm: Move singlestep check from gen_jmp to gen_goto_tb
  target/arm: Merge gen_bx_im into trans_BLX_i

 target/arm/helper.h   |1 -
 target/arm/translate.h|   10 +
 target/arm/op_helper.c|   15 -
 target/arm/translate-vfp.inc.c|   41 +-
 target/arm/translate.c| 7142 -
 scripts/decodetree.py |5 +-
 target/arm/Makefile.objs  |   24 +
 target/arm/a32-uncond.decode  |   74 +
 target/arm/a32.decode |  534 +++
 target/arm/t16.decode |  279 ++
 target/arm/t32.decode |  629 +++
 tests/decode/succ_function.decode |2 +
 12 files changed, 4559 insertions(+), 4197 deletions(-)
 create mode 100644 target/arm/a32-uncond.decode
 create mode 100644 target/arm/a32.decode
 create mode 100644 target/arm/t16.decode
 create mode 100644 target/arm/t32.decode
 create mode 100644 

[Qemu-devel] [PATCH 01/67] decodetree: Allow !function with no input bits

2019-07-26 Thread Richard Henderson
With this, we can have the function return a value from the DisasContext.

Signed-off-by: Richard Henderson 
---
 scripts/decodetree.py | 5 -
 tests/decode/succ_function.decode | 2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)
 create mode 100644 tests/decode/succ_function.decode

diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index d7a59d63ac..4259d87a95 100755
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -195,7 +195,10 @@ class MultiField:
 """Class representing a compound instruction field"""
 def __init__(self, subs, mask):
 self.subs = subs
-self.sign = subs[0].sign
+if len(subs):
+self.sign = subs[0].sign
+else:
+self.sign = 0
 self.mask = mask
 
 def __str__(self):
diff --git a/tests/decode/succ_function.decode 
b/tests/decode/succ_function.decode
new file mode 100644
index 00..632a9de252
--- /dev/null
+++ b/tests/decode/succ_function.decode
@@ -0,0 +1,2 @@
+%foo  !function=foo
+foo    %foo
-- 
2.17.1




[Qemu-devel] [PATCH 03/67] target/arm: Remove offset argument to gen_exception_bkpt_insn

2019-07-26 Thread Richard Henderson
The address of the current insn is still available in s->base.pc_next.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 33f78296eb..19b126d4f3 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1256,12 +1256,12 @@ static void gen_exception_insn(DisasContext *s, int 
excp, int syn,
 s->base.is_jmp = DISAS_NORETURN;
 }
 
-static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn)
+static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
 {
 TCGv_i32 tcg_syn;
 
 gen_set_condexec(s);
-gen_set_pc_im(s, s->pc - offset);
+gen_set_pc_im(s, s->base.pc_next);
 tcg_syn = tcg_const_i32(syn);
 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
 tcg_temp_free_i32(tcg_syn);
@@ -8139,7 +8139,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int 
insn)
 case 1:
 /* bkpt */
 ARCH(5);
-gen_exception_bkpt_insn(s, 4, syn_aa32_bkpt(imm16, false));
+gen_exception_bkpt_insn(s, syn_aa32_bkpt(imm16, false));
 break;
 case 2:
 /* Hypervisor call (v7) */
@@ -11611,7 +11611,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t 
insn)
 {
 int imm8 = extract32(insn, 0, 8);
 ARCH(5);
-gen_exception_bkpt_insn(s, 2, syn_aa32_bkpt(imm8, true));
+gen_exception_bkpt_insn(s, syn_aa32_bkpt(imm8, true));
 break;
 }
 
-- 
2.17.1




  1   2   3   4   >