Re: device compatibility interface for live migration with assigned devices

2020-09-08 Thread Yan Zhao
hi All,
Per our previous discussion, there are two main concerns to the previous
proposal:
(1) it's currently hard for openstack to match mdev types.
(2) complicated.

so, we further propose below changes:
(1) requiring two compatible mdevs to have the same mdev type for now.
(though kernel still exposes compatible_type attributes for future use)  
(2) requiring 1:1 match for other attributes under sysfs type node for now
(those attributes are specified via compatible_ but
with only 1 value in it.)
(3) do not match attributes under device instance node.
rather, they are regarded as part of resource claiming process.
so src and dest values are ensured to be 1:1.
A dynamic_resources attribute under sysfs  node is added to
list the attributes under device instance that mgt tools need to
ensure 1:1 from src and dest.
the "aggregator" attribute under device instance node is such one that
needs to be listed.
Those listed attributes can actually be treated as device state set by
vendor driver during live migration. but we still want to ask for them to
be set by mgt tools before live migration starts, in oder to reduce the
chance of live migration failure.

do you like those changes?

after the changes, the sysfs interface would look like blow:

  |- [parent physical device]
  |--- Vendor-specific-attributes [optional]
  |--- [mdev_supported_types]
  | |--- []
  | |   |--- create
  | |   |--- name
  | |   |--- available_instances
  | |   |--- device_api
  | |   |--- software_version
  | |   |--- compatible_type
  | |   |--- compatible_
  | |   |--- compatible_
  | |   |--- dynamic_resources
  | |   |--- description
  | |   |--- [devices]

- device_api : exact match between src and dest is required.
   its value can be one of 
   "vfio-pci", "vfio-platform", "vfio-amba", "vfio-ccw", "vfio-ap"
- software_version: version of vendor driver.
in major.minor.bugfix scheme. 
dest major should be equal to src major,
dest minor should be no less than src minor.
once migration stream related code changed, vendor
drivers need to bump the version.
- compatible_type: not used by mgt tools currently.
   vendor drivers can provide this attribute, but need to
   know that mgt apps would ignore it.
   when in future mgt tools support this attribute, it
   would allow migration across different mdev types,
   so that devices of older generation may be able to
   migrate to newer generations.

- compatible_: for device api specific attributes,
  e.g. compatible_subchannel_type,
  dest values should be superset of arc values.
  vendor drivers can specify only one value in this attribute,
  in order to do exact match between src and dest.
  It's ok for mgt tools to only read one value in the
  attribute so that src:dest values are 1:1.

- compatible_: for mdev type specific attributes,
  e.g. compatible_pci_ids, compatible_chpid_type
  dest values should be superset of arc values.
  vendor drivers can specify only one value in the attribute
  in order to do exact match between src and dest.
  It's ok for mgt tools to only read one value in the
  attribute so that src:dest values are 1:1.

- dynamic_resources: though defined statically under ,
  this attribute lists attributes under device instance that
  need to be set as part of claiming dest resources.
  e.g. $cat dynamic_resources: aggregator, fps,...
  then after dest device is created, values of its device
  attributes need to be set to that of src device attributes.
  Failure in syncing src device values to dest device
  values is treated the same as failing to claiming
  dest resources.
  attributes under device instance that are not listed
  in this attribute would not be part of resource checking in
  mgt tools.



Thanks
Yan



Re: [RFC 1/4] memory: add memory_region_init_io_with_dev interface

2020-09-08 Thread Li Qiang
Gerd Hoffmann  于2020年9月9日周三 下午12:49写道:
>
> On Wed, Sep 09, 2020 at 10:15:47AM +0800, Jason Wang wrote:
> >
> > On 2020/9/9 上午12:41, Li Qiang wrote:
> > > Currently the MR is not explicitly connecting with its device instead of
> > > a opaque. In most situation this opaque is the deivce but it is not an
> > > enforcement. This patch adds a DeviceState member of to MemoryRegion
> > > we will use it in later patch.
> >
> >
> > I don't have a deep investigation. But I wonder whether we could make sure
> > of owner instead of adding a new field here.
>
> Should be possible.  There is object_dynamic_cast() which can be used to
> figure whenever a given owner object is a device.
>

I found most caller of 'memory_region_init_io' will set the owner to
the device object.
But some of them will just set it to NULL. Do will have a clear rule
that the device's MR
'owner' should be the device object? If yes, we can use this field.

Thanks,
Li Qiang

> take care,
>   Gerd
>



Re: [PATCH 04/16] curses: Fixes curses compiling errors.

2020-09-08 Thread Gerd Hoffmann
On Wed, Sep 09, 2020 at 03:48:08AM +0800, Yonggang Luo wrote:
> This is the compiling error:
> ../ui/curses.c: In function 'curses_refresh':
> ../ui/curses.c:256:5: error: 'next_maybe_keycode' may be used uninitialized 
> in this function [-Werror=maybe-uninitialized]
>   256 | curses2foo(_curses2keycode, _curseskey2keycode, chr, 
> maybe_keycode)
>   | ^~
> ../ui/curses.c:302:32: note: 'next_maybe_keycode' was declared here
>   302 | enum maybe_keycode next_maybe_keycode;
>   |^~
> ../ui/curses.c:256:5: error: 'maybe_keycode' may be used uninitialized in 
> this function [-Werror=maybe-uninitialized]
>   256 | curses2foo(_curses2keycode, _curseskey2keycode, chr, 
> maybe_keycode)
>   | ^~
> ../ui/curses.c:265:24: note: 'maybe_keycode' was declared here
>   265 | enum maybe_keycode maybe_keycode;
>   |^
> cc1.exe: all warnings being treated as errors
> 
> Signed-off-by: Yonggang Luo 

Reviewed-by: Gerd Hoffmann 




Re: [PATCH 03/16] configure: Fixes ncursesw detection under msys2/mingw and enable curses

2020-09-08 Thread Gerd Hoffmann
On Wed, Sep 09, 2020 at 03:48:07AM +0800, Yonggang Luo wrote:
> The mingw pkg-config are showing following absolute path and contains : as 
> the separator,
> so we must handling : properly.
> 
> -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199506L 
> -IC:/CI-Tools/msys64/mingw64/include/ncursesw:-I/usr/include/ncursesw:
> -DNCURSES_WIDECHAR -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199506L -IC -pipe 
> -lncursesw -lgnurx -ltre -lintl -liconv
> -DNCURSES_WIDECHAR -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199506L -IC 
> -lncursesw
> -DNCURSES_WIDECHAR -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199506L -IC -lcursesw
> -DNCURSES_WIDECHAR /CI-Tools/msys64/mingw64/include/ncursesw -pipe -lncursesw 
> -lgnurx -ltre -lintl -liconv
> -DNCURSES_WIDECHAR /CI-Tools/msys64/mingw64/include/ncursesw -lncursesw
> -DNCURSES_WIDECHAR /CI-Tools/msys64/mingw64/include/ncursesw -lcursesw
> -DNCURSES_WIDECHAR -I/usr/include/ncursesw -pipe -lncursesw -lgnurx -ltre 
> -lintl -liconv
> -DNCURSES_WIDECHAR -I/usr/include/ncursesw -lncursesw
> -DNCURSES_WIDECHAR -I/usr/include/ncursesw -lcursesw
> 
> msys2/mingw lacks the POSIX-required langinfo.h.
> 
> gcc test.c -DNCURSES_WIDECHAR -I/mingw64/include/ncursesw -pipe -lncursesw 
> -lgnurx -ltre -lintl -liconv
> test.c:4:10: fatal error: langinfo.h: No such file or directory
> 4 | #include 
>   |  ^~~~
> compilation terminated.
> 
> So we using g_get_codeset instead of nl_langinfo(CODESET)
> 
> Signed-off-by: Yonggang Luo 

Reviewed-by: Gerd Hoffmann 




Re: [RFC 1/4] memory: add memory_region_init_io_with_dev interface

2020-09-08 Thread Gerd Hoffmann
On Wed, Sep 09, 2020 at 10:15:47AM +0800, Jason Wang wrote:
> 
> On 2020/9/9 上午12:41, Li Qiang wrote:
> > Currently the MR is not explicitly connecting with its device instead of
> > a opaque. In most situation this opaque is the deivce but it is not an
> > enforcement. This patch adds a DeviceState member of to MemoryRegion
> > we will use it in later patch.
> 
> 
> I don't have a deep investigation. But I wonder whether we could make sure
> of owner instead of adding a new field here.

Should be possible.  There is object_dynamic_cast() which can be used to
figure whenever a given owner object is a device.

take care,
  Gerd




Re: [RFC 1/4] memory: add memory_region_init_io_with_dev interface

2020-09-08 Thread Li Qiang
Jason Wang  于2020年9月9日周三 上午10:16写道:
>
>
> On 2020/9/9 上午12:41, Li Qiang wrote:
> > Currently the MR is not explicitly connecting with its device instead of
> > a opaque. In most situation this opaque is the deivce but it is not an
> > enforcement. This patch adds a DeviceState member of to MemoryRegion
> > we will use it in later patch.
>
>
> I don't have a deep investigation. But I wonder whether we could make
> sure of owner instead of adding a new field here.

I have did some investigation.

void memory_region_init_io(MemoryRegion *mr,
struct Object *owner,
const MemoryRegionOps *ops,
void *opaque,
const char *name,
uint64_t size);


memory_region_init_io now mostly connects to the device with an opaque member.
But it has no guaranteen that this should be true. So we can't assume this.

The 'owner' is just in the 'object' context.

For the MR itself, MR may have sub-MR and alias. This will complicated
the issue.

As the device emulation and MR has a clear relation. I think add such
field is reasonable.


Thanks,
Li Qiang

>
> Thanks
>
>
> >
> > Signed-off-by: Li Qiang 
> > ---
> >   include/exec/memory.h |  9 +
> >   softmmu/memory.c  | 15 +++
> >   2 files changed, 24 insertions(+)
> >
> > diff --git a/include/exec/memory.h b/include/exec/memory.h
> > index 0cfe987ab4..620fb12d9b 100644
> > --- a/include/exec/memory.h
> > +++ b/include/exec/memory.h
> > @@ -404,6 +404,7 @@ struct MemoryRegion {
> >   const char *name;
> >   unsigned ioeventfd_nb;
> >   MemoryRegionIoeventfd *ioeventfds;
> > +DeviceState *dev;
> >   };
> >
> >   struct IOMMUMemoryRegion {
> > @@ -794,6 +795,14 @@ void memory_region_init_io(MemoryRegion *mr,
> >  const char *name,
> >  uint64_t size);
> >
> > +void memory_region_init_io_with_dev(MemoryRegion *mr,
> > +   struct Object *owner,
> > +   const MemoryRegionOps *ops,
> > +   void *opaque,
> > +   const char *name,
> > +   uint64_t size,
> > +   DeviceState *dev);
> > +
> >   /**
> >* memory_region_init_ram_nomigrate:  Initialize RAM memory region.  
> > Accesses
> >*into the region will modify memory
> > diff --git a/softmmu/memory.c b/softmmu/memory.c
> > index 70b93104e8..2628c9d2d9 100644
> > --- a/softmmu/memory.c
> > +++ b/softmmu/memory.c
> > @@ -1490,6 +1490,21 @@ void memory_region_init_io(MemoryRegion *mr,
> >   mr->terminates = true;
> >   }
> >
> > +void memory_region_init_io_with_dev(MemoryRegion *mr,
> > +   Object *owner,
> > +   const MemoryRegionOps *ops,
> > +   void *opaque,
> > +   const char *name,
> > +   uint64_t size,
> > +   DeviceState *dev)
> > +{
> > +memory_region_init(mr, owner, name, size);
> > +mr->ops = ops ? ops : _mem_ops;
> > +mr->opaque = opaque;
> > +mr->terminates = true;
> > +mr->dev = dev;
> > +}
> > +
> >   void memory_region_init_ram_nomigrate(MemoryRegion *mr,
> > Object *owner,
> > const char *name,
>



Re: [RFC 0/4] Add a 'in_mmio' device flag to avoid the DMA to MMIO

2020-09-08 Thread Li Qiang
Jason Wang  于2020年9月9日周三 上午10:17写道:
>
>
> On 2020/9/9 上午12:41, Li Qiang wrote:
> > Currently the qemu device fuzzer find some DMA to MMIO issue. If the
> > device handling MMIO currently trigger a DMA which the address is MMIO,
> > this will reenter the device MMIO handler. As some of the device doesn't
> > consider this it will sometimes crash the qemu.
> >
> > This patch tries to solve this by adding a per-device flag 'in_mmio'.
> > When the memory core dispatch MMIO it will check/set this flag and when
> > it leaves it will clean this flag.
>
>
> What's the plan for fixing the irq issues pointed out by Peter?
>

Just have a basic idea. Just like this we can add a per-device flag,
'in_mmio' or 'in_emulation'
or some other names. The device need solve the irq handler/mmio and
anything other reenter issue by themself
or they can just check/set/clean this flag. This way we may can define
a principle which Peter mentioned that the device emulation should
obey.



Thanks,
Li Qiang


> Thanks
>
>
> >
> >
> > Li Qiang (4):
> >memory: add memory_region_init_io_with_dev interface
> >memory: avoid reenter the device's MMIO handler while processing MMIO
> >e1000e: use the new memory_region_init_io_with_dev interface
> >hcd-xhci: use the new memory_region_init_io_with_dev interface
> >
> >   hw/net/e1000e.c|  8 
> >   hw/usb/hcd-xhci.c  | 25 ++-
> >   include/exec/memory.h  |  9 +
> >   include/hw/qdev-core.h |  1 +
> >   softmmu/memory.c   | 46 +++---
> >   5 files changed, 72 insertions(+), 17 deletions(-)
> >
>



Re: [PATCH v2 12/12] target/arm: spe: Add corresponding doc and test.

2020-09-08 Thread Haibo Xu
On Tue, 8 Sep 2020 at 19:41, Andrew Jones  wrote:
>
> On Tue, Sep 08, 2020 at 08:13:30AM +, Haibo Xu wrote:
> > Signed-off-by: Haibo Xu 
> > ---
> >  docs/system/arm/cpu-features.rst | 20 
> >  target/arm/monitor.c |  2 +-
> >  tests/qtest/arm-cpu-features.c   |  9 +
> >  3 files changed, 30 insertions(+), 1 deletion(-)
> >
> > diff --git a/docs/system/arm/cpu-features.rst 
> > b/docs/system/arm/cpu-features.rst
> > index 2d5c06cd01..5b81b9a560 100644
> > --- a/docs/system/arm/cpu-features.rst
> > +++ b/docs/system/arm/cpu-features.rst
> > @@ -344,3 +344,23 @@ verbose command lines.  However, the recommended way 
> > to select vector
> >  lengths is to explicitly enable each desired length.  Therefore only
> >  example's (1), (4), and (6) exhibit recommended uses of the properties.
> >
> > +SPE CPU Property
> > +==
>
> Too many '='
>
> > +
> > +The SPE CPU property `spe` is used to enable or disable the SPE feature,
> > +just as the `pmu` CPU property completely enables or disables the PMU.
> > +
> > +Currently, this property is only available with KVM mode, and is enabled
> > +by default if KVM support it. When KVM is enabled, if the host does not
> > +support SPE, then an error is generated when attempting to enable it.
> > +
> > +Following are 2 examples to use this property:
> > +
> > +  1) Disable SPE::
> > +
> > + $ qemu-system-aarch64 -M virt,accel=kvm -cpu max,spe=off
> > +
> > +  2) Implicitly enable it with the `host` CPU type if host cpu
> > + support it::
>
> if the host CPU supports it
>
>
> Actually, I'm not sure we need to document this feature. We didn't bother
> documenting pauth, since there wasn't anything special about it and
> there's nothing special about this feature either.
>

Yes, there is no special treatment for this feature, and it just
follows the syntax
of other vCPU features. Will remove this doc in v3.
Anyway, thanks so much for the review!

Regards,
Haibo

> > +
> > + $ qemu-system-aarch64 -M virt,accel=kvm -cpu host
> > diff --git a/target/arm/monitor.c b/target/arm/monitor.c
> > index ba6e01abd0..1b8f08988a 100644
> > --- a/target/arm/monitor.c
> > +++ b/target/arm/monitor.c
> > @@ -99,7 +99,7 @@ QEMU_BUILD_BUG_ON(ARM_MAX_VQ > 16);
> >   * then the order that considers those dependencies must be used.
> >   */
> >  static const char *cpu_model_advertised_features[] = {
> > -"aarch64", "pmu", "sve",
> > +"aarch64", "pmu", "spe", "sve",
> >  "sve128", "sve256", "sve384", "sve512",
> >  "sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280",
> >  "sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048",
> > diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
> > index 77b5e30a9c..4d393fb2e2 100644
> > --- a/tests/qtest/arm-cpu-features.c
> > +++ b/tests/qtest/arm-cpu-features.c
> > @@ -494,6 +494,7 @@ static void test_query_cpu_model_expansion_kvm(const 
> > void *data)
> >
> >  if (g_str_equal(qtest_get_arch(), "aarch64")) {
> >  bool kvm_supports_sve;
> > +bool kvm_supports_spe;
> >  char max_name[8], name[8];
> >  uint32_t max_vq, vq;
> >  uint64_t vls;
> > @@ -512,8 +513,10 @@ static void test_query_cpu_model_expansion_kvm(const 
> > void *data)
> >  "with KVM on this host", NULL);
> >
> >  assert_has_feature(qts, "host", "sve");
> > +assert_has_feature(qts, "host", "spe");
> >  resp = do_query_no_props(qts, "host");
> >  kvm_supports_sve = resp_get_feature(resp, "sve");
> > +kvm_supports_spe = resp_get_feature(resp, "spe");
> >  vls = resp_get_sve_vls(resp);
> >  qobject_unref(resp);
> >
> > @@ -573,10 +576,16 @@ static void test_query_cpu_model_expansion_kvm(const 
> > void *data)
> >  } else {
> >  g_assert(vls == 0);
> >  }
> > +
> > +if (kvm_supports_spe) {
> > +assert_set_feature(qts, "host", "spe", false);
> > +assert_set_feature(qts, "host", "spe", true);
> > +}
> >  } else {
> >  assert_has_not_feature(qts, "host", "aarch64");
> >  assert_has_not_feature(qts, "host", "pmu");
> >  assert_has_not_feature(qts, "host", "sve");
> > +assert_has_not_feature(qts, "host", "spe");
> >  }
> >
> >  qtest_quit(qts);
> > --
> > 2.17.1
> >
>
> Otherwise
>
> Reviewed-by: Andrew Jones 
>



答复: [PATCH] ide:do nothing for identify cmd if no any device attached

2020-09-08 Thread RockCui-oc
Hi John & Max,


  1.  Follow my Log,there are 1 read 0x1x7 ops. On my Intel I5 platform, if 
down the frequency to 1.2G, you can see a obviously lag during WINDOWS LOGO 
animation playing.
  2.  We must supply a CD-ROM to our VDI users.
  3.  In ide_ioport_read() :

---
case 7:
   if ((!bus->ifs[0].blk && !bus->ifs[1].blk) || (s != bus->ifs && 
!s->blk)) {
ret = 0;
   } else {
ret = s->status;
   }

so I follow this.

Rock




发件人: Max Reitz 
发送时间: 2020年9月3日 18:40
收件人: John Snow; RockCui-oc; qemu-devel@nongnu.org
抄送: Cobe Chen(BJ-RD); Peter Maydell
主题: Re: [PATCH] ide:do nothing for identify cmd if no any device attached

On 02.09.20 20:02, John Snow wrote:
> (CC Max for block backend model confusion, see below)
>
> On 8/16/20 11:38 PM, zhaoxin\RockCuioc wrote:
>> This patch is for avoiding win7 IDE driver polling 0x1f7 when
>> no any device attached. During Win7 VM boot procedure, if use virtio for
>> disk and there is no any device be attached on hda & hdb, the win7 IDE
>> driver
>> would poll 0x1f7 for a while. This action may be stop windows LOGO
>> atomic for
>> a while too on a poor performance CPU.
>>
>
> A few questions:
>
> (1) How slow is the probing?
>
> (2) If there are no devices attached, why don't you remove the IDE
> controller so that Windows doesn't have to probe it?
>
>> Signed-off-by: zhaoxin\RockCuioc 
>> ---
>>   hw/ide/core.c | 5 +++--
>>   1 file changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/ide/core.c b/hw/ide/core.c
>> index d997a78e47..26d86f4b40 100644
>> --- a/hw/ide/core.c
>> +++ b/hw/ide/core.c
>> @@ -2073,8 +2073,9 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
>>   s = idebus_active_if(bus);
>>   trace_ide_exec_cmd(bus, s, val);
>>   -/* ignore commands to non existent slave */
>> -if (s != bus->ifs && !s->blk) {

(Was the first one basically meant to be “s != >ifs[0]”, i.e. to
check that this doesn’t go to the ma^W primary?  Not too obvious.)

>> +/* ignore commands if no any device exist or non existent slave */
>> +if ((!bus->ifs[0].blk && !bus->ifs[1].blk) ||
>> +(s != bus->ifs && !s->blk)) {

(Maybe this could be improved here)

>>   return;
>>   }
>>
>
> I think it's the case that Empty CD-ROM drives will have an anonymous
> block backend representing the empty drive,

(As far as I remember,) yes.

(ide_dev_initfn() ensures all CD drives have one, even if it’s empty.)

> so I suppose this is maybe
> fine?
>
> I suppose the idea is that with no drives on the bus that it's fine to
> ignore the register writes, as there are no devices to record those writes.
>
> (But then, why did we ever only check device1? ...)
>
> Maybe before the block-backend split we used to have to check to see if
> we had attached media or not, but I think nowadays we should always have
> a blk pointer if we have a device model intended to be operating at this
> address.

The check in ide_dev_initfn() looks that way to me.

> So I guess it can be simplified ...?
>
> if (!s->blk) {
> return;
> }

Probably.  Although there’s a difference, of course, namely if you have
only a secondary device and try to access the primary, this simplified
version will be a no-op, whereas the more complicated version in this
patch would still go on.  I don’t know how real hardware would handle
that case.  Is it even possible to have just a secondary with no primary?

Max



Re: [PATCH v2 11/12] target/arm/kvm: spe: Enable userspace irqchip support.

2020-09-08 Thread Haibo Xu
On Tue, 8 Sep 2020 at 19:35, Andrew Jones  wrote:
>
> On Tue, Sep 08, 2020 at 08:13:29AM +, Haibo Xu wrote:
> > Since the current kernel patches haven't enabled the
> > userspace irqchip support, this patch is not verified yet!
> >
> > Signed-off-by: Haibo Xu 
> > ---
> >  linux-headers/linux/kvm.h | 1 +
> >  target/arm/kvm.c  | 5 +
> >  2 files changed, 6 insertions(+)
> >
> > diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
> > index 8840cbb01c..35ef0ae842 100644
> > --- a/linux-headers/linux/kvm.h
> > +++ b/linux-headers/linux/kvm.h
> > @@ -1672,6 +1672,7 @@ struct kvm_assigned_msix_entry {
> >  #define KVM_ARM_DEV_EL1_VTIMER   (1 << 0)
> >  #define KVM_ARM_DEV_EL1_PTIMER   (1 << 1)
> >  #define KVM_ARM_DEV_PMU  (1 << 2)
> > +#define KVM_ARM_DEV_SPE  (1 << 3)
>
> kernel header changes should be separate patches
>

Will move this line to patch 01 in v3.

Thanks,
Haibo

> >
> >  struct kvm_hyperv_eventfd {
> >   __u32 conn_id;
> > diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> > index 58f991e890..7950ff1d83 100644
> > --- a/target/arm/kvm.c
> > +++ b/target/arm/kvm.c
> > @@ -820,6 +820,11 @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct 
> > kvm_run *run)
> >  switched_level &= ~KVM_ARM_DEV_PMU;
> >  }
> >
> > +if (switched_level & KVM_ARM_DEV_SPE) {
> > +qemu_set_irq(cpu->spe_interrupt,
> > + !!(run->s.regs.device_irq_level & 
> > KVM_ARM_DEV_SPE));
> > +switched_level &= ~KVM_ARM_DEV_SPE;
> > +}
> >  if (switched_level) {
> >  qemu_log_mask(LOG_UNIMP, "%s: unhandled in-kernel device IRQ 
> > %x\n",
> >__func__, switched_level);
> > --
> > 2.17.1
> >
>
> Otherwise
>
> Reviewed-by: Andrew Jones 
>



Re: [PATCH v4 7/7] tests/qtest/vhost-user-test: enable the reconnect tests

2020-09-08 Thread Raphael Norwitz
This works for me, and looks good, but I figure those who added the
check should confirm that these tests are reliable now.

Marc-Andre - thoughts?

On Fri, Sep 4, 2020 at 5:36 AM Dima Stepanov  wrote:
>
> For now a QTEST_VHOST_USER_FIXME environment variable is used to
> separate reconnect tests for the vhost-user-net device. Looks like the
> reconnect functionality is pretty stable, so this separation is
> deprecated.
> Remove it and enable these tests for the default run.
>
> Signed-off-by: Dima Stepanov 
> ---
>  tests/qtest/vhost-user-test.c | 25 +++--
>  1 file changed, 11 insertions(+), 14 deletions(-)
>
> diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c
> index 4b715d3..4b96312 100644
> --- a/tests/qtest/vhost-user-test.c
> +++ b/tests/qtest/vhost-user-test.c
> @@ -1140,20 +1140,17 @@ static void register_vhost_user_test(void)
>   "virtio-net",
>   test_migrate, );
>
> -/* keeps failing on build-system since Aug 15 2017 */
> -if (getenv("QTEST_VHOST_USER_FIXME")) {
> -opts.before = vhost_user_test_setup_reconnect;
> -qos_add_test("vhost-user/reconnect", "virtio-net",
> - test_reconnect, );
> -
> -opts.before = vhost_user_test_setup_connect_fail;
> -qos_add_test("vhost-user/connect-fail", "virtio-net",
> - test_vhost_user_started, );
> -
> -opts.before = vhost_user_test_setup_flags_mismatch;
> -qos_add_test("vhost-user/flags-mismatch", "virtio-net",
> - test_vhost_user_started, );
> -}
> +opts.before = vhost_user_test_setup_reconnect;
> +qos_add_test("vhost-user/reconnect", "virtio-net",
> + test_reconnect, );
> +
> +opts.before = vhost_user_test_setup_connect_fail;
> +qos_add_test("vhost-user/connect-fail", "virtio-net",
> + test_vhost_user_started, );
> +
> +opts.before = vhost_user_test_setup_flags_mismatch;
> +qos_add_test("vhost-user/flags-mismatch", "virtio-net",
> + test_vhost_user_started, );
>
>  opts.before = vhost_user_test_setup_multiqueue;
>  opts.edge.extra_device_opts = "mq=on";
> --
> 2.7.4
>
>



Re: [PATCH v4 6/7] tests/qtest/vhost-user-test: add migrate_reconnect test

2020-09-08 Thread Raphael Norwitz
On Fri, Sep 4, 2020 at 5:36 AM Dima Stepanov  wrote:
>
> Add new migrate_reconnect test for the vhost-user-blk device. Perform a
> disconnect after sending response for the VHOST_USER_SET_LOG_BASE
> command.
>
> Signed-off-by: Dima Stepanov 

Reviewed-by: Raphael Norwitz 


> ---
>  tests/qtest/vhost-user-test.c | 25 +
>  1 file changed, 25 insertions(+)
>
> diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c
> index a8af613..4b715d3 100644
> --- a/tests/qtest/vhost-user-test.c
> +++ b/tests/qtest/vhost-user-test.c
> @@ -146,6 +146,7 @@ static VhostUserMsg m __attribute__ ((unused));
>  enum {
>  TEST_FLAGS_OK,
>  TEST_FLAGS_DISCONNECT,
> +TEST_FLAGS_MIGRATE_DISCONNECT,
>  TEST_FLAGS_BAD,
>  TEST_FLAGS_END,
>  };
> @@ -436,6 +437,15 @@ static void chr_read(void *opaque, const uint8_t *buf, 
> int size)
>  qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE);
>
>  g_cond_broadcast(>data_cond);
> +/*
> + * Perform disconnect after sending a response. In this
> + * case the next write command on the QEMU side (for now
> + * it is SET_FEATURES will return -1, because of disconnect.
> + */
> +if (s->test_flags == TEST_FLAGS_MIGRATE_DISCONNECT) {
> +qemu_chr_fe_disconnect(chr);
> +s->test_flags = TEST_FLAGS_BAD;
> +}
>  break;
>
>  case VHOST_USER_SET_VRING_BASE:
> @@ -737,6 +747,17 @@ static void *vhost_user_test_setup_memfd(GString 
> *cmd_line, void *arg)
>  return server;
>  }
>
> +static void *vhost_user_test_setup_migrate_reconnect(GString *cmd_line,
> +void *arg)
> +{
> +TestServer *server;
> +
> +server = vhost_user_test_setup_memfd(cmd_line, arg);
> +server->test_flags = TEST_FLAGS_MIGRATE_DISCONNECT;
> +
> +return server;
> +}
> +
>  static void test_read_guest_mem(void *obj, void *arg, QGuestAllocator *alloc)
>  {
>  TestServer *server = arg;
> @@ -1150,5 +1171,9 @@ static void register_vhost_user_test(void)
>  opts.before = vhost_user_test_setup_memfd;
>  qos_add_test("migrate", "vhost-user-blk",
>   test_migrate, );
> +
> +opts.before = vhost_user_test_setup_migrate_reconnect;
> +qos_add_test("migrate_reconnect", "vhost-user-blk",
> + test_migrate, );
>  }
>  libqos_init(register_vhost_user_test);
> --
> 2.7.4
>
>



Re: [PATCH v4 5/7] tests/qtest/vhost-user-test: add support for the vhost-user-blk device

2020-09-08 Thread Raphael Norwitz
On Fri, Sep 4, 2020 at 5:35 AM Dima Stepanov  wrote:
>
> Add vhost_user_ops structure for the vhost-user-blk device class. Add
> the test_reconnect and test_migrate tests for this device.
>
> Signed-off-by: Dima Stepanov 

Reviewed-by: Raphael Norwitz 

Just one small suggestion.

> ---
>  tests/qtest/vhost-user-test.c | 139 
> +-
>  1 file changed, 137 insertions(+), 2 deletions(-)

> @@ -857,12 +911,21 @@ static void test_reconnect(void *obj, void *arg, 
> QGuestAllocator *alloc)
>  {
>  TestServer *s = arg;
>  GSource *src;
> +int nq;
>
> +if (s->vu_ops->driver_init) {
> +s->vu_ops->driver_init(obj, alloc);
> +}
>  if (!wait_for_fds(s)) {
>  return;
>  }
>

Maybe we could break this logic out into a helper? I imagine there may
be other cases where we might want to get a number of rings for a
given device type.


> -wait_for_rings_started(s, 2);
> +nq = 1;
> +if (s->vu_ops->type == VHOST_USER_NET) {
> +/* tx and rx queues */
> +nq = 2;
> +}
> +wait_for_rings_started(s, nq);
>



Re: [PATCH v4 4/7] tests/qtest/libqos/virtio-blk: add support for vhost-user-blk

2020-09-08 Thread Raphael Norwitz
On Fri, Sep 4, 2020 at 5:34 AM Dima Stepanov  wrote:
>
> Add support for the vhost-user-blk-pci device. This node can be used by
> the vhost-user-blk tests. Tests for the vhost-user-blk device are added
> in the following patches.
>
> Signed-off-by: Dima Stepanov 
> ---
>  tests/qtest/libqos/virtio-blk.c | 14 ++
>  1 file changed, 14 insertions(+)
>
> diff --git a/tests/qtest/libqos/virtio-blk.c b/tests/qtest/libqos/virtio-blk.c
> index 5da0259..959c5dc 100644
> --- a/tests/qtest/libqos/virtio-blk.c
> +++ b/tests/qtest/libqos/virtio-blk.c
> @@ -36,6 +36,9 @@ static void *qvirtio_blk_get_driver(QVirtioBlk *v_blk,
>  if (!g_strcmp0(interface, "virtio")) {
>  return v_blk->vdev;
>  }
> +if (!g_strcmp0(interface, "vhost-user-blk")) {

Small point but why not merge this conditional with the
!g_strcmp0(interface, "virtio-blk") check above? They both return
v_blk.

Otherwise looks good.

> +return v_blk;
> +}
>
>  fprintf(stderr, "%s not present in virtio-blk-device\n", interface);
>  g_assert_not_reached();
> @@ -120,6 +123,17 @@ static void virtio_blk_register_nodes(void)
>  qos_node_produces("virtio-blk-pci", "virtio-blk");
>
>  g_free(arg);
> +
> +/* vhost-user-blk-pci */
> +arg = g_strdup_printf("id=drv0,chardev=chdev0,addr=%x.%x",
> +PCI_SLOT, PCI_FN);
> +opts.extra_device_opts = arg;
> +add_qpci_address(, );
> +qos_node_create_driver("vhost-user-blk-pci", virtio_blk_pci_create);
> +qos_node_consumes("vhost-user-blk-pci", "pci-bus", );
> +qos_node_produces("vhost-user-blk-pci", "vhost-user-blk");
> +
> +g_free(arg);
>  }
>
>  libqos_init(virtio_blk_register_nodes);
> --
> 2.7.4
>
>



Re: [PATCH v4 3/7] tests/qtest/vhost-user-test: prepare the tests for adding new dev class

2020-09-08 Thread Raphael Norwitz
On Fri, Sep 4, 2020 at 5:32 AM Dima Stepanov  wrote:
>
> For now only vhost-user-net device is supported by the test. Other
> vhost-user devices are not tested. As a first step make source code
> refactoring so new devices can reuse the same test routines. To make
> this provide a new vhost_user_ops structure with the methods to
> initialize device, its command line or make a proper vhost-user
> responses.
>
> Signed-off-by: Dima Stepanov 

Reviewed-by: Raphael Norwitz 

> ---
>  tests/qtest/vhost-user-test.c | 105 
> ++
>  1 file changed, 76 insertions(+), 29 deletions(-)
>
> diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c
> index 9ee0f1e..3df5322 100644
> --- a/tests/qtest/vhost-user-test.c
> +++ b/tests/qtest/vhost-user-test.c
> @@ -135,6 +135,10 @@ enum {
>  TEST_FLAGS_END,
>  };
>
> +enum {
> +VHOST_USER_NET,
> +};
> +
>  typedef struct TestServer {
>  gchar *socket_path;
>  gchar *mig_path;
> @@ -154,10 +158,25 @@ typedef struct TestServer {
>  bool test_fail;
>  int test_flags;
>  int queues;
> +struct vhost_user_ops *vu_ops;
>  } TestServer;
>
> +struct vhost_user_ops {
> +/* Device types. */
> +int type;
> +void (*append_opts)(TestServer *s, GString *cmd_line,
> +const char *chr_opts);
> +
> +/* VHOST-USER commands. */
> +void (*set_features)(TestServer *s, CharBackend *chr,
> +VhostUserMsg *msg);
> +void (*get_protocol_features)(TestServer *s,
> +CharBackend *chr, VhostUserMsg *msg);
> +};
> +
>  static const char *init_hugepagefs(void);
> -static TestServer *test_server_new(const gchar *name);
> +static TestServer *test_server_new(const gchar *name,
> +struct vhost_user_ops *ops);
>  static void test_server_free(TestServer *server);
>  static void test_server_listen(TestServer *server);
>
> @@ -167,7 +186,7 @@ enum test_memfd {
>  TEST_MEMFD_NO,
>  };
>
> -static void append_vhost_opts(TestServer *s, GString *cmd_line,
> +static void append_vhost_net_opts(TestServer *s, GString *cmd_line,
>   const char *chr_opts)
>  {
>  g_string_append_printf(cmd_line, QEMU_CMD_CHR QEMU_CMD_NETDEV,
> @@ -332,25 +351,15 @@ static void chr_read(void *opaque, const uint8_t *buf, 
> int size)
>  break;
>
>  case VHOST_USER_SET_FEATURES:
> -g_assert_cmpint(msg.payload.u64 & (0x1ULL << 
> VHOST_USER_F_PROTOCOL_FEATURES),
> -!=, 0ULL);
> -if (s->test_flags == TEST_FLAGS_DISCONNECT) {
> -qemu_chr_fe_disconnect(chr);
> -s->test_flags = TEST_FLAGS_BAD;
> +if (s->vu_ops->set_features) {
> +s->vu_ops->set_features(s, chr, );
>  }
>  break;
>
>  case VHOST_USER_GET_PROTOCOL_FEATURES:
> -/* send back features to qemu */
> -msg.flags |= VHOST_USER_REPLY_MASK;
> -msg.size = sizeof(m.payload.u64);
> -msg.payload.u64 = 1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD;
> -msg.payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_CROSS_ENDIAN;
> -if (s->queues > 1) {
> -msg.payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_MQ;
> +if (s->vu_ops->get_protocol_features) {
> +s->vu_ops->get_protocol_features(s, chr, );
>  }
> -p = (uint8_t *) 
> -qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
>  break;
>
>  case VHOST_USER_GET_VRING_BASE:
> @@ -467,7 +476,8 @@ static const char *init_hugepagefs(void)
>  #endif
>  }
>
> -static TestServer *test_server_new(const gchar *name)
> +static TestServer *test_server_new(const gchar *name,
> +struct vhost_user_ops *ops)
>  {
>  TestServer *server = g_new0(TestServer, 1);
>  char template[] = "/tmp/vhost-test-XX";
> @@ -495,6 +505,7 @@ static TestServer *test_server_new(const gchar *name)
>
>  server->log_fd = -1;
>  server->queues = 1;
> +server->vu_ops = ops;
>
>  return server;
>  }
> @@ -669,11 +680,11 @@ static void vhost_user_test_cleanup(void *s)
>
>  static void *vhost_user_test_setup(GString *cmd_line, void *arg)
>  {
> -TestServer *server = test_server_new("vhost-user-test");
> +TestServer *server = test_server_new("vhost-user-test", arg);
>  test_server_listen(server);
>
>  append_mem_opts(server, cmd_line, 256, TEST_MEMFD_AUTO);
> -append_vhost_opts(server, cmd_line, "");
> +server->vu_ops->append_opts(server, cmd_line, "");
>
>  g_test_queue_destroy(vhost_user_test_cleanup, server);
>
> @@ -682,11 +693,11 @@ static void *vhost_user_test_setup(GString *cmd_line, 
> void *arg)
>
>  static void *vhost_user_test_setup_memfd(GString *cmd_line, void *arg)
>  {
> -TestServer *server = test_server_new("vhost-user-test");
> +TestServer *server = test_server_new("vhost-user-test", arg);
>  test_server_listen(server);
>
>  append_mem_opts(server, cmd_line, 256, TEST_MEMFD_YES);
> -

Re: [PATCH V2 for-5.2] hw/null-machine: Add the kvm_type() hook for MIPS

2020-09-08 Thread chen huacai
Hi, all,

On Wed, Sep 9, 2020 at 1:25 AM Thomas Huth  wrote:
>
> On 24/08/2020 10.11, Huacai Chen wrote:
> > MIPS has two types of KVM: TE & VZ, and TE is the default type. Now,
> > libvirt uses a null-machine to detect the kvm capability. In the MIPS
> > case, it will return "KVM not supported" on a VZ platform by default.
> > So, add the kvm_type() hook to the null-machine.
> >
> > This seems not a very good solution, but I cannot do it better now.
>
> This is still ugly. Why do the other architectures do not have the
> same problem? Let's see... in kvm-all.c, we have:
>
> int type = 0;
> [...]
> kvm_type = qemu_opt_get(qemu_get_machine_opts(), "kvm-type");
> if (mc->kvm_type) {
> type = mc->kvm_type(ms, kvm_type);
> } else if (kvm_type) {
> ret = -EINVAL;
> fprintf(stderr, "Invalid argument kvm-type=%s\n", kvm_type);
> goto err;
> }
>
> do {
> ret = kvm_ioctl(s, KVM_CREATE_VM, type);
> } while (ret == -EINTR);
>
> Thus the KVM_CREATE_VM ioctl is likely called with type = 0 in this
> case (i.e. when libvirt probes with the "null"-machine).
>
> Now let's have a look at the kernel. The "type" parameter is passed
> there to the architecture specific function kvm_arch_init_vm().
> For powerpc, this looks like:
>
> if (type == 0) {
> if (kvmppc_hv_ops)
> kvm_ops = kvmppc_hv_ops;
> else
> kvm_ops = kvmppc_pr_ops;
> if (!kvm_ops)
> goto err_out;
> } else  if (type == KVM_VM_PPC_HV) {
> if (!kvmppc_hv_ops)
> goto err_out;
> kvm_ops = kvmppc_hv_ops;
> } else if (type == KVM_VM_PPC_PR) {
> if (!kvmppc_pr_ops)
> goto err_out;
> kvm_ops = kvmppc_pr_ops;
> } else
> goto err_out;
>
> That means for type == 0, it automatically detects the best
> kvm-type.
>
> For mips, this function looks like this:
>
> switch (type) {
> #ifdef CONFIG_KVM_MIPS_VZ
> case KVM_VM_MIPS_VZ:
> #else
> case KVM_VM_MIPS_TE:
> #endif
> break;
> default:
> /* Unsupported KVM type */
> return -EINVAL;
> };
>
> That means, for type == 0, it returns -EINVAL here!
>
> Looking at the API docu in Documentation/virt/kvm/api.rst
> the description of the type parameter is quite sparse, but it
> says:
>
>  "You probably want to use 0 as machine type."
>
> So I think this is a bug in the implementation of KVM in the
> mips kernel code. The kvm_arch_init_vm() in the mips code should
> do the same as on powerpc, and use the best available KVM type
> there instead of returning EINVAL. Once that is fixed there,
> you don't need this patch here for QEMU anymore.
Yes, PPC use a good method, because it can use 0 as "automatic"
#define KVM_VM_PPC_HV 1
#define KVM_VM_PPC_PR 2

Unfortunately, MIPS cannot do like this because it define 0 as "TE":
#define KVM_VM_MIPS_TE  0
#define KVM_VM_MIPS_VZ  1

So, it cannot be solved in kernel side, unless changing the definition
of TE/VZ, but I think changing their definition is also unacceptable.

Huacai

>
>  HTH,
>   Thomas
>
>
> > Reviewed-by: Aleksandar Markovic 
> > Signed-off-by: Huacai Chen 
> > Co-developed-by: Jiaxun Yang 
> > ---
> >  hw/core/meson.build| 2 +-
> >  hw/core/null-machine.c | 6 ++
> >  2 files changed, 7 insertions(+), 1 deletion(-)
> >
> > diff --git a/hw/core/meson.build b/hw/core/meson.build
> > index fc91f98..b6591b9 100644
> > --- a/hw/core/meson.build
> > +++ b/hw/core/meson.build
> > @@ -35,7 +35,6 @@ softmmu_ss.add(files(
> >'machine-hmp-cmds.c',
> >'machine.c',
> >'nmi.c',
> > -  'null-machine.c',
> >'qdev-fw.c',
> >'qdev-properties-system.c',
> >'sysbus.c',
> > @@ -45,5 +44,6 @@ softmmu_ss.add(files(
> >
> >  specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files(
> >'machine-qmp-cmds.c',
> > +  'null-machine.c',
> >'numa.c',
> >  ))
> > diff --git a/hw/core/null-machine.c b/hw/core/null-machine.c
> > index 7e69352..4b4ab76 100644
> > --- a/hw/core/null-machine.c
> > +++ b/hw/core/null-machine.c
> > @@ -17,6 +17,9 @@
> >  #include "sysemu/sysemu.h"
> >  #include "exec/address-spaces.h"
> >  #include "hw/core/cpu.h"
> > +#ifdef TARGET_MIPS
> > +#include "kvm_mips.h"
> > +#endif
> >
> >  static void machine_none_init(MachineState *mch)
> >  {
> > @@ -55,6 +58,9 @@ static void machine_none_machine_init(MachineClass *mc)
> >  mc->no_floppy = 1;
> >  mc->no_cdrom = 1;
> >  mc->no_sdcard = 1;
> > +#ifdef TARGET_MIPS
> > +mc->kvm_type = mips_kvm_type;
> > +#endif
> >  }
> >
> >  DEFINE_MACHINE("none", machine_none_machine_init)
> >
>


-- 
Huacai Chen



Re: [PATCH v4 2/7] vhost: check queue state in the vhost_dev_set_log routine

2020-09-08 Thread Raphael Norwitz
On Fri, Sep 4, 2020 at 5:32 AM Dima Stepanov  wrote:
>
> If the vhost-user-blk daemon provides only one virtqueue, but device was
> added with several queues, then QEMU will send more VHOST-USER command
> than expected by daemon side. The vhost_virtqueue_start() routine
> handles such case by checking the return value from the
> virtio_queue_get_desc_addr() function call. Add the same check to the
> vhost_dev_set_log() routine.
>
> Signed-off-by: Dima Stepanov 

Reviewed-by: Raphael Norwitz 


> ---
>  hw/virtio/vhost.c | 12 
>  1 file changed, 12 insertions(+)
>
> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
> index ffef7ab..a08b7d8 100644
> --- a/hw/virtio/vhost.c
> +++ b/hw/virtio/vhost.c
> @@ -825,12 +825,24 @@ static int vhost_dev_set_features(struct vhost_dev *dev,
>  static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log)
>  {
>  int r, i, idx;
> +hwaddr addr;
> +
>  r = vhost_dev_set_features(dev, enable_log);
>  if (r < 0) {
>  goto err_features;
>  }
>  for (i = 0; i < dev->nvqs; ++i) {
>  idx = dev->vhost_ops->vhost_get_vq_index(dev, dev->vq_index + i);
> +addr = virtio_queue_get_desc_addr(dev->vdev, idx);
> +if (!addr) {
> +/*
> + * The queue might not be ready for start. If this
> + * is the case there is no reason to continue the process.
> + * The similar logic is used by the vhost_virtqueue_start()
> + * routine.
> + */
> +continue;
> +}
>  r = vhost_virtqueue_set_addr(dev, dev->vqs + i, idx,
>   enable_log);
>  if (r < 0) {
> --
> 2.7.4
>
>



[Bug 1894818] Re: COLO's guest VNC client hang after failover

2020-09-08 Thread Derek Su
Hi,

I also tested some emulated nic devices and virtio network devices (in
the attachment).

The VNC client's screen cannot be recovered while using all virtio
network devices and the emulated e1000e nic.

Thanks.

Regards,
Derek


** Attachment added: "截圖 2020-09-09 上午10.39.09.png"
   
https://bugs.launchpad.net/qemu/+bug/1894818/+attachment/5408894/+files/%E6%88%AA%E5%9C%96%202020-09-09%20%E4%B8%8A%E5%8D%8810.39.09.png

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

Title:
  COLO's guest VNC client hang after failover

Status in QEMU:
  New

Bug description:
  Hello,

  After setting up COLO's primary and secondary VMs,
  I installed the vncserver and xrdp (apt install tightvncserver xrdp) inside 
the VM.

  I access the VM from another PC via VNC/RDP client, and everything is OK.
  Then, kill the primary VM and issue the failover commands.

  The expected result is that the VNC/RDP client can reconnect and
  resume automatically after failover. (I've confirmed the VNC/RDP
  client can reconnect automatically.)

  But in my test, the VNC client's screen hangs and cannot be recovered
  no longer. I need to restart VNC client by myself.

  BTW, it works well after killing SVM.

  Here is my QEMU networking device
  ```
  -device virtio-net-pci,id=e0,netdev=hn0 \
  -netdev 
tap,id=hn0,br=br0,vhost=off,helper=/usr/local/libexec/qemu-bridge-helper \
  ```

  Thanks.

  Regards,
  Derek

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



Re: [PATCH v2 05/12] target/arm/kvm: spe: Unify device attr operation helper

2020-09-08 Thread Haibo Xu
On Tue, 8 Sep 2020 at 18:56, Andrew Jones  wrote:
>
> On Tue, Sep 08, 2020 at 08:13:23AM +, Haibo Xu wrote:
> > From: Andrew Jones 
> >
> > Rename kvm_arm_pmu_set_attr() to kvm_arm_set_device_attr(),
> > So both the vPMU and vSPE device can share the same API.
> >
> > Signed-off-by: Andrew Jones 
>
> Looks like a faithful port of what I posted as a hunk of another patch, so
> I'll accept the authorship. Please also add you s-b though.
>
> Thanks,
> drew
>

Ok, will fix it in v3.

Thanks,
Haibo

> > ---
> >  target/arm/kvm64.c | 11 ++-
> >  1 file changed, 6 insertions(+), 5 deletions(-)
> >
> > diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
> > index ef1e960285..8ffd31ffdf 100644
> > --- a/target/arm/kvm64.c
> > +++ b/target/arm/kvm64.c
> > @@ -397,19 +397,20 @@ static CPUWatchpoint *find_hw_watchpoint(CPUState 
> > *cpu, target_ulong addr)
> >  return NULL;
> >  }
> >
> > -static bool kvm_arm_pmu_set_attr(CPUState *cs, struct kvm_device_attr 
> > *attr)
> > +static bool kvm_arm_set_device_attr(CPUState *cs, struct kvm_device_attr 
> > *attr,
> > +const char *name)
> >  {
> >  int err;
> >
> >  err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
> >  if (err != 0) {
> > -error_report("PMU: KVM_HAS_DEVICE_ATTR: %s", strerror(-err));
> > +error_report("%s: KVM_HAS_DEVICE_ATTR: %s", name, strerror(-err));
> >  return false;
> >  }
> >
> >  err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr);
> >  if (err != 0) {
> > -error_report("PMU: KVM_SET_DEVICE_ATTR: %s", strerror(-err));
> > +error_report("%s: KVM_SET_DEVICE_ATTR: %s", name, strerror(-err));
> >  return false;
> >  }
> >
> > @@ -426,7 +427,7 @@ void kvm_arm_pmu_init(CPUState *cs)
> >  if (!ARM_CPU(cs)->has_pmu) {
> >  return;
> >  }
> > -if (!kvm_arm_pmu_set_attr(cs, )) {
> > +if (!kvm_arm_set_device_attr(cs, , "PMU")) {
> >  error_report("failed to init PMU");
> >  abort();
> >  }
> > @@ -443,7 +444,7 @@ void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
> >  if (!ARM_CPU(cs)->has_pmu) {
> >  return;
> >  }
> > -if (!kvm_arm_pmu_set_attr(cs, )) {
> > +if (!kvm_arm_set_device_attr(cs, , "PMU")) {
> >  error_report("failed to set irq for PMU");
> >  abort();
> >  }
> > --
> > 2.17.1
> >
> >
>



Re: [RFC 0/4] Add a 'in_mmio' device flag to avoid the DMA to MMIO

2020-09-08 Thread Jason Wang



On 2020/9/9 上午12:41, Li Qiang wrote:

Currently the qemu device fuzzer find some DMA to MMIO issue. If the
device handling MMIO currently trigger a DMA which the address is MMIO,
this will reenter the device MMIO handler. As some of the device doesn't
consider this it will sometimes crash the qemu.

This patch tries to solve this by adding a per-device flag 'in_mmio'.
When the memory core dispatch MMIO it will check/set this flag and when
it leaves it will clean this flag.



What's the plan for fixing the irq issues pointed out by Peter?

Thanks





Li Qiang (4):
   memory: add memory_region_init_io_with_dev interface
   memory: avoid reenter the device's MMIO handler while processing MMIO
   e1000e: use the new memory_region_init_io_with_dev interface
   hcd-xhci: use the new memory_region_init_io_with_dev interface

  hw/net/e1000e.c|  8 
  hw/usb/hcd-xhci.c  | 25 ++-
  include/exec/memory.h  |  9 +
  include/hw/qdev-core.h |  1 +
  softmmu/memory.c   | 46 +++---
  5 files changed, 72 insertions(+), 17 deletions(-)






Re: [RFC 1/4] memory: add memory_region_init_io_with_dev interface

2020-09-08 Thread Jason Wang



On 2020/9/9 上午12:41, Li Qiang wrote:

Currently the MR is not explicitly connecting with its device instead of
a opaque. In most situation this opaque is the deivce but it is not an
enforcement. This patch adds a DeviceState member of to MemoryRegion
we will use it in later patch.



I don't have a deep investigation. But I wonder whether we could make 
sure of owner instead of adding a new field here.


Thanks




Signed-off-by: Li Qiang 
---
  include/exec/memory.h |  9 +
  softmmu/memory.c  | 15 +++
  2 files changed, 24 insertions(+)

diff --git a/include/exec/memory.h b/include/exec/memory.h
index 0cfe987ab4..620fb12d9b 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -404,6 +404,7 @@ struct MemoryRegion {
  const char *name;
  unsigned ioeventfd_nb;
  MemoryRegionIoeventfd *ioeventfds;
+DeviceState *dev;
  };
  
  struct IOMMUMemoryRegion {

@@ -794,6 +795,14 @@ void memory_region_init_io(MemoryRegion *mr,
 const char *name,
 uint64_t size);
  
+void memory_region_init_io_with_dev(MemoryRegion *mr,

+   struct Object *owner,
+   const MemoryRegionOps *ops,
+   void *opaque,
+   const char *name,
+   uint64_t size,
+   DeviceState *dev);
+
  /**
   * memory_region_init_ram_nomigrate:  Initialize RAM memory region.  Accesses
   *into the region will modify memory
diff --git a/softmmu/memory.c b/softmmu/memory.c
index 70b93104e8..2628c9d2d9 100644
--- a/softmmu/memory.c
+++ b/softmmu/memory.c
@@ -1490,6 +1490,21 @@ void memory_region_init_io(MemoryRegion *mr,
  mr->terminates = true;
  }
  
+void memory_region_init_io_with_dev(MemoryRegion *mr,

+   Object *owner,
+   const MemoryRegionOps *ops,
+   void *opaque,
+   const char *name,
+   uint64_t size,
+   DeviceState *dev)
+{
+memory_region_init(mr, owner, name, size);
+mr->ops = ops ? ops : _mem_ops;
+mr->opaque = opaque;
+mr->terminates = true;
+mr->dev = dev;
+}
+
  void memory_region_init_ram_nomigrate(MemoryRegion *mr,
Object *owner,
const char *name,





Re: device compatibility interface for live migration with assigned devices

2020-09-08 Thread Yan Zhao
> > still, I'd like to put it more explicitly to make ensure it's not missed:
> > the reason we want to specify compatible_type as a trait and check
> > whether target compatible_type is the superset of source
> > compatible_type is for the consideration of backward compatibility.
> > e.g.
> > an old generation device may have a mdev type xxx-v4-yyy, while a newer
> > generation  device may be of mdev type xxx-v5-yyy.
> > with the compatible_type traits, the old generation device is still
> > able to be regarded as compatible to newer generation device even their
> > mdev types are not equal.
> 
> If you want to support migration from v4 to v5, can't the (presumably
> newer) driver that supports v5 simply register the v4 type as well, so
> that the mdev can be created as v4? (Just like QEMU versioned machine
> types work.)
yes, it should work in some conditions.
but it may not be that good in some cases when v5 and v4 in the name string
of mdev type identify hardware generation (e.g. v4 for gen8, and v5 for
gen9)

e.g.
(1). when src mdev type is v4 and target mdev type is v5 as
software does not support it initially, and v4 and v5 identify hardware
differences.
then after software upgrade, v5 is now compatible to v4, should the
software now downgrade mdev type from v5 to v4?
not sure if moving hardware generation info into a separate attribute
from mdev type name is better. e.g. remove v4, v5 in mdev type, while use
compatible_pci_ids to identify compatibility.

(2) name string of mdev type is composed by "driver_name + type_name".
in some devices, e.g. qat, different generations of devices are binding to
drivers of different names, e.g. "qat-v4", "qat-v5".
then though type_name is equal, mdev type is not equal. e.g.
"qat-v4-type1", "qat-v5-type1".

Thanks
Yan




Re: [PATCH 2/2] vhost-vdpa: improve error reporting

2020-09-08 Thread Jason Wang



On 2020/9/4 上午2:53, Laurent Vivier wrote:

Use Error framework to report the id of the device and the details of
the error (vhostdev name and errno).

For instance:

  qemu-system-x86_64 ... -netdev vhost-vdpa,id=hostnet1 ...
  hostnet1: Cannot open '/dev/vhost-vdpa-0': No such file or directory

Signed-off-by: Laurent Vivier 
---
  net/vhost-vdpa.c | 14 ++
  1 file changed, 10 insertions(+), 4 deletions(-)



Hi Laurent:

If you don't mind I will add this patch to v2 of my series[1]

Thanks

[1] 
https://lore.kernel.org/qemu-devel/20200831082737.10983-1-jasow...@redhat.com/




diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index 24103ef241e4..8260902334ae 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -176,7 +176,8 @@ static NetClientInfo net_vhost_vdpa_info = {
  };
  
  static int net_vhost_vdpa_init(NetClientState *peer, const char *device,

-   const char *name, const char *vhostdev)
+   const char *name, const char *vhostdev,
+   Error **errp)
  {
  NetClientState *nc = NULL;
  VhostVDPAState *s;
@@ -189,11 +190,15 @@ static int net_vhost_vdpa_init(NetClientState *peer, 
const char *device,
  s = DO_UPCAST(VhostVDPAState, nc, nc);
  vdpa_device_fd = qemu_open(vhostdev, O_RDWR);
  if (vdpa_device_fd == -1) {
-return -errno;
+error_setg_errno(errp, errno, "%s: Cannot open '%s'", name, vhostdev);
+return -1;
  }
  s->vhost_vdpa.device_fd = vdpa_device_fd;
  ret = vhost_vdpa_add(nc, (void *)>vhost_vdpa);
-assert(s->vhost_net);
+if (ret == -1) {
+error_setg(errp, "%s: Cannot add vhost-vdpa '%s'", name, vhostdev);
+return -1;
+}
  return ret;
  }
  
@@ -229,5 +234,6 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name,

  }
  return net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name,
 opts->has_vhostdev ?
-   opts->vhostdev : VHOST_VDPA_DEFAULT_VHOSTDEV);
+   opts->vhostdev : VHOST_VDPA_DEFAULT_VHOSTDEV,
+   errp);
  }





Re: [PATCH 1/2] vhost-vdpa: define and use default value for vhostdev

2020-09-08 Thread Jason Wang



On 2020/9/4 上午2:53, Laurent Vivier wrote:

vhostdev is defined as optional in net.json, and if not set
/dev/vhost-vdpa-0 should be used.

The default value is not set and if vhostdev is not provided
QEMU crashes with a SIGSEGV exception.

Fixes: 1e0a84ea49b6 ("vhost-vdpa: introduce vhost-vdpa net client")
Cc: l...@redhat.com
Signed-off-by: Laurent Vivier 
---
  net/vhost-vdpa.c | 7 ++-
  1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index bc0e0d2d35b7..24103ef241e4 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -24,6 +24,9 @@
  #include "monitor/monitor.h"
  #include "hw/virtio/vhost.h"
  
+/* default vhostdev as defined in qapi/net.json */

+#define VHOST_VDPA_DEFAULT_VHOSTDEV "/dev/vhost-vdpa-0"
+
  /* Todo:need to add the multiqueue support here */
  typedef struct VhostVDPAState {
  NetClientState nc;
@@ -224,5 +227,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char 
*name,
(char *)name, errp)) {
  return -1;
  }
-return net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, opts->vhostdev);
+return net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name,
+   opts->has_vhostdev ?
+   opts->vhostdev : VHOST_VDPA_DEFAULT_VHOSTDEV);
  }



Hi Laurent:

I think having a default path could introduce more confusion here.

So I post a patch to remove the default [1].

Thanks

[1] 
https://lore.kernel.org/qemu-devel/20200831082737.10983-2-jasow...@redhat.com/






Re: [PATCH v8 00/14] Add Nuvoton NPCM730/NPCM750 SoCs and two BMC machines

2020-09-08 Thread Havard Skinnemoen
On Tue, Sep 8, 2020 at 12:52 PM Havard Skinnemoen
 wrote:
>
> On Tue, Sep 8, 2020 at 9:58 AM Philippe Mathieu-Daudé  wrote:
> >
> > On 9/8/20 5:52 PM, Philippe Mathieu-Daudé wrote:
> > > On 9/8/20 5:02 PM, Alexander Bulekov wrote:
> > >> Hi Havard,
> > >> I fuzzed the npcm750-evb machine until I hit over 85% coverage over all
> > >> the new npcm.*\.c files. The only thing I found specific to the new
> > >> code, so far:
> > >>
> > >> cat << EOF | ./qemu-system-arm -machine npcm750-evb -m 128M -qtest stdio
> > >> write 0xf0009040 0x4 0xc4c4c4c4
> > >> write 0xf0009040 0x4 0x4
> > >> EOF
> > >
> > > This is an odd test because with -qtest the timer is not running,
> > > so this can not really happen on real hw.
> > >
> > > The fix is:
> > >
> > > -g_assert(t->remaining_ns > 0);
> > > +g_assert(qtest_enabled() || t->remaining_ns > 0);
> >
> > Alex corrected me on IRC, qtest is irrelevant here.
> > The problem is he disables the timer twice.
> >
> > So maybe something like:
> >
> >  static void npcm7xx_timer_pause(NPCM7xxTimer *t)
> >  {
> >  int64_t now;
> >
> > +if (!timer_pending(>qtimer)) {
> > +return;
> > +}
> >  timer_del(>qtimer);
> >  now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> >  t->remaining_ns = t->expires_ns - now;
> >  g_assert(t->remaining_ns > 0);
> >  }
>
> Thanks, that makes sense. I was worried that making the assert
> conditional on qtest_enabled() might hide real issues.

Hmm, that didn't help, though it might make sense to keep it there anyway.

What the test case does is:

  1. Enable the timer (with zero expiration time) and reset it at the same time.
  2. Disable the timer zero cycles after it was enabled.

It also touches a bunch of other bits (including reserved bits), but
they should be irrelevant.

I think there are two issues here.

When the Reset bit is set, the Enable bit should be forced to zero.
This is easy to fix.

If the timer is enabled with zero expiration time, and immediately
disabled without advancing the virtual time, npcm7xx_timer_pause() is
called while the timer is active, but t->expires_ns ==
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL). So t->remaining_ns becomes zero
and triggers the assertion.

If I revert a change that Philippe asked me to do earlier:

timer_del(>qtimer);
 now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 t->remaining_ns = t->expires_ns - now;
-g_assert(t->remaining_ns > 0);
+if (t->remaining_ns <= 0) {
+npcm7xx_timer_reached_zero(t);
+}
 }

it doesn't crash:

$ cat << EOF | ./qemu-system-arm -machine npcm750-evb -m 128M -qtest
stdio --trace npcm7xx_timer*
write 0xf0009040 0x4 0xc4c4c4c4
write 0xf0009040 0x4 0x4
EOF
[I 1599613445.620379] OPENED
[R +0.180771] write 0xf0009040 0x4 0xc4c4c4c4
1361079@1599613445.801182:npcm7xx_timer_write /machine/soc/tim[1]
offset: 0x0040 value 0xc4c4c4c4
OK
[S +0.180816] OK
[R +0.180833] write 0xf0009040 0x4 0x4
1361079@1599613445.801220:npcm7xx_timer_write /machine/soc/tim[1]
offset: 0x0040 value 0x
1361079@1599613445.801295:npcm7xx_timer_irq /machine/soc/tim[1] timer 4 state 0
OK
[S +0.180927] OK
[I +0.181319] CLOSED
[I +4.003267] CLOSED

Note that the npcm7xx_timer_irq trace event is a sign of the first
bug, but fixing that might mask the second bug. If we write the same
pattern, only without the Reset bit, this would be the correct
behavior (and it still causes the v8 code to crash).

I think this device deserves a qtest. I wonder if we'd trigger the
assertion if we set a nonzero expiration time, but happen to clear the
Enable bit on the exact cycle it's supposed to expire. That would be a
more realistic scenario, as it wouldn't require multiple register
writes in the same virtual clock cycle.

I probably won't add the qtest to the same series, as I'd like someone
from Nuvoton to get a chance to review it first.

Havard

>
> This fuzz testing is great, it would have been hard to find this bug
> without it. Thanks a lot Alex for running it.
>
> Havard
>
> > >
> > >>
> > >> ERROR:../hw/timer/npcm7xx_timer.c:160:npcm7xx_timer_pause: assertion 
> > >> failed: (t->remaining_ns > 0)
> > >> Bail out! ERROR:../hw/timer/npcm7xx_timer.c:160:npcm7xx_timer_pause: 
> > >> assertion failed: (t->remaining_ns > 0)
> > >> Aborted
> > >>
> > >> I'm doing the same for the quanta-gsj machine, but I'm not sure whether
> > >> it will cover more code, so I'm happy to leave a:
> > >>
> > >> Tested-by: Alexander Bulekov 
> > >>
> > >> for the patches that add new virtual-device code (1-5, 7-12 ?)
> > >> -Alex
> > >
> > > Very nice from you for testing running the fuzzer!
> > >
> > > Regards,
> > >
> > > Phil.
> > >
> > >>
> > >>
> > >> On 200824 1716, Havard Skinnemoen via wrote:
> > >>> I also pushed this and the previous patchsets to my qemu fork on github.
> > >>> The branches are named npcm7xx-v[1-8].
> > >>>
> > >>>   https://github.com/hskinnemoen/qemu
> > >>>
> > >>> This patch series models enough of the Nuvoton NPCM730 and NPCM750 SoCs 
> > >>> to 

[PATCH 39/43] tcg/ppc: Convert to tcg-constr.c.inc

2020-09-08 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/ppc/tcg-target-constr.h |  37 ++
 tcg/ppc/tcg-target.c.inc| 135 +++-
 2 files changed, 94 insertions(+), 78 deletions(-)
 create mode 100644 tcg/ppc/tcg-target-constr.h

diff --git a/tcg/ppc/tcg-target-constr.h b/tcg/ppc/tcg-target-constr.h
new file mode 100644
index 00..9a38f8ed89
--- /dev/null
+++ b/tcg/ppc/tcg-target-constr.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * PowerPC target-specific operand constaints. 
+ * Copyright (c) 2020 Linaro
+ */
+
+C_O0_I1(r)
+C_O0_I2(r, r)
+C_O0_I2(r, ri)
+C_O0_I2(S, S)
+C_O0_I2(v, r)
+C_O0_I3(S, S, S)
+C_O0_I4(r, r, ri, ri)
+C_O0_I4(S, S, S, S)
+C_O1_I1(r, L)
+C_O1_I1(r, r)
+C_O1_I1(v, r)
+C_O1_I1(v, v)
+C_O1_I1(v, vr)
+C_O1_I2(r, 0, rZ)
+C_O1_I2(r, L, L)
+C_O1_I2(r, rI, ri)
+C_O1_I2(r, rI, rT)
+C_O1_I2(r, r, r)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, r, rI)
+C_O1_I2(r, r, rT)
+C_O1_I2(r, r, rU)
+C_O1_I2(r, r, rZW)
+C_O1_I2(v, v, v)
+C_O1_I3(v, v, v, v)
+C_O1_I4(r, r, ri, rZ, rZ)
+C_O1_I4(r, r, r, ri, ri)
+C_O2_I1(L, L, L)
+C_O2_I2(L, L, L, L)
+C_O2_I4(r, r, rI, rZM, r, r)
+C_O2_I4(r, r, r, r, rI, rZM)
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 155c42ed24..e34a02ee04 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -3495,62 +3495,20 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece,
 va_end(va);
 }
 
+/* Define all constraint sets. */
+#include "../tcg-constr.c.inc"
+
 static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
 {
-static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
-static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
-static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
-static const TCGTargetOpDef S_S = { .args_ct_str = { "S", "S" } };
-static const TCGTargetOpDef r_ri = { .args_ct_str = { "r", "ri" } };
-static const TCGTargetOpDef r_r_r = { .args_ct_str = { "r", "r", "r" } };
-static const TCGTargetOpDef r_L_L = { .args_ct_str = { "r", "L", "L" } };
-static const TCGTargetOpDef L_L_L = { .args_ct_str = { "L", "L", "L" } };
-static const TCGTargetOpDef S_S_S = { .args_ct_str = { "S", "S", "S" } };
-static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
-static const TCGTargetOpDef r_r_rI = { .args_ct_str = { "r", "r", "rI" } };
-static const TCGTargetOpDef r_r_rT = { .args_ct_str = { "r", "r", "rT" } };
-static const TCGTargetOpDef r_r_rU = { .args_ct_str = { "r", "r", "rU" } };
-static const TCGTargetOpDef r_rI_ri
-= { .args_ct_str = { "r", "rI", "ri" } };
-static const TCGTargetOpDef r_rI_rT
-= { .args_ct_str = { "r", "rI", "rT" } };
-static const TCGTargetOpDef r_r_rZW
-= { .args_ct_str = { "r", "r", "rZW" } };
-static const TCGTargetOpDef L_L_L_L
-= { .args_ct_str = { "L", "L", "L", "L" } };
-static const TCGTargetOpDef S_S_S_S
-= { .args_ct_str = { "S", "S", "S", "S" } };
-static const TCGTargetOpDef movc
-= { .args_ct_str = { "r", "r", "ri", "rZ", "rZ" } };
-static const TCGTargetOpDef dep
-= { .args_ct_str = { "r", "0", "rZ" } };
-static const TCGTargetOpDef br2
-= { .args_ct_str = { "r", "r", "ri", "ri" } };
-static const TCGTargetOpDef setc2
-= { .args_ct_str = { "r", "r", "r", "ri", "ri" } };
-static const TCGTargetOpDef add2
-= { .args_ct_str = { "r", "r", "r", "r", "rI", "rZM" } };
-static const TCGTargetOpDef sub2
-= { .args_ct_str = { "r", "r", "rI", "rZM", "r", "r" } };
-static const TCGTargetOpDef v_r = { .args_ct_str = { "v", "r" } };
-static const TCGTargetOpDef v_vr = { .args_ct_str = { "v", "vr" } };
-static const TCGTargetOpDef v_v = { .args_ct_str = { "v", "v" } };
-static const TCGTargetOpDef v_v_v = { .args_ct_str = { "v", "v", "v" } };
-static const TCGTargetOpDef v_v_v_v
-= { .args_ct_str = { "v", "v", "v", "v" } };
-
 switch (op) {
 case INDEX_op_goto_ptr:
-return 
+return C_O0_I1(r);
 
 case INDEX_op_ld8u_i32:
 case INDEX_op_ld8s_i32:
 case INDEX_op_ld16u_i32:
 case INDEX_op_ld16s_i32:
 case INDEX_op_ld_i32:
-case INDEX_op_st8_i32:
-case INDEX_op_st16_i32:
-case INDEX_op_st_i32:
 case INDEX_op_ctpop_i32:
 case INDEX_op_neg_i32:
 case INDEX_op_not_i32:
@@ -3566,10 +3524,6 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_ld32u_i64:
 case INDEX_op_ld32s_i64:
 case INDEX_op_ld_i64:
-case INDEX_op_st8_i64:
-case INDEX_op_st16_i64:
-case INDEX_op_st32_i64:
-case INDEX_op_st_i64:
 case INDEX_op_ctpop_i64:
 case INDEX_op_neg_i64:
 case INDEX_op_not_i64:
@@ -3582,7 +3536,16 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_bswap32_i64:
 case INDEX_op_bswap64_i64:
 case INDEX_op_extract_i64:
- 

[PATCH 38/43] tcg/mips: Convert to tcg-constr.c.inc

2020-09-08 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target-constr.h | 31 
 tcg/mips/tcg-target.c.inc| 95 
 2 files changed, 61 insertions(+), 65 deletions(-)
 create mode 100644 tcg/mips/tcg-target-constr.h

diff --git a/tcg/mips/tcg-target-constr.h b/tcg/mips/tcg-target-constr.h
new file mode 100644
index 00..831e2d8a01
--- /dev/null
+++ b/tcg/mips/tcg-target-constr.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * MIPS target-specific operand constaints.
+ * Copyright (c) 2020 Linaro
+ */
+
+C_O0_I1(r)
+C_O0_I2(rZ, r)
+C_O0_I2(rZ, rZ)
+C_O0_I2(SZ, S)
+C_O0_I3(SZ, S, S)
+C_O0_I3(SZ, SZ, S)
+C_O0_I4(rZ, rZ, rZ, rZ)
+C_O0_I4(SZ, SZ, S, S)
+C_O1_I1(r, L)
+C_O1_I1(r, r)
+C_O1_I2(r, 0, rZ)
+C_O1_I2(r, L, L)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, r, rI)
+C_O1_I2(r, r, rIK)
+C_O1_I2(r, r, rJ)
+C_O1_I2(r, r, rWZ)
+C_O1_I2(r, rZ, rN)
+C_O1_I2(r, rZ, rZ)
+C_O1_I4(r, rZ, rZ, rZ, 0)
+C_O1_I4(r, rZ, rZ, rZ, rZ)
+C_O2_I1(r, r, L)
+C_O2_I2(r, r, L, L)
+C_O2_I2(r, r, r, r)
+C_O2_I4(r, r, rZ, rZ, rN, rN)
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 3e282c1bde..9e78a79eb6 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -2158,52 +2158,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
 }
 }
 
+/* Define all constraint sets. */
+#include "../tcg-constr.c.inc"
+
 static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
 {
-static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
-static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
-static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
-static const TCGTargetOpDef rZ_r = { .args_ct_str = { "rZ", "r" } };
-static const TCGTargetOpDef SZ_S = { .args_ct_str = { "SZ", "S" } };
-static const TCGTargetOpDef rZ_rZ = { .args_ct_str = { "rZ", "rZ" } };
-static const TCGTargetOpDef r_r_L = { .args_ct_str = { "r", "r", "L" } };
-static const TCGTargetOpDef r_L_L = { .args_ct_str = { "r", "L", "L" } };
-static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
-static const TCGTargetOpDef r_r_rI = { .args_ct_str = { "r", "r", "rI" } };
-static const TCGTargetOpDef r_r_rJ = { .args_ct_str = { "r", "r", "rJ" } };
-static const TCGTargetOpDef SZ_S_S = { .args_ct_str = { "SZ", "S", "S" } };
-static const TCGTargetOpDef SZ_SZ_S
-= { .args_ct_str = { "SZ", "SZ", "S" } };
-static const TCGTargetOpDef SZ_SZ_S_S
-= { .args_ct_str = { "SZ", "SZ", "S", "S" } };
-static const TCGTargetOpDef r_rZ_rN
-= { .args_ct_str = { "r", "rZ", "rN" } };
-static const TCGTargetOpDef r_rZ_rZ
-= { .args_ct_str = { "r", "rZ", "rZ" } };
-static const TCGTargetOpDef r_r_rIK
-= { .args_ct_str = { "r", "r", "rIK" } };
-static const TCGTargetOpDef r_r_rWZ
-= { .args_ct_str = { "r", "r", "rWZ" } };
-static const TCGTargetOpDef r_r_r_r
-= { .args_ct_str = { "r", "r", "r", "r" } };
-static const TCGTargetOpDef r_r_L_L
-= { .args_ct_str = { "r", "r", "L", "L" } };
-static const TCGTargetOpDef dep
-= { .args_ct_str = { "r", "0", "rZ" } };
-static const TCGTargetOpDef movc
-= { .args_ct_str = { "r", "rZ", "rZ", "rZ", "0" } };
-static const TCGTargetOpDef movc_r6
-= { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
-static const TCGTargetOpDef add2
-= { .args_ct_str = { "r", "r", "rZ", "rZ", "rN", "rN" } };
-static const TCGTargetOpDef br2
-= { .args_ct_str = { "rZ", "rZ", "rZ", "rZ" } };
-static const TCGTargetOpDef setc2
-= { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
-
 switch (op) {
 case INDEX_op_goto_ptr:
-return 
+return C_O0_I1(r);
 
 case INDEX_op_ld8u_i32:
 case INDEX_op_ld8s_i32:
@@ -2236,7 +2198,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_extrl_i64_i32:
 case INDEX_op_extrh_i64_i32:
 case INDEX_op_extract_i64:
-return _r;
+return C_O1_I1(r, r);
 
 case INDEX_op_st8_i32:
 case INDEX_op_st16_i32:
@@ -2245,14 +2207,14 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_st16_i64:
 case INDEX_op_st32_i64:
 case INDEX_op_st_i64:
-return _r;
+return C_O0_I2(rZ, r);
 
 case INDEX_op_add_i32:
 case INDEX_op_add_i64:
-return _r_rJ;
+return C_O1_I2(r, r, rJ);
 case INDEX_op_sub_i32:
 case INDEX_op_sub_i64:
-return _rZ_rN;
+return C_O1_I2(r, rZ, rN);
 case INDEX_op_mul_i32:
 case INDEX_op_mulsh_i32:
 case INDEX_op_muluh_i32:
@@ -2271,20 +2233,20 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_remu_i64:
 case INDEX_op_nor_i64:
 case INDEX_op_setcond_i64:
-return _rZ_rZ;
+return C_O1_I2(r, rZ, rZ);
 case INDEX_op_muls2_i32:

[PATCH 43/43] tcg/tci: Convert to tcg-constr.c.inc

2020-09-08 Thread Richard Henderson
This does require finishing the conversion to tcg_target_op_def.
Remove quite a lot of ifdefs, since we can reference opcodes
even if they are not implemented.

Signed-off-by: Richard Henderson 
---
 tcg/tci/tcg-target-constr.h |  28 +++
 tcg/tci/tcg-target.c.inc| 360 ++--
 2 files changed, 163 insertions(+), 225 deletions(-)
 create mode 100644 tcg/tci/tcg-target-constr.h

diff --git a/tcg/tci/tcg-target-constr.h b/tcg/tci/tcg-target-constr.h
new file mode 100644
index 00..6658e905e6
--- /dev/null
+++ b/tcg/tci/tcg-target-constr.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * TCI target-specific operand constaints.
+ * Copyright (c) 2020 Linaro
+ */
+
+C_O0_I2(r, r)
+C_O0_I2(r, ri)
+C_O0_I2(r, S)
+C_O0_I3(r, r, S)
+C_O0_I3(r, S, S)
+C_O0_I4(r, r, S, S)
+C_O1_I1(r, L)
+C_O1_I1(r, r)
+C_O1_I2(r, 0, r)
+C_O1_I2(r, L, L)
+C_O1_I2(r, ri, ri)
+C_O1_I2(r, r, r)
+C_O1_I2(r, r, ri)
+C_O2_I1(r, r, L)
+C_O2_I2(r, r, L, L)
+
+#if TCG_TARGET_REG_BITS == 32
+C_O0_I4(r, r, ri, ri)
+C_O1_I4(r, r, r, ri, ri)
+C_O2_I2(r, r, r, r)
+C_O2_I4(r, r, r, r, r, r)
+#endif
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
index 25ed868505..350cb498d7 100644
--- a/tcg/tci/tcg-target.c.inc
+++ b/tcg/tci/tcg-target.c.inc
@@ -37,236 +37,146 @@
 /* Bitfield n...m (in 32 bit value). */
 #define BITS(n, m) (((0xU << (31 - n)) >> (31 - n + m)) << m)
 
-/* Macros used in tcg_target_op_defs. */
-#define R   "r"
-#define RI  "ri"
-#if TCG_TARGET_REG_BITS == 32
-# define R64"r", "r"
-#else
-# define R64"r"
-#endif
-#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
-# define L  "L", "L"
-# define S  "S", "S"
-#else
-# define L  "L"
-# define S  "S"
-#endif
-
-/* TODO: documentation. */
-static const TCGTargetOpDef tcg_target_op_defs[] = {
-{ INDEX_op_exit_tb, { NULL } },
-{ INDEX_op_goto_tb, { NULL } },
-{ INDEX_op_br, { NULL } },
-
-{ INDEX_op_ld8u_i32, { R, R } },
-{ INDEX_op_ld8s_i32, { R, R } },
-{ INDEX_op_ld16u_i32, { R, R } },
-{ INDEX_op_ld16s_i32, { R, R } },
-{ INDEX_op_ld_i32, { R, R } },
-{ INDEX_op_st8_i32, { R, R } },
-{ INDEX_op_st16_i32, { R, R } },
-{ INDEX_op_st_i32, { R, R } },
-
-{ INDEX_op_add_i32, { R, RI, RI } },
-{ INDEX_op_sub_i32, { R, RI, RI } },
-{ INDEX_op_mul_i32, { R, RI, RI } },
-#if TCG_TARGET_HAS_div_i32
-{ INDEX_op_div_i32, { R, R, R } },
-{ INDEX_op_divu_i32, { R, R, R } },
-{ INDEX_op_rem_i32, { R, R, R } },
-{ INDEX_op_remu_i32, { R, R, R } },
-#elif TCG_TARGET_HAS_div2_i32
-{ INDEX_op_div2_i32, { R, R, "0", "1", R } },
-{ INDEX_op_divu2_i32, { R, R, "0", "1", R } },
-#endif
-/* TODO: Does R, RI, RI result in faster code than R, R, RI?
-   If both operands are constants, we can optimize. */
-{ INDEX_op_and_i32, { R, RI, RI } },
-#if TCG_TARGET_HAS_andc_i32
-{ INDEX_op_andc_i32, { R, RI, RI } },
-#endif
-#if TCG_TARGET_HAS_eqv_i32
-{ INDEX_op_eqv_i32, { R, RI, RI } },
-#endif
-#if TCG_TARGET_HAS_nand_i32
-{ INDEX_op_nand_i32, { R, RI, RI } },
-#endif
-#if TCG_TARGET_HAS_nor_i32
-{ INDEX_op_nor_i32, { R, RI, RI } },
-#endif
-{ INDEX_op_or_i32, { R, RI, RI } },
-#if TCG_TARGET_HAS_orc_i32
-{ INDEX_op_orc_i32, { R, RI, RI } },
-#endif
-{ INDEX_op_xor_i32, { R, RI, RI } },
-{ INDEX_op_shl_i32, { R, RI, RI } },
-{ INDEX_op_shr_i32, { R, RI, RI } },
-{ INDEX_op_sar_i32, { R, RI, RI } },
-#if TCG_TARGET_HAS_rot_i32
-{ INDEX_op_rotl_i32, { R, RI, RI } },
-{ INDEX_op_rotr_i32, { R, RI, RI } },
-#endif
-#if TCG_TARGET_HAS_deposit_i32
-{ INDEX_op_deposit_i32, { R, "0", R } },
-#endif
-
-{ INDEX_op_brcond_i32, { R, RI } },
-
-{ INDEX_op_setcond_i32, { R, R, RI } },
-#if TCG_TARGET_REG_BITS == 64
-{ INDEX_op_setcond_i64, { R, R, RI } },
-#endif /* TCG_TARGET_REG_BITS == 64 */
-
-#if TCG_TARGET_REG_BITS == 32
-/* TODO: Support R, R, R, R, RI, RI? Will it be faster? */
-{ INDEX_op_add2_i32, { R, R, R, R, R, R } },
-{ INDEX_op_sub2_i32, { R, R, R, R, R, R } },
-{ INDEX_op_brcond2_i32, { R, R, RI, RI } },
-{ INDEX_op_mulu2_i32, { R, R, R, R } },
-{ INDEX_op_setcond2_i32, { R, R, R, RI, RI } },
-#endif
-
-#if TCG_TARGET_HAS_not_i32
-{ INDEX_op_not_i32, { R, R } },
-#endif
-#if TCG_TARGET_HAS_neg_i32
-{ INDEX_op_neg_i32, { R, R } },
-#endif
-
-#if TCG_TARGET_REG_BITS == 64
-{ INDEX_op_ld8u_i64, { R, R } },
-{ INDEX_op_ld8s_i64, { R, R } },
-{ INDEX_op_ld16u_i64, { R, R } },
-{ INDEX_op_ld16s_i64, { R, R } },
-{ INDEX_op_ld32u_i64, { R, R } },
-{ INDEX_op_ld32s_i64, { R, R } },
-{ INDEX_op_ld_i64, { R, R } },
-
-{ INDEX_op_st8_i64, { R, R } },
-{ INDEX_op_st16_i64, { R, R } },
-{ INDEX_op_st32_i64, { R, R } },
-{ INDEX_op_st_i64, { R, R } },
-
-{ INDEX_op_add_i64, { R, RI, RI } },
-{ INDEX_op_sub_i64, { R, RI, RI } },
-{ INDEX_op_mul_i64, { R, RI, RI } },
-#if 

[PATCH 37/43] tcg/arm: Convert to tcg-constr.c.inc

2020-09-08 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/arm/tcg-target-constr.h | 30 
 tcg/arm/tcg-target.c.inc| 93 +
 2 files changed, 63 insertions(+), 60 deletions(-)
 create mode 100644 tcg/arm/tcg-target-constr.h

diff --git a/tcg/arm/tcg-target-constr.h b/tcg/arm/tcg-target-constr.h
new file mode 100644
index 00..c59be2da11
--- /dev/null
+++ b/tcg/arm/tcg-target-constr.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * ARM32 target-specific operand constaints. 
+ * Copyright (c) 2020 Linaro
+ */
+
+C_O0_I1(r)
+C_O0_I2(r, r)
+C_O0_I2(r, rIN)
+C_O0_I2(s, s)
+C_O0_I3(s, s, s)
+C_O0_I4(r, r, rI, rI)
+C_O0_I4(s, s, s, s)
+C_O1_I1(r, l)
+C_O1_I1(r, r)
+C_O1_I2(r, 0, rZ)
+C_O1_I2(r, l, l)
+C_O1_I2(r, r, r)
+C_O1_I2(r, r, rI)
+C_O1_I2(r, r, rIK)
+C_O1_I2(r, r, rIN)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, rZ, rZ)
+C_O1_I4(r, r, r, rI, rI)
+C_O1_I4(r, r, rIN, rIK, 0)
+C_O2_I1(r, r, l)
+C_O2_I2(r, r, l, l)
+C_O2_I2(r, r, r, r)
+C_O2_I4(r, r, r, r, rIN, rIK)
+C_O2_I4(r, r, rI, rI, rIN, rIK)
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index 30d30874c7..70a9e798e3 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -2071,57 +2071,20 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
 }
 }
 
+/* Define all constraint sets. */
+#include "../tcg-constr.c.inc"
+
 static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
 {
-static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
-static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
-static const TCGTargetOpDef s_s = { .args_ct_str = { "s", "s" } };
-static const TCGTargetOpDef r_l = { .args_ct_str = { "r", "l" } };
-static const TCGTargetOpDef r_r_r = { .args_ct_str = { "r", "r", "r" } };
-static const TCGTargetOpDef r_r_l = { .args_ct_str = { "r", "r", "l" } };
-static const TCGTargetOpDef r_l_l = { .args_ct_str = { "r", "l", "l" } };
-static const TCGTargetOpDef s_s_s = { .args_ct_str = { "s", "s", "s" } };
-static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
-static const TCGTargetOpDef r_r_rI = { .args_ct_str = { "r", "r", "rI" } };
-static const TCGTargetOpDef r_r_rIN
-= { .args_ct_str = { "r", "r", "rIN" } };
-static const TCGTargetOpDef r_r_rIK
-= { .args_ct_str = { "r", "r", "rIK" } };
-static const TCGTargetOpDef r_r_r_r
-= { .args_ct_str = { "r", "r", "r", "r" } };
-static const TCGTargetOpDef r_r_l_l
-= { .args_ct_str = { "r", "r", "l", "l" } };
-static const TCGTargetOpDef s_s_s_s
-= { .args_ct_str = { "s", "s", "s", "s" } };
-static const TCGTargetOpDef br
-= { .args_ct_str = { "r", "rIN" } };
-static const TCGTargetOpDef ext2
-= { .args_ct_str = { "r", "rZ", "rZ" } };
-static const TCGTargetOpDef dep
-= { .args_ct_str = { "r", "0", "rZ" } };
-static const TCGTargetOpDef movc
-= { .args_ct_str = { "r", "r", "rIN", "rIK", "0" } };
-static const TCGTargetOpDef add2
-= { .args_ct_str = { "r", "r", "r", "r", "rIN", "rIK" } };
-static const TCGTargetOpDef sub2
-= { .args_ct_str = { "r", "r", "rI", "rI", "rIN", "rIK" } };
-static const TCGTargetOpDef br2
-= { .args_ct_str = { "r", "r", "rI", "rI" } };
-static const TCGTargetOpDef setc2
-= { .args_ct_str = { "r", "r", "r", "rI", "rI" } };
-
 switch (op) {
 case INDEX_op_goto_ptr:
-return 
+return C_O0_I1(r);
 
 case INDEX_op_ld8u_i32:
 case INDEX_op_ld8s_i32:
 case INDEX_op_ld16u_i32:
 case INDEX_op_ld16s_i32:
 case INDEX_op_ld_i32:
-case INDEX_op_st8_i32:
-case INDEX_op_st16_i32:
-case INDEX_op_st_i32:
 case INDEX_op_neg_i32:
 case INDEX_op_not_i32:
 case INDEX_op_bswap16_i32:
@@ -2131,59 +2094,69 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_ext16u_i32:
 case INDEX_op_extract_i32:
 case INDEX_op_sextract_i32:
-return _r;
+return C_O1_I1(r, r);
+
+case INDEX_op_st8_i32:
+case INDEX_op_st16_i32:
+case INDEX_op_st_i32:
+return C_O0_I2(r, r);
 
 case INDEX_op_add_i32:
 case INDEX_op_sub_i32:
 case INDEX_op_setcond_i32:
-return _r_rIN;
+return C_O1_I2(r, r, rIN);
+
 case INDEX_op_and_i32:
 case INDEX_op_andc_i32:
 case INDEX_op_clz_i32:
 case INDEX_op_ctz_i32:
-return _r_rIK;
+return C_O1_I2(r, r, rIK);
+
 case INDEX_op_mul_i32:
 case INDEX_op_div_i32:
 case INDEX_op_divu_i32:
-return _r_r;
+return C_O1_I2(r, r, r);
+
 case INDEX_op_mulu2_i32:
 case INDEX_op_muls2_i32:
-return _r_r_r;
+return C_O2_I2(r, r, r, r);
+
 case INDEX_op_or_i32:
 case INDEX_op_xor_i32:
-return _r_rI;
+return C_O1_I2(r, r, rI);
+
 case INDEX_op_shl_i32:
 case INDEX_op_shr_i32:
 case 

[PATCH 42/43] tcg/sparc: Convert to tcg-constr.c.inc

2020-09-08 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/sparc/tcg-target-constr.h | 27 +
 tcg/sparc/tcg-target.c.inc| 74 ---
 2 files changed, 51 insertions(+), 50 deletions(-)
 create mode 100644 tcg/sparc/tcg-target-constr.h

diff --git a/tcg/sparc/tcg-target-constr.h b/tcg/sparc/tcg-target-constr.h
new file mode 100644
index 00..28aec2ae0f
--- /dev/null
+++ b/tcg/sparc/tcg-target-constr.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Sparc target-specific operand constaints.
+ * Copyright (c) 2020 Linaro
+ */
+
+C_O0_I1(r)
+C_O0_I2(rZ, r)
+C_O0_I2(RZ, r)
+C_O0_I2(rZ, rJ)
+C_O0_I2(RZ, RJ)
+C_O0_I2(sZ, A)
+C_O0_I2(SZ, A)
+C_O1_I1(r, A)
+C_O1_I1(R, A)
+C_O1_I1(r, r)
+C_O1_I1(r, R)
+C_O1_I1(R, r)
+C_O1_I1(R, R)
+C_O1_I2(R, R, R)
+C_O1_I2(r, rZ, rJ)
+C_O1_I2(R, RZ, RJ)
+C_O1_I4(r, rZ, rJ, rI, 0)
+C_O1_I4(R, RZ, RJ, RI, 0)
+C_O2_I2(r, r, rZ, rJ)
+C_O2_I4(R, R, RZ, RZ, RJ, RI)
+C_O2_I4(r, r, rZ, rZ, rJ, rJ)
diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc
index af480115c5..aa426a1c90 100644
--- a/tcg/sparc/tcg-target.c.inc
+++ b/tcg/sparc/tcg-target.c.inc
@@ -1592,40 +1592,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 }
 }
 
+/* Define all constraint sets. */
+#include "../tcg-constr.c.inc"
+
 static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
 {
-static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
-static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
-static const TCGTargetOpDef R_r = { .args_ct_str = { "R", "r" } };
-static const TCGTargetOpDef r_R = { .args_ct_str = { "r", "R" } };
-static const TCGTargetOpDef R_R = { .args_ct_str = { "R", "R" } };
-static const TCGTargetOpDef r_A = { .args_ct_str = { "r", "A" } };
-static const TCGTargetOpDef R_A = { .args_ct_str = { "R", "A" } };
-static const TCGTargetOpDef rZ_r = { .args_ct_str = { "rZ", "r" } };
-static const TCGTargetOpDef RZ_r = { .args_ct_str = { "RZ", "r" } };
-static const TCGTargetOpDef sZ_A = { .args_ct_str = { "sZ", "A" } };
-static const TCGTargetOpDef SZ_A = { .args_ct_str = { "SZ", "A" } };
-static const TCGTargetOpDef rZ_rJ = { .args_ct_str = { "rZ", "rJ" } };
-static const TCGTargetOpDef RZ_RJ = { .args_ct_str = { "RZ", "RJ" } };
-static const TCGTargetOpDef R_R_R = { .args_ct_str = { "R", "R", "R" } };
-static const TCGTargetOpDef r_rZ_rJ
-= { .args_ct_str = { "r", "rZ", "rJ" } };
-static const TCGTargetOpDef R_RZ_RJ
-= { .args_ct_str = { "R", "RZ", "RJ" } };
-static const TCGTargetOpDef r_r_rZ_rJ
-= { .args_ct_str = { "r", "r", "rZ", "rJ" } };
-static const TCGTargetOpDef movc_32
-= { .args_ct_str = { "r", "rZ", "rJ", "rI", "0" } };
-static const TCGTargetOpDef movc_64
-= { .args_ct_str = { "R", "RZ", "RJ", "RI", "0" } };
-static const TCGTargetOpDef add2_32
-= { .args_ct_str = { "r", "r", "rZ", "rZ", "rJ", "rJ" } };
-static const TCGTargetOpDef add2_64
-= { .args_ct_str = { "R", "R", "RZ", "RZ", "RJ", "RI" } };
-
 switch (op) {
 case INDEX_op_goto_ptr:
-return 
+return C_O0_I1(r);
 
 case INDEX_op_ld8u_i32:
 case INDEX_op_ld8s_i32:
@@ -1634,12 +1608,12 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_ld_i32:
 case INDEX_op_neg_i32:
 case INDEX_op_not_i32:
-return _r;
+return C_O1_I1(r, r);
 
 case INDEX_op_st8_i32:
 case INDEX_op_st16_i32:
 case INDEX_op_st_i32:
-return _r;
+return C_O0_I2(rZ, r);
 
 case INDEX_op_add_i32:
 case INDEX_op_mul_i32:
@@ -1655,18 +1629,18 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_shr_i32:
 case INDEX_op_sar_i32:
 case INDEX_op_setcond_i32:
-return _rZ_rJ;
+return C_O1_I2(r, rZ, rJ);
 
 case INDEX_op_brcond_i32:
-return _rJ;
+return C_O0_I2(rZ, rJ);
 case INDEX_op_movcond_i32:
-return _32;
+return C_O1_I4(r, rZ, rJ, rI, 0);
 case INDEX_op_add2_i32:
 case INDEX_op_sub2_i32:
-return _32;
+return C_O2_I4(r, r, rZ, rZ, rJ, rJ);
 case INDEX_op_mulu2_i32:
 case INDEX_op_muls2_i32:
-return _r_rZ_rJ;
+return C_O2_I2(r, r, rZ, rJ);
 
 case INDEX_op_ld8u_i64:
 case INDEX_op_ld8s_i64:
@@ -1677,13 +1651,13 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_ld_i64:
 case INDEX_op_ext_i32_i64:
 case INDEX_op_extu_i32_i64:
-return _r;
+return C_O1_I1(R, r);
 
 case INDEX_op_st8_i64:
 case INDEX_op_st16_i64:
 case INDEX_op_st32_i64:
 case INDEX_op_st_i64:
-return _r;
+return C_O0_I2(RZ, r);
 
 case INDEX_op_add_i64:
 case INDEX_op_mul_i64:
@@ -1699,36 +1673,36 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_shr_i64:
 case 

[PATCH 36/43] tcg/aarch64: Convert to tcg-constr.c.inc

2020-09-08 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/aarch64/tcg-target-constr.h | 31 
 tcg/aarch64/tcg-target.c.inc| 85 +++--
 2 files changed, 60 insertions(+), 56 deletions(-)
 create mode 100644 tcg/aarch64/tcg-target-constr.h

diff --git a/tcg/aarch64/tcg-target-constr.h b/tcg/aarch64/tcg-target-constr.h
new file mode 100644
index 00..dcf46a7457
--- /dev/null
+++ b/tcg/aarch64/tcg-target-constr.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * AArch64 target-specific operand constaints.
+ * Copyright (c) 2020 Linaro
+ */
+
+C_O0_I1(r)
+C_O0_I2(lZ, l)
+C_O0_I2(r, rA)
+C_O0_I2(rZ, r)
+C_O0_I2(w, r)
+C_O1_I1(r, l)
+C_O1_I1(r, r)
+C_O1_I1(w, r)
+C_O1_I1(w, w)
+C_O1_I1(w, wr)
+C_O1_I2(r, 0, rZ)
+C_O1_I2(r, r, r)
+C_O1_I2(r, r, rA)
+C_O1_I2(r, r, rAL)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, r, rL)
+C_O1_I2(r, rZ, rZ)
+C_O1_I2(w, 0, w)
+C_O1_I2(w, w, w)
+C_O1_I2(w, w, wN)
+C_O1_I2(w, w, wO)
+C_O1_I2(w, w, wZ)
+C_O1_I3(w, w, w, w)
+C_O1_I4(r, r, rA, rZ, rZ)
+C_O2_I4(r, r, rZ, rZ, rA, rMZ)
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index d9d397075a..e352f7f56b 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -2577,42 +2577,14 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece,
 va_end(va);
 }
 
+/* Define all constraint sets. */
+#include "../tcg-constr.c.inc"
+
 static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
 {
-static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
-static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
-static const TCGTargetOpDef w_w = { .args_ct_str = { "w", "w" } };
-static const TCGTargetOpDef w_r = { .args_ct_str = { "w", "r" } };
-static const TCGTargetOpDef w_wr = { .args_ct_str = { "w", "wr" } };
-static const TCGTargetOpDef r_l = { .args_ct_str = { "r", "l" } };
-static const TCGTargetOpDef r_rA = { .args_ct_str = { "r", "rA" } };
-static const TCGTargetOpDef rZ_r = { .args_ct_str = { "rZ", "r" } };
-static const TCGTargetOpDef lZ_l = { .args_ct_str = { "lZ", "l" } };
-static const TCGTargetOpDef r_r_r = { .args_ct_str = { "r", "r", "r" } };
-static const TCGTargetOpDef w_w_w = { .args_ct_str = { "w", "w", "w" } };
-static const TCGTargetOpDef w_0_w = { .args_ct_str = { "w", "0", "w" } };
-static const TCGTargetOpDef w_w_wO = { .args_ct_str = { "w", "w", "wO" } };
-static const TCGTargetOpDef w_w_wN = { .args_ct_str = { "w", "w", "wN" } };
-static const TCGTargetOpDef w_w_wZ = { .args_ct_str = { "w", "w", "wZ" } };
-static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
-static const TCGTargetOpDef r_r_rA = { .args_ct_str = { "r", "r", "rA" } };
-static const TCGTargetOpDef r_r_rL = { .args_ct_str = { "r", "r", "rL" } };
-static const TCGTargetOpDef r_r_rAL
-= { .args_ct_str = { "r", "r", "rAL" } };
-static const TCGTargetOpDef dep
-= { .args_ct_str = { "r", "0", "rZ" } };
-static const TCGTargetOpDef ext2
-= { .args_ct_str = { "r", "rZ", "rZ" } };
-static const TCGTargetOpDef movc
-= { .args_ct_str = { "r", "r", "rA", "rZ", "rZ" } };
-static const TCGTargetOpDef add2
-= { .args_ct_str = { "r", "r", "rZ", "rZ", "rA", "rMZ" } };
-static const TCGTargetOpDef w_w_w_w
-= { .args_ct_str = { "w", "w", "w", "w" } };
-
 switch (op) {
 case INDEX_op_goto_ptr:
-return 
+return C_O0_I1(r);
 
 case INDEX_op_ld8u_i32:
 case INDEX_op_ld8s_i32:
@@ -2651,7 +2623,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_extract_i64:
 case INDEX_op_sextract_i32:
 case INDEX_op_sextract_i64:
-return _r;
+return C_O1_I1(r, r);
 
 case INDEX_op_st8_i32:
 case INDEX_op_st16_i32:
@@ -2660,7 +2632,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_st16_i64:
 case INDEX_op_st32_i64:
 case INDEX_op_st_i64:
-return _r;
+return C_O0_I2(rZ, r);
 
 case INDEX_op_add_i32:
 case INDEX_op_add_i64:
@@ -2668,7 +2640,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_sub_i64:
 case INDEX_op_setcond_i32:
 case INDEX_op_setcond_i64:
-return _r_rA;
+return C_O1_I2(r, r, rA);
 
 case INDEX_op_mul_i32:
 case INDEX_op_mul_i64:
@@ -2682,7 +2654,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_remu_i64:
 case INDEX_op_muluh_i64:
 case INDEX_op_mulsh_i64:
-return _r_r;
+return C_O1_I2(r, r, r);
 
 case INDEX_op_and_i32:
 case INDEX_op_and_i64:
@@ -2696,7 +2668,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_orc_i64:
 case INDEX_op_eqv_i32:
 case INDEX_op_eqv_i64:
-return _r_rL;
+return C_O1_I2(r, r, rL);
 
 case INDEX_op_shl_i32:
 

[PATCH 41/43] tcg/s390: Convert to tcg-constr.c.inc

2020-09-08 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/s390/tcg-target-constr.h |  24 +++
 tcg/s390/tcg-target.c.inc| 119 +++
 2 files changed, 76 insertions(+), 67 deletions(-)
 create mode 100644 tcg/s390/tcg-target-constr.h

diff --git a/tcg/s390/tcg-target-constr.h b/tcg/s390/tcg-target-constr.h
new file mode 100644
index 00..06c1f4a944
--- /dev/null
+++ b/tcg/s390/tcg-target-constr.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * S390 target-specific operand constaints.
+ * Copyright (c) 2020 Linaro
+ */
+
+C_O0_I1(r)
+C_O0_I2(L, L)
+C_O0_I2(r, r)
+C_O0_I2(r, ri)
+C_O1_I1(r, L)
+C_O1_I1(r, r)
+C_O1_I2(r, 0, ri)
+C_O1_I2(r, 0, rI)
+C_O1_I2(r, 0, rJ)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, rZ, r)
+C_O1_I4(r, r, ri, r, 0)
+C_O1_I4(r, r, ri, rI, 0)
+C_O2_I2(b, a, 0, r)
+C_O2_I3(b, a, 0, 1, r)
+C_O2_I4(r, r, 0, 1, rA, r)
+C_O2_I4(r, r, 0, 1, ri, r)
+C_O2_I4(r, r, 0, 1, r, r)
diff --git a/tcg/s390/tcg-target.c.inc b/tcg/s390/tcg-target.c.inc
index 824a07aa7a..c628194421 100644
--- a/tcg/s390/tcg-target.c.inc
+++ b/tcg/s390/tcg-target.c.inc
@@ -2312,27 +2312,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
 }
 }
 
+/* Define all constraint sets. */
+#include "../tcg-constr.c.inc"
+
 static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
 {
-static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
-static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
-static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
-static const TCGTargetOpDef L_L = { .args_ct_str = { "L", "L" } };
-static const TCGTargetOpDef r_ri = { .args_ct_str = { "r", "ri" } };
-static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
-static const TCGTargetOpDef r_0_ri = { .args_ct_str = { "r", "0", "ri" } };
-static const TCGTargetOpDef r_0_rI = { .args_ct_str = { "r", "0", "rI" } };
-static const TCGTargetOpDef r_0_rJ = { .args_ct_str = { "r", "0", "rJ" } };
-static const TCGTargetOpDef a2_r
-= { .args_ct_str = { "r", "r", "0", "1", "r", "r" } };
-static const TCGTargetOpDef a2_ri
-= { .args_ct_str = { "r", "r", "0", "1", "ri", "r" } };
-static const TCGTargetOpDef a2_rA
-= { .args_ct_str = { "r", "r", "0", "1", "rA", "r" } };
-
 switch (op) {
 case INDEX_op_goto_ptr:
-return 
+return C_O0_I1(r);
 
 case INDEX_op_ld8u_i32:
 case INDEX_op_ld8u_i64:
@@ -2346,6 +2333,8 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_ld32u_i64:
 case INDEX_op_ld32s_i64:
 case INDEX_op_ld_i64:
+return C_O1_I1(r, r);
+
 case INDEX_op_st8_i32:
 case INDEX_op_st8_i64:
 case INDEX_op_st16_i32:
@@ -2353,11 +2342,22 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_st_i32:
 case INDEX_op_st32_i64:
 case INDEX_op_st_i64:
-return _r;
+return C_O0_I2(r, r);
 
 case INDEX_op_add_i32:
 case INDEX_op_add_i64:
-return _r_ri;
+case INDEX_op_shl_i64:
+case INDEX_op_shr_i64:
+case INDEX_op_sar_i64:
+case INDEX_op_rotl_i32:
+case INDEX_op_rotl_i64:
+case INDEX_op_rotr_i32:
+case INDEX_op_rotr_i64:
+case INDEX_op_clz_i64:
+case INDEX_op_setcond_i32:
+case INDEX_op_setcond_i64:
+return C_O1_I2(r, r, ri);
+
 case INDEX_op_sub_i32:
 case INDEX_op_sub_i64:
 case INDEX_op_and_i32:
@@ -2366,35 +2366,33 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_or_i64:
 case INDEX_op_xor_i32:
 case INDEX_op_xor_i64:
-return (s390_facilities & FACILITY_DISTINCT_OPS ? _r_ri : _0_ri);
+return (s390_facilities & FACILITY_DISTINCT_OPS
+? C_O1_I2(r, r, ri)
+: C_O1_I2(r, 0, ri));
 
 case INDEX_op_mul_i32:
 /* If we have the general-instruction-extensions, then we have
MULTIPLY SINGLE IMMEDIATE with a signed 32-bit, otherwise we
have only MULTIPLY HALFWORD IMMEDIATE, with a signed 16-bit.  */
-return (s390_facilities & FACILITY_GEN_INST_EXT ? _0_ri : _0_rI);
+return (s390_facilities & FACILITY_GEN_INST_EXT
+? C_O1_I2(r, 0, ri)
+: C_O1_I2(r, 0, rI));
+
 case INDEX_op_mul_i64:
-return (s390_facilities & FACILITY_GEN_INST_EXT ? _0_rJ : _0_rI);
+return (s390_facilities & FACILITY_GEN_INST_EXT
+? C_O1_I2(r, 0, rJ)
+: C_O1_I2(r, 0, rI));
 
 case INDEX_op_shl_i32:
 case INDEX_op_shr_i32:
 case INDEX_op_sar_i32:
-return (s390_facilities & FACILITY_DISTINCT_OPS ? _r_ri : _0_ri);
-
-case INDEX_op_shl_i64:
-case INDEX_op_shr_i64:
-case INDEX_op_sar_i64:
-return _r_ri;
-
-case INDEX_op_rotl_i32:
-case INDEX_op_rotl_i64:
-case INDEX_op_rotr_i32:
-case INDEX_op_rotr_i64:
-return _r_ri;
+return 

[PATCH 35/43] tcg/i386: Convert to tcg-constr.c.inc

2020-09-08 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/i386/tcg-target-constr.h |  55 +++
 tcg/i386/tcg-target.c.inc| 187 +--
 2 files changed, 121 insertions(+), 121 deletions(-)
 create mode 100644 tcg/i386/tcg-target-constr.h

diff --git a/tcg/i386/tcg-target-constr.h b/tcg/i386/tcg-target-constr.h
new file mode 100644
index 00..91d394612e
--- /dev/null
+++ b/tcg/i386/tcg-target-constr.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * i386 target-specific operand constaints.
+ * Copyright (c) 2020 Linaro
+ */
+
+C_O0_I1(r)
+
+C_O0_I2(qi, r)
+C_O0_I2(ri, r)
+C_O0_I2(re, r)
+C_O0_I2(r, re)
+C_O0_I2(L, L)
+C_O0_I2(x, r)
+
+C_O0_I3(L, L, L)
+
+C_O0_I4(L, L, L, L)
+C_O0_I4(r, r, ri, ri)
+
+C_O1_I1(r, 0)
+C_O1_I1(r, q)
+C_O1_I1(r, r)
+C_O1_I1(r, L)
+C_O1_I1(x, r)
+C_O1_I1(x, x)
+
+C_O1_I2(r, r, re)
+C_O1_I2(r, 0, r)
+C_O1_I2(r, 0, re)
+C_O1_I2(r, 0, reZ)
+C_O1_I2(r, 0, rI)
+C_O1_I2(r, 0, ri)
+C_O1_I2(r, 0, ci)
+C_O1_I2(r, r, ri)
+C_O1_I2(Q, 0, Q)
+C_O1_I2(q, r, re)
+C_O1_I2(r, L, L)
+C_O1_I2(x, x, x)
+C_N1_I2(r, r, r)
+C_N1_I2(r, r, rW)
+
+C_O1_I3(x, x, x, x)
+
+C_O1_I4(r, r, re, r, 0)
+C_O1_I4(r, r, r, ri, ri)
+
+C_O2_I1(r, r, L)
+
+C_O2_I2(r, r, L, L)
+C_O2_I2(a, d, a, r)
+
+C_O2_I3(a, d, 0, 1, r)
+
+C_O2_I4(r, r, 0, 1, re, re)
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 36a90e7ef3..1dac1b33d1 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -2983,39 +2983,14 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 }
 }
 
+/* Define all constraint sets. */
+#include "../tcg-constr.c.inc"
+
 static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
 {
-static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
-static const TCGTargetOpDef ri_r = { .args_ct_str = { "ri", "r" } };
-static const TCGTargetOpDef re_r = { .args_ct_str = { "re", "r" } };
-static const TCGTargetOpDef qi_r = { .args_ct_str = { "qi", "r" } };
-static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
-static const TCGTargetOpDef r_q = { .args_ct_str = { "r", "q" } };
-static const TCGTargetOpDef r_re = { .args_ct_str = { "r", "re" } };
-static const TCGTargetOpDef r_0 = { .args_ct_str = { "r", "0" } };
-static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
-static const TCGTargetOpDef r_r_re = { .args_ct_str = { "r", "r", "re" } };
-static const TCGTargetOpDef r_0_r = { .args_ct_str = { "r", "0", "r" } };
-static const TCGTargetOpDef r_0_re = { .args_ct_str = { "r", "0", "re" } };
-static const TCGTargetOpDef r_0_ci = { .args_ct_str = { "r", "0", "ci" } };
-static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
-static const TCGTargetOpDef L_L = { .args_ct_str = { "L", "L" } };
-static const TCGTargetOpDef r_L_L = { .args_ct_str = { "r", "L", "L" } };
-static const TCGTargetOpDef r_r_L = { .args_ct_str = { "r", "r", "L" } };
-static const TCGTargetOpDef L_L_L = { .args_ct_str = { "L", "L", "L" } };
-static const TCGTargetOpDef r_r_L_L
-= { .args_ct_str = { "r", "r", "L", "L" } };
-static const TCGTargetOpDef L_L_L_L
-= { .args_ct_str = { "L", "L", "L", "L" } };
-static const TCGTargetOpDef x_x = { .args_ct_str = { "x", "x" } };
-static const TCGTargetOpDef x_x_x = { .args_ct_str = { "x", "x", "x" } };
-static const TCGTargetOpDef x_x_x_x
-= { .args_ct_str = { "x", "x", "x", "x" } };
-static const TCGTargetOpDef x_r = { .args_ct_str = { "x", "r" } };
-
 switch (op) {
 case INDEX_op_goto_ptr:
-return 
+return C_O0_I1(r);
 
 case INDEX_op_ld8u_i32:
 case INDEX_op_ld8u_i64:
@@ -3029,22 +3004,25 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_ld32u_i64:
 case INDEX_op_ld32s_i64:
 case INDEX_op_ld_i64:
-return _r;
+return C_O1_I1(r, r);
 
 case INDEX_op_st8_i32:
 case INDEX_op_st8_i64:
-return _r;
+return C_O0_I2(qi, r);
+
 case INDEX_op_st16_i32:
 case INDEX_op_st16_i64:
 case INDEX_op_st_i32:
 case INDEX_op_st32_i64:
-return _r;
+return C_O0_I2(ri, r);
+
 case INDEX_op_st_i64:
-return _r;
+return C_O0_I2(re, r);
 
 case INDEX_op_add_i32:
 case INDEX_op_add_i64:
-return _r_re;
+return C_O1_I2(r, r, re);
+
 case INDEX_op_sub_i32:
 case INDEX_op_sub_i64:
 case INDEX_op_mul_i32:
@@ -3053,24 +3031,15 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_or_i64:
 case INDEX_op_xor_i32:
 case INDEX_op_xor_i64:
-return _0_re;
+return C_O1_I2(r, 0, re);
 
 case INDEX_op_and_i32:
 case INDEX_op_and_i64:
-{
-static const TCGTargetOpDef and
-= { .args_ct_str = { "r", "0", "reZ" } };
-return 
-}
-break;
+return C_O1_I2(r, 0, 

[PATCH 31/43] tcg: Remove tcg_gen_dup{8,16,32,64}i_vec

2020-09-08 Thread Richard Henderson
These interfaces have been replaced by tcg_gen_dupi_vec
and tcg_constant_vec.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-op.h |  4 
 tcg/tcg-op-vec.c | 20 
 2 files changed, 24 deletions(-)

diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
index b4fba35e87..d0319692ec 100644
--- a/include/tcg/tcg-op.h
+++ b/include/tcg/tcg-op.h
@@ -959,10 +959,6 @@ void tcg_gen_mov_vec(TCGv_vec, TCGv_vec);
 void tcg_gen_dup_i32_vec(unsigned vece, TCGv_vec, TCGv_i32);
 void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec, TCGv_i64);
 void tcg_gen_dup_mem_vec(unsigned vece, TCGv_vec, TCGv_ptr, tcg_target_long);
-void tcg_gen_dup8i_vec(TCGv_vec, uint32_t);
-void tcg_gen_dup16i_vec(TCGv_vec, uint32_t);
-void tcg_gen_dup32i_vec(TCGv_vec, uint32_t);
-void tcg_gen_dup64i_vec(TCGv_vec, uint64_t);
 void tcg_gen_dupi_vec(unsigned vece, TCGv_vec, uint64_t);
 void tcg_gen_add_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
 void tcg_gen_sub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c
index ce0d2f6e0e..d19aa7373e 100644
--- a/tcg/tcg-op-vec.c
+++ b/tcg/tcg-op-vec.c
@@ -241,26 +241,6 @@ TCGv_vec tcg_const_ones_vec_matching(TCGv_vec m)
 return tcg_const_ones_vec(t->base_type);
 }
 
-void tcg_gen_dup64i_vec(TCGv_vec r, uint64_t a)
-{
-tcg_gen_dupi_vec(MO_64, r, a);
-}
-
-void tcg_gen_dup32i_vec(TCGv_vec r, uint32_t a)
-{
-tcg_gen_dupi_vec(MO_32, r, a);
-}
-
-void tcg_gen_dup16i_vec(TCGv_vec r, uint32_t a)
-{
-tcg_gen_dupi_vec(MO_16, r, a);
-}
-
-void tcg_gen_dup8i_vec(TCGv_vec r, uint32_t a)
-{
-tcg_gen_dupi_vec(MO_8, r, a);
-}
-
 void tcg_gen_dupi_vec(unsigned vece, TCGv_vec r, uint64_t a)
 {
 TCGTemp *rt = tcgv_vec_temp(r);
-- 
2.25.1




[PATCH 33/43] tcg/aarch64: Use tcg_constant_vec with tcg vec expanders

2020-09-08 Thread Richard Henderson
Improve rotrv_vec to reduce "t1 = -v2, t2 = t1 + c" to
"t1 = -v, t2 = c - v2".  This avoids a serial dependency
between t1 and t2.

Signed-off-by: Richard Henderson 
---
 tcg/aarch64/tcg-target.c.inc | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index fdc118391c..d9d397075a 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -2511,7 +2511,7 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece,
TCGArg a0, ...)
 {
 va_list va;
-TCGv_vec v0, v1, v2, t1, t2;
+TCGv_vec v0, v1, v2, t1, t2, c1;
 TCGArg a2;
 
 va_start(va, a0);
@@ -2543,8 +2543,8 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece,
 
 case INDEX_op_rotlv_vec:
 t1 = tcg_temp_new_vec(type);
-tcg_gen_dupi_vec(vece, t1, 8 << vece);
-tcg_gen_sub_vec(vece, t1, v2, t1);
+c1 = tcg_constant_vec(type, vece, 8 << vece);
+tcg_gen_sub_vec(vece, t1, v2, c1);
 /* Right shifts are negative left shifts for AArch64.  */
 vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t1),
   tcgv_vec_arg(v1), tcgv_vec_arg(t1));
@@ -2557,9 +2557,9 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece,
 case INDEX_op_rotrv_vec:
 t1 = tcg_temp_new_vec(type);
 t2 = tcg_temp_new_vec(type);
+c1 = tcg_constant_vec(type, vece, 8 << vece);
 tcg_gen_neg_vec(vece, t1, v2);
-tcg_gen_dupi_vec(vece, t2, 8 << vece);
-tcg_gen_add_vec(vece, t2, t1, t2);
+tcg_gen_sub_vec(vece, t2, c1, v2);
 /* Right shifts are negative left shifts for AArch64.  */
 vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t1),
   tcgv_vec_arg(v1), tcgv_vec_arg(t1));
-- 
2.25.1




[PATCH 40/43] tcg/riscv: Convert to tcg-constr.c.inc

2020-09-08 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/riscv/tcg-target-constr.h | 25 +++
 tcg/riscv/tcg-target.c.inc| 82 ++-
 2 files changed, 49 insertions(+), 58 deletions(-)
 create mode 100644 tcg/riscv/tcg-target-constr.h

diff --git a/tcg/riscv/tcg-target-constr.h b/tcg/riscv/tcg-target-constr.h
new file mode 100644
index 00..aeff74034c
--- /dev/null
+++ b/tcg/riscv/tcg-target-constr.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * RISC-V target-specific operand constaints.
+ * Copyright (c) 2020 Linaro
+ */
+
+C_O0_I1(r)
+C_O0_I2(LZ, L)
+C_O0_I2(rZ, r)
+C_O0_I2(rZ, rZ)
+C_O0_I3(LZ, L, L)
+C_O0_I3(LZ, LZ, L)
+C_O0_I4(LZ, LZ, L, L)
+C_O0_I4(rZ, rZ, rZ, rZ)
+C_O1_I1(r, L)
+C_O1_I1(r, r)
+C_O1_I2(r, L, L)
+C_O1_I2(r, r, ri)
+C_O1_I2(r, r, rI)
+C_O1_I2(r, rZ, rN)
+C_O1_I2(r, rZ, rZ)
+C_O1_I4(r, rZ, rZ, rZ, rZ)
+C_O2_I1(r, r, L)
+C_O2_I2(r, r, L, L)
+C_O2_I4(r, r, rZ, rZ, rM, rM)
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index aaef1c5eed..042a41e1f4 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -1608,50 +1608,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 }
 }
 
+/* Define all constraint sets. */
+#include "../tcg-constr.c.inc"
+
 static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
 {
-static const TCGTargetOpDef r
-= { .args_ct_str = { "r" } };
-static const TCGTargetOpDef r_r
-= { .args_ct_str = { "r", "r" } };
-static const TCGTargetOpDef rZ_r
-= { .args_ct_str = { "rZ", "r" } };
-static const TCGTargetOpDef rZ_rZ
-= { .args_ct_str = { "rZ", "rZ" } };
-static const TCGTargetOpDef rZ_rZ_rZ_rZ
-= { .args_ct_str = { "rZ", "rZ", "rZ", "rZ" } };
-static const TCGTargetOpDef r_r_ri
-= { .args_ct_str = { "r", "r", "ri" } };
-static const TCGTargetOpDef r_r_rI
-= { .args_ct_str = { "r", "r", "rI" } };
-static const TCGTargetOpDef r_rZ_rN
-= { .args_ct_str = { "r", "rZ", "rN" } };
-static const TCGTargetOpDef r_rZ_rZ
-= { .args_ct_str = { "r", "rZ", "rZ" } };
-static const TCGTargetOpDef r_rZ_rZ_rZ_rZ
-= { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
-static const TCGTargetOpDef r_L
-= { .args_ct_str = { "r", "L" } };
-static const TCGTargetOpDef r_r_L
-= { .args_ct_str = { "r", "r", "L" } };
-static const TCGTargetOpDef r_L_L
-= { .args_ct_str = { "r", "L", "L" } };
-static const TCGTargetOpDef r_r_L_L
-= { .args_ct_str = { "r", "r", "L", "L" } };
-static const TCGTargetOpDef LZ_L
-= { .args_ct_str = { "LZ", "L" } };
-static const TCGTargetOpDef LZ_L_L
-= { .args_ct_str = { "LZ", "L", "L" } };
-static const TCGTargetOpDef LZ_LZ_L
-= { .args_ct_str = { "LZ", "LZ", "L" } };
-static const TCGTargetOpDef LZ_LZ_L_L
-= { .args_ct_str = { "LZ", "LZ", "L", "L" } };
-static const TCGTargetOpDef r_r_rZ_rZ_rM_rM
-= { .args_ct_str = { "r", "r", "rZ", "rZ", "rM", "rM" } };
-
 switch (op) {
 case INDEX_op_goto_ptr:
-return 
+return C_O0_I1(r);
 
 case INDEX_op_ld8u_i32:
 case INDEX_op_ld8s_i32:
@@ -1683,7 +1647,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_extrl_i64_i32:
 case INDEX_op_extrh_i64_i32:
 case INDEX_op_ext_i32_i64:
-return _r;
+return C_O1_I1(r, r);
 
 case INDEX_op_st8_i32:
 case INDEX_op_st16_i32:
@@ -1692,7 +1656,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_st16_i64:
 case INDEX_op_st32_i64:
 case INDEX_op_st_i64:
-return _r;
+return C_O0_I2(rZ, r);
 
 case INDEX_op_add_i32:
 case INDEX_op_and_i32:
@@ -1702,11 +1666,11 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_and_i64:
 case INDEX_op_or_i64:
 case INDEX_op_xor_i64:
-return _r_rI;
+return C_O1_I2(r, r, rI);
 
 case INDEX_op_sub_i32:
 case INDEX_op_sub_i64:
-return _rZ_rN;
+return C_O1_I2(r, rZ, rN);
 
 case INDEX_op_mul_i32:
 case INDEX_op_mulsh_i32:
@@ -1724,7 +1688,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_rem_i64:
 case INDEX_op_remu_i64:
 case INDEX_op_setcond_i64:
-return _rZ_rZ;
+return C_O1_I2(r, rZ, rZ);
 
 case INDEX_op_shl_i32:
 case INDEX_op_shr_i32:
@@ -1732,36 +1696,38 @@ static const TCGTargetOpDef 
*tcg_target_op_def(TCGOpcode op)
 case INDEX_op_shl_i64:
 case INDEX_op_shr_i64:
 case INDEX_op_sar_i64:
-return _r_ri;
+return C_O1_I2(r, r, ri);
 
 case INDEX_op_brcond_i32:
 case INDEX_op_brcond_i64:
-return _rZ;
+return C_O0_I2(rZ, rZ);
 
 case INDEX_op_add2_i32:
 case INDEX_op_add2_i64:
 case INDEX_op_sub2_i32:
 case INDEX_op_sub2_i64:
-return 

[PATCH 30/43] tcg/i386: Use tcg_constant_vec with tcg vec expanders

2020-09-08 Thread Richard Henderson
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 tcg/i386/tcg-target.c.inc | 26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 819ee25cff..36a90e7ef3 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -3508,7 +3508,7 @@ static void expand_vec_rotv(TCGType type, unsigned vece, 
TCGv_vec v0,
 static void expand_vec_mul(TCGType type, unsigned vece,
TCGv_vec v0, TCGv_vec v1, TCGv_vec v2)
 {
-TCGv_vec t1, t2, t3, t4;
+TCGv_vec t1, t2, t3, t4, zero;
 
 tcg_debug_assert(vece == MO_8);
 
@@ -3526,11 +3526,11 @@ static void expand_vec_mul(TCGType type, unsigned vece,
 case TCG_TYPE_V64:
 t1 = tcg_temp_new_vec(TCG_TYPE_V128);
 t2 = tcg_temp_new_vec(TCG_TYPE_V128);
-tcg_gen_dup16i_vec(t2, 0);
+zero = tcg_constant_vec(TCG_TYPE_V128, MO_8, 0);
 vec_gen_3(INDEX_op_x86_punpckl_vec, TCG_TYPE_V128, MO_8,
-  tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(t2));
+  tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(zero));
 vec_gen_3(INDEX_op_x86_punpckl_vec, TCG_TYPE_V128, MO_8,
-  tcgv_vec_arg(t2), tcgv_vec_arg(t2), tcgv_vec_arg(v2));
+  tcgv_vec_arg(t2), tcgv_vec_arg(zero), tcgv_vec_arg(v2));
 tcg_gen_mul_vec(MO_16, t1, t1, t2);
 tcg_gen_shri_vec(MO_16, t1, t1, 8);
 vec_gen_3(INDEX_op_x86_packus_vec, TCG_TYPE_V128, MO_8,
@@ -3545,15 +3545,15 @@ static void expand_vec_mul(TCGType type, unsigned vece,
 t2 = tcg_temp_new_vec(type);
 t3 = tcg_temp_new_vec(type);
 t4 = tcg_temp_new_vec(type);
-tcg_gen_dup16i_vec(t4, 0);
+zero = tcg_constant_vec(TCG_TYPE_V128, MO_8, 0);
 vec_gen_3(INDEX_op_x86_punpckl_vec, type, MO_8,
-  tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(t4));
+  tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(zero));
 vec_gen_3(INDEX_op_x86_punpckl_vec, type, MO_8,
-  tcgv_vec_arg(t2), tcgv_vec_arg(t4), tcgv_vec_arg(v2));
+  tcgv_vec_arg(t2), tcgv_vec_arg(zero), tcgv_vec_arg(v2));
 vec_gen_3(INDEX_op_x86_punpckh_vec, type, MO_8,
-  tcgv_vec_arg(t3), tcgv_vec_arg(v1), tcgv_vec_arg(t4));
+  tcgv_vec_arg(t3), tcgv_vec_arg(v1), tcgv_vec_arg(zero));
 vec_gen_3(INDEX_op_x86_punpckh_vec, type, MO_8,
-  tcgv_vec_arg(t4), tcgv_vec_arg(t4), tcgv_vec_arg(v2));
+  tcgv_vec_arg(t4), tcgv_vec_arg(zero), tcgv_vec_arg(v2));
 tcg_gen_mul_vec(MO_16, t1, t1, t2);
 tcg_gen_mul_vec(MO_16, t3, t3, t4);
 tcg_gen_shri_vec(MO_16, t1, t1, 8);
@@ -3581,7 +3581,7 @@ static bool expand_vec_cmp_noinv(TCGType type, unsigned 
vece, TCGv_vec v0,
 NEED_UMIN = 8,
 NEED_UMAX = 16,
 };
-TCGv_vec t1, t2;
+TCGv_vec t1, t2, t3;
 uint8_t fixup;
 
 switch (cond) {
@@ -3652,9 +3652,9 @@ static bool expand_vec_cmp_noinv(TCGType type, unsigned 
vece, TCGv_vec v0,
 } else if (fixup & NEED_BIAS) {
 t1 = tcg_temp_new_vec(type);
 t2 = tcg_temp_new_vec(type);
-tcg_gen_dupi_vec(vece, t2, 1ull << ((8 << vece) - 1));
-tcg_gen_sub_vec(vece, t1, v1, t2);
-tcg_gen_sub_vec(vece, t2, v2, t2);
+t3 = tcg_constant_vec(type, vece, 1ull << ((8 << vece) - 1));
+tcg_gen_sub_vec(vece, t1, v1, t3);
+tcg_gen_sub_vec(vece, t2, v2, t3);
 v1 = t1;
 v2 = t2;
 cond = tcg_signed_cond(cond);
-- 
2.25.1




[PATCH 23/43] tcg: Use tcg_constant_i32 with icount expander

2020-09-08 Thread Richard Henderson
We must do this before we adjust tcg_out_movi_i32, lest the
under-the-hood poking that we do for icount be broken.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 include/exec/gen-icount.h | 25 +
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index 822c43cfd3..404732518a 100644
--- a/include/exec/gen-icount.h
+++ b/include/exec/gen-icount.h
@@ -34,7 +34,7 @@ static inline void gen_io_end(void)
 
 static inline void gen_tb_start(TranslationBlock *tb)
 {
-TCGv_i32 count, imm;
+TCGv_i32 count;
 
 tcg_ctx->exitreq_label = gen_new_label();
 if (tb_cflags(tb) & CF_USE_ICOUNT) {
@@ -48,15 +48,13 @@ static inline void gen_tb_start(TranslationBlock *tb)
offsetof(ArchCPU, env));
 
 if (tb_cflags(tb) & CF_USE_ICOUNT) {
-imm = tcg_temp_new_i32();
-/* We emit a movi with a dummy immediate argument. Keep the insn index
- * of the movi so that we later (when we know the actual insn count)
- * can update the immediate argument with the actual insn count.  */
-tcg_gen_movi_i32(imm, 0xdeadbeef);
+/*
+ * We emit a sub with a dummy immediate argument. Keep the insn index
+ * of the sub so that we later (when we know the actual insn count)
+ * can update the argument with the actual insn count.
+ */
+tcg_gen_sub_i32(count, count, tcg_constant_i32(0));
 icount_start_insn = tcg_last_op();
-
-tcg_gen_sub_i32(count, count, imm);
-tcg_temp_free_i32(imm);
 }
 
 tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label);
@@ -74,9 +72,12 @@ static inline void gen_tb_start(TranslationBlock *tb)
 static inline void gen_tb_end(TranslationBlock *tb, int num_insns)
 {
 if (tb_cflags(tb) & CF_USE_ICOUNT) {
-/* Update the num_insn immediate parameter now that we know
- * the actual insn count.  */
-tcg_set_insn_param(icount_start_insn, 1, num_insns);
+/*
+ * Update the num_insn immediate parameter now that we know
+ * the actual insn count.
+ */
+tcg_set_insn_param(icount_start_insn, 2,
+   tcgv_i32_arg(tcg_constant_i32(num_insns)));
 }
 
 gen_set_label(tcg_ctx->exitreq_label);
-- 
2.25.1




[PATCH 29/43] tcg: Add tcg_reg_alloc_dup2

2020-09-08 Thread Richard Henderson
There are several ways we can expand a vector dup of a 64-bit
element on a 32-bit host.

Signed-off-by: Richard Henderson 
---
 tcg/tcg.c | 97 +++
 1 file changed, 97 insertions(+)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index f9c6450837..507c95cd39 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -3954,6 +3954,100 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 }
 }
 
+static void tcg_reg_alloc_dup2(TCGContext *s, const TCGOp *op)
+{
+const TCGLifeData arg_life = op->life;
+TCGTemp *ots, *itsl, *itsh;
+TCGType vtype = TCGOP_VECL(op) + TCG_TYPE_V64;
+
+/* This opcode is only valid for 32-bit hosts, for 64-bit elements. */
+tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
+tcg_debug_assert(TCGOP_VECE(op) == MO_64);
+
+ots = arg_temp(op->args[0]);
+itsl = arg_temp(op->args[1]);
+itsh = arg_temp(op->args[2]);
+
+/* ENV should not be modified.  */
+tcg_debug_assert(!temp_readonly(ots));
+
+/* Allocate the output register now.  */
+if (ots->val_type != TEMP_VAL_REG) {
+TCGRegSet allocated_regs = s->reserved_regs;
+TCGRegSet dup_out_regs =
+tcg_op_defs[INDEX_op_dup_vec].args_ct[0].regs;
+
+/* Make sure to not spill the input registers. */
+if (!IS_DEAD_ARG(1) && itsl->val_type == TEMP_VAL_REG) {
+tcg_regset_set_reg(allocated_regs, itsl->reg);
+}
+if (!IS_DEAD_ARG(2) && itsh->val_type == TEMP_VAL_REG) {
+tcg_regset_set_reg(allocated_regs, itsh->reg);
+}
+
+ots->reg = tcg_reg_alloc(s, dup_out_regs, allocated_regs,
+ op->output_pref[0], ots->indirect_base);
+ots->val_type = TEMP_VAL_REG;
+ots->mem_coherent = 0;
+s->reg_to_temp[ots->reg] = ots;
+}
+
+/* Promote dup2 of immediates to dupi_vec. */
+if (itsl->val_type == TEMP_VAL_CONST && itsh->val_type == TEMP_VAL_CONST) {
+uint64_t val = deposit64(itsl->val, 32, 32, itsh->val);
+MemOp vece = MO_64;
+
+if (val == dup_const(MO_8, val)) {
+vece = MO_8;
+} else if (val == dup_const(MO_16, val)) {
+vece = MO_16;
+} else if (val == dup_const(MO_32, val)) {
+vece = MO_32;
+}
+
+tcg_out_dupi_vec(s, vtype, vece, ots->reg, val);
+goto done;
+}
+
+/* If the two inputs form one 64-bit value, try dupm_vec. */
+if (itsl + 1 == itsh &&
+itsl->base_type == TCG_TYPE_I64 &&
+itsh->base_type == TCG_TYPE_I64) {
+if (!itsl->mem_coherent) {
+temp_sync(s, itsl, s->reserved_regs, 0, 0);
+}
+if (!itsl->mem_coherent) {
+temp_sync(s, itsl, s->reserved_regs, 0, 0);
+}
+#ifdef HOST_WORDS_BIGENDIAN
+TCGTemp *its = itsh;
+#else
+TCGTemp *its = itsl;
+#endif
+if (tcg_out_dupm_vec(s, vtype, MO_64, ots->reg,
+ its->mem_base->reg, its->mem_offset)) {
+goto done;
+}
+}
+
+/* Fall back to generic expansion. */
+tcg_reg_alloc_op(s, op);
+return;
+
+ done:
+if (IS_DEAD_ARG(1)) {
+temp_dead(s, itsl);
+}
+if (IS_DEAD_ARG(2)) {
+temp_dead(s, itsh);
+}
+if (NEED_SYNC_ARG(0)) {
+temp_sync(s, ots, s->reserved_regs, 0, IS_DEAD_ARG(0));
+} else if (IS_DEAD_ARG(0)) {
+temp_dead(s, ots);
+}
+}
+
 #ifdef TCG_TARGET_STACK_GROWSUP
 #define STACK_DIR(x) (-(x))
 #else
@@ -4345,6 +4439,9 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
 case INDEX_op_dup_vec:
 tcg_reg_alloc_dup(s, op);
 break;
+case INDEX_op_dup2_vec:
+tcg_reg_alloc_dup2(s, op);
+break;
 case INDEX_op_insn_start:
 if (num_insns >= 0) {
 size_t off = tcg_current_code_size(s);
-- 
2.25.1




[PATCH 27/43] tcg/tci: Add special tci_movi_{i32,i64} opcodes

2020-09-08 Thread Richard Henderson
The normal movi opcodes are going away.  We need something
for TCI to use internally.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-opc.h| 8 
 tcg/tci.c| 4 ++--
 tcg/tci/tcg-target.c.inc | 4 ++--
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
index e3929b80d2..5a941eaa07 100644
--- a/include/tcg/tcg-opc.h
+++ b/include/tcg/tcg-opc.h
@@ -272,6 +272,14 @@ DEF(last_generic, 0, 0, 0, TCG_OPF_NOT_PRESENT)
 #include "tcg-target.opc.h"
 #endif
 
+#ifdef TCG_TARGET_INTERPRETER
+/* These opcodes are only for use between the tci generator and interpreter. */
+DEF(tci_movi_i32, 1, 0, 1, TCG_OPF_NOT_PRESENT)
+#if TCG_TARGET_REG_BITS == 64
+DEF(tci_movi_i64, 1, 0, 1, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
+#endif
+#endif
+
 #undef TLADDR_ARGS
 #undef DATA64_ARGS
 #undef IMPL
diff --git a/tcg/tci.c b/tcg/tci.c
index 46fe9ce63f..a6c1aaf5af 100644
--- a/tcg/tci.c
+++ b/tcg/tci.c
@@ -576,7 +576,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t 
*tb_ptr)
 t1 = tci_read_r32(regs, _ptr);
 tci_write_reg32(regs, t0, t1);
 break;
-case INDEX_op_movi_i32:
+case INDEX_op_tci_movi_i32:
 t0 = *tb_ptr++;
 t1 = tci_read_i32(_ptr);
 tci_write_reg32(regs, t0, t1);
@@ -847,7 +847,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t 
*tb_ptr)
 t1 = tci_read_r64(regs, _ptr);
 tci_write_reg64(regs, t0, t1);
 break;
-case INDEX_op_movi_i64:
+case INDEX_op_tci_movi_i64:
 t0 = *tb_ptr++;
 t1 = tci_read_i64(_ptr);
 tci_write_reg64(regs, t0, t1);
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
index 231b9b1775..c8c8386a72 100644
--- a/tcg/tci/tcg-target.c.inc
+++ b/tcg/tci/tcg-target.c.inc
@@ -529,13 +529,13 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
 uint8_t *old_code_ptr = s->code_ptr;
 uint32_t arg32 = arg;
 if (type == TCG_TYPE_I32 || arg == arg32) {
-tcg_out_op_t(s, INDEX_op_movi_i32);
+tcg_out_op_t(s, INDEX_op_tci_movi_i32);
 tcg_out_r(s, t0);
 tcg_out32(s, arg32);
 } else {
 tcg_debug_assert(type == TCG_TYPE_I64);
 #if TCG_TARGET_REG_BITS == 64
-tcg_out_op_t(s, INDEX_op_movi_i64);
+tcg_out_op_t(s, INDEX_op_tci_movi_i64);
 tcg_out_r(s, t0);
 tcg_out64(s, arg);
 #else
-- 
2.25.1




[PATCH 17/43] tcg: Expand TempOptInfo to 64-bits

2020-09-08 Thread Richard Henderson
This propagates the extended value of TCGTemp.val that we did before.
In addition, it will be required for vector constants.

Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 40 +---
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 81faf7cf10..33d1fc8f87 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -39,8 +39,8 @@ typedef struct TempOptInfo {
 bool is_const;
 TCGTemp *prev_copy;
 TCGTemp *next_copy;
-tcg_target_ulong val;
-tcg_target_ulong mask;
+uint64_t val;
+uint64_t mask;
 } TempOptInfo;
 
 static inline TempOptInfo *ts_info(TCGTemp *ts)
@@ -166,11 +166,11 @@ static bool args_are_copies(TCGArg arg1, TCGArg arg2)
 return ts_are_copies(arg_temp(arg1), arg_temp(arg2));
 }
 
-static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg val)
+static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg dst, uint64_t 
val)
 {
 const TCGOpDef *def;
 TCGOpcode new_op;
-tcg_target_ulong mask;
+uint64_t mask;
 TempOptInfo *di = arg_info(dst);
 
 def = _op_defs[op->opc];
@@ -204,7 +204,7 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 const TCGOpDef *def;
 TempOptInfo *di;
 TempOptInfo *si;
-tcg_target_ulong mask;
+uint64_t mask;
 TCGOpcode new_op;
 
 if (ts_are_copies(dst_ts, src_ts)) {
@@ -247,7 +247,7 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 }
 }
 
-static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
+static uint64_t do_constant_folding_2(TCGOpcode op, uint64_t x, uint64_t y)
 {
 uint64_t l64, h64;
 
@@ -410,10 +410,10 @@ static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg 
x, TCGArg y)
 }
 }
 
-static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
+static uint64_t do_constant_folding(TCGOpcode op, uint64_t x, uint64_t y)
 {
 const TCGOpDef *def = _op_defs[op];
-TCGArg res = do_constant_folding_2(op, x, y);
+uint64_t res = do_constant_folding_2(op, x, y);
 if (!(def->flags & TCG_OPF_64BIT)) {
 res = (int32_t)res;
 }
@@ -501,8 +501,9 @@ static bool do_constant_folding_cond_eq(TCGCond c)
 static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
TCGArg y, TCGCond c)
 {
-tcg_target_ulong xv = arg_info(x)->val;
-tcg_target_ulong yv = arg_info(y)->val;
+uint64_t xv = arg_info(x)->val;
+uint64_t yv = arg_info(y)->val;
+
 if (arg_is_const(x) && arg_is_const(y)) {
 const TCGOpDef *def = _op_defs[op];
 tcg_debug_assert(!(def->flags & TCG_OPF_VECTOR));
@@ -613,9 +614,8 @@ void tcg_optimize(TCGContext *s)
 infos = tcg_malloc(sizeof(TempOptInfo) * nb_temps);
 
 QTAILQ_FOREACH_SAFE(op, >ops, link, op_next) {
-tcg_target_ulong mask, partmask, affected;
+uint64_t mask, partmask, affected, tmp;
 int nb_oargs, nb_iargs, i;
-TCGArg tmp;
 TCGOpcode opc = op->opc;
 const TCGOpDef *def = _op_defs[opc];
 
@@ -1221,14 +1221,15 @@ void tcg_optimize(TCGContext *s)
 
 CASE_OP_32_64(extract2):
 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
-TCGArg v1 = arg_info(op->args[1])->val;
-TCGArg v2 = arg_info(op->args[2])->val;
+uint64_t v1 = arg_info(op->args[1])->val;
+uint64_t v2 = arg_info(op->args[2])->val;
+int shr = op->args[3];
 
 if (opc == INDEX_op_extract2_i64) {
-tmp = (v1 >> op->args[3]) | (v2 << (64 - op->args[3]));
+tmp = (v1 >> shr) | (v2 << (64 - shr));
 } else {
-tmp = (int32_t)(((uint32_t)v1 >> op->args[3]) |
-((uint32_t)v2 << (32 - op->args[3])));
+tmp = (int32_t)(((uint32_t)v1 >> shr) |
+((uint32_t)v2 << (32 - shr)));
 }
 tcg_opt_gen_movi(s, op, op->args[0], tmp);
 break;
@@ -1267,9 +1268,10 @@ void tcg_optimize(TCGContext *s)
 break;
 }
 if (arg_is_const(op->args[3]) && arg_is_const(op->args[4])) {
-tcg_target_ulong tv = arg_info(op->args[3])->val;
-tcg_target_ulong fv = arg_info(op->args[4])->val;
+uint64_t tv = arg_info(op->args[3])->val;
+uint64_t fv = arg_info(op->args[4])->val;
 TCGCond cond = op->args[5];
+
 if (fv == 1 && tv == 0) {
 cond = tcg_invert_cond(cond);
 } else if (!(tv == 1 && fv == 0)) {
-- 
2.25.1




[PATCH 32/43] tcg/ppc: Use tcg_constant_vec with tcg vec expanders

2020-09-08 Thread Richard Henderson
Improve expand_vec_shi to use sign-extraction for MO_32.
This allows a single VSPLTISB instruction to load all of
the valid shift constants.

Signed-off-by: Richard Henderson 
---
 tcg/ppc/tcg-target.c.inc | 44 
 1 file changed, 27 insertions(+), 17 deletions(-)

diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 3d23a6b226..155c42ed24 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -3332,13 +3332,22 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 static void expand_vec_shi(TCGType type, unsigned vece, TCGv_vec v0,
TCGv_vec v1, TCGArg imm, TCGOpcode opci)
 {
-TCGv_vec t1 = tcg_temp_new_vec(type);
+TCGv_vec t1;
 
-/* Splat w/bytes for xxspltib.  */
-tcg_gen_dupi_vec(MO_8, t1, imm & ((8 << vece) - 1));
+if (vece == MO_32) {
+/*
+ * Only 5 bits are significant, and VSPLTISB can represent -16..15.
+ * So using negative numbers gets us the 4th bit easily.
+ */
+imm = sextract32(imm, 0, 5);
+} else {
+imm &= (8 << vece) - 1;
+}
+
+/* Splat w/bytes for xxspltib when 2.07 allows MO_64. */
+t1 = tcg_constant_vec(type, MO_8, imm);
 vec_gen_3(opci, type, vece, tcgv_vec_arg(v0),
   tcgv_vec_arg(v1), tcgv_vec_arg(t1));
-tcg_temp_free_vec(t1);
 }
 
 static void expand_vec_cmp(TCGType type, unsigned vece, TCGv_vec v0,
@@ -3396,7 +3405,7 @@ static void expand_vec_mul(TCGType type, unsigned vece, 
TCGv_vec v0,
 {
 TCGv_vec t1 = tcg_temp_new_vec(type);
 TCGv_vec t2 = tcg_temp_new_vec(type);
-TCGv_vec t3, t4;
+TCGv_vec c0, c16;
 
 switch (vece) {
 case MO_8:
@@ -3415,21 +3424,22 @@ static void expand_vec_mul(TCGType type, unsigned vece, 
TCGv_vec v0,
 
 case MO_32:
 tcg_debug_assert(!have_isa_2_07);
-t3 = tcg_temp_new_vec(type);
-t4 = tcg_temp_new_vec(type);
-tcg_gen_dupi_vec(MO_8, t4, -16);
+/*
+ * Only 5 bits are significant, and VSPLTISB can represent -16..15.
+ * So using -16 is a quick way to represent 16.
+ */
+c16 = tcg_constant_vec(type, MO_8, -16);
+c0 = tcg_constant_vec(type, MO_8, 0);
+
 vec_gen_3(INDEX_op_rotlv_vec, type, MO_32, tcgv_vec_arg(t1),
-  tcgv_vec_arg(v2), tcgv_vec_arg(t4));
+  tcgv_vec_arg(v2), tcgv_vec_arg(c16));
 vec_gen_3(INDEX_op_ppc_mulou_vec, type, MO_16, tcgv_vec_arg(t2),
   tcgv_vec_arg(v1), tcgv_vec_arg(v2));
-tcg_gen_dupi_vec(MO_8, t3, 0);
-vec_gen_4(INDEX_op_ppc_msum_vec, type, MO_16, tcgv_vec_arg(t3),
-  tcgv_vec_arg(v1), tcgv_vec_arg(t1), tcgv_vec_arg(t3));
-vec_gen_3(INDEX_op_shlv_vec, type, MO_32, tcgv_vec_arg(t3),
-  tcgv_vec_arg(t3), tcgv_vec_arg(t4));
-tcg_gen_add_vec(MO_32, v0, t2, t3);
-tcg_temp_free_vec(t3);
-tcg_temp_free_vec(t4);
+vec_gen_4(INDEX_op_ppc_msum_vec, type, MO_16, tcgv_vec_arg(t1),
+  tcgv_vec_arg(v1), tcgv_vec_arg(t1), tcgv_vec_arg(c0));
+vec_gen_3(INDEX_op_shlv_vec, type, MO_32, tcgv_vec_arg(t1),
+  tcgv_vec_arg(t1), tcgv_vec_arg(c16));
+tcg_gen_add_vec(MO_32, v0, t1, t2);
 break;
 
 default:
-- 
2.25.1




[PATCH 22/43] tcg: Convert tcg_gen_dupi_vec to TCG_CONST

2020-09-08 Thread Richard Henderson
Because we now store uint64_t in TCGTemp, we can now always
store the full 64-bit duplicate immediate.  So remove the
difference between 32- and 64-bit hosts.

Signed-off-by: Richard Henderson 
---
 tcg/optimize.c   |  9 -
 tcg/tcg-op-vec.c | 39 ++-
 tcg/tcg.c|  7 +--
 3 files changed, 15 insertions(+), 40 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 1eda7dc419..af07c6f628 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -1116,11 +1116,10 @@ void tcg_optimize(TCGContext *s)
 case INDEX_op_dup2_vec:
 assert(TCG_TARGET_REG_BITS == 32);
 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
-tmp = arg_info(op->args[1])->val;
-if (tmp == arg_info(op->args[2])->val) {
-tcg_opt_gen_movi(s, _used, op, op->args[0], tmp);
-break;
-}
+tcg_opt_gen_movi(s, _used, op, op->args[0],
+ deposit64(arg_info(op->args[1])->val, 32, 32,
+   arg_info(op->args[2])->val));
+break;
 } else if (args_are_copies(op->args[1], op->args[2])) {
 op->opc = INDEX_op_dup_vec;
 TCGOP_VECE(op) = MO_32;
diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c
index cdbf11c573..9fbed1366c 100644
--- a/tcg/tcg-op-vec.c
+++ b/tcg/tcg-op-vec.c
@@ -216,25 +216,17 @@ void tcg_gen_mov_vec(TCGv_vec r, TCGv_vec a)
 }
 }
 
-#define MO_REG  (TCG_TARGET_REG_BITS == 64 ? MO_64 : MO_32)
-
-static void do_dupi_vec(TCGv_vec r, unsigned vece, TCGArg a)
-{
-TCGTemp *rt = tcgv_vec_temp(r);
-vec_gen_2(INDEX_op_dupi_vec, rt->base_type, vece, temp_arg(rt), a);
-}
-
 TCGv_vec tcg_const_zeros_vec(TCGType type)
 {
 TCGv_vec ret = tcg_temp_new_vec(type);
-do_dupi_vec(ret, MO_REG, 0);
+tcg_gen_dupi_vec(MO_64, ret, 0);
 return ret;
 }
 
 TCGv_vec tcg_const_ones_vec(TCGType type)
 {
 TCGv_vec ret = tcg_temp_new_vec(type);
-do_dupi_vec(ret, MO_REG, -1);
+tcg_gen_dupi_vec(MO_64, ret, -1);
 return ret;
 }
 
@@ -252,39 +244,28 @@ TCGv_vec tcg_const_ones_vec_matching(TCGv_vec m)
 
 void tcg_gen_dup64i_vec(TCGv_vec r, uint64_t a)
 {
-if (TCG_TARGET_REG_BITS == 64) {
-do_dupi_vec(r, MO_64, a);
-} else if (a == dup_const(MO_32, a)) {
-do_dupi_vec(r, MO_32, a);
-} else {
-TCGv_i64 c = tcg_const_i64(a);
-tcg_gen_dup_i64_vec(MO_64, r, c);
-tcg_temp_free_i64(c);
-}
+tcg_gen_dupi_vec(MO_64, r, a);
 }
 
 void tcg_gen_dup32i_vec(TCGv_vec r, uint32_t a)
 {
-do_dupi_vec(r, MO_REG, dup_const(MO_32, a));
+tcg_gen_dupi_vec(MO_32, r, a);
 }
 
 void tcg_gen_dup16i_vec(TCGv_vec r, uint32_t a)
 {
-do_dupi_vec(r, MO_REG, dup_const(MO_16, a));
+tcg_gen_dupi_vec(MO_16, r, a);
 }
 
 void tcg_gen_dup8i_vec(TCGv_vec r, uint32_t a)
 {
-do_dupi_vec(r, MO_REG, dup_const(MO_8, a));
+tcg_gen_dupi_vec(MO_8, r, a);
 }
 
 void tcg_gen_dupi_vec(unsigned vece, TCGv_vec r, uint64_t a)
 {
-if (vece == MO_64) {
-tcg_gen_dup64i_vec(r, a);
-} else {
-do_dupi_vec(r, MO_REG, dup_const(vece, a));
-}
+TCGTemp *rt = tcgv_vec_temp(r);
+tcg_gen_mov_vec(r, tcg_constant_vec(rt->base_type, vece, a));
 }
 
 void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec r, TCGv_i64 a)
@@ -489,8 +470,8 @@ void tcg_gen_abs_vec(unsigned vece, TCGv_vec r, TCGv_vec a)
 if (tcg_can_emit_vec_op(INDEX_op_sari_vec, type, vece) > 0) {
 tcg_gen_sari_vec(vece, t, a, (8 << vece) - 1);
 } else {
-do_dupi_vec(t, MO_REG, 0);
-tcg_gen_cmp_vec(TCG_COND_LT, vece, t, a, t);
+tcg_gen_cmp_vec(TCG_COND_LT, vece, t, a,
+tcg_constant_vec(type, vece, 0));
 }
 tcg_gen_xor_vec(vece, r, a, t);
 tcg_gen_sub_vec(vece, r, r, t);
diff --git a/tcg/tcg.c b/tcg/tcg.c
index e413bf70d4..0ce45fd123 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -3440,16 +3440,11 @@ static void temp_load(TCGContext *s, TCGTemp *ts, 
TCGRegSet desired_regs,
  * The targets will, in general, have to do this search anyway,
  * do this generically.
  */
-if (TCG_TARGET_REG_BITS == 32) {
-val = dup_const(MO_32, val);
-vece = MO_32;
-}
 if (val == dup_const(MO_8, val)) {
 vece = MO_8;
 } else if (val == dup_const(MO_16, val)) {
 vece = MO_16;
-} else if (TCG_TARGET_REG_BITS == 64 &&
-   val == dup_const(MO_32, val)) {
+} else if (val == dup_const(MO_32, val)) {
 vece = MO_32;
 }
 
-- 
2.25.1




[PATCH 20/43] tcg/optimize: Adjust TempOptInfo allocation

2020-09-08 Thread Richard Henderson
Do not allocate a large block for indexing.  Instead, allocate
for each temporary as they are seen.

In general, this will use less memory, if we consider that most
TBs do not touch every target register.  This also allows us to
allocate TempOptInfo for new temps created during optimization.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 60 --
 1 file changed, 34 insertions(+), 26 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index bf2c2a3ce5..e269962932 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -89,35 +89,41 @@ static void reset_temp(TCGArg arg)
 }
 
 /* Initialize and activate a temporary.  */
-static void init_ts_info(TempOptInfo *infos,
- TCGTempSet *temps_used, TCGTemp *ts)
+static void init_ts_info(TCGTempSet *temps_used, TCGTemp *ts)
 {
 size_t idx = temp_idx(ts);
-if (!test_bit(idx, temps_used->l)) {
-TempOptInfo *ti = [idx];
+TempOptInfo *ti;
 
+if (test_bit(idx, temps_used->l)) {
+return;
+}
+set_bit(idx, temps_used->l);
+
+ti = ts->state_ptr;
+if (ti == NULL) {
+ti = tcg_malloc(sizeof(TempOptInfo));
 ts->state_ptr = ti;
-ti->next_copy = ts;
-ti->prev_copy = ts;
-if (ts->kind == TEMP_CONST) {
-ti->is_const = true;
-ti->val = ti->mask = ts->val;
-if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) {
-/* High bits of a 32-bit quantity are garbage.  */
-ti->mask |= ~0xull;
-}
-} else {
-ti->is_const = false;
-ti->mask = -1;
+}
+
+ti->next_copy = ts;
+ti->prev_copy = ts;
+if (ts->kind == TEMP_CONST) {
+ti->is_const = true;
+ti->val = ts->val;
+ti->mask = ts->val;
+if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) {
+/* High bits of a 32-bit quantity are garbage.  */
+ti->mask |= ~0xull;
 }
-set_bit(idx, temps_used->l);
+} else {
+ti->is_const = false;
+ti->mask = -1;
 }
 }
 
-static void init_arg_info(TempOptInfo *infos,
-  TCGTempSet *temps_used, TCGArg arg)
+static void init_arg_info(TCGTempSet *temps_used, TCGArg arg)
 {
-init_ts_info(infos, temps_used, arg_temp(arg));
+init_ts_info(temps_used, arg_temp(arg));
 }
 
 static TCGTemp *find_better_copy(TCGContext *s, TCGTemp *ts)
@@ -604,9 +610,8 @@ static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
 /* Propagate constants and copies, fold constant expressions. */
 void tcg_optimize(TCGContext *s)
 {
-int nb_temps, nb_globals;
+int nb_temps, nb_globals, i;
 TCGOp *op, *op_next, *prev_mb = NULL;
-TempOptInfo *infos;
 TCGTempSet temps_used;
 
 /* Array VALS has an element for each temp.
@@ -616,12 +621,15 @@ void tcg_optimize(TCGContext *s)
 
 nb_temps = s->nb_temps;
 nb_globals = s->nb_globals;
+
 bitmap_zero(temps_used.l, nb_temps);
-infos = tcg_malloc(sizeof(TempOptInfo) * nb_temps);
+for (i = 0; i < nb_temps; ++i) {
+s->temps[i].state_ptr = NULL;
+}
 
 QTAILQ_FOREACH_SAFE(op, >ops, link, op_next) {
 uint64_t mask, partmask, affected, tmp;
-int nb_oargs, nb_iargs, i;
+int nb_oargs, nb_iargs;
 TCGOpcode opc = op->opc;
 const TCGOpDef *def = _op_defs[opc];
 
@@ -633,14 +641,14 @@ void tcg_optimize(TCGContext *s)
 for (i = 0; i < nb_oargs + nb_iargs; i++) {
 TCGTemp *ts = arg_temp(op->args[i]);
 if (ts) {
-init_ts_info(infos, _used, ts);
+init_ts_info(_used, ts);
 }
 }
 } else {
 nb_oargs = def->nb_oargs;
 nb_iargs = def->nb_iargs;
 for (i = 0; i < nb_oargs + nb_iargs; i++) {
-init_arg_info(infos, _used, op->args[i]);
+init_arg_info(_used, op->args[i]);
 }
 }
 
-- 
2.25.1




[PATCH 13/43] tcg: Consolidate 3 bits into enum TCGTempKind

2020-09-08 Thread Richard Henderson
The temp_fixed, temp_global, temp_local bits are all related.
Combine them into a single enumeration.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h |  20 +---
 tcg/optimize.c|   8 +--
 tcg/tcg.c | 122 --
 3 files changed, 90 insertions(+), 60 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 8804a8c4a2..f157092b51 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -483,23 +483,27 @@ typedef enum TCGTempVal {
 TEMP_VAL_CONST,
 } TCGTempVal;
 
+typedef enum TCGTempKind {
+/* Temp is dead at the end of all basic blocks. */
+TEMP_NORMAL,
+/* Temp is saved across basic blocks but dead at the end of TBs. */
+TEMP_LOCAL,
+/* Temp is saved across both basic blocks and translation blocks. */
+TEMP_GLOBAL,
+/* Temp is in a fixed register. */
+TEMP_FIXED,
+} TCGTempKind;
+
 typedef struct TCGTemp {
 TCGReg reg:8;
 TCGTempVal val_type:8;
 TCGType base_type:8;
 TCGType type:8;
-unsigned int fixed_reg:1;
+TCGTempKind kind:3;
 unsigned int indirect_reg:1;
 unsigned int indirect_base:1;
 unsigned int mem_coherent:1;
 unsigned int mem_allocated:1;
-/* If true, the temp is saved across both basic blocks and
-   translation blocks.  */
-unsigned int temp_global:1;
-/* If true, the temp is saved across basic blocks but dead
-   at the end of translation blocks.  If false, the temp is
-   dead at the end of basic blocks.  */
-unsigned int temp_local:1;
 unsigned int temp_allocated:1;
 
 tcg_target_long val;
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 220f4601d5..3cffd941bd 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -116,21 +116,21 @@ static TCGTemp *find_better_copy(TCGContext *s, TCGTemp 
*ts)
 TCGTemp *i;
 
 /* If this is already a global, we can't do better. */
-if (ts->temp_global) {
+if (ts->kind >= TEMP_GLOBAL) {
 return ts;
 }
 
 /* Search for a global first. */
 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (i->temp_global) {
+if (i->kind >= TEMP_GLOBAL) {
 return i;
 }
 }
 
 /* If it is a temp, search for a temp local. */
-if (!ts->temp_local) {
+if (ts->kind == TEMP_NORMAL) {
 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (ts->temp_local) {
+if (i->kind >= TEMP_LOCAL) {
 return i;
 }
 }
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 6474a695f2..67e122527b 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1160,7 +1160,7 @@ static inline TCGTemp *tcg_global_alloc(TCGContext *s)
 tcg_debug_assert(s->nb_globals == s->nb_temps);
 s->nb_globals++;
 ts = tcg_temp_alloc(s);
-ts->temp_global = 1;
+ts->kind = TEMP_GLOBAL;
 
 return ts;
 }
@@ -1177,7 +1177,7 @@ static TCGTemp *tcg_global_reg_new_internal(TCGContext 
*s, TCGType type,
 ts = tcg_global_alloc(s);
 ts->base_type = type;
 ts->type = type;
-ts->fixed_reg = 1;
+ts->kind = TEMP_FIXED;
 ts->reg = reg;
 ts->name = name;
 tcg_regset_set_reg(s->reserved_regs, reg);
@@ -1204,7 +1204,7 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, 
TCGv_ptr base,
 bigendian = 1;
 #endif
 
-if (!base_ts->fixed_reg) {
+if (base_ts->kind != TEMP_FIXED) {
 /* We do not support double-indirect registers.  */
 tcg_debug_assert(!base_ts->indirect_reg);
 base_ts->indirect_base = 1;
@@ -1252,6 +1252,7 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, 
TCGv_ptr base,
 TCGTemp *tcg_temp_new_internal(TCGType type, bool temp_local)
 {
 TCGContext *s = tcg_ctx;
+TCGTempKind kind = temp_local ? TEMP_LOCAL : TEMP_NORMAL;
 TCGTemp *ts;
 int idx, k;
 
@@ -1264,7 +1265,7 @@ TCGTemp *tcg_temp_new_internal(TCGType type, bool 
temp_local)
 ts = >temps[idx];
 ts->temp_allocated = 1;
 tcg_debug_assert(ts->base_type == type);
-tcg_debug_assert(ts->temp_local == temp_local);
+tcg_debug_assert(ts->kind == kind);
 } else {
 ts = tcg_temp_alloc(s);
 if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
@@ -1273,18 +1274,18 @@ TCGTemp *tcg_temp_new_internal(TCGType type, bool 
temp_local)
 ts->base_type = type;
 ts->type = TCG_TYPE_I32;
 ts->temp_allocated = 1;
-ts->temp_local = temp_local;
+ts->kind = kind;
 
 tcg_debug_assert(ts2 == ts + 1);
 ts2->base_type = TCG_TYPE_I64;
 ts2->type = TCG_TYPE_I32;
 ts2->temp_allocated = 1;
-ts2->temp_local = temp_local;
+ts2->kind = kind;
 } else {
 ts->base_type = type;
 ts->type = type;
 ts->temp_allocated = 1;
-ts->temp_local = temp_local;
+ts->kind = kind;
 

[PATCH 26/43] tcg: Use tcg_constant_{i32, i64, vec} with gvec expanders

2020-09-08 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h |   1 +
 tcg/tcg-op-gvec.c | 125 ++
 tcg/tcg.c |   8 +++
 3 files changed, 58 insertions(+), 76 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index aa7b0ba163..309460704a 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -1081,6 +1081,7 @@ static inline TCGv_i64 tcg_constant_i64(int64_t val)
 }
 
 TCGv_vec tcg_constant_vec(TCGType type, unsigned vece, int64_t val);
+TCGv_vec tcg_constant_vec_matching(TCGv_vec match, unsigned vece, int64_t val);
 
 #if UINTPTR_MAX == UINT32_MAX
 # define tcg_const_ptr(x)((TCGv_ptr)tcg_const_i32((intptr_t)(x)))
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
index ddbe06b71a..80eb53c770 100644
--- a/tcg/tcg-op-gvec.c
+++ b/tcg/tcg-op-gvec.c
@@ -115,7 +115,7 @@ void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
 gen_helper_gvec_2 *fn)
 {
 TCGv_ptr a0, a1;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -127,7 +127,6 @@ void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
 
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with two vector operands
@@ -137,7 +136,7 @@ void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, 
TCGv_i64 c,
  gen_helper_gvec_2i *fn)
 {
 TCGv_ptr a0, a1;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -149,7 +148,6 @@ void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, 
TCGv_i64 c,
 
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with three vector operands.  */
@@ -158,7 +156,7 @@ void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 gen_helper_gvec_3 *fn)
 {
 TCGv_ptr a0, a1, a2;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -173,7 +171,6 @@ void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
 tcg_temp_free_ptr(a2);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with four vector operands.  */
@@ -182,7 +179,7 @@ void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 int32_t data, gen_helper_gvec_4 *fn)
 {
 TCGv_ptr a0, a1, a2, a3;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -200,7 +197,6 @@ void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 tcg_temp_free_ptr(a1);
 tcg_temp_free_ptr(a2);
 tcg_temp_free_ptr(a3);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with five vector operands.  */
@@ -209,7 +205,7 @@ void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 uint32_t maxsz, int32_t data, gen_helper_gvec_5 *fn)
 {
 TCGv_ptr a0, a1, a2, a3, a4;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -230,7 +226,6 @@ void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 tcg_temp_free_ptr(a2);
 tcg_temp_free_ptr(a3);
 tcg_temp_free_ptr(a4);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with three vector operands
@@ -240,7 +235,7 @@ void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs,
 int32_t data, gen_helper_gvec_2_ptr *fn)
 {
 TCGv_ptr a0, a1;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -252,7 +247,6 @@ void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs,
 
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with three vector operands
@@ -262,7 +256,7 @@ void tcg_gen_gvec_3_ptr(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 int32_t data, gen_helper_gvec_3_ptr *fn)
 {
 TCGv_ptr a0, a1, a2;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = 

[PATCH 19/43] tcg/optimize: Improve find_better_copy

2020-09-08 Thread Richard Henderson
Prefer TEMP_CONST over anything else.

Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 27 ---
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index c0fd65d2e4..bf2c2a3ce5 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -122,31 +122,28 @@ static void init_arg_info(TempOptInfo *infos,
 
 static TCGTemp *find_better_copy(TCGContext *s, TCGTemp *ts)
 {
-TCGTemp *i;
+TCGTemp *i, *g, *l;
 
-/* If this is already a global, we can't do better. */
-if (ts->kind >= TEMP_GLOBAL) {
+/* If this is already readonly, we can't do better. */
+if (temp_readonly(ts)) {
 return ts;
 }
 
-/* Search for a global first. */
+g = l = NULL;
 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (i->kind >= TEMP_GLOBAL) {
+if (temp_readonly(i)) {
 return i;
-}
-}
-
-/* If it is a temp, search for a temp local. */
-if (ts->kind == TEMP_NORMAL) {
-for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (i->kind >= TEMP_LOCAL) {
-return i;
+} else if (i->kind > ts->kind) {
+if (i->kind == TEMP_GLOBAL) {
+g = i;
+} else if (i->kind == TEMP_LOCAL) {
+l = i;
 }
 }
 }
 
-/* Failure to find a better representation, return the same temp. */
-return ts;
+/* If we didn't find a better representation, return the same temp. */
+return g ? g : l ? l : ts;
 }
 
 static bool ts_are_copies(TCGTemp *ts1, TCGTemp *ts2)
-- 
2.25.1




[PATCH 09/43] tcg/optimize: Fold dup2_vec

2020-09-08 Thread Richard Henderson
When the two arguments are identical, this can be reduced to
dup_vec or to mov_vec from a tcg_constant_vec.

Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 53aa8e5329..220f4601d5 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -1109,6 +1109,21 @@ void tcg_optimize(TCGContext *s)
 }
 goto do_default;
 
+case INDEX_op_dup2_vec:
+assert(TCG_TARGET_REG_BITS == 32);
+if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
+tmp = arg_info(op->args[1])->val;
+if (tmp == arg_info(op->args[2])->val) {
+tcg_opt_gen_movi(s, op, op->args[0], tmp);
+break;
+}
+} else if (args_are_copies(op->args[1], op->args[2])) {
+op->opc = INDEX_op_dup_vec;
+TCGOP_VECE(op) = MO_32;
+nb_iargs = 1;
+}
+goto do_default;
+
 CASE_OP_32_64(not):
 CASE_OP_32_64(neg):
 CASE_OP_32_64(ext8s):
-- 
2.25.1




[PATCH 34/43] tcg: Add tcg-constr.c.inc

2020-09-08 Thread Richard Henderson
Begin conversion of constraints to pre-validated, read-only entities.
To begin, create a simple method by which sets of TCGTargetOpDef
structures may be declared and used.  This simplifies each host's
tcg_target_op_def function and ensures that we have a collected
set of constraints.

Signed-off-by: Richard Henderson 
---
 tcg/tcg-constr.c.inc | 108 +++
 1 file changed, 108 insertions(+)
 create mode 100644 tcg/tcg-constr.c.inc

diff --git a/tcg/tcg-constr.c.inc b/tcg/tcg-constr.c.inc
new file mode 100644
index 00..f7490a096e
--- /dev/null
+++ b/tcg/tcg-constr.c.inc
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * TCG backend data: operand constaints.
+ * Copyright (c) 2020 Linaro
+ */
+
+/*
+ * Define structures for each set of constraints.
+ */
+
+#define C_PFX1(P, A) P##A
+#define C_PFX2(P, A, B)  P##A##_##B
+#define C_PFX3(P, A, B, C)   P##A##_##B##_##C
+#define C_PFX4(P, A, B, C, D)P##A##_##B##_##C##_##D
+#define C_PFX5(P, A, B, C, D, E) P##A##_##B##_##C##_##D##_##E
+#define C_PFX6(P, A, B, C, D, E, F)  P##A##_##B##_##C##_##D##_##E##_##F
+
+#define C_O0_I1(I1) \
+static const TCGTargetOpDef C_PFX1(c_o0_i1_, I1) \
+  = { .args_ct_str = { #I1 } };
+
+#define C_O0_I2(I1, I2) \
+static const TCGTargetOpDef C_PFX2(c_o0_i2_, I1, I2) \
+  = { .args_ct_str = { #I1, #I2 } };
+
+#define C_O0_I3(I1, I2, I3) \
+static const TCGTargetOpDef C_PFX3(c_o0_i3_, I1, I2, I3) \
+  = { .args_ct_str = { #I1, #I2, #I3 } };
+
+#define C_O0_I4(I1, I2, I3, I4) \
+static const TCGTargetOpDef C_PFX4(c_o0_i4_, I1, I2, I3, I4) \
+  = { .args_ct_str = { #I1, #I2, #I3, #I4 } };
+
+#define C_O1_I1(O1, I1) \
+static const TCGTargetOpDef C_PFX2(c_o1_i1_, O1, I1) \
+  = { .args_ct_str = { #O1, #I1 } };
+
+#define C_O1_I2(O1, I1, I2) \
+static const TCGTargetOpDef C_PFX3(c_o1_i2_, O1, I1, I2) \
+  = { .args_ct_str = { #O1, #I1, #I2 } };
+
+#define C_O1_I3(O1, I1, I2, I3) \
+static const TCGTargetOpDef C_PFX4(c_o1_i3_, O1, I1, I2, I3) \
+  = { .args_ct_str = { #O1, #I1, #I2, #I3 } };
+
+#define C_O1_I4(O1, I1, I2, I3, I4) \
+static const TCGTargetOpDef C_PFX5(c_o1_i4_, O1, I1, I2, I3, I4) \
+  = { .args_ct_str = { #O1, #I1, #I2, #I3, #I4 } };
+
+#define C_N1_I2(O1, I1, I2) \
+static const TCGTargetOpDef C_PFX3(c_n1_i2_, O1, I1, I2) \
+  = { .args_ct_str = { "&" #O1, #I1, #I2 } };
+
+#define C_O2_I1(O1, O2, I1) \
+static const TCGTargetOpDef C_PFX3(c_o2_i1_, O1, O2, I1) \
+  = { .args_ct_str = { #O1, #O2, #I1 } };
+
+#define C_O2_I2(O1, O2, I1, I2) \
+static const TCGTargetOpDef C_PFX4(c_o2_i2_, O1, O2, I1, I2) \
+  = { .args_ct_str = { #O1, #O2, #I1, #I2 } };
+
+#define C_O2_I3(O1, O2, I1, I2, I3) \
+static const TCGTargetOpDef C_PFX5(c_o2_i3_, O1, O2, I1, I2, I3) \
+  = { .args_ct_str = { #O1, #O2, #I1, #I2, #I3 } };
+
+#define C_O2_I4(O1, O2, I1, I2, I3, I4) \
+static const TCGTargetOpDef C_PFX6(c_o2_i4_, O1, O2, I1, I2, I3, I4) \
+  = { .args_ct_str = { #O1, #O2, #I1, #I2, #I3, #I4 } };
+
+#include "tcg-target-constr.h"
+
+
+/*
+ * Redefine the macros so that they now reference those structures.
+ * These values should be returned from tcg_target_op_def().
+ */
+
+#undef C_O0_I1
+#undef C_O0_I2
+#undef C_O0_I3
+#undef C_O0_I4
+#undef C_O1_I1
+#undef C_O1_I2
+#undef C_O1_I3
+#undef C_O1_I4
+#undef C_N1_I2
+#undef C_O2_I1
+#undef C_O2_I2
+#undef C_O2_I3
+#undef C_O2_I4
+
+#define C_O0_I1(I1) _PFX1(c_o0_i1_, I1)
+#define C_O0_I2(I1, I2) _PFX2(c_o0_i2_, I1, I2)
+#define C_O0_I3(I1, I2, I3) _PFX3(c_o0_i3_, I1, I2, I3)
+#define C_O0_I4(I1, I2, I3, I4) _PFX4(c_o0_i4_, I1, I2, I3, I4)
+
+#define C_O1_I1(O1, I1) _PFX2(c_o1_i1_, O1, I1)
+#define C_O1_I2(O1, I1, I2) _PFX3(c_o1_i2_, O1, I1, I2)
+#define C_O1_I3(O1, I1, I2, I3) _PFX4(c_o1_i3_, O1, I1, I2, I3)
+#define C_O1_I4(O1, I1, I2, I3, I4) _PFX5(c_o1_i4_, O1, I1, I2, I3, I4)
+
+#define C_N1_I2(O1, I1, I2) _PFX3(c_n1_i2_, O1, I1, I2)
+
+#define C_O2_I1(O1, O2, I1) _PFX3(c_o2_i1_, O1, O2, I1)
+#define C_O2_I2(O1, O2, I1, I2) _PFX4(c_o2_i2_, O1, O2, I1, I2)
+#define C_O2_I3(O1, O2, I1, I2, I3) _PFX5(c_o2_i3_, O1, O2, I1, I2, I3)
+#define C_O2_I4(O1, O2, I1, I2, I3, I4) \
+_PFX6(c_o2_i4_, O1, O2, I1, I2, I3, I4)
-- 
2.25.1




[PATCH 25/43] tcg: Use tcg_constant_{i32,i64} with tcg plugins

2020-09-08 Thread Richard Henderson
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 accel/tcg/plugin-gen.c | 49 +++---
 1 file changed, 22 insertions(+), 27 deletions(-)

diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
index 51580d51a0..e5dc9d0ca9 100644
--- a/accel/tcg/plugin-gen.c
+++ b/accel/tcg/plugin-gen.c
@@ -284,8 +284,8 @@ static TCGOp *copy_extu_i32_i64(TCGOp **begin_op, TCGOp *op)
 if (TCG_TARGET_REG_BITS == 32) {
 /* mov_i32 */
 op = copy_op(begin_op, op, INDEX_op_mov_i32);
-/* movi_i32 */
-op = copy_op(begin_op, op, INDEX_op_movi_i32);
+/* mov_i32 w/ $0 */
+op = copy_op(begin_op, op, INDEX_op_mov_i32);
 } else {
 /* extu_i32_i64 */
 op = copy_op(begin_op, op, INDEX_op_extu_i32_i64);
@@ -306,39 +306,34 @@ static TCGOp *copy_mov_i64(TCGOp **begin_op, TCGOp *op)
 return op;
 }
 
-static TCGOp *copy_movi_i64(TCGOp **begin_op, TCGOp *op, uint64_t v)
-{
-if (TCG_TARGET_REG_BITS == 32) {
-/* 2x movi_i32 */
-op = copy_op(begin_op, op, INDEX_op_movi_i32);
-op->args[1] = v;
-
-op = copy_op(begin_op, op, INDEX_op_movi_i32);
-op->args[1] = v >> 32;
-} else {
-/* movi_i64 */
-op = copy_op(begin_op, op, INDEX_op_movi_i64);
-op->args[1] = v;
-}
-return op;
-}
-
 static TCGOp *copy_const_ptr(TCGOp **begin_op, TCGOp *op, void *ptr)
 {
 if (UINTPTR_MAX == UINT32_MAX) {
-/* movi_i32 */
-op = copy_op(begin_op, op, INDEX_op_movi_i32);
-op->args[1] = (uintptr_t)ptr;
+/* mov_i32 */
+op = copy_op(begin_op, op, INDEX_op_mov_i32);
+op->args[1] = tcgv_i32_arg(tcg_constant_i32((uintptr_t)ptr));
 } else {
-/* movi_i64 */
-op = copy_movi_i64(begin_op, op, (uint64_t)(uintptr_t)ptr);
+/* mov_i64 */
+op = copy_op(begin_op, op, INDEX_op_mov_i64);
+op->args[1] = tcgv_i64_arg(tcg_constant_i64((uintptr_t)ptr));
 }
 return op;
 }
 
 static TCGOp *copy_const_i64(TCGOp **begin_op, TCGOp *op, uint64_t v)
 {
-return copy_movi_i64(begin_op, op, v);
+if (TCG_TARGET_REG_BITS == 32) {
+/* 2x mov_i32 */
+op = copy_op(begin_op, op, INDEX_op_mov_i32);
+op->args[1] = tcgv_i32_arg(tcg_constant_i32(v));
+op = copy_op(begin_op, op, INDEX_op_mov_i32);
+op->args[1] = tcgv_i32_arg(tcg_constant_i32(v >> 32));
+} else {
+/* mov_i64 */
+op = copy_op(begin_op, op, INDEX_op_mov_i64);
+op->args[1] = tcgv_i64_arg(tcg_constant_i64(v));
+}
+return op;
 }
 
 static TCGOp *copy_extu_tl_i64(TCGOp **begin_op, TCGOp *op)
@@ -486,8 +481,8 @@ static TCGOp *append_mem_cb(const struct qemu_plugin_dyn_cb 
*cb,
 
 tcg_debug_assert(type == PLUGIN_GEN_CB_MEM);
 
-/* const_i32 == movi_i32 ("info", so it remains as is) */
-op = copy_op(_op, op, INDEX_op_movi_i32);
+/* const_i32 == mov_i32 ("info", so it remains as is) */
+op = copy_op(_op, op, INDEX_op_mov_i32);
 
 /* const_ptr */
 op = copy_const_ptr(_op, op, cb->userp);
-- 
2.25.1




[PATCH 28/43] tcg: Remove movi and dupi opcodes

2020-09-08 Thread Richard Henderson
These are now completely covered by mov from a
TYPE_CONST temporary.

Reviewed-by: Alex Bennée 
Reviewed-by: Aleksandar Markovic 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-opc.h|  3 ---
 tcg/optimize.c   |  4 
 tcg/tcg-op-vec.c |  1 -
 tcg/tcg.c| 18 +-
 tcg/aarch64/tcg-target.c.inc |  3 ---
 tcg/arm/tcg-target.c.inc |  1 -
 tcg/i386/tcg-target.c.inc|  3 ---
 tcg/mips/tcg-target.c.inc|  2 --
 tcg/ppc/tcg-target.c.inc |  3 ---
 tcg/riscv/tcg-target.c.inc   |  2 --
 tcg/s390/tcg-target.c.inc|  2 --
 tcg/sparc/tcg-target.c.inc   |  2 --
 tcg/tci/tcg-target.c.inc |  2 --
 13 files changed, 1 insertion(+), 45 deletions(-)

diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
index 5a941eaa07..d63c6bcb3d 100644
--- a/include/tcg/tcg-opc.h
+++ b/include/tcg/tcg-opc.h
@@ -45,7 +45,6 @@ DEF(br, 0, 0, 1, TCG_OPF_BB_END)
 DEF(mb, 0, 0, 1, 0)
 
 DEF(mov_i32, 1, 1, 0, TCG_OPF_NOT_PRESENT)
-DEF(movi_i32, 1, 0, 1, TCG_OPF_NOT_PRESENT)
 DEF(setcond_i32, 1, 2, 1, 0)
 DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32))
 /* load/store */
@@ -110,7 +109,6 @@ DEF(ctz_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_ctz_i32))
 DEF(ctpop_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ctpop_i32))
 
 DEF(mov_i64, 1, 1, 0, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
-DEF(movi_i64, 1, 0, 1, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
 DEF(setcond_i64, 1, 2, 1, IMPL64)
 DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64))
 /* load/store */
@@ -215,7 +213,6 @@ DEF(qemu_st_i64, 0, TLADDR_ARGS + DATA64_ARGS, 1,
 #define IMPLVEC  TCG_OPF_VECTOR | IMPL(TCG_TARGET_MAYBE_vec)
 
 DEF(mov_vec, 1, 1, 0, TCG_OPF_VECTOR | TCG_OPF_NOT_PRESENT)
-DEF(dupi_vec, 1, 0, 1, TCG_OPF_VECTOR | TCG_OPF_NOT_PRESENT)
 
 DEF(dup_vec, 1, 1, 0, IMPLVEC)
 DEF(dup2_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_REG_BITS == 32))
diff --git a/tcg/optimize.c b/tcg/optimize.c
index af07c6f628..1a94e9a41b 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -1099,10 +1099,6 @@ void tcg_optimize(TCGContext *s)
 CASE_OP_32_64_VEC(mov):
 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
 break;
-CASE_OP_32_64(movi):
-case INDEX_op_dupi_vec:
-tcg_opt_gen_movi(s, _used, op, op->args[0], op->args[1]);
-break;
 
 case INDEX_op_dup_vec:
 if (arg_is_const(op->args[1])) {
diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c
index 9fbed1366c..ce0d2f6e0e 100644
--- a/tcg/tcg-op-vec.c
+++ b/tcg/tcg-op-vec.c
@@ -83,7 +83,6 @@ bool tcg_can_emit_vecop_list(const TCGOpcode *list,
 case INDEX_op_xor_vec:
 case INDEX_op_mov_vec:
 case INDEX_op_dup_vec:
-case INDEX_op_dupi_vec:
 case INDEX_op_dup2_vec:
 case INDEX_op_ld_vec:
 case INDEX_op_st_vec:
diff --git a/tcg/tcg.c b/tcg/tcg.c
index b63da0b603..f9c6450837 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1503,7 +1503,6 @@ bool tcg_op_supported(TCGOpcode op)
 return TCG_TARGET_HAS_goto_ptr;
 
 case INDEX_op_mov_i32:
-case INDEX_op_movi_i32:
 case INDEX_op_setcond_i32:
 case INDEX_op_brcond_i32:
 case INDEX_op_ld8u_i32:
@@ -1597,7 +1596,6 @@ bool tcg_op_supported(TCGOpcode op)
 return TCG_TARGET_REG_BITS == 32;
 
 case INDEX_op_mov_i64:
-case INDEX_op_movi_i64:
 case INDEX_op_setcond_i64:
 case INDEX_op_brcond_i64:
 case INDEX_op_ld8u_i64:
@@ -1703,7 +1701,6 @@ bool tcg_op_supported(TCGOpcode op)
 
 case INDEX_op_mov_vec:
 case INDEX_op_dup_vec:
-case INDEX_op_dupi_vec:
 case INDEX_op_dupm_vec:
 case INDEX_op_ld_vec:
 case INDEX_op_st_vec:
@@ -3542,7 +3539,7 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet 
allocated_regs)
 }
 
 /*
- * Specialized code generation for INDEX_op_movi_*.
+ * Specialized code generation for INDEX_op_mov_* with a constant.
  */
 static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp *ots,
   tcg_target_ulong val, TCGLifeData arg_life,
@@ -3565,14 +3562,6 @@ static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp 
*ots,
 }
 }
 
-static void tcg_reg_alloc_movi(TCGContext *s, const TCGOp *op)
-{
-TCGTemp *ots = arg_temp(op->args[0]);
-tcg_target_ulong val = op->args[1];
-
-tcg_reg_alloc_do_movi(s, ots, val, op->life, op->output_pref[0]);
-}
-
 /*
  * Specialized code generation for INDEX_op_mov_*.
  */
@@ -4353,11 +4342,6 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
 case INDEX_op_mov_vec:
 tcg_reg_alloc_mov(s, op);
 break;
-case INDEX_op_movi_i32:
-case INDEX_op_movi_i64:
-case INDEX_op_dupi_vec:
-tcg_reg_alloc_movi(s, op);
-break;
 case INDEX_op_dup_vec:
 tcg_reg_alloc_dup(s, op);
 break;
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 5692607087..fdc118391c 100644
--- 

[PATCH 08/43] tcg: Fix generation of dupi_vec for 32-bit host

2020-09-08 Thread Richard Henderson
The definition of INDEX_op_dupi_vec is that it operates on
units of tcg_target_ulong -- in this case 32 bits.  It does
not work to use this for a uint64_t value that happens to be
small enough to fit in tcg_target_ulong.

Fixes: d2fd745fe8b
Fixes: db432672dc5
Cc: qemu-sta...@nongnu.org
Signed-off-by: Richard Henderson 
---
 tcg/tcg-op-vec.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c
index ed6fb55fe1..cdbf11c573 100644
--- a/tcg/tcg-op-vec.c
+++ b/tcg/tcg-op-vec.c
@@ -252,10 +252,10 @@ TCGv_vec tcg_const_ones_vec_matching(TCGv_vec m)
 
 void tcg_gen_dup64i_vec(TCGv_vec r, uint64_t a)
 {
-if (TCG_TARGET_REG_BITS == 32 && a == deposit64(a, 32, 32, a)) {
-do_dupi_vec(r, MO_32, a);
-} else if (TCG_TARGET_REG_BITS == 64 || a == (uint64_t)(int32_t)a) {
+if (TCG_TARGET_REG_BITS == 64) {
 do_dupi_vec(r, MO_64, a);
+} else if (a == dup_const(MO_32, a)) {
+do_dupi_vec(r, MO_32, a);
 } else {
 TCGv_i64 c = tcg_const_i64(a);
 tcg_gen_dup_i64_vec(MO_64, r, c);
@@ -280,7 +280,11 @@ void tcg_gen_dup8i_vec(TCGv_vec r, uint32_t a)
 
 void tcg_gen_dupi_vec(unsigned vece, TCGv_vec r, uint64_t a)
 {
-do_dupi_vec(r, MO_REG, dup_const(vece, a));
+if (vece == MO_64) {
+tcg_gen_dup64i_vec(r, a);
+} else {
+do_dupi_vec(r, MO_REG, dup_const(vece, a));
+}
 }
 
 void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec r, TCGv_i64 a)
-- 
2.25.1




[PATCH 16/43] tcg: Rename struct tcg_temp_info to TempOptInfo

2020-09-08 Thread Richard Henderson
Fix this name vs our coding style.

Reviewed-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 32 
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 3cffd941bd..81faf7cf10 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -35,20 +35,20 @@
 glue(glue(case INDEX_op_, x), _i64):\
 glue(glue(case INDEX_op_, x), _vec)
 
-struct tcg_temp_info {
+typedef struct TempOptInfo {
 bool is_const;
 TCGTemp *prev_copy;
 TCGTemp *next_copy;
 tcg_target_ulong val;
 tcg_target_ulong mask;
-};
+} TempOptInfo;
 
-static inline struct tcg_temp_info *ts_info(TCGTemp *ts)
+static inline TempOptInfo *ts_info(TCGTemp *ts)
 {
 return ts->state_ptr;
 }
 
-static inline struct tcg_temp_info *arg_info(TCGArg arg)
+static inline TempOptInfo *arg_info(TCGArg arg)
 {
 return ts_info(arg_temp(arg));
 }
@@ -71,9 +71,9 @@ static inline bool ts_is_copy(TCGTemp *ts)
 /* Reset TEMP's state, possibly removing the temp for the list of copies.  */
 static void reset_ts(TCGTemp *ts)
 {
-struct tcg_temp_info *ti = ts_info(ts);
-struct tcg_temp_info *pi = ts_info(ti->prev_copy);
-struct tcg_temp_info *ni = ts_info(ti->next_copy);
+TempOptInfo *ti = ts_info(ts);
+TempOptInfo *pi = ts_info(ti->prev_copy);
+TempOptInfo *ni = ts_info(ti->next_copy);
 
 ni->prev_copy = ti->prev_copy;
 pi->next_copy = ti->next_copy;
@@ -89,12 +89,12 @@ static void reset_temp(TCGArg arg)
 }
 
 /* Initialize and activate a temporary.  */
-static void init_ts_info(struct tcg_temp_info *infos,
+static void init_ts_info(TempOptInfo *infos,
  TCGTempSet *temps_used, TCGTemp *ts)
 {
 size_t idx = temp_idx(ts);
 if (!test_bit(idx, temps_used->l)) {
-struct tcg_temp_info *ti = [idx];
+TempOptInfo *ti = [idx];
 
 ts->state_ptr = ti;
 ti->next_copy = ts;
@@ -105,7 +105,7 @@ static void init_ts_info(struct tcg_temp_info *infos,
 }
 }
 
-static void init_arg_info(struct tcg_temp_info *infos,
+static void init_arg_info(TempOptInfo *infos,
   TCGTempSet *temps_used, TCGArg arg)
 {
 init_ts_info(infos, temps_used, arg_temp(arg));
@@ -171,7 +171,7 @@ static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg val)
 const TCGOpDef *def;
 TCGOpcode new_op;
 tcg_target_ulong mask;
-struct tcg_temp_info *di = arg_info(dst);
+TempOptInfo *di = arg_info(dst);
 
 def = _op_defs[op->opc];
 if (def->flags & TCG_OPF_VECTOR) {
@@ -202,8 +202,8 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 TCGTemp *dst_ts = arg_temp(dst);
 TCGTemp *src_ts = arg_temp(src);
 const TCGOpDef *def;
-struct tcg_temp_info *di;
-struct tcg_temp_info *si;
+TempOptInfo *di;
+TempOptInfo *si;
 tcg_target_ulong mask;
 TCGOpcode new_op;
 
@@ -236,7 +236,7 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 di->mask = mask;
 
 if (src_ts->type == dst_ts->type) {
-struct tcg_temp_info *ni = ts_info(si->next_copy);
+TempOptInfo *ni = ts_info(si->next_copy);
 
 di->next_copy = si->next_copy;
 di->prev_copy = src_ts;
@@ -599,7 +599,7 @@ void tcg_optimize(TCGContext *s)
 {
 int nb_temps, nb_globals;
 TCGOp *op, *op_next, *prev_mb = NULL;
-struct tcg_temp_info *infos;
+TempOptInfo *infos;
 TCGTempSet temps_used;
 
 /* Array VALS has an element for each temp.
@@ -610,7 +610,7 @@ void tcg_optimize(TCGContext *s)
 nb_temps = s->nb_temps;
 nb_globals = s->nb_globals;
 bitmap_zero(temps_used.l, nb_temps);
-infos = tcg_malloc(sizeof(struct tcg_temp_info) * nb_temps);
+infos = tcg_malloc(sizeof(TempOptInfo) * nb_temps);
 
 QTAILQ_FOREACH_SAFE(op, >ops, link, op_next) {
 tcg_target_ulong mask, partmask, affected;
-- 
2.25.1




[PATCH 21/43] tcg/optimize: Use tcg_constant_internal with constant folding

2020-09-08 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 108 ++---
 1 file changed, 49 insertions(+), 59 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index e269962932..1eda7dc419 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -178,37 +178,6 @@ static bool args_are_copies(TCGArg arg1, TCGArg arg2)
 return ts_are_copies(arg_temp(arg1), arg_temp(arg2));
 }
 
-static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg dst, uint64_t 
val)
-{
-const TCGOpDef *def;
-TCGOpcode new_op;
-uint64_t mask;
-TempOptInfo *di = arg_info(dst);
-
-def = _op_defs[op->opc];
-if (def->flags & TCG_OPF_VECTOR) {
-new_op = INDEX_op_dupi_vec;
-} else if (def->flags & TCG_OPF_64BIT) {
-new_op = INDEX_op_movi_i64;
-} else {
-new_op = INDEX_op_movi_i32;
-}
-op->opc = new_op;
-/* TCGOP_VECL and TCGOP_VECE remain unchanged.  */
-op->args[0] = dst;
-op->args[1] = val;
-
-reset_temp(dst);
-di->is_const = true;
-di->val = val;
-mask = val;
-if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_movi_i32) {
-/* High bits of the destination are now garbage.  */
-mask |= ~0xull;
-}
-di->mask = mask;
-}
-
 static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg src)
 {
 TCGTemp *dst_ts = arg_temp(dst);
@@ -259,6 +228,27 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 }
 }
 
+static void tcg_opt_gen_movi(TCGContext *s, TCGTempSet *temps_used,
+ TCGOp *op, TCGArg dst, uint64_t val)
+{
+const TCGOpDef *def = _op_defs[op->opc];
+TCGType type;
+TCGTemp *tv;
+
+if (def->flags & TCG_OPF_VECTOR) {
+type = TCGOP_VECL(op) + TCG_TYPE_V64;
+} else if (def->flags & TCG_OPF_64BIT) {
+type = TCG_TYPE_I64;
+} else {
+type = TCG_TYPE_I32;
+}
+
+/* Convert movi to mov with constant temp. */
+tv = tcg_constant_internal(type, val);
+init_ts_info(temps_used, tv);
+tcg_opt_gen_mov(s, op, dst, temp_arg(tv));
+}
+
 static uint64_t do_constant_folding_2(TCGOpcode op, uint64_t x, uint64_t y)
 {
 uint64_t l64, h64;
@@ -622,7 +612,7 @@ void tcg_optimize(TCGContext *s)
 nb_temps = s->nb_temps;
 nb_globals = s->nb_globals;
 
-bitmap_zero(temps_used.l, nb_temps);
+memset(_used, 0, sizeof(temps_used));
 for (i = 0; i < nb_temps; ++i) {
 s->temps[i].state_ptr = NULL;
 }
@@ -727,7 +717,7 @@ void tcg_optimize(TCGContext *s)
 CASE_OP_32_64(rotr):
 if (arg_is_const(op->args[1])
 && arg_info(op->args[1])->val == 0) {
-tcg_opt_gen_movi(s, op, op->args[0], 0);
+tcg_opt_gen_movi(s, _used, op, op->args[0], 0);
 continue;
 }
 break;
@@ -1050,7 +1040,7 @@ void tcg_optimize(TCGContext *s)
 
 if (partmask == 0) {
 tcg_debug_assert(nb_oargs == 1);
-tcg_opt_gen_movi(s, op, op->args[0], 0);
+tcg_opt_gen_movi(s, _used, op, op->args[0], 0);
 continue;
 }
 if (affected == 0) {
@@ -1067,7 +1057,7 @@ void tcg_optimize(TCGContext *s)
 CASE_OP_32_64(mulsh):
 if (arg_is_const(op->args[2])
 && arg_info(op->args[2])->val == 0) {
-tcg_opt_gen_movi(s, op, op->args[0], 0);
+tcg_opt_gen_movi(s, _used, op, op->args[0], 0);
 continue;
 }
 break;
@@ -1094,7 +1084,7 @@ void tcg_optimize(TCGContext *s)
 CASE_OP_32_64_VEC(sub):
 CASE_OP_32_64_VEC(xor):
 if (args_are_copies(op->args[1], op->args[2])) {
-tcg_opt_gen_movi(s, op, op->args[0], 0);
+tcg_opt_gen_movi(s, _used, op, op->args[0], 0);
 continue;
 }
 break;
@@ -,14 +1101,14 @@ void tcg_optimize(TCGContext *s)
 break;
 CASE_OP_32_64(movi):
 case INDEX_op_dupi_vec:
-tcg_opt_gen_movi(s, op, op->args[0], op->args[1]);
+tcg_opt_gen_movi(s, _used, op, op->args[0], op->args[1]);
 break;
 
 case INDEX_op_dup_vec:
 if (arg_is_const(op->args[1])) {
 tmp = arg_info(op->args[1])->val;
 tmp = dup_const(TCGOP_VECE(op), tmp);
-tcg_opt_gen_movi(s, op, op->args[0], tmp);
+tcg_opt_gen_movi(s, _used, op, op->args[0], tmp);
 break;
 }
 goto do_default;
@@ -1128,7 +1118,7 @@ void tcg_optimize(TCGContext *s)
 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
 tmp = arg_info(op->args[1])->val;
 if (tmp == arg_info(op->args[2])->val) {
-tcg_opt_gen_movi(s, op, op->args[0], tmp);
+tcg_opt_gen_movi(s, _used, op, op->args[0], tmp);
  

[PATCH 24/43] tcg: Use tcg_constant_{i32,i64} with tcg int expanders

2020-09-08 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-op.h |  13 +--
 tcg/tcg-op.c | 227 ---
 2 files changed, 109 insertions(+), 131 deletions(-)

diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
index 5abf17fecc..b4fba35e87 100644
--- a/include/tcg/tcg-op.h
+++ b/include/tcg/tcg-op.h
@@ -271,6 +271,7 @@ void tcg_gen_mb(TCGBar);
 
 /* 32 bit ops */
 
+void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg);
 void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
 void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2);
 void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
@@ -349,11 +350,6 @@ static inline void tcg_gen_mov_i32(TCGv_i32 ret, TCGv_i32 
arg)
 }
 }
 
-static inline void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg)
-{
-tcg_gen_op2i_i32(INDEX_op_movi_i32, ret, arg);
-}
-
 static inline void tcg_gen_ld8u_i32(TCGv_i32 ret, TCGv_ptr arg2,
 tcg_target_long offset)
 {
@@ -467,6 +463,7 @@ static inline void tcg_gen_not_i32(TCGv_i32 ret, TCGv_i32 
arg)
 
 /* 64 bit ops */
 
+void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg);
 void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
 void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2);
 void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
@@ -550,11 +547,6 @@ static inline void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 
arg)
 }
 }
 
-static inline void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
-{
-tcg_gen_op2i_i64(INDEX_op_movi_i64, ret, arg);
-}
-
 static inline void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2,
 tcg_target_long offset)
 {
@@ -698,7 +690,6 @@ static inline void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 
arg1, TCGv_i64 arg2)
 
 void tcg_gen_discard_i64(TCGv_i64 arg);
 void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg);
-void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg);
 void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
 void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
 void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index 4b8a473fad..e2d8ae3234 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -104,15 +104,18 @@ void tcg_gen_mb(TCGBar mb_type)
 
 /* 32 bit ops */
 
+void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg)
+{
+tcg_gen_mov_i32(ret, tcg_constant_i32(arg));
+}
+
 void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
 {
 /* some cases can be optimized here */
 if (arg2 == 0) {
 tcg_gen_mov_i32(ret, arg1);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg2);
-tcg_gen_add_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+tcg_gen_add_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 }
 
@@ -122,9 +125,7 @@ void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 
arg2)
 /* Don't recurse with tcg_gen_neg_i32.  */
 tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg1);
-tcg_gen_sub_i32(ret, t0, arg2);
-tcg_temp_free_i32(t0);
+tcg_gen_sub_i32(ret, tcg_constant_i32(arg1), arg2);
 }
 }
 
@@ -134,15 +135,12 @@ void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, 
int32_t arg2)
 if (arg2 == 0) {
 tcg_gen_mov_i32(ret, arg1);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg2);
-tcg_gen_sub_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+tcg_gen_sub_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 }
 
 void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
 {
-TCGv_i32 t0;
 /* Some cases can be optimized here.  */
 switch (arg2) {
 case 0:
@@ -165,9 +163,8 @@ void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t 
arg2)
 }
 break;
 }
-t0 = tcg_const_i32(arg2);
-tcg_gen_and_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+
+tcg_gen_and_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 
 void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
@@ -178,9 +175,7 @@ void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t 
arg2)
 } else if (arg2 == 0) {
 tcg_gen_mov_i32(ret, arg1);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg2);
-tcg_gen_or_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+tcg_gen_or_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 }
 
@@ -193,9 +188,7 @@ void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t 
arg2)
 /* Don't recurse with tcg_gen_not_i32.  */
 tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg2);
-tcg_gen_xor_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+tcg_gen_xor_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 }
 
@@ -205,9 +198,7 @@ void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t 
arg2)
 if (arg2 == 0) {
   

[PATCH 14/43] tcg: Add temp_readonly

2020-09-08 Thread Richard Henderson
In most, but not all, places that we check for TEMP_FIXED,
we are really testing that we do not modify the temporary.

Reviewed-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h |  5 +
 tcg/tcg.c | 21 ++---
 2 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index f157092b51..44ca8845cf 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -681,6 +681,11 @@ struct TCGContext {
 target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS];
 };
 
+static inline bool temp_readonly(TCGTemp *ts)
+{
+return ts->kind == TEMP_FIXED;
+}
+
 extern TCGContext tcg_init_ctx;
 extern __thread TCGContext *tcg_ctx;
 extern TCGv_env cpu_env;
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 67e122527b..577bfec202 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -3172,7 +3172,7 @@ static void temp_load(TCGContext *, TCGTemp *, TCGRegSet, 
TCGRegSet, TCGRegSet);
mark it free; otherwise mark it dead.  */
 static void temp_free_or_dead(TCGContext *s, TCGTemp *ts, int free_or_dead)
 {
-if (ts->kind == TEMP_FIXED) {
+if (temp_readonly(ts)) {
 return;
 }
 if (ts->val_type == TEMP_VAL_REG) {
@@ -3196,7 +3196,7 @@ static inline void temp_dead(TCGContext *s, TCGTemp *ts)
 static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs,
   TCGRegSet preferred_regs, int free_or_dead)
 {
-if (ts->kind == TEMP_FIXED) {
+if (temp_readonly(ts)) {
 return;
 }
 if (!ts->mem_coherent) {
@@ -3379,8 +3379,7 @@ static void temp_save(TCGContext *s, TCGTemp *ts, 
TCGRegSet allocated_regs)
 {
 /* The liveness analysis already ensures that globals are back
in memory. Keep an tcg_debug_assert for safety. */
-tcg_debug_assert(ts->val_type == TEMP_VAL_MEM
- || ts->kind == TEMP_FIXED);
+tcg_debug_assert(ts->val_type == TEMP_VAL_MEM || temp_readonly(ts));
 }
 
 /* save globals to their canonical location and assume they can be
@@ -3438,7 +3437,7 @@ static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp 
*ots,
   TCGRegSet preferred_regs)
 {
 /* ENV should not be modified.  */
-tcg_debug_assert(ots->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ots));
 
 /* The movi is not explicitly generated here.  */
 if (ots->val_type == TEMP_VAL_REG) {
@@ -3478,7 +3477,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp 
*op)
 ts = arg_temp(op->args[1]);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ots->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ots));
 
 /* Note that otype != itype for no-op truncation.  */
 otype = ots->type;
@@ -3539,7 +3538,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp 
*op)
  * Store the source register into the destination slot
  * and leave the destination temp as TEMP_VAL_MEM.
  */
-assert(ots->kind != TEMP_FIXED);
+assert(!temp_readonly(ots));
 if (!ts->mem_allocated) {
 temp_allocate_frame(s, ots);
 }
@@ -3576,7 +3575,7 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp 
*op)
 its = arg_temp(op->args[1]);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ots->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ots));
 
 itype = its->type;
 vece = TCGOP_VECE(op);
@@ -3806,7 +3805,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 ts = arg_temp(arg);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ts->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ts));
 
 if (arg_ct->oalias && !const_args[arg_ct->alias_index]) {
 reg = new_args[arg_ct->alias_index];
@@ -3847,7 +3846,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 ts = arg_temp(op->args[i]);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ts->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ts));
 
 if (NEED_SYNC_ARG(i)) {
 temp_sync(s, ts, o_allocated_regs, 0, IS_DEAD_ARG(i));
@@ -3979,7 +3978,7 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op)
 ts = arg_temp(arg);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ts->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ts));
 
 reg = tcg_target_call_oarg_regs[i];
 tcg_debug_assert(s->reg_to_temp[reg] == NULL);
-- 
2.25.1




[PATCH 07/43] tcg/i386: Fix dupi for avx2 32-bit hosts

2020-09-08 Thread Richard Henderson
The previous change wrongly stated that 32-bit avx2 should have
used VPBROADCASTW.  But that's a 16-bit broadcast and we want a
32-bit broadcast.

Fixes: 7b60ef3264e
Cc: qemu-sta...@nongnu.org
Signed-off-by: Richard Henderson 
---
 tcg/i386/tcg-target.c.inc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 2f696074ab..d8797ed398 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -958,7 +958,7 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
 new_pool_label(s, arg, R_386_PC32, s->code_ptr - 4, -4);
 } else {
 if (have_avx2) {
-tcg_out_vex_modrm_pool(s, OPC_VPBROADCASTW + vex_l, ret);
+tcg_out_vex_modrm_pool(s, OPC_VPBROADCASTD + vex_l, ret);
 } else {
 tcg_out_vex_modrm_pool(s, OPC_VBROADCASTSS, ret);
 }
-- 
2.25.1




[PATCH 18/43] tcg: Introduce TYPE_CONST temporaries

2020-09-08 Thread Richard Henderson
These will hold a single constant for the duration of the TB.
They are hashed, so that each value has one temp across the TB.

Not used yet, this is all infrastructure.

Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h |  24 +-
 tcg/optimize.c|  13 +++-
 tcg/tcg.c | 195 --
 3 files changed, 188 insertions(+), 44 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index f3eca6feb0..aa7b0ba163 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -492,6 +492,8 @@ typedef enum TCGTempKind {
 TEMP_GLOBAL,
 /* Temp is in a fixed register. */
 TEMP_FIXED,
+/* Temp is a fixed constant. */
+TEMP_CONST,
 } TCGTempKind;
 
 typedef struct TCGTemp {
@@ -667,6 +669,7 @@ struct TCGContext {
 QSIMPLEQ_HEAD(, TCGOp) plugin_ops;
 #endif
 
+GHashTable *const_table[TCG_TYPE_COUNT];
 TCGTempSet free_temps[TCG_TYPE_COUNT * 2];
 TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
 
@@ -683,7 +686,7 @@ struct TCGContext {
 
 static inline bool temp_readonly(TCGTemp *ts)
 {
-return ts->kind == TEMP_FIXED;
+return ts->kind >= TEMP_FIXED;
 }
 
 extern TCGContext tcg_init_ctx;
@@ -1051,6 +1054,7 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, 
TCGOpcode opc);
 
 void tcg_optimize(TCGContext *s);
 
+/* Allocate a new temporary and initialize it with a constant. */
 TCGv_i32 tcg_const_i32(int32_t val);
 TCGv_i64 tcg_const_i64(int64_t val);
 TCGv_i32 tcg_const_local_i32(int32_t val);
@@ -1060,6 +1064,24 @@ TCGv_vec tcg_const_ones_vec(TCGType);
 TCGv_vec tcg_const_zeros_vec_matching(TCGv_vec);
 TCGv_vec tcg_const_ones_vec_matching(TCGv_vec);
 
+/*
+ * Locate or create a read-only temporary that is a constant.
+ * This kind of temporary need not and should not be freed.
+ */
+TCGTemp *tcg_constant_internal(TCGType type, int64_t val);
+
+static inline TCGv_i32 tcg_constant_i32(int32_t val)
+{
+return temp_tcgv_i32(tcg_constant_internal(TCG_TYPE_I32, val));
+}
+
+static inline TCGv_i64 tcg_constant_i64(int64_t val)
+{
+return temp_tcgv_i64(tcg_constant_internal(TCG_TYPE_I64, val));
+}
+
+TCGv_vec tcg_constant_vec(TCGType type, unsigned vece, int64_t val);
+
 #if UINTPTR_MAX == UINT32_MAX
 # define tcg_const_ptr(x)((TCGv_ptr)tcg_const_i32((intptr_t)(x)))
 # define tcg_const_local_ptr(x)  ((TCGv_ptr)tcg_const_local_i32((intptr_t)(x)))
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 33d1fc8f87..c0fd65d2e4 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -99,8 +99,17 @@ static void init_ts_info(TempOptInfo *infos,
 ts->state_ptr = ti;
 ti->next_copy = ts;
 ti->prev_copy = ts;
-ti->is_const = false;
-ti->mask = -1;
+if (ts->kind == TEMP_CONST) {
+ti->is_const = true;
+ti->val = ti->mask = ts->val;
+if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) {
+/* High bits of a 32-bit quantity are garbage.  */
+ti->mask |= ~0xull;
+}
+} else {
+ti->is_const = false;
+ti->mask = -1;
+}
 set_bit(idx, temps_used->l);
 }
 }
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 1650c5a9db..e413bf70d4 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1204,13 +1204,19 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, 
TCGv_ptr base,
 bigendian = 1;
 #endif
 
-if (base_ts->kind != TEMP_FIXED) {
+switch (base_ts->kind) {
+case TEMP_FIXED:
+break;
+case TEMP_GLOBAL:
 /* We do not support double-indirect registers.  */
 tcg_debug_assert(!base_ts->indirect_reg);
 base_ts->indirect_base = 1;
 s->nb_indirects += (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64
 ? 2 : 1);
 indirect_reg = 1;
+break;
+default:
+g_assert_not_reached();
 }
 
 if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
@@ -1335,6 +1341,11 @@ void tcg_temp_free_internal(TCGTemp *ts)
 TCGContext *s = tcg_ctx;
 int k, idx;
 
+/* In order to simplify users of tcg_constant_*, silently ignore free. */
+if (ts->kind == TEMP_CONST) {
+return;
+}
+
 #if defined(CONFIG_DEBUG_TCG)
 s->temps_in_use--;
 if (s->temps_in_use < 0) {
@@ -1351,6 +1362,60 @@ void tcg_temp_free_internal(TCGTemp *ts)
 set_bit(idx, s->free_temps[k].l);
 }
 
+TCGTemp *tcg_constant_internal(TCGType type, int64_t val)
+{
+TCGContext *s = tcg_ctx;
+GHashTable *h = s->const_table[type];
+TCGTemp *ts;
+
+if (h == NULL) {
+h = g_hash_table_new(g_int64_hash, g_int64_equal);
+s->const_table[type] = h;
+}
+
+ts = g_hash_table_lookup(h, );
+if (ts == NULL) {
+ts = tcg_temp_alloc(s);
+
+if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
+TCGTemp *ts2 = tcg_temp_alloc(s);
+
+ts->base_type = TCG_TYPE_I64;
+ts->type = TCG_TYPE_I32;
+   

[PATCH 10/43] tcg: Remove TCG_TARGET_HAS_cmp_vec

2020-09-08 Thread Richard Henderson
The cmp_vec opcode is mandatory; this symbol is unused.

Signed-off-by: Richard Henderson 
---
 tcg/aarch64/tcg-target.h | 1 -
 tcg/i386/tcg-target.h| 1 -
 tcg/ppc/tcg-target.h | 1 -
 3 files changed, 3 deletions(-)

diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
index 9bc2a5ecbe..663dd0b95e 100644
--- a/tcg/aarch64/tcg-target.h
+++ b/tcg/aarch64/tcg-target.h
@@ -139,7 +139,6 @@ typedef enum {
 #define TCG_TARGET_HAS_shi_vec  1
 #define TCG_TARGET_HAS_shs_vec  0
 #define TCG_TARGET_HAS_shv_vec  1
-#define TCG_TARGET_HAS_cmp_vec  1
 #define TCG_TARGET_HAS_mul_vec  1
 #define TCG_TARGET_HAS_sat_vec  1
 #define TCG_TARGET_HAS_minmax_vec   1
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index 99ac1e3958..1f6dd8f45d 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -189,7 +189,6 @@ extern bool have_avx2;
 #define TCG_TARGET_HAS_shi_vec  1
 #define TCG_TARGET_HAS_shs_vec  1
 #define TCG_TARGET_HAS_shv_vec  have_avx2
-#define TCG_TARGET_HAS_cmp_vec  1
 #define TCG_TARGET_HAS_mul_vec  1
 #define TCG_TARGET_HAS_sat_vec  1
 #define TCG_TARGET_HAS_minmax_vec   1
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index aee38157a2..be10363956 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -169,7 +169,6 @@ extern bool have_vsx;
 #define TCG_TARGET_HAS_shi_vec  0
 #define TCG_TARGET_HAS_shs_vec  0
 #define TCG_TARGET_HAS_shv_vec  1
-#define TCG_TARGET_HAS_cmp_vec  1
 #define TCG_TARGET_HAS_mul_vec  1
 #define TCG_TARGET_HAS_sat_vec  1
 #define TCG_TARGET_HAS_minmax_vec   1
-- 
2.25.1




[PATCH 12/43] tcg: Increase tcg_out_dupi_vec immediate to int64_t

2020-09-08 Thread Richard Henderson
While we don't store more than tcg_target_long in TCGTemp,
we shouldn't be limited to that for code generation.  We will
be able to use this for INDEX_op_dup2_vec with 2 constants.

Also pass along the minimal vece that may be said to apply
to the constant.  This allows some simplification in the
various backends.

Signed-off-by: Richard Henderson 
---
 tcg/tcg.c| 31 +-
 tcg/aarch64/tcg-target.c.inc | 12 ++--
 tcg/i386/tcg-target.c.inc| 22 -
 tcg/ppc/tcg-target.c.inc | 37 +++-
 4 files changed, 69 insertions(+), 33 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 84bdcc6537..6474a695f2 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -116,8 +116,8 @@ static bool tcg_out_dup_vec(TCGContext *s, TCGType type, 
unsigned vece,
 TCGReg dst, TCGReg src);
 static bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
  TCGReg dst, TCGReg base, intptr_t offset);
-static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
- TCGReg dst, tcg_target_long arg);
+static void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
+ TCGReg dst, int64_t arg);
 static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, unsigned vecl,
unsigned vece, const TCGArg *args,
const int *const_args);
@@ -132,8 +132,8 @@ static inline bool tcg_out_dupm_vec(TCGContext *s, TCGType 
type, unsigned vece,
 {
 g_assert_not_reached();
 }
-static inline void tcg_out_dupi_vec(TCGContext *s, TCGType type,
-TCGReg dst, tcg_target_long arg)
+static inline void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
+TCGReg dst, int64_t arg)
 {
 g_assert_not_reached();
 }
@@ -3308,7 +3308,28 @@ static void temp_load(TCGContext *s, TCGTemp *ts, 
TCGRegSet desired_regs,
 if (ts->type <= TCG_TYPE_I64) {
 tcg_out_movi(s, ts->type, reg, ts->val);
 } else {
-tcg_out_dupi_vec(s, ts->type, reg, ts->val);
+uint64_t val = ts->val;
+MemOp vece = MO_64;
+
+/*
+ * Find the minimal vector element that matches the constant.
+ * The targets will, in general, have to do this search anyway,
+ * do this generically.
+ */
+if (TCG_TARGET_REG_BITS == 32) {
+val = dup_const(MO_32, val);
+vece = MO_32;
+}
+if (val == dup_const(MO_8, val)) {
+vece = MO_8;
+} else if (val == dup_const(MO_16, val)) {
+vece = MO_16;
+} else if (TCG_TARGET_REG_BITS == 64 &&
+   val == dup_const(MO_32, val)) {
+vece = MO_32;
+}
+
+tcg_out_dupi_vec(s, ts->type, vece, reg, ts->val);
 }
 ts->mem_coherent = 0;
 break;
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 72c4d25fdb..5692607087 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -853,14 +853,14 @@ static void tcg_out_logicali(TCGContext *s, AArch64Insn 
insn, TCGType ext,
 tcg_out_insn_3404(s, insn, ext, rd, rn, ext, r, c);
 }
 
-static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
- TCGReg rd, tcg_target_long v64)
+static void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
+ TCGReg rd, int64_t v64)
 {
 bool q = type == TCG_TYPE_V128;
 int cmode, imm8, i;
 
 /* Test all bytes equal first.  */
-if (v64 == dup_const(MO_8, v64)) {
+if (vece == MO_8) {
 imm8 = (uint8_t)v64;
 tcg_out_insn(s, 3606, MOVI, q, rd, 0, 0xe, imm8);
 return;
@@ -887,7 +887,7 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
  * cannot find an expansion there's no point checking a larger
  * width because we already know by replication it cannot match.
  */
-if (v64 == dup_const(MO_16, v64)) {
+if (vece == MO_16) {
 uint16_t v16 = v64;
 
 if (is_shimm16(v16, , )) {
@@ -906,7 +906,7 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
 tcg_out_insn(s, 3606, MOVI, q, rd, 0, 0x8, v16 & 0xff);
 tcg_out_insn(s, 3606, ORR, q, rd, 0, 0xa, v16 >> 8);
 return;
-} else if (v64 == dup_const(MO_32, v64)) {
+} else if (vece == MO_32) {
 uint32_t v32 = v64;
 uint32_t n32 = ~v32;
 
@@ -2430,7 +2430,7 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 tcg_out_insn_3617(s, insn, is_q, vece, a0, a1);
 break;
 }
-tcg_out_dupi_vec(s, type, TCG_VEC_TMP, 0);
+tcg_out_dupi_vec(s, type, MO_8, 

[PATCH 06/43] tcg: Remove TCGOpDef.used

2020-09-08 Thread Richard Henderson
The last user of this field disappeared in f69d277ece4.

Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index e8629b58c8..8804a8c4a2 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -1015,9 +1015,6 @@ typedef struct TCGOpDef {
 uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args;
 uint8_t flags;
 TCGArgConstraint *args_ct;
-#if defined(CONFIG_DEBUG_TCG)
-int used;
-#endif
 } TCGOpDef;
 
 extern TCGOpDef tcg_op_defs[];
-- 
2.25.1




[PATCH 15/43] tcg: Expand TCGTemp.val to 64-bits

2020-09-08 Thread Richard Henderson
This will reduce the differences between 32-bit and 64-bit hosts,
allowing full 64-bit constants to be created with the same interface.

Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h | 2 +-
 tcg/tcg.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 44ca8845cf..f3eca6feb0 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -506,7 +506,7 @@ typedef struct TCGTemp {
 unsigned int mem_allocated:1;
 unsigned int temp_allocated:1;
 
-tcg_target_long val;
+int64_t val;
 struct TCGTemp *mem_base;
 intptr_t mem_offset;
 const char *name;
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 577bfec202..1650c5a9db 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -3094,7 +3094,7 @@ static void dump_regs(TCGContext *s)
tcg_target_reg_names[ts->mem_base->reg]);
 break;
 case TEMP_VAL_CONST:
-printf("$0x%" TCG_PRIlx, ts->val);
+printf("$0x%" PRIx64, ts->val);
 break;
 case TEMP_VAL_DEAD:
 printf("D");
-- 
2.25.1




[PATCH 05/43] tcg: Move some TCG_CT_* bits to TCGArgConstraint bitfields

2020-09-08 Thread Richard Henderson
These are easier to set and test when they have their own fields.
Reduce the size of alias_index and sort_index to 4 bits, which is
sufficient for TCG_MAX_OP_ARGS.  This leaves only the bits indicating
constants within the ct field.

Move all initialization to allocation time, rather than init
individual fields in process_op_defs.

Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h | 14 +++---
 tcg/tcg.c | 28 
 2 files changed, 19 insertions(+), 23 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 3168315bb8..e8629b58c8 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -976,15 +976,15 @@ int64_t tcg_cpu_exec_time(void);
 void tcg_dump_info(void);
 void tcg_dump_op_count(void);
 
-#define TCG_CT_ALIAS  0x80
-#define TCG_CT_IALIAS 0x40
-#define TCG_CT_NEWREG 0x20 /* output requires a new register */
-#define TCG_CT_CONST  0x02 /* any constant of register size */
+#define TCG_CT_CONST  1 /* any constant of register size */
 
 typedef struct TCGArgConstraint {
-uint16_t ct;
-uint8_t alias_index;
-uint8_t sort_index;
+unsigned ct : 16;
+unsigned alias_index : 4;
+unsigned sort_index : 4;
+bool oalias : 1;
+bool ialias : 1;
+bool newreg : 1;
 TCGRegSet regs;
 } TCGArgConstraint;
 
diff --git a/tcg/tcg.c b/tcg/tcg.c
index a618497c94..ad4b7fb90f 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -958,7 +958,7 @@ void tcg_context_init(TCGContext *s)
 total_args += n;
 }
 
-args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
+args_ct = g_new0(TCGArgConstraint, total_args);
 
 for(op = 0; op < NB_OPS; op++) {
 def = _op_defs[op];
@@ -2197,7 +2197,7 @@ static int get_constraint_priority(const TCGOpDef *def, 
int k)
 const TCGArgConstraint *arg_ct = >args_ct[k];
 int n;
 
-if (arg_ct->ct & TCG_CT_ALIAS) {
+if (arg_ct->oalias) {
 /* an alias is equivalent to a single register */
 n = 1;
 } else {
@@ -2260,8 +2260,6 @@ static void process_op_defs(TCGContext *s)
 /* Incomplete TCGTargetOpDef entry. */
 tcg_debug_assert(ct_str != NULL);
 
-def->args_ct[i].regs = 0;
-def->args_ct[i].ct = 0;
 while (*ct_str != '\0') {
 switch(*ct_str) {
 case '0' ... '9':
@@ -2270,18 +2268,18 @@ static void process_op_defs(TCGContext *s)
 tcg_debug_assert(ct_str == tdefs->args_ct_str[i]);
 tcg_debug_assert(oarg < def->nb_oargs);
 tcg_debug_assert(def->args_ct[oarg].regs != 0);
-/* TCG_CT_ALIAS is for the output arguments.
-   The input is tagged with TCG_CT_IALIAS. */
 def->args_ct[i] = def->args_ct[oarg];
-def->args_ct[oarg].ct |= TCG_CT_ALIAS;
+/* The output sets oalias.  */
+def->args_ct[oarg].oalias = true;
 def->args_ct[oarg].alias_index = i;
-def->args_ct[i].ct |= TCG_CT_IALIAS;
+/* The input sets ialias. */
+def->args_ct[i].ialias = true;
 def->args_ct[i].alias_index = oarg;
 }
 ct_str++;
 break;
 case '&':
-def->args_ct[i].ct |= TCG_CT_NEWREG;
+def->args_ct[i].newreg = true;
 ct_str++;
 break;
 case 'i':
@@ -2848,7 +2846,7 @@ static void liveness_pass_1(TCGContext *s)
 set = *pset;
 
 set &= ct->regs;
-if (ct->ct & TCG_CT_IALIAS) {
+if (ct->ialias) {
 set &= op->output_pref[ct->alias_index];
 }
 /* If the combination is not possible, restart.  */
@@ -3665,7 +3663,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 }
 
 i_preferred_regs = o_preferred_regs = 0;
-if (arg_ct->ct & TCG_CT_IALIAS) {
+if (arg_ct->ialias) {
 o_preferred_regs = op->output_pref[arg_ct->alias_index];
 if (ts->fixed_reg) {
 /* if fixed register, we must allocate a new register
@@ -3688,8 +3686,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 reg = ts->reg;
 for (k2 = 0 ; k2 < k ; k2++) {
 i2 = def->args_ct[nb_oargs + k2].sort_index;
-if ((def->args_ct[i2].ct & TCG_CT_IALIAS) &&
-reg == new_args[i2]) {
+if (def->args_ct[i2].ialias && reg == new_args[i2]) {
 goto allocate_in_reg;
 }
 }
@@ -3760,10 +3757,9 @@ static void 

[PATCH 02/43] tcg: Drop union from TCGArgConstraint

2020-09-08 Thread Richard Henderson
The union is unused; let "regs" appear in the main structure
without the "u.regs" wrapping.

Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h|  4 +---
 tcg/tcg.c| 22 +++---
 tcg/aarch64/tcg-target.c.inc | 14 +++---
 tcg/arm/tcg-target.c.inc | 26 +-
 tcg/i386/tcg-target.c.inc| 26 +-
 tcg/mips/tcg-target.c.inc| 18 +-
 tcg/ppc/tcg-target.c.inc | 24 
 tcg/riscv/tcg-target.c.inc   | 14 +++---
 tcg/s390/tcg-target.c.inc| 18 +-
 tcg/sparc/tcg-target.c.inc   | 16 
 tcg/tci/tcg-target.c.inc |  2 +-
 11 files changed, 91 insertions(+), 93 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 53ce94c2c5..a5a0ea4ada 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -985,9 +985,7 @@ void tcg_dump_op_count(void);
 typedef struct TCGArgConstraint {
 uint16_t ct;
 uint8_t alias_index;
-union {
-TCGRegSet regs;
-} u;
+TCGRegSet regs;
 } TCGArgConstraint;
 
 #define TCG_MAX_OP_ARGS 16
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 62f299e36e..dcb38bf1e0 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -2210,7 +2210,7 @@ static int get_constraint_priority(const TCGOpDef *def, 
int k)
 return 0;
 n = 0;
 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
-if (tcg_regset_test_reg(arg_ct->u.regs, i))
+if (tcg_regset_test_reg(arg_ct->regs, i))
 n++;
 }
 }
@@ -2268,7 +2268,7 @@ static void process_op_defs(TCGContext *s)
 /* Incomplete TCGTargetOpDef entry. */
 tcg_debug_assert(ct_str != NULL);
 
-def->args_ct[i].u.regs = 0;
+def->args_ct[i].regs = 0;
 def->args_ct[i].ct = 0;
 while (*ct_str != '\0') {
 switch(*ct_str) {
@@ -2855,13 +2855,13 @@ static void liveness_pass_1(TCGContext *s)
 pset = la_temp_pref(ts);
 set = *pset;
 
-set &= ct->u.regs;
+set &= ct->regs;
 if (ct->ct & TCG_CT_IALIAS) {
 set &= op->output_pref[ct->alias_index];
 }
 /* If the combination is not possible, restart.  */
 if (set == 0) {
-set = ct->u.regs;
+set = ct->regs;
 }
 *pset = set;
 }
@@ -3551,8 +3551,8 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp 
*op)
 return;
 }
 
-dup_out_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[0].u.regs;
-dup_in_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[1].u.regs;
+dup_out_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[0].regs;
+dup_in_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[1].regs;
 
 /* Allocate the output register now.  */
 if (ots->val_type != TEMP_VAL_REG) {
@@ -3706,10 +3706,10 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 }
 }
 
-temp_load(s, ts, arg_ct->u.regs, i_allocated_regs, i_preferred_regs);
+temp_load(s, ts, arg_ct->regs, i_allocated_regs, i_preferred_regs);
 reg = ts->reg;
 
-if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
+if (tcg_regset_test_reg(arg_ct->regs, reg)) {
 /* nothing to do : the constraint is satisfied */
 } else {
 allocate_in_reg:
@@ -3717,7 +3717,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
and move the temporary register into it */
 temp_load(s, ts, tcg_target_available_regs[ts->type],
   i_allocated_regs, 0);
-reg = tcg_reg_alloc(s, arg_ct->u.regs, i_allocated_regs,
+reg = tcg_reg_alloc(s, arg_ct->regs, i_allocated_regs,
 o_preferred_regs, ts->indirect_base);
 if (!tcg_out_mov(s, ts->type, reg, ts->reg)) {
 /*
@@ -3772,11 +3772,11 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 && !const_args[arg_ct->alias_index]) {
 reg = new_args[arg_ct->alias_index];
 } else if (arg_ct->ct & TCG_CT_NEWREG) {
-reg = tcg_reg_alloc(s, arg_ct->u.regs,
+reg = tcg_reg_alloc(s, arg_ct->regs,
 i_allocated_regs | o_allocated_regs,
 op->output_pref[k], ts->indirect_base);
 } else {
-reg = tcg_reg_alloc(s, arg_ct->u.regs, o_allocated_regs,
+reg = tcg_reg_alloc(s, arg_ct->regs, o_allocated_regs,
 op->output_pref[k], ts->indirect_base);
 }
 tcg_regset_set_reg(o_allocated_regs, reg);
diff --git a/tcg/aarch64/tcg-target.c.inc 

[PATCH 11/43] tcg: Use tcg_out_dupi_vec from temp_load

2020-09-08 Thread Richard Henderson
Having dupi pass though movi is confusing and arguably wrong.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 tcg/tcg.c|  6 +++-
 tcg/aarch64/tcg-target.c.inc |  7 
 tcg/i386/tcg-target.c.inc| 63 
 tcg/ppc/tcg-target.c.inc |  6 
 4 files changed, 47 insertions(+), 35 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index ad4b7fb90f..84bdcc6537 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -3305,7 +3305,11 @@ static void temp_load(TCGContext *s, TCGTemp *ts, 
TCGRegSet desired_regs,
 case TEMP_VAL_CONST:
 reg = tcg_reg_alloc(s, desired_regs, allocated_regs,
 preferred_regs, ts->indirect_base);
-tcg_out_movi(s, ts->type, reg, ts->val);
+if (ts->type <= TCG_TYPE_I64) {
+tcg_out_movi(s, ts->type, reg, ts->val);
+} else {
+tcg_out_dupi_vec(s, ts->type, reg, ts->val);
+}
 ts->mem_coherent = 0;
 break;
 case TEMP_VAL_MEM:
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 479a9d26be..72c4d25fdb 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -1007,13 +1007,6 @@ static void tcg_out_movi(TCGContext *s, TCGType type, 
TCGReg rd,
 case TCG_TYPE_I64:
 tcg_debug_assert(rd < 32);
 break;
-
-case TCG_TYPE_V64:
-case TCG_TYPE_V128:
-tcg_debug_assert(rd >= 32);
-tcg_out_dupi_vec(s, type, rd, value);
-return;
-
 default:
 g_assert_not_reached();
 }
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index d8797ed398..e2852cbb09 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -966,30 +966,32 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
 }
 }
 
-static void tcg_out_movi(TCGContext *s, TCGType type,
- TCGReg ret, tcg_target_long arg)
+static void tcg_out_movi_vec(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg)
+{
+if (arg == 0) {
+tcg_out_vex_modrm(s, OPC_PXOR, ret, ret, ret);
+return;
+}
+if (arg == -1) {
+tcg_out_vex_modrm(s, OPC_PCMPEQB, ret, ret, ret);
+return;
+}
+
+int rexw = (type == TCG_TYPE_I32 ? 0 : P_REXW);
+tcg_out_vex_modrm_pool(s, OPC_MOVD_VyEy + rexw, ret);
+if (TCG_TARGET_REG_BITS == 64) {
+new_pool_label(s, arg, R_386_PC32, s->code_ptr - 4, -4);
+} else {
+new_pool_label(s, arg, R_386_32, s->code_ptr - 4, 0);
+}
+}
+
+static void tcg_out_movi_int(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg)
 {
 tcg_target_long diff;
 
-switch (type) {
-case TCG_TYPE_I32:
-#if TCG_TARGET_REG_BITS == 64
-case TCG_TYPE_I64:
-#endif
-if (ret < 16) {
-break;
-}
-/* fallthru */
-case TCG_TYPE_V64:
-case TCG_TYPE_V128:
-case TCG_TYPE_V256:
-tcg_debug_assert(ret >= 16);
-tcg_out_dupi_vec(s, type, ret, arg);
-return;
-default:
-g_assert_not_reached();
-}
-
 if (arg == 0) {
 tgen_arithr(s, ARITH_XOR, ret, ret);
 return;
@@ -1018,6 +1020,25 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
 tcg_out64(s, arg);
 }
 
+static void tcg_out_movi(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg)
+{
+switch (type) {
+case TCG_TYPE_I32:
+#if TCG_TARGET_REG_BITS == 64
+case TCG_TYPE_I64:
+#endif
+if (ret < 16) {
+tcg_out_movi_int(s, type, ret, arg);
+} else {
+tcg_out_movi_vec(s, type, ret, arg);
+}
+break;
+default:
+g_assert_not_reached();
+}
+}
+
 static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
 {
 if (val == (int8_t)val) {
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 7a5760bb23..bc6fb09adb 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -983,12 +983,6 @@ static void tcg_out_movi(TCGContext *s, TCGType type, 
TCGReg ret,
 tcg_out_movi_int(s, type, ret, arg, false);
 break;
 
-case TCG_TYPE_V64:
-case TCG_TYPE_V128:
-tcg_debug_assert(ret >= TCG_REG_V0);
-tcg_out_dupi_vec(s, type, ret, arg);
-break;
-
 default:
 g_assert_not_reached();
 }
-- 
2.25.1




[PATCH 03/43] tcg: Move sorted_args into TCGArgConstraint.sort_index

2020-09-08 Thread Richard Henderson
This uses an existing hole in the TCGArgConstraint structure
and will be convenient for keeping the data in one place.

Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h |  2 +-
 tcg/tcg.c | 35 +--
 2 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index a5a0ea4ada..63955ac85b 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -985,6 +985,7 @@ void tcg_dump_op_count(void);
 typedef struct TCGArgConstraint {
 uint16_t ct;
 uint8_t alias_index;
+uint8_t sort_index;
 TCGRegSet regs;
 } TCGArgConstraint;
 
@@ -1015,7 +1016,6 @@ typedef struct TCGOpDef {
 uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args;
 uint8_t flags;
 TCGArgConstraint *args_ct;
-int *sorted_args;
 #if defined(CONFIG_DEBUG_TCG)
 int used;
 #endif
diff --git a/tcg/tcg.c b/tcg/tcg.c
index dcb38bf1e0..0a04b6cbd9 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -944,7 +944,6 @@ void tcg_context_init(TCGContext *s)
 int op, total_args, n, i;
 TCGOpDef *def;
 TCGArgConstraint *args_ct;
-int *sorted_args;
 TCGTemp *ts;
 
 memset(s, 0, sizeof(*s));
@@ -960,14 +959,11 @@ void tcg_context_init(TCGContext *s)
 }
 
 args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
-sorted_args = g_malloc(sizeof(int) * total_args);
 
 for(op = 0; op < NB_OPS; op++) {
 def = _op_defs[op];
 def->args_ct = args_ct;
-def->sorted_args = sorted_args;
 n = def->nb_iargs + def->nb_oargs;
-sorted_args += n;
 args_ct += n;
 }
 
@@ -2220,20 +2216,23 @@ static int get_constraint_priority(const TCGOpDef *def, 
int k)
 /* sort from highest priority to lowest */
 static void sort_constraints(TCGOpDef *def, int start, int n)
 {
-int i, j, p1, p2, tmp;
+int i, j;
+TCGArgConstraint *a = def->args_ct;
 
-for(i = 0; i < n; i++)
-def->sorted_args[start + i] = start + i;
-if (n <= 1)
+for (i = 0; i < n; i++) {
+a[start + i].sort_index = start + i;
+}
+if (n <= 1) {
 return;
-for(i = 0; i < n - 1; i++) {
-for(j = i + 1; j < n; j++) {
-p1 = get_constraint_priority(def, def->sorted_args[start + i]);
-p2 = get_constraint_priority(def, def->sorted_args[start + j]);
+}
+for (i = 0; i < n - 1; i++) {
+for (j = i + 1; j < n; j++) {
+int p1 = get_constraint_priority(def, a[start + i].sort_index);
+int p2 = get_constraint_priority(def, a[start + j].sort_index);
 if (p1 < p2) {
-tmp = def->sorted_args[start + i];
-def->sorted_args[start + i] = def->sorted_args[start + j];
-def->sorted_args[start + j] = tmp;
+int tmp = a[start + i].sort_index;
+a[start + i].sort_index = a[start + j].sort_index;
+a[start + j].sort_index = tmp;
 }
 }
 }
@@ -3659,7 +3658,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 for (k = 0; k < nb_iargs; k++) {
 TCGRegSet i_preferred_regs, o_preferred_regs;
 
-i = def->sorted_args[nb_oargs + k];
+i = def->args_ct[nb_oargs + k].sort_index;
 arg = op->args[i];
 arg_ct = >args_ct[i];
 ts = arg_temp(arg);
@@ -3695,7 +3694,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 int k2, i2;
 reg = ts->reg;
 for (k2 = 0 ; k2 < k ; k2++) {
-i2 = def->sorted_args[nb_oargs + k2];
+i2 = def->args_ct[nb_oargs + k2].sort_index;
 if ((def->args_ct[i2].ct & TCG_CT_IALIAS) &&
 reg == new_args[i2]) {
 goto allocate_in_reg;
@@ -3760,7 +3759,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 
 /* satisfy the output constraints */
 for(k = 0; k < nb_oargs; k++) {
-i = def->sorted_args[k];
+i = def->args_ct[k].sort_index;
 arg = op->args[i];
 arg_ct = >args_ct[i];
 ts = arg_temp(arg);
-- 
2.25.1




[PATCH 04/43] tcg: Remove TCG_CT_REG

2020-09-08 Thread Richard Henderson
This wasn't actually used for anything, really.  All variable
operands must accept registers, and which are indicated by the
set in TCGArgConstraint.regs.

Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h|  1 -
 tcg/tcg.c| 15 ---
 tcg/aarch64/tcg-target.c.inc |  3 ---
 tcg/arm/tcg-target.c.inc |  3 ---
 tcg/i386/tcg-target.c.inc| 11 ---
 tcg/mips/tcg-target.c.inc|  3 ---
 tcg/ppc/tcg-target.c.inc |  5 -
 tcg/riscv/tcg-target.c.inc   |  2 --
 tcg/s390/tcg-target.c.inc|  4 
 tcg/sparc/tcg-target.c.inc   |  5 -
 tcg/tci/tcg-target.c.inc |  1 -
 11 files changed, 4 insertions(+), 49 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 63955ac85b..3168315bb8 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -979,7 +979,6 @@ void tcg_dump_op_count(void);
 #define TCG_CT_ALIAS  0x80
 #define TCG_CT_IALIAS 0x40
 #define TCG_CT_NEWREG 0x20 /* output requires a new register */
-#define TCG_CT_REG0x01
 #define TCG_CT_CONST  0x02 /* any constant of register size */
 
 typedef struct TCGArgConstraint {
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 0a04b6cbd9..a618497c94 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -2194,21 +2194,14 @@ static void tcg_dump_ops(TCGContext *s, bool have_prefs)
 /* we give more priority to constraints with less registers */
 static int get_constraint_priority(const TCGOpDef *def, int k)
 {
-const TCGArgConstraint *arg_ct;
+const TCGArgConstraint *arg_ct = >args_ct[k];
+int n;
 
-int i, n;
-arg_ct = >args_ct[k];
 if (arg_ct->ct & TCG_CT_ALIAS) {
 /* an alias is equivalent to a single register */
 n = 1;
 } else {
-if (!(arg_ct->ct & TCG_CT_REG))
-return 0;
-n = 0;
-for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
-if (tcg_regset_test_reg(arg_ct->regs, i))
-n++;
-}
+n = ctpop64(arg_ct->regs);
 }
 return TCG_TARGET_NB_REGS - n + 1;
 }
@@ -2276,7 +2269,7 @@ static void process_op_defs(TCGContext *s)
 int oarg = *ct_str - '0';
 tcg_debug_assert(ct_str == tdefs->args_ct_str[i]);
 tcg_debug_assert(oarg < def->nb_oargs);
-tcg_debug_assert(def->args_ct[oarg].ct & TCG_CT_REG);
+tcg_debug_assert(def->args_ct[oarg].regs != 0);
 /* TCG_CT_ALIAS is for the output arguments.
The input is tagged with TCG_CT_IALIAS. */
 def->args_ct[i] = def->args_ct[oarg];
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index d4b7cb4867..479a9d26be 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -128,15 +128,12 @@ static const char 
*target_parse_constraint(TCGArgConstraint *ct,
 {
 switch (*ct_str++) {
 case 'r': /* general registers */
-ct->ct |= TCG_CT_REG;
 ct->regs |= 0xu;
 break;
 case 'w': /* advsimd registers */
-ct->ct |= TCG_CT_REG;
 ct->regs |= 0xull;
 break;
 case 'l': /* qemu_ld / qemu_st address, data_reg */
-ct->ct |= TCG_CT_REG;
 ct->regs = 0xu;
 #ifdef CONFIG_SOFTMMU
 /* x0 and x1 will be overwritten when reading the tlb entry,
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index 978eb1dd70..62c37a954b 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -253,13 +253,11 @@ static const char 
*target_parse_constraint(TCGArgConstraint *ct,
 break;
 
 case 'r':
-ct->ct |= TCG_CT_REG;
 ct->regs = 0x;
 break;
 
 /* qemu_ld address */
 case 'l':
-ct->ct |= TCG_CT_REG;
 ct->regs = 0x;
 #ifdef CONFIG_SOFTMMU
 /* r0-r2,lr will be overwritten when reading the tlb entry,
@@ -274,7 +272,6 @@ static const char *target_parse_constraint(TCGArgConstraint 
*ct,
 
 /* qemu_st address & data */
 case 's':
-ct->ct |= TCG_CT_REG;
 ct->regs = 0x;
 /* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
and r0-r1 doing the byte swapping, so don't use these. */
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 8661ec3393..2f696074ab 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -208,42 +208,33 @@ static const char 
*target_parse_constraint(TCGArgConstraint *ct,
 {
 switch(*ct_str++) {
 case 'a':
-ct->ct |= TCG_CT_REG;
 tcg_regset_set_reg(ct->regs, TCG_REG_EAX);
 break;
 case 'b':
-ct->ct |= TCG_CT_REG;
 tcg_regset_set_reg(ct->regs, TCG_REG_EBX);
 break;
 case 'c':
-ct->ct |= TCG_CT_REG;
 tcg_regset_set_reg(ct->regs, TCG_REG_ECX);
 break;
 case 'd':
-ct->ct |= TCG_CT_REG;
 

[PATCH 00/43] tcg patch queue

2020-09-08 Thread Richard Henderson
This patch collection contains:

  * A couple of fixes for i386 host vector support.

  * Some random cleanups cherry-picked from some inactive branches.

  * A reposting (with fix) of my "better handling of constants" set:

https://lists.nongnu.org/archive/html/qemu-devel/2020-05/msg02152.html

  * A couple patches that centralizes the set of host constraints.
This, I believe is slightly cleaner than the current state of
afairs, even before the ultimtate goal of pre-validating the
contents as well.


r~


Richard Henderson (43):
  tcg: Adjust simd_desc size encoding
  tcg: Drop union from TCGArgConstraint
  tcg: Move sorted_args into TCGArgConstraint.sort_index
  tcg: Remove TCG_CT_REG
  tcg: Move some TCG_CT_* bits to TCGArgConstraint bitfields
  tcg: Remove TCGOpDef.used
  tcg/i386: Fix dupi for avx2 32-bit hosts
  tcg: Fix generation of dupi_vec for 32-bit host
  tcg/optimize: Fold dup2_vec
  tcg: Remove TCG_TARGET_HAS_cmp_vec
  tcg: Use tcg_out_dupi_vec from temp_load
  tcg: Increase tcg_out_dupi_vec immediate to int64_t
  tcg: Consolidate 3 bits into enum TCGTempKind
  tcg: Add temp_readonly
  tcg: Expand TCGTemp.val to 64-bits
  tcg: Rename struct tcg_temp_info to TempOptInfo
  tcg: Expand TempOptInfo to 64-bits
  tcg: Introduce TYPE_CONST temporaries
  tcg/optimize: Improve find_better_copy
  tcg/optimize: Adjust TempOptInfo allocation
  tcg/optimize: Use tcg_constant_internal with constant folding
  tcg: Convert tcg_gen_dupi_vec to TCG_CONST
  tcg: Use tcg_constant_i32 with icount expander
  tcg: Use tcg_constant_{i32,i64} with tcg int expanders
  tcg: Use tcg_constant_{i32,i64} with tcg plugins
  tcg: Use tcg_constant_{i32,i64,vec} with gvec expanders
  tcg/tci: Add special tci_movi_{i32,i64} opcodes
  tcg: Remove movi and dupi opcodes
  tcg: Add tcg_reg_alloc_dup2
  tcg/i386: Use tcg_constant_vec with tcg vec expanders
  tcg: Remove tcg_gen_dup{8,16,32,64}i_vec
  tcg/ppc: Use tcg_constant_vec with tcg vec expanders
  tcg/aarch64: Use tcg_constant_vec with tcg vec expanders
  tcg: Add tcg-constr.c.inc
  tcg/i386: Convert to tcg-constr.c.inc
  tcg/aarch64: Convert to tcg-constr.c.inc
  tcg/arm: Convert to tcg-constr.c.inc
  tcg/mips: Convert to tcg-constr.c.inc
  tcg/ppc: Convert to tcg-constr.c.inc
  tcg/riscv: Convert to tcg-constr.c.inc
  tcg/s390: Convert to tcg-constr.c.inc
  tcg/sparc: Convert to tcg-constr.c.inc
  tcg/tci: Convert to tcg-constr.c.inc

 include/exec/gen-icount.h   |  25 +-
 include/tcg/tcg-gvec-desc.h |  38 ++-
 include/tcg/tcg-op.h|  17 +-
 include/tcg/tcg-opc.h   |  11 +-
 include/tcg/tcg.h   |  72 +++--
 tcg/aarch64/tcg-target-constr.h |  31 ++
 tcg/aarch64/tcg-target.h|   1 -
 tcg/arm/tcg-target-constr.h |  30 ++
 tcg/i386/tcg-target-constr.h|  55 
 tcg/i386/tcg-target.h   |   1 -
 tcg/mips/tcg-target-constr.h|  31 ++
 tcg/ppc/tcg-target-constr.h |  37 +++
 tcg/ppc/tcg-target.h|   1 -
 tcg/riscv/tcg-target-constr.h   |  25 ++
 tcg/s390/tcg-target-constr.h|  24 ++
 tcg/sparc/tcg-target-constr.h   |  27 ++
 tcg/tci/tcg-target-constr.h |  28 ++
 accel/tcg/plugin-gen.c  |  49 ++-
 tcg/optimize.c  | 254 ---
 tcg/tcg-op-gvec.c   | 160 +-
 tcg/tcg-op-vec.c|  48 +--
 tcg/tcg-op.c| 227 +++--
 tcg/tcg.c   | 549 +++-
 tcg/tci.c   |   4 +-
 tcg/aarch64/tcg-target.c.inc| 134 +++-
 tcg/arm/tcg-target.c.inc| 123 +++
 tcg/i386/tcg-target.c.inc   | 336 +--
 tcg/mips/tcg-target.c.inc   | 118 +++
 tcg/ppc/tcg-target.c.inc| 254 +++
 tcg/riscv/tcg-target.c.inc  | 100 ++
 tcg/s390/tcg-target.c.inc   | 143 -
 tcg/sparc/tcg-target.c.inc  |  97 ++
 tcg/tcg-constr.c.inc| 108 +++
 tcg/tci/tcg-target.c.inc| 369 -
 34 files changed, 1893 insertions(+), 1634 deletions(-)
 create mode 100644 tcg/aarch64/tcg-target-constr.h
 create mode 100644 tcg/arm/tcg-target-constr.h
 create mode 100644 tcg/i386/tcg-target-constr.h
 create mode 100644 tcg/mips/tcg-target-constr.h
 create mode 100644 tcg/ppc/tcg-target-constr.h
 create mode 100644 tcg/riscv/tcg-target-constr.h
 create mode 100644 tcg/s390/tcg-target-constr.h
 create mode 100644 tcg/sparc/tcg-target-constr.h
 create mode 100644 tcg/tci/tcg-target-constr.h
 create mode 100644 tcg/tcg-constr.c.inc

-- 
2.25.1




[PATCH 01/43] tcg: Adjust simd_desc size encoding

2020-09-08 Thread Richard Henderson
With larger vector sizes, it turns out oprsz == maxsz, and we only
need to represent mismatch for oprsz <= 32.  We do, however, need
to represent larger oprsz and do so without reducing SIMD_DATA_BITS.

Reduce the size of the oprsz field and increase the maxsz field.
Steal the oprsz value of 24 to indicate equality with maxsz.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-gvec-desc.h | 38 -
 tcg/tcg-op-gvec.c   | 35 ++
 2 files changed, 52 insertions(+), 21 deletions(-)

diff --git a/include/tcg/tcg-gvec-desc.h b/include/tcg/tcg-gvec-desc.h
index 0224ac3e78..704bd86454 100644
--- a/include/tcg/tcg-gvec-desc.h
+++ b/include/tcg/tcg-gvec-desc.h
@@ -20,29 +20,41 @@
 #ifndef TCG_TCG_GVEC_DESC_H
 #define TCG_TCG_GVEC_DESC_H
 
-/* ??? These bit widths are set for ARM SVE, maxing out at 256 byte vectors. */
-#define SIMD_OPRSZ_SHIFT   0
-#define SIMD_OPRSZ_BITS5
+/*
+ * This configuration allows MAXSZ to represent 2048 bytes, and
+ * OPRSZ to match MAXSZ, or represent the smaller values 8, 16, or 32.
+ *
+ * Encode this with:
+ *   0, 1, 3 -> 8, 16, 32
+ *   2   -> maxsz
+ *
+ * This steals the input that would otherwise map to 24 to match maxsz.
+ */
+#define SIMD_MAXSZ_SHIFT   0
+#define SIMD_MAXSZ_BITS8
 
-#define SIMD_MAXSZ_SHIFT   (SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS)
-#define SIMD_MAXSZ_BITS5
+#define SIMD_OPRSZ_SHIFT   (SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS)
+#define SIMD_OPRSZ_BITS2
 
-#define SIMD_DATA_SHIFT(SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS)
+#define SIMD_DATA_SHIFT(SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS)
 #define SIMD_DATA_BITS (32 - SIMD_DATA_SHIFT)
 
 /* Create a descriptor from components.  */
 uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data);
 
-/* Extract the operation size from a descriptor.  */
-static inline intptr_t simd_oprsz(uint32_t desc)
-{
-return (extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS) + 1) * 8;
-}
-
 /* Extract the max vector size from a descriptor.  */
 static inline intptr_t simd_maxsz(uint32_t desc)
 {
-return (extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) + 1) * 8;
+return extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) * 8 + 8;
+}
+
+/* Extract the operation size from a descriptor.  */
+static inline intptr_t simd_oprsz(uint32_t desc)
+{
+uint32_t f = extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS);
+intptr_t o = f * 8 + 8;
+intptr_t m = simd_maxsz(desc);
+return f == 2 ? m : o;
 }
 
 /* Extract the operation-specific data from a descriptor.  */
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
index 7ebd9e8298..ddbe06b71a 100644
--- a/tcg/tcg-op-gvec.c
+++ b/tcg/tcg-op-gvec.c
@@ -37,11 +37,21 @@ static const TCGOpcode vecop_list_empty[1] = { 0 };
of the operand offsets so that we can check them all at once.  */
 static void check_size_align(uint32_t oprsz, uint32_t maxsz, uint32_t ofs)
 {
-uint32_t opr_align = oprsz >= 16 ? 15 : 7;
-uint32_t max_align = maxsz >= 16 || oprsz >= 16 ? 15 : 7;
-tcg_debug_assert(oprsz > 0);
-tcg_debug_assert(oprsz <= maxsz);
-tcg_debug_assert((oprsz & opr_align) == 0);
+uint32_t max_align;
+
+switch (oprsz) {
+case 8:
+case 16:
+case 32:
+tcg_debug_assert(oprsz <= maxsz);
+break;
+default:
+tcg_debug_assert(oprsz == maxsz);
+break;
+}
+tcg_debug_assert(maxsz <= (8 << SIMD_MAXSZ_BITS));
+
+max_align = maxsz >= 16 ? 15 : 7;
 tcg_debug_assert((maxsz & max_align) == 0);
 tcg_debug_assert((ofs & max_align) == 0);
 }
@@ -77,12 +87,21 @@ uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t 
data)
 {
 uint32_t desc = 0;
 
-assert(oprsz % 8 == 0 && oprsz <= (8 << SIMD_OPRSZ_BITS));
-assert(maxsz % 8 == 0 && maxsz <= (8 << SIMD_MAXSZ_BITS));
-assert(data == sextract32(data, 0, SIMD_DATA_BITS));
+check_size_align(oprsz, maxsz, 0);
+tcg_debug_assert(data == sextract32(data, 0, SIMD_DATA_BITS));
 
 oprsz = (oprsz / 8) - 1;
 maxsz = (maxsz / 8) - 1;
+
+/*
+ * We have just asserted in check_size_align that either
+ * oprsz is {8,16,32} or matches maxsz.  Encode the final
+ * case with '2', as that would otherwise map to 24.
+ */
+if (oprsz == maxsz) {
+oprsz = 2;
+}
+
 desc = deposit32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS, oprsz);
 desc = deposit32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS, maxsz);
 desc = deposit32(desc, SIMD_DATA_SHIFT, SIMD_DATA_BITS, data);
-- 
2.25.1




[REPORT] Nightly Performance Tests - Tuesday, September 8, 2020

2020-09-08 Thread Ahmed Karaman

Host CPU : Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
Host Memory  : 15.49 GB

Start Time (UTC) : 2020-09-08 22:30:02
End Time (UTC)   : 2020-09-08 23:03:19
Execution Time   : 0:33:16.914858

Status   : SUCCESS

Note:
Changes denoted by '-' are less than 0.01%.


SUMMARY REPORT - COMMIT 67790385

AVERAGE RESULTS

Target  Instructions  Latest  v5.1.0
--    --  --
aarch642 158 526 758   - +1.704%
alpha  1 914 949 603   - +3.523%
arm8 076 536 751   - +2.308%
hppa   4 261 694 044   - +3.164%
m68k   2 690 302 191   - +7.135%
mips   1 861 899 373   - +2.484%
mipsel 2 008 222 249   - +2.675%
mips64 1 918 624 363   - +2.817%
mips64el   2 051 551 547   - +3.025%
ppc2 480 197 737   - +3.111%
ppc64  2 576 708 052   - +3.142%
ppc64le2 558 825 498   - +3.171%
riscv641 406 678 911   - +2.647%
s390x  3 158 128 812   - +3.118%
sh42 364 598 659   - +3.341%
sparc643 318 700 221   - +3.855%
x86_64 1 775 940 947   - +2.167%


   DETAILED RESULTS

Test Program: dijkstra_double

Target  Instructions  Latest  v5.1.0
--    --  --
aarch643 062 759 323   -  +1.43%
alpha  3 191 847 048   - +3.695%
arm   16 357 300 631   - +2.348%
hppa   7 228 408 847   - +3.086%
m68k   4 294 067 760   - +9.693%
mips   3 051 313 439   - +2.423%
mipsel 3 231 530 724   - +2.869%
mips64 3 245 816 156   - +2.596%
mips64el   3 414 213 537   - +3.021%
ppc4 914 582 254   - +4.741%
ppc64  5 098 145 682   - +4.565%
ppc64le5 082 392 870   - +4.579%
riscv642 192 263 039   - +1.954%
s390x  4 584 577 681   - +2.897%
sh43 949 190 599   - +3.468%
sparc644 586 105 365   - +4.235%
x86_64 2 484 245 841   - +1.757%


Test Program: dijkstra_int32

Target  Instructions  Latest  v5.1.0
--    --  --
aarch642 210 374 595   - +1.502%
alpha  1 494 113 126   - +2.149%
arm8 263 054 865   - +2.667%
hppa   5 207 327 123   - +3.047%
m68k   1 725 888 200   - +2.528%
mips   1 495 106 430 -0.011% +1.484%
mipsel 1 497 151 197   - +1.479%
mips64 1 715 420 469   - +1.893%
mips64el   1 695 205 871   - +1.909%
ppc2 014 623 828   - +1.823%
ppc64  2 206 264 991   - +2.138%
ppc64le2 197 972 278   - +2.145%
riscv641 354 872 661   - +2.393%
s390x  2 916 085 978   - +1.236%
sh41 990 686 615   - +2.677%
sparc642 874 142 528   - +3.827%
x86_64 1 554 139 013   -  +2.13%


Test Program: matmult_double

Target  Instructions  Latest  v5.1.0
--    --  --
aarch641 412 431 616 +0.011% +0.313%
alpha  3 233 973 783   - +7.473%
arm8 545 311 751   -  +1.09%
hppa   3 483 537 736   - +4.467%
m68k   3 919 119 423   -+18.433%
mips   2 344 643 485   - +4.085%
mipsel 3 329 903 673   - +5.177%
mips64 2 359 030 673   - +4.075%

Re: [PULL 0/3] Sirius/ipxe 20200908 patches

2020-09-08 Thread Peter Maydell
On Tue, 8 Sep 2020 at 07:12, Gerd Hoffmann  wrote:
>
> The following changes since commit e11bd71f89649da3cff439c030d2ccac0cc914e3:
>
>   Merge remote-tracking branch 
> 'remotes/huth-gitlab/tags/pull-request-2020-09-07' into staging (2020-09-07 
> 16:51:00 +0100)
>
> are available in the Git repository at:
>
>   git://git.kraxel.org/qemu tags/sirius/ipxe-20200908-pull-request
>
> for you to fetch changes up to 3e570a9ae9b966362596fd649f2cbcff0b2199c9:
>
>   ipxe: update binaries (2020-09-08 08:08:30 +0200)
>
> 
> ipxe: update to aug 2020 snapshot.
>
> 
>
> Gerd Hoffmann (3):
>   ipxe: update submodule
>   ipxe: drop ia32 efi roms
>   ipxe: update binaries


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/5.2
for any user-visible changes.

-- PMM



[PULL 33/34] vhost-user-vga: Use typedef name for instance_size

2020-09-08 Thread Eduardo Habkost
This makes the code consistent with the rest of QOM code in QEMU,
and will make automated conversion to type declaration macros
simpler.

Signed-off-by: Eduardo Habkost 
Message-Id: <20200824215936.2961951-6-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/display/vhost-user-vga.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/display/vhost-user-vga.c b/hw/display/vhost-user-vga.c
index 7110ea6231..a34a99856d 100644
--- a/hw/display/vhost-user-vga.c
+++ b/hw/display/vhost-user-vga.c
@@ -41,7 +41,7 @@ static void vhost_user_vga_inst_initfn(Object *obj)
 static const VirtioPCIDeviceTypeInfo vhost_user_vga_info = {
 .generic_name  = TYPE_VHOST_USER_VGA,
 .parent= TYPE_VIRTIO_VGA_BASE,
-.instance_size = sizeof(struct VhostUserVGA),
+.instance_size = sizeof(VhostUserVGA),
 .instance_init = vhost_user_vga_inst_initfn,
 };
 
-- 
2.26.2




[PULL 31/34] lpc_ich9: Use typedef name for instance_size

2020-09-08 Thread Eduardo Habkost
This makes the code consistent with the rest of QOM code in QEMU,
and will make automated conversion to type declaration macros
simpler.

Signed-off-by: Eduardo Habkost 
Message-Id: <20200824215936.2961951-4-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/isa/lpc_ich9.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index cd6e169d47..3303d2eab6 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -792,7 +792,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void 
*data)
 static const TypeInfo ich9_lpc_info = {
 .name   = TYPE_ICH9_LPC_DEVICE,
 .parent = TYPE_PCI_DEVICE,
-.instance_size = sizeof(struct ICH9LPCState),
+.instance_size = sizeof(ICH9LPCState),
 .instance_init = ich9_lpc_initfn,
 .class_init  = ich9_lpc_class_init,
 .interfaces = (InterfaceInfo[]) {
-- 
2.26.2




[PULL 19/34] vmgenid: Rename VMGENID_DEVICE to TYPE_VMGENID

2020-09-08 Thread Eduardo Habkost
This will make the type name constant consistent with the name of
the type checking macro.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20200902224311.1321159-11-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 include/hw/acpi/vmgenid.h | 6 +++---
 hw/acpi/vmgenid.c | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h
index 86cd1da605..aff574df5f 100644
--- a/include/hw/acpi/vmgenid.h
+++ b/include/hw/acpi/vmgenid.h
@@ -6,7 +6,7 @@
 #include "qemu/uuid.h"
 #include "qom/object.h"
 
-#define VMGENID_DEVICE   "vmgenid"
+#define TYPE_VMGENID   "vmgenid"
 #define VMGENID_GUID "guid"
 #define VMGENID_GUID_FW_CFG_FILE  "etc/vmgenid_guid"
 #define VMGENID_ADDR_FW_CFG_FILE  "etc/vmgenid_addr"
@@ -18,7 +18,7 @@
 
 typedef struct VmGenIdState VmGenIdState;
 DECLARE_INSTANCE_CHECKER(VmGenIdState, VMGENID,
- VMGENID_DEVICE)
+ TYPE_VMGENID)
 
 struct VmGenIdState {
 DeviceClass parent_obj;
@@ -29,7 +29,7 @@ struct VmGenIdState {
 /* returns NULL unless there is exactly one device */
 static inline Object *find_vmgenid_dev(void)
 {
-return object_resolve_path_type("", VMGENID_DEVICE, NULL);
+return object_resolve_path_type("", TYPE_VMGENID, NULL);
 }
 
 void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
index 2df7623d74..53db6af75d 100644
--- a/hw/acpi/vmgenid.c
+++ b/hw/acpi/vmgenid.c
@@ -198,7 +198,7 @@ static void vmgenid_realize(DeviceState *dev, Error **errp)
 
 if (!bios_linker_loader_can_write_pointer()) {
 error_setg(errp, "%s requires DMA write support in fw_cfg, "
-   "which this machine type does not provide", VMGENID_DEVICE);
+   "which this machine type does not provide", TYPE_VMGENID);
 return;
 }
 
@@ -206,7 +206,7 @@ static void vmgenid_realize(DeviceState *dev, Error **errp)
  * device. Check if there are several.
  */
 if (!find_vmgenid_dev()) {
-error_setg(errp, "at most one %s device is permitted", VMGENID_DEVICE);
+error_setg(errp, "at most one %s device is permitted", TYPE_VMGENID);
 return;
 }
 
@@ -232,7 +232,7 @@ static void vmgenid_device_class_init(ObjectClass *klass, 
void *data)
 }
 
 static const TypeInfo vmgenid_device_info = {
-.name  = VMGENID_DEVICE,
+.name  = TYPE_VMGENID,
 .parent= TYPE_DEVICE,
 .instance_size = sizeof(VmGenIdState),
 .class_init= vmgenid_device_class_init,
-- 
2.26.2




[PULL 34/34] virtio-vga: Use typedef name for instance_size

2020-09-08 Thread Eduardo Habkost
This makes the code consistent with the rest of QOM code in QEMU,
and will make automated conversion to type declaration macros
simpler.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Gerd Hoffmann 
Message-Id: <20200824215936.2961951-7-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/display/virtio-vga.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
index 17e5658d43..573e7d5928 100644
--- a/hw/display/virtio-vga.c
+++ b/hw/display/virtio-vga.c
@@ -195,8 +195,8 @@ static void virtio_vga_base_class_init(ObjectClass *klass, 
void *data)
 static TypeInfo virtio_vga_base_info = {
 .name  = TYPE_VIRTIO_VGA_BASE,
 .parent= TYPE_VIRTIO_PCI,
-.instance_size = sizeof(struct VirtIOVGABase),
-.class_size= sizeof(struct VirtIOVGABaseClass),
+.instance_size = sizeof(VirtIOVGABase),
+.class_size= sizeof(VirtIOVGABaseClass),
 .class_init= virtio_vga_base_class_init,
 .abstract  = true,
 };
@@ -226,7 +226,7 @@ static void virtio_vga_inst_initfn(Object *obj)
 static VirtioPCIDeviceTypeInfo virtio_vga_info = {
 .generic_name  = TYPE_VIRTIO_VGA,
 .parent= TYPE_VIRTIO_VGA_BASE,
-.instance_size = sizeof(struct VirtIOVGA),
+.instance_size = sizeof(VirtIOVGA),
 .instance_init = virtio_vga_inst_initfn,
 };
 
-- 
2.26.2




[PULL 18/34] vfio: Rename VFIO_AP_DEVICE_TYPE to TYPE_VFIO_AP_DEVICE

2020-09-08 Thread Eduardo Habkost
This will make the type name constant consistent with the name of
the type checking macro.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Thomas Huth 
Message-Id: <20200902224311.1321159-9-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/vfio/ap.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c
index 68ed059b39..582c091a24 100644
--- a/hw/vfio/ap.c
+++ b/hw/vfio/ap.c
@@ -30,7 +30,7 @@
 #include "exec/address-spaces.h"
 #include "qom/object.h"
 
-#define VFIO_AP_DEVICE_TYPE  "vfio-ap"
+#define TYPE_VFIO_AP_DEVICE  "vfio-ap"
 
 struct VFIOAPDevice {
 APDevice apdev;
@@ -39,7 +39,7 @@ struct VFIOAPDevice {
 typedef struct VFIOAPDevice VFIOAPDevice;
 
 DECLARE_INSTANCE_CHECKER(VFIOAPDevice, VFIO_AP_DEVICE,
- VFIO_AP_DEVICE_TYPE)
+ TYPE_VFIO_AP_DEVICE)
 
 static void vfio_ap_compute_needs_reset(VFIODevice *vdev)
 {
@@ -72,7 +72,7 @@ static VFIOGroup *vfio_ap_get_group(VFIOAPDevice *vapdev, 
Error **errp)
 
 if (!group_path) {
 error_setg(errp, "%s: no iommu_group found for %s: %s",
-   VFIO_AP_DEVICE_TYPE, vapdev->vdev.sysfsdev, 
gerror->message);
+   TYPE_VFIO_AP_DEVICE, vapdev->vdev.sysfsdev, 
gerror->message);
 g_error_free(gerror);
 return NULL;
 }
@@ -176,7 +176,7 @@ static void vfio_ap_class_init(ObjectClass *klass, void 
*data)
 }
 
 static const TypeInfo vfio_ap_info = {
-.name = VFIO_AP_DEVICE_TYPE,
+.name = TYPE_VFIO_AP_DEVICE,
 .parent = TYPE_AP_DEVICE,
 .instance_size = sizeof(VFIOAPDevice),
 .class_init = vfio_ap_class_init,
-- 
2.26.2




[PULL 30/34] omap_intc: Use typedef name for instance_size

2020-09-08 Thread Eduardo Habkost
This makes the code consistent with the rest of QOM code in QEMU,
and will make automated conversion to type declaration macros
simpler.

Signed-off-by: Eduardo Habkost 
Message-Id: <20200824215936.2961951-3-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/intc/omap_intc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
index b8a1d1fd7d..d7183d035e 100644
--- a/hw/intc/omap_intc.c
+++ b/hw/intc/omap_intc.c
@@ -676,7 +676,7 @@ static const TypeInfo omap2_intc_info = {
 static const TypeInfo omap_intc_type_info = {
 .name  = TYPE_OMAP_INTC,
 .parent= TYPE_SYS_BUS_DEVICE,
-.instance_size = sizeof(struct omap_intr_handler_s),
+.instance_size = sizeof(omap_intr_handler),
 .abstract  = true,
 };
 
-- 
2.26.2




[PULL 12/34] Use OBJECT_DECLARE_TYPE where possible

2020-09-08 Thread Eduardo Habkost
Replace DECLARE_OBJ_CHECKERS with OBJECT_DECLARE_TYPE where the
typedefs can be safely removed.

Generated running:

$ ./scripts/codeconverter/converter.py -i \
  --pattern=DeclareObjCheckers $(git grep -l '' -- '*.[ch]')

Reviewed-by: Daniel P. Berrangé 
Message-Id: <20200831210740.126168-16-ehabk...@redhat.com>
Message-Id: <20200831210740.126168-17-ehabk...@redhat.com>
Message-Id: <20200831210740.126168-18-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/audio/intel-hda.h| 6 ++
 hw/display/virtio-vga.h | 6 ++
 include/authz/base.h| 6 ++
 include/authz/list.h| 6 ++
 include/authz/listfile.h| 6 ++
 include/authz/pamacct.h | 6 ++
 include/authz/simple.h  | 6 ++
 include/crypto/secret_common.h  | 6 ++
 include/crypto/secret_keyring.h | 6 ++
 include/hw/arm/armsse.h | 6 ++
 include/hw/hyperv/vmbus.h   | 6 ++
 include/hw/i2c/i2c.h| 6 ++
 include/hw/i2c/smbus_slave.h| 6 ++
 include/hw/ipack/ipack.h| 6 ++
 include/hw/ipmi/ipmi.h  | 6 ++
 include/hw/mem/pc-dimm.h| 6 ++
 include/hw/ppc/pnv.h| 6 ++
 include/hw/ppc/pnv_core.h   | 6 ++
 include/hw/ppc/pnv_homer.h  | 6 ++
 include/hw/ppc/pnv_occ.h| 6 ++
 include/hw/ppc/pnv_psi.h| 6 ++
 include/hw/ppc/pnv_xive.h   | 6 ++
 include/hw/ppc/spapr_cpu_core.h | 6 ++
 include/hw/ppc/spapr_vio.h  | 6 ++
 include/hw/ppc/xics.h   | 6 ++
 include/hw/ppc/xive.h   | 6 ++
 include/hw/s390x/event-facility.h   | 6 ++
 include/hw/s390x/s390_flic.h| 6 ++
 include/hw/s390x/sclp.h | 6 ++
 include/hw/sd/sd.h  | 6 ++
 include/hw/ssi/ssi.h| 6 ++
 include/hw/sysbus.h | 6 ++
 include/hw/virtio/virtio-gpu.h  | 6 ++
 include/hw/virtio/virtio-input.h| 6 ++
 include/hw/virtio/virtio-mem.h  | 6 ++
 include/hw/virtio/virtio-pmem.h | 6 ++
 include/hw/virtio/virtio-serial.h   | 6 ++
 include/hw/xen/xen-bus.h| 6 ++
 include/io/channel.h| 6 ++
 include/io/dns-resolver.h   | 6 ++
 include/io/net-listener.h   | 6 ++
 include/scsi/pr-manager.h   | 6 ++
 include/sysemu/cryptodev.h  | 6 ++
 include/sysemu/hostmem.h| 6 ++
 include/sysemu/rng.h| 6 ++
 include/sysemu/tpm_backend.h| 6 ++
 include/sysemu/vhost-user-backend.h | 6 ++
 target/alpha/cpu-qom.h  | 6 ++
 target/arm/cpu-qom.h| 6 ++
 target/avr/cpu-qom.h| 6 ++
 target/cris/cpu-qom.h   | 6 ++
 target/hppa/cpu-qom.h   | 6 ++
 target/i386/cpu-qom.h   | 6 ++
 target/lm32/cpu-qom.h   | 6 ++
 target/m68k/cpu-qom.h   | 6 ++
 target/microblaze/cpu-qom.h | 6 ++
 target/mips/cpu-qom.h   | 6 ++
 target/moxie/cpu.h  | 6 ++
 target/nios2/cpu.h  | 6 ++
 target/openrisc/cpu.h   | 6 ++
 target/ppc/cpu-qom.h| 6 ++
 target/riscv/cpu.h  | 6 ++
 target/rx/cpu-qom.h | 6 ++
 target/s390x/cpu-qom.h  | 6 ++
 target/sh4/cpu-qom.h| 6 ++
 target/sparc/cpu-qom.h  | 6 ++
 target/tilegx/cpu.h | 6 ++
 target/tricore/cpu-qom.h| 6 ++
 target/unicore32/cpu-qom.h  | 6 ++
 target/xtensa/cpu-qom.h | 6 ++
 backends/dbus-vmstate.c | 6 ++
 ui/input-barrier.c  | 6 ++
 ui/input-linux.c| 6 ++
 73 files changed, 146 insertions(+), 292 deletions(-)

diff --git a/hw/audio/intel-hda.h b/hw/audio/intel-hda.h
index 813a7a357d..f5cce18fa3 100644
--- a/hw/audio/intel-hda.h
+++ b/hw/audio/intel-hda.h
@@ -8,10 +8,8 @@
 /* hda bus   */
 
 #define TYPE_HDA_CODEC_DEVICE "hda-codec"
-typedef struct HDACodecDevice HDACodecDevice;
-typedef struct HDACodecDeviceClass HDACodecDeviceClass;
-DECLARE_OBJ_CHECKERS(HDACodecDevice, HDACodecDeviceClass,
- HDA_CODEC_DEVICE, TYPE_HDA_CODEC_DEVICE)
+OBJECT_DECLARE_TYPE(HDACodecDevice, HDACodecDeviceClass,
+hda_codec_device, HDA_CODEC_DEVICE)
 
 #define TYPE_HDA_BUS "HDA"
 typedef struct HDACodecBus HDACodecBus;
diff --git a/hw/display/virtio-vga.h b/hw/display/virtio-vga.h
index 19f8af7356..5c5671c9c1 100644
--- a/hw/display/virtio-vga.h
+++ b/hw/display/virtio-vga.h
@@ -9,10 +9,8 @@
  * virtio-vga-base: This extends VirtioPCIProxy.
  */
 #define TYPE_VIRTIO_VGA_BASE 

[PULL 29/34] xilinx_axidma: Use typedef name for instance_size

2020-09-08 Thread Eduardo Habkost
This makes the code consistent with the rest of QOM code in QEMU,
and will make automated conversion to type declaration macros
simpler.

Signed-off-by: Eduardo Habkost 
Message-Id: <20200824215936.2961951-2-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/dma/xilinx_axidma.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index f313453495..498fc17d8a 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -633,7 +633,7 @@ static const TypeInfo axidma_info = {
 static const TypeInfo xilinx_axidma_data_stream_info = {
 .name  = TYPE_XILINX_AXI_DMA_DATA_STREAM,
 .parent= TYPE_OBJECT,
-.instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
+.instance_size = sizeof(XilinxAXIDMAStreamSlave),
 .class_init= xilinx_axidma_stream_class_init,
 .class_data= _axidma_data_stream_class,
 .interfaces = (InterfaceInfo[]) {
@@ -645,7 +645,7 @@ static const TypeInfo xilinx_axidma_data_stream_info = {
 static const TypeInfo xilinx_axidma_control_stream_info = {
 .name  = TYPE_XILINX_AXI_DMA_CONTROL_STREAM,
 .parent= TYPE_OBJECT,
-.instance_size = sizeof(struct XilinxAXIDMAStreamSlave),
+.instance_size = sizeof(XilinxAXIDMAStreamSlave),
 .class_init= xilinx_axidma_stream_class_init,
 .class_data= _axidma_control_stream_class,
 .interfaces = (InterfaceInfo[]) {
-- 
2.26.2




[PULL 14/34] gpex: Fix type checking function name

2020-09-08 Thread Eduardo Habkost
This looks like a copy/paste mistake: the instance type checking
macro for TYPE_GPEX_ROOT_DEVICE was named MCH_PCI_DEVICE.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20200902224311.1321159-2-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 include/hw/pci-host/gpex.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h
index e8432eced8..2f4e852eee 100644
--- a/include/hw/pci-host/gpex.h
+++ b/include/hw/pci-host/gpex.h
@@ -32,7 +32,7 @@ DECLARE_INSTANCE_CHECKER(GPEXHost, GPEX_HOST,
 
 #define TYPE_GPEX_ROOT_DEVICE "gpex-root"
 typedef struct GPEXRootState GPEXRootState;
-DECLARE_INSTANCE_CHECKER(GPEXRootState, MCH_PCI_DEVICE,
+DECLARE_INSTANCE_CHECKER(GPEXRootState, GPEX_ROOT_DEVICE,
  TYPE_GPEX_ROOT_DEVICE)
 
 #define GPEX_NUM_IRQS 4
-- 
2.26.2




[PULL 32/34] xilinx_axienet: Use typedef name for instance_size

2020-09-08 Thread Eduardo Habkost
This makes the code consistent with the rest of QOM code in QEMU,
and will make automated conversion to type declaration macros
simpler.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Alistair Francis 
Message-Id: <20200824215936.2961951-5-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/net/xilinx_axienet.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
index 10a33cb4a5..4e13786e50 100644
--- a/hw/net/xilinx_axienet.c
+++ b/hw/net/xilinx_axienet.c
@@ -1045,7 +1045,7 @@ static const TypeInfo xilinx_enet_info = {
 static const TypeInfo xilinx_enet_data_stream_info = {
 .name  = TYPE_XILINX_AXI_ENET_DATA_STREAM,
 .parent= TYPE_OBJECT,
-.instance_size = sizeof(struct XilinxAXIEnetStreamSlave),
+.instance_size = sizeof(XilinxAXIEnetStreamSlave),
 .class_init= xilinx_enet_data_stream_class_init,
 .interfaces = (InterfaceInfo[]) {
 { TYPE_STREAM_SLAVE },
@@ -1056,7 +1056,7 @@ static const TypeInfo xilinx_enet_data_stream_info = {
 static const TypeInfo xilinx_enet_control_stream_info = {
 .name  = TYPE_XILINX_AXI_ENET_CONTROL_STREAM,
 .parent= TYPE_OBJECT,
-.instance_size = sizeof(struct XilinxAXIEnetStreamSlave),
+.instance_size = sizeof(XilinxAXIEnetStreamSlave),
 .class_init= xilinx_enet_control_stream_class_init,
 .interfaces = (InterfaceInfo[]) {
 { TYPE_STREAM_SLAVE },
-- 
2.26.2




[PULL 24/34] sabre: Rename SABRE_DEVICE to SABRE

2020-09-08 Thread Eduardo Habkost
Make the type checking macro name consistent with the TYPE_*
constant.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20200902224311.1321159-49-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 include/hw/pci-host/sabre.h | 2 +-
 hw/pci-host/sabre.c | 8 
 hw/sparc64/sun4u.c  | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/hw/pci-host/sabre.h b/include/hw/pci-host/sabre.h
index 597bf70d69..7a76de4b9e 100644
--- a/include/hw/pci-host/sabre.h
+++ b/include/hw/pci-host/sabre.h
@@ -51,7 +51,7 @@ struct SabreState {
 typedef struct SabreState SabreState;
 
 #define TYPE_SABRE "sabre"
-DECLARE_INSTANCE_CHECKER(SabreState, SABRE_DEVICE,
+DECLARE_INSTANCE_CHECKER(SabreState, SABRE,
  TYPE_SABRE)
 
 #endif
diff --git a/hw/pci-host/sabre.c b/hw/pci-host/sabre.c
index 0cc68585f8..5ac6283623 100644
--- a/hw/pci-host/sabre.c
+++ b/hw/pci-host/sabre.c
@@ -338,7 +338,7 @@ static void pci_sabre_set_irq(void *opaque, int irq_num, 
int level)
 
 static void sabre_reset(DeviceState *d)
 {
-SabreState *s = SABRE_DEVICE(d);
+SabreState *s = SABRE(d);
 PCIDevice *pci_dev;
 unsigned int i;
 uint16_t cmd;
@@ -376,7 +376,7 @@ static const MemoryRegionOps pci_config_ops = {
 
 static void sabre_realize(DeviceState *dev, Error **errp)
 {
-SabreState *s = SABRE_DEVICE(dev);
+SabreState *s = SABRE(dev);
 PCIHostState *phb = PCI_HOST_BRIDGE(dev);
 SysBusDevice *sbd = SYS_BUS_DEVICE(s);
 PCIDevice *pci_dev;
@@ -421,7 +421,7 @@ static void sabre_realize(DeviceState *dev, Error **errp)
 
 static void sabre_init(Object *obj)
 {
-SabreState *s = SABRE_DEVICE(obj);
+SabreState *s = SABRE(obj);
 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 unsigned int i;
 
@@ -502,7 +502,7 @@ static const TypeInfo sabre_pci_info = {
 
 static char *sabre_ofw_unit_address(const SysBusDevice *dev)
 {
-SabreState *s = SABRE_DEVICE(dev);
+SabreState *s = SABRE(dev);
 
 return g_strdup_printf("%x,%x",
(uint32_t)((s->special_base >> 32) & 0x),
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 67985414e2..b4aabfc076 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -585,7 +585,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 prom_init(hwdef->prom_addr, bios_name);
 
 /* Init sabre (PCI host bridge) */
-sabre = SABRE_DEVICE(qdev_new(TYPE_SABRE));
+sabre = SABRE(qdev_new(TYPE_SABRE));
 qdev_prop_set_uint64(DEVICE(sabre), "special-base", PBM_SPECIAL_BASE);
 qdev_prop_set_uint64(DEVICE(sabre), "mem-base", PBM_MEM_BASE);
 object_property_set_link(OBJECT(sabre), "iommu", OBJECT(iommu),
-- 
2.26.2




[PULL 13/34] Use OBJECT_DECLARE_SIMPLE_TYPE when possible

2020-09-08 Thread Eduardo Habkost
Generated using:

 $ ./scripts/codeconverter/converter.py -i \
   --pattern=ObjectDeclareType $(git grep -l '' -- '*.[ch]')

Reviewed-by: Daniel P. Berrangé 
Signed-off-by: Eduardo Habkost 
Message-Id: <20200831210740.126168-19-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 include/authz/list.h| 7 ++-
 include/authz/listfile.h| 7 ++-
 include/authz/pamacct.h | 7 ++-
 include/authz/simple.h  | 7 ++-
 include/crypto/secret_keyring.h | 7 ++-
 include/io/dns-resolver.h   | 7 ++-
 include/io/net-listener.h   | 7 ++-
 include/sysemu/vhost-user-backend.h | 7 ++-
 backends/dbus-vmstate.c | 7 ++-
 ui/input-barrier.c  | 7 ++-
 ui/input-linux.c| 7 ++-
 11 files changed, 22 insertions(+), 55 deletions(-)

diff --git a/include/authz/list.h b/include/authz/list.h
index e4e1040472..5676bb375c 100644
--- a/include/authz/list.h
+++ b/include/authz/list.h
@@ -27,8 +27,8 @@
 
 #define TYPE_QAUTHZ_LIST "authz-list"
 
-OBJECT_DECLARE_TYPE(QAuthZList, QAuthZListClass,
-qauthz_list, QAUTHZ_LIST)
+OBJECT_DECLARE_SIMPLE_TYPE(QAuthZList, qauthz_list,
+   QAUTHZ_LIST, QAuthZClass)
 
 
 
@@ -68,9 +68,6 @@ struct QAuthZList {
 };
 
 
-struct QAuthZListClass {
-QAuthZClass parent_class;
-};
 
 
 QAuthZList *qauthz_list_new(const char *id,
diff --git a/include/authz/listfile.h b/include/authz/listfile.h
index 89c5eafbfa..b491227bbe 100644
--- a/include/authz/listfile.h
+++ b/include/authz/listfile.h
@@ -27,8 +27,8 @@
 
 #define TYPE_QAUTHZ_LIST_FILE "authz-list-file"
 
-OBJECT_DECLARE_TYPE(QAuthZListFile, QAuthZListFileClass,
-qauthz_list_file, QAUTHZ_LIST_FILE)
+OBJECT_DECLARE_SIMPLE_TYPE(QAuthZListFile, qauthz_list_file,
+   QAUTHZ_LIST_FILE, QAuthZClass)
 
 
 
@@ -87,9 +87,6 @@ struct QAuthZListFile {
 };
 
 
-struct QAuthZListFileClass {
-QAuthZClass parent_class;
-};
 
 
 QAuthZListFile *qauthz_list_file_new(const char *id,
diff --git a/include/authz/pamacct.h b/include/authz/pamacct.h
index 44bb5ff28d..7804853ddf 100644
--- a/include/authz/pamacct.h
+++ b/include/authz/pamacct.h
@@ -27,8 +27,8 @@
 
 #define TYPE_QAUTHZ_PAM "authz-pam"
 
-OBJECT_DECLARE_TYPE(QAuthZPAM, QAuthZPAMClass,
-qauthz_pam, QAUTHZ_PAM)
+OBJECT_DECLARE_SIMPLE_TYPE(QAuthZPAM, qauthz_pam,
+   QAUTHZ_PAM, QAuthZClass)
 
 
 
@@ -79,9 +79,6 @@ struct QAuthZPAM {
 };
 
 
-struct QAuthZPAMClass {
-QAuthZClass parent_class;
-};
 
 
 QAuthZPAM *qauthz_pam_new(const char *id,
diff --git a/include/authz/simple.h b/include/authz/simple.h
index ba4a5ec5ea..346fcb0c6c 100644
--- a/include/authz/simple.h
+++ b/include/authz/simple.h
@@ -26,8 +26,8 @@
 
 #define TYPE_QAUTHZ_SIMPLE "authz-simple"
 
-OBJECT_DECLARE_TYPE(QAuthZSimple, QAuthZSimpleClass,
-qauthz_simple, QAUTHZ_SIMPLE)
+OBJECT_DECLARE_SIMPLE_TYPE(QAuthZSimple, qauthz_simple,
+   QAUTHZ_SIMPLE, QAuthZClass)
 
 
 
@@ -62,9 +62,6 @@ struct QAuthZSimple {
 };
 
 
-struct QAuthZSimpleClass {
-QAuthZClass parent_class;
-};
 
 
 QAuthZSimple *qauthz_simple_new(const char *id,
diff --git a/include/crypto/secret_keyring.h b/include/crypto/secret_keyring.h
index cc2c7397db..73d2a8f501 100644
--- a/include/crypto/secret_keyring.h
+++ b/include/crypto/secret_keyring.h
@@ -26,8 +26,8 @@
 #include "crypto/secret_common.h"
 
 #define TYPE_QCRYPTO_SECRET_KEYRING "secret_keyring"
-OBJECT_DECLARE_TYPE(QCryptoSecretKeyring, QCryptoSecretKeyringClass,
-qcrypto_secret_keyring, QCRYPTO_SECRET_KEYRING)
+OBJECT_DECLARE_SIMPLE_TYPE(QCryptoSecretKeyring, qcrypto_secret_keyring,
+   QCRYPTO_SECRET_KEYRING, QCryptoSecretCommonClass)
 
 
 struct QCryptoSecretKeyring {
@@ -36,8 +36,5 @@ struct QCryptoSecretKeyring {
 };
 
 
-struct QCryptoSecretKeyringClass {
-QCryptoSecretCommonClass parent;
-};
 
 #endif /* QCRYPTO_SECRET_KEYRING_H */
diff --git a/include/io/dns-resolver.h b/include/io/dns-resolver.h
index 8ae4857e05..e248fba5bd 100644
--- a/include/io/dns-resolver.h
+++ b/include/io/dns-resolver.h
@@ -26,8 +26,8 @@
 #include "io/task.h"
 
 #define TYPE_QIO_DNS_RESOLVER "qio-dns-resolver"
-OBJECT_DECLARE_TYPE(QIODNSResolver, QIODNSResolverClass,
-qio_dns_resolver, QIO_DNS_RESOLVER)
+OBJECT_DECLARE_SIMPLE_TYPE(QIODNSResolver, qio_dns_resolver,
+   QIO_DNS_RESOLVER, ObjectClass)
 
 
 /**
@@ -133,9 +133,6 @@ struct QIODNSResolver {
 Object parent;
 };
 
-struct QIODNSResolverClass {
-ObjectClass parent;
-};
 
 
 /**
diff --git a/include/io/net-listener.h b/include/io/net-listener.h
index 4f0847ff19..60fad29ff4 100644
--- a/include/io/net-listener.h
+++ b/include/io/net-listener.h
@@ -25,8 +25,8 @@
 #include "qom/object.h"
 
 #define TYPE_QIO_NET_LISTENER "qio-net-listener"

[PULL 27/34] pc87312: Rename TYPE_PC87312_SUPERIO to TYPE_PC87312

2020-09-08 Thread Eduardo Habkost
This will make the type name constant consistent with the name of
the type checking macro.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Hervé Poussineau 
Message-Id: <20200902224311.1321159-21-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 include/hw/isa/pc87312.h | 4 ++--
 hw/isa/pc87312.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/hw/isa/pc87312.h b/include/hw/isa/pc87312.h
index a65168a157..da8dc5ddf5 100644
--- a/include/hw/isa/pc87312.h
+++ b/include/hw/isa/pc87312.h
@@ -29,10 +29,10 @@
 #include "qom/object.h"
 
 
-#define TYPE_PC87312_SUPERIO "pc87312"
+#define TYPE_PC87312 "pc87312"
 typedef struct PC87312State PC87312State;
 DECLARE_INSTANCE_CHECKER(PC87312State, PC87312,
- TYPE_PC87312_SUPERIO)
+ TYPE_PC87312)
 
 struct PC87312State {
 /*< private >*/
diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c
index 0cacbbc91b..8d7b8d3db2 100644
--- a/hw/isa/pc87312.c
+++ b/hw/isa/pc87312.c
@@ -371,7 +371,7 @@ static void pc87312_class_init(ObjectClass *klass, void 
*data)
 }
 
 static const TypeInfo pc87312_type_info = {
-.name  = TYPE_PC87312_SUPERIO,
+.name  = TYPE_PC87312,
 .parent= TYPE_ISA_SUPERIO,
 .instance_size = sizeof(PC87312State),
 .instance_init = pc87312_initfn,
-- 
2.26.2




[PULL 23/34] rs6000_mc: Rename RS6000MC_DEVICE to RS6000MC

2020-09-08 Thread Eduardo Habkost
Make the type checking macro name consistent with the TYPE_*
constant.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Hervé Poussineau 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20200902224311.1321159-48-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/ppc/rs6000_mc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/rs6000_mc.c b/hw/ppc/rs6000_mc.c
index 56e96010b8..8611ffa96d 100644
--- a/hw/ppc/rs6000_mc.c
+++ b/hw/ppc/rs6000_mc.c
@@ -30,7 +30,7 @@
 
 #define TYPE_RS6000MC "rs6000-mc"
 typedef struct RS6000MCState RS6000MCState;
-DECLARE_INSTANCE_CHECKER(RS6000MCState, RS6000MC_DEVICE,
+DECLARE_INSTANCE_CHECKER(RS6000MCState, RS6000MC,
  TYPE_RS6000MC)
 
 struct RS6000MCState {
@@ -143,7 +143,7 @@ static const MemoryRegionPortio rs6000mc_port_list[] = {
 
 static void rs6000mc_realize(DeviceState *dev, Error **errp)
 {
-RS6000MCState *s = RS6000MC_DEVICE(dev);
+RS6000MCState *s = RS6000MC(dev);
 int socket = 0;
 unsigned int ram_size = s->ram_size / MiB;
 Error *local_err = NULL;
-- 
2.26.2




[PULL 25/34] usb: Rename USB_SERIAL_DEV to USB_SERIAL

2020-09-08 Thread Eduardo Habkost
Make the type checking macro name consistent with the TYPE_*
constant.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20200902224311.1321159-54-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/usb/dev-serial.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 1a58851d4b..1a038a222e 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -113,7 +113,7 @@ struct USBSerialState {
 typedef struct USBSerialState USBSerialState;
 
 #define TYPE_USB_SERIAL "usb-serial-dev"
-DECLARE_INSTANCE_CHECKER(USBSerialState, USB_SERIAL_DEV,
+DECLARE_INSTANCE_CHECKER(USBSerialState, USB_SERIAL,
  TYPE_USB_SERIAL)
 
 enum {
@@ -517,7 +517,7 @@ static void usb_serial_event(void *opaque, QEMUChrEvent 
event)
 
 static void usb_serial_realize(USBDevice *dev, Error **errp)
 {
-USBSerialState *s = USB_SERIAL_DEV(dev);
+USBSerialState *s = USB_SERIAL(dev);
 Error *local_err = NULL;
 
 usb_desc_create_serial(dev);
-- 
2.26.2




[PULL 28/34] tusb6010: Rename TUSB to TUSB6010

2020-09-08 Thread Eduardo Habkost
Make type checking function name consistent with the TYPE_TUSB6010
constant and QOM type name ("tusb6010").

Suggested-by: Philippe Mathieu-Daudé 
Suggested-by: "Daniel P. Berrangé" 
Signed-off-by: Eduardo Habkost 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20200903180128.1523959-9-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/usb/tusb6010.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/usb/tusb6010.c b/hw/usb/tusb6010.c
index 2bee3ae59f..dd20996d13 100644
--- a/hw/usb/tusb6010.c
+++ b/hw/usb/tusb6010.c
@@ -32,7 +32,7 @@
 
 #define TYPE_TUSB6010 "tusb6010"
 typedef struct TUSBState TUSBState;
-DECLARE_INSTANCE_CHECKER(TUSBState, TUSB,
+DECLARE_INSTANCE_CHECKER(TUSBState, TUSB6010,
  TYPE_TUSB6010)
 
 struct TUSBState {
@@ -779,7 +779,7 @@ static void tusb6010_irq(void *opaque, int source, int 
level)
 
 static void tusb6010_reset(DeviceState *dev)
 {
-TUSBState *s = TUSB(dev);
+TUSBState *s = TUSB6010(dev);
 int i;
 
 s->test_reset = TUSB_PROD_TEST_RESET_VAL;
@@ -815,7 +815,7 @@ static void tusb6010_reset(DeviceState *dev)
 
 static void tusb6010_realize(DeviceState *dev, Error **errp)
 {
-TUSBState *s = TUSB(dev);
+TUSBState *s = TUSB6010(dev);
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 
 s->otg_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tusb_otg_tick, s);
-- 
2.26.2




[PULL 03/34] qom: provide convenient macros for declaring and defining types

2020-09-08 Thread Eduardo Habkost
From: Daniel P. Berrangé 

When creating new QOM types, there is a lot of boilerplate code that
must be repeated using a standard pattern. This is tedious to write
and liable to suffer from subtle inconsistencies. Thus it would
benefit from some simple automation.

QOM was loosely inspired by GLib's GObject, and indeed GObject suffers
from the same burden of boilerplate code, but has long provided a set of
macros to eliminate this burden in the source implementation. More
recently it has also provided a set of macros to eliminate this burden
in the header declaration.

In GLib there are the G_DECLARE_* and G_DEFINE_* family of macros
for the header declaration and source implementation respectively:

  https://developer.gnome.org/gobject/stable/chapter-gobject.html
  https://developer.gnome.org/gobject/stable/howto-gobject.html

This patch takes inspiration from GObject to provide the equivalent
functionality for QOM.

In the header file, instead of:

typedef struct MyDevice MyDevice;
typedef struct MyDeviceClass MyDeviceClass;

G_DEFINE_AUTOPTR_CLEANUP_FUNC(MyDeviceClass, object_unref)

#define MY_DEVICE_GET_CLASS(void *obj) \
OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE)
#define MY_DEVICE_CLASS(void *klass) \
OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE)
#define MY_DEVICE(void *obj)
OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE)

struct MyDeviceClass {
DeviceClass parent_class;
};

We now have

OBJECT_DECLARE_SIMPLE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)

In cases where the class needs some virtual methods, it can be left
to be implemented manually using

OBJECT_DECLARE_TYPE(MyDevice, my_device, MY_DEVICE)

Note that these macros are including support for g_autoptr() for the
object types, which is something previously only supported for variables
declared as the base Object * type.

Meanwhile in the source file, instead of:

static void my_device_finalize(Object *obj);
static void my_device_class_init(ObjectClass *oc, void *data);
static void my_device_init(Object *obj);

static const TypeInfo my_device_info = {
.parent = TYPE_DEVICE,
.name = TYPE_MY_DEVICE,
.instance_size = sizeof(MyDevice),
.instance_init = my_device_init,
.instance_finalize = my_device_finalize,
.class_size = sizeof(MyDeviceClass),
.class_init = my_device_class_init,
};

static void
my_device_register_types(void)
{
type_register_static(_device_info);
}
type_init(my_device_register_types);

We now have

OBJECT_DEFINE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)

Or, if a class needs to implement interfaces:

OBJECT_DEFINE_TYPE_WITH_INTERFACES(MyDevice, my_device, MY_DEVICE, DEVICE,
   { TYPE_USER_CREATABLE }, { NULL })

Or, if a class needs to be abstract

OBJECT_DEFINE_ABSTRACT_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)

IOW, in both cases the maintainer now only has to think about the
interesting part of the code which implements useful functionality
and avoids much of the boilerplate.

Signed-off-by: Daniel P. Berrangé 
Message-Id: <20200723181410.3145233-3-berra...@redhat.com>
[ehabkost: Fix G_DEFINE_AUTOPTR_CLEANUP_FUNC usage]
Signed-off-by: Eduardo Habkost 
Message-Id: <20200831210740.126168-3-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 include/qom/object.h | 277 +++
 1 file changed, 277 insertions(+)

diff --git a/include/qom/object.h b/include/qom/object.h
index 1f8aa2d48e..f515230f61 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -304,6 +304,119 @@ typedef struct InterfaceInfo InterfaceInfo;
  *
  * The first example of such a QOM method was #CPUClass.reset,
  * another example is #DeviceClass.realize.
+ *
+ * # Standard type declaration and definition macros #
+ *
+ * A lot of the code outlined above follows a standard pattern and naming
+ * convention. To reduce the amount of boilerplate code that needs to be
+ * written for a new type there are two sets of macros to generate the
+ * common parts in a standard format.
+ *
+ * A type is declared using the OBJECT_DECLARE macro family. In types
+ * which do not require any virtual functions in the class, the
+ * OBJECT_DECLARE_SIMPLE_TYPE macro is suitable, and is commonly placed
+ * in the header file:
+ *
+ * 
+ *   Declaring a simple type
+ *   
+ * OBJECT_DECLARE_SIMPLE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)
+ *   
+ * 
+ *
+ * This is equivalent to the following:
+ *
+ * 
+ *   Expansion from declaring a simple type
+ *   
+ * typedef struct MyDevice MyDevice;
+ * typedef struct MyDeviceClass MyDeviceClass;
+ *
+ * G_DEFINE_AUTOPTR_CLEANUP_FUNC(MyDeviceClass, object_unref)
+ *
+ * #define MY_DEVICE_GET_CLASS(void *obj) \
+ * OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE)
+ * #define 

[PULL 21/34] esp: Rename ESP_STATE to ESP

2020-09-08 Thread Eduardo Habkost
Make the type checking macro name consistent with the TYPE_*
constant.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Hervé Poussineau 
Message-Id: <20200902224311.1321159-40-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 include/hw/scsi/esp.h | 2 +-
 hw/dma/sparc32_dma.c  | 2 +-
 hw/m68k/q800.c| 2 +-
 hw/mips/jazz.c| 2 +-
 hw/scsi/esp.c | 6 +++---
 hw/sparc/sun4m.c  | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
index f281625dd5..20800dbf5b 100644
--- a/include/hw/scsi/esp.h
+++ b/include/hw/scsi/esp.h
@@ -67,7 +67,7 @@ struct ESPState {
 
 #define TYPE_ESP "esp"
 typedef struct SysBusESPState SysBusESPState;
-DECLARE_INSTANCE_CHECKER(SysBusESPState, ESP_STATE,
+DECLARE_INSTANCE_CHECKER(SysBusESPState, ESP,
  TYPE_ESP)
 
 struct SysBusESPState {
diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c
index bcd1626fbd..d20a5bc065 100644
--- a/hw/dma/sparc32_dma.c
+++ b/hw/dma/sparc32_dma.c
@@ -303,7 +303,7 @@ static void sparc32_espdma_device_realize(DeviceState *dev, 
Error **errp)
 
 d = qdev_new(TYPE_ESP);
 object_property_add_child(OBJECT(dev), "esp", OBJECT(d));
-sysbus = ESP_STATE(d);
+sysbus = ESP(d);
 esp = >esp;
 esp->dma_memory_read = espdma_memory_read;
 esp->dma_memory_write = espdma_memory_write;
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 1ca482ad81..ce4b47c3e3 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -290,7 +290,7 @@ static void q800_init(MachineState *machine)
 /* SCSI */
 
 dev = qdev_new(TYPE_ESP);
-sysbus_esp = ESP_STATE(dev);
+sysbus_esp = ESP(dev);
 esp = _esp->esp;
 esp->dma_memory_read = NULL;
 esp->dma_memory_write = NULL;
diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c
index 82a6e3220e..47723093b6 100644
--- a/hw/mips/jazz.c
+++ b/hw/mips/jazz.c
@@ -309,7 +309,7 @@ static void mips_jazz_init(MachineState *machine,
 
 /* SCSI adapter */
 dev = qdev_new(TYPE_ESP);
-sysbus_esp = ESP_STATE(dev);
+sysbus_esp = ESP(dev);
 esp = _esp->esp;
 esp->dma_memory_read = rc4030_dma_read;
 esp->dma_memory_write = rc4030_dma_write;
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 405f8b7cbc..b84e0fe33e 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -929,7 +929,7 @@ static const struct SCSIBusInfo esp_scsi_info = {
 
 static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
 {
-SysBusESPState *sysbus = ESP_STATE(opaque);
+SysBusESPState *sysbus = ESP(opaque);
 ESPState *s = >esp;
 
 switch (irq) {
@@ -945,7 +945,7 @@ static void sysbus_esp_gpio_demux(void *opaque, int irq, 
int level)
 static void sysbus_esp_realize(DeviceState *dev, Error **errp)
 {
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
-SysBusESPState *sysbus = ESP_STATE(dev);
+SysBusESPState *sysbus = ESP(dev);
 ESPState *s = >esp;
 
 sysbus_init_irq(sbd, >irq);
@@ -967,7 +967,7 @@ static void sysbus_esp_realize(DeviceState *dev, Error 
**errp)
 
 static void sysbus_esp_hard_reset(DeviceState *dev)
 {
-SysBusESPState *sysbus = ESP_STATE(dev);
+SysBusESPState *sysbus = ESP(dev);
 esp_hard_reset(>esp);
 }
 
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 256033b9a0..947b69d159 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -335,7 +335,7 @@ static void *sparc32_dma_init(hwaddr dma_base,
OBJECT(dma), "espdma"));
 sysbus_connect_irq(SYS_BUS_DEVICE(espdma), 0, espdma_irq);
 
-esp = ESP_STATE(object_resolve_path_component(OBJECT(espdma), "esp"));
+esp = ESP(object_resolve_path_component(OBJECT(espdma), "esp"));
 sysbus_mmio_map(SYS_BUS_DEVICE(esp), 0, esp_base);
 scsi_bus_legacy_handle_cmdline(>esp.bus);
 
-- 
2.26.2




[PULL 22/34] filter-rewriter: Rename FILTER_COLO_REWRITER to FILTER_REWRITER

2020-09-08 Thread Eduardo Habkost
Make the type checking macro name consistent with the TYPE_*
constant.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Zhang Chen 
Message-Id: <20200902224311.1321159-41-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 net/filter-rewriter.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
index 113e293207..44f6021dd8 100644
--- a/net/filter-rewriter.c
+++ b/net/filter-rewriter.c
@@ -25,7 +25,7 @@
 
 #define TYPE_FILTER_REWRITER "filter-rewriter"
 typedef struct RewriterState RewriterState;
-DECLARE_INSTANCE_CHECKER(RewriterState, FILTER_COLO_REWRITER,
+DECLARE_INSTANCE_CHECKER(RewriterState, FILTER_REWRITER,
  TYPE_FILTER_REWRITER)
 
 #define FAILOVER_MODE_ON  true
@@ -47,7 +47,7 @@ static void filter_rewriter_failover_mode(RewriterState *s)
 
 static void filter_rewriter_flush(NetFilterState *nf)
 {
-RewriterState *s = FILTER_COLO_REWRITER(nf);
+RewriterState *s = FILTER_REWRITER(nf);
 
 if (!qemu_net_queue_flush(s->incoming_queue)) {
 /* Unable to empty the queue, purge remaining packets */
@@ -252,7 +252,7 @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
  int iovcnt,
  NetPacketSent *sent_cb)
 {
-RewriterState *s = FILTER_COLO_REWRITER(nf);
+RewriterState *s = FILTER_REWRITER(nf);
 Connection *conn;
 ConnectionKey key;
 Packet *pkt;
@@ -350,7 +350,7 @@ static gboolean offset_is_nonzero(gpointer key,
 static void colo_rewriter_handle_event(NetFilterState *nf, int event,
Error **errp)
 {
-RewriterState *rs = FILTER_COLO_REWRITER(nf);
+RewriterState *rs = FILTER_REWRITER(nf);
 
 switch (event) {
 case COLO_EVENT_CHECKPOINT:
@@ -370,7 +370,7 @@ static void colo_rewriter_handle_event(NetFilterState *nf, 
int event,
 
 static void colo_rewriter_cleanup(NetFilterState *nf)
 {
-RewriterState *s = FILTER_COLO_REWRITER(nf);
+RewriterState *s = FILTER_REWRITER(nf);
 
 /* flush packets */
 if (s->incoming_queue) {
@@ -381,7 +381,7 @@ static void colo_rewriter_cleanup(NetFilterState *nf)
 
 static void colo_rewriter_setup(NetFilterState *nf, Error **errp)
 {
-RewriterState *s = FILTER_COLO_REWRITER(nf);
+RewriterState *s = FILTER_REWRITER(nf);
 
 s->connection_track_table = g_hash_table_new_full(connection_key_hash,
   connection_key_equal,
@@ -392,7 +392,7 @@ static void colo_rewriter_setup(NetFilterState *nf, Error 
**errp)
 
 static bool filter_rewriter_get_vnet_hdr(Object *obj, Error **errp)
 {
-RewriterState *s = FILTER_COLO_REWRITER(obj);
+RewriterState *s = FILTER_REWRITER(obj);
 
 return s->vnet_hdr;
 }
@@ -401,14 +401,14 @@ static void filter_rewriter_set_vnet_hdr(Object *obj,
  bool value,
  Error **errp)
 {
-RewriterState *s = FILTER_COLO_REWRITER(obj);
+RewriterState *s = FILTER_REWRITER(obj);
 
 s->vnet_hdr = value;
 }
 
 static void filter_rewriter_init(Object *obj)
 {
-RewriterState *s = FILTER_COLO_REWRITER(obj);
+RewriterState *s = FILTER_REWRITER(obj);
 
 s->vnet_hdr = false;
 s->failover_mode = FAILOVER_MODE_OFF;
-- 
2.26.2




[PULL 26/34] vfio: Rename PCI_VFIO to VFIO_PCI

2020-09-08 Thread Eduardo Habkost
Make the type checking macro name consistent with the TYPE_*
constant.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Eric Auger 
Message-Id: <20200902224311.1321159-56-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/vfio/pci.h |  2 +-
 hw/vfio/pci.c | 22 +++---
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index 846d60e56c..5e53d5b863 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -116,7 +116,7 @@ typedef struct VFIOMSIXInfo {
 
 #define TYPE_VFIO_PCI "vfio-pci"
 typedef struct VFIOPCIDevice VFIOPCIDevice;
-DECLARE_INSTANCE_CHECKER(VFIOPCIDevice, PCI_VFIO,
+DECLARE_INSTANCE_CHECKER(VFIOPCIDevice, VFIO_PCI,
  TYPE_VFIO_PCI)
 
 struct VFIOPCIDevice {
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 3611dcd38b..0d83eb0e47 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -230,7 +230,7 @@ static void vfio_intx_update(VFIOPCIDevice *vdev, 
PCIINTxRoute *route)
 
 static void vfio_intx_routing_notifier(PCIDevice *pdev)
 {
-VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+VFIOPCIDevice *vdev = VFIO_PCI(pdev);
 PCIINTxRoute route;
 
 if (vdev->interrupt != VFIO_INT_INTx) {
@@ -456,7 +456,7 @@ static void vfio_update_kvm_msi_virq(VFIOMSIVector *vector, 
MSIMessage msg,
 static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
MSIMessage *msg, IOHandler *handler)
 {
-VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+VFIOPCIDevice *vdev = VFIO_PCI(pdev);
 VFIOMSIVector *vector;
 int ret;
 
@@ -541,7 +541,7 @@ static int vfio_msix_vector_use(PCIDevice *pdev,
 
 static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr)
 {
-VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+VFIOPCIDevice *vdev = VFIO_PCI(pdev);
 VFIOMSIVector *vector = >msi_vectors[nr];
 
 trace_vfio_msix_vector_release(vdev->vbasedev.name, nr);
@@ -1048,7 +1048,7 @@ static const MemoryRegionOps vfio_vga_ops = {
  */
 static void vfio_sub_page_bar_update_mapping(PCIDevice *pdev, int bar)
 {
-VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+VFIOPCIDevice *vdev = VFIO_PCI(pdev);
 VFIORegion *region = >bars[bar].region;
 MemoryRegion *mmap_mr, *region_mr, *base_mr;
 PCIIORegion *r;
@@ -1094,7 +1094,7 @@ static void vfio_sub_page_bar_update_mapping(PCIDevice 
*pdev, int bar)
  */
 uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len)
 {
-VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+VFIOPCIDevice *vdev = VFIO_PCI(pdev);
 uint32_t emu_bits = 0, emu_val = 0, phys_val = 0, val;
 
 memcpy(_bits, vdev->emulated_config_bits + addr, len);
@@ -1127,7 +1127,7 @@ uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t 
addr, int len)
 void vfio_pci_write_config(PCIDevice *pdev,
uint32_t addr, uint32_t val, int len)
 {
-VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+VFIOPCIDevice *vdev = VFIO_PCI(pdev);
 uint32_t val_le = cpu_to_le32(val);
 
 trace_vfio_pci_write_config(vdev->vbasedev.name, addr, val, len);
@@ -2701,7 +2701,7 @@ static void vfio_unregister_req_notifier(VFIOPCIDevice 
*vdev)
 
 static void vfio_realize(PCIDevice *pdev, Error **errp)
 {
-VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+VFIOPCIDevice *vdev = VFIO_PCI(pdev);
 VFIODevice *vbasedev_iter;
 VFIOGroup *group;
 char *tmp, *subsys, group_path[PATH_MAX], *group_name;
@@ -3033,7 +3033,7 @@ error:
 
 static void vfio_instance_finalize(Object *obj)
 {
-VFIOPCIDevice *vdev = PCI_VFIO(obj);
+VFIOPCIDevice *vdev = VFIO_PCI(obj);
 VFIOGroup *group = vdev->vbasedev.group;
 
 vfio_display_finalize(vdev);
@@ -3057,7 +3057,7 @@ static void vfio_instance_finalize(Object *obj)
 
 static void vfio_exitfn(PCIDevice *pdev)
 {
-VFIOPCIDevice *vdev = PCI_VFIO(pdev);
+VFIOPCIDevice *vdev = VFIO_PCI(pdev);
 
 vfio_unregister_req_notifier(vdev);
 vfio_unregister_err_notifier(vdev);
@@ -3075,7 +3075,7 @@ static void vfio_exitfn(PCIDevice *pdev)
 
 static void vfio_pci_reset(DeviceState *dev)
 {
-VFIOPCIDevice *vdev = PCI_VFIO(dev);
+VFIOPCIDevice *vdev = VFIO_PCI(dev);
 
 trace_vfio_pci_reset(vdev->vbasedev.name);
 
@@ -3115,7 +3115,7 @@ post_reset:
 static void vfio_instance_init(Object *obj)
 {
 PCIDevice *pci_dev = PCI_DEVICE(obj);
-VFIOPCIDevice *vdev = PCI_VFIO(obj);
+VFIOPCIDevice *vdev = VFIO_PCI(obj);
 
 device_add_bootindex_property(obj, >bootindex,
   "bootindex", NULL,
-- 
2.26.2




[PULL 08/34] Delete duplicate QOM typedefs

2020-09-08 Thread Eduardo Habkost
Generated using:

 $ ./scripts/codeconverter/converter.py -i \
   --pattern=QOMDuplicatedTypedefs $(git grep -l '' -- '*.[ch]')

Reviewed-by: Daniel P. Berrangé 
Signed-off-by: Eduardo Habkost 
Message-Id: <20200831210740.126168-8-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 include/crypto/secret_keyring.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/crypto/secret_keyring.h b/include/crypto/secret_keyring.h
index 9f371ad251..4345eb048e 100644
--- a/include/crypto/secret_keyring.h
+++ b/include/crypto/secret_keyring.h
@@ -39,14 +39,14 @@
 typedef struct QCryptoSecretKeyring QCryptoSecretKeyring;
 typedef struct QCryptoSecretKeyringClass QCryptoSecretKeyringClass;
 
-typedef struct QCryptoSecretKeyring {
+struct QCryptoSecretKeyring {
 QCryptoSecretCommon parent;
 int32_t serial;
-} QCryptoSecretKeyring;
+};
 
 
-typedef struct QCryptoSecretKeyringClass {
+struct QCryptoSecretKeyringClass {
 QCryptoSecretCommonClass parent;
-} QCryptoSecretKeyringClass;
+};
 
 #endif /* QCRYPTO_SECRET_KEYRING_H */
-- 
2.26.2




[PULL 16/34] ap-device: Rename AP_DEVICE_TYPE to TYPE_AP_DEVICE

2020-09-08 Thread Eduardo Habkost
This will make the type name constant consistent with the name of
the type checking macro.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Thomas Huth 
Message-Id: <20200902224311.1321159-6-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 include/hw/s390x/ap-device.h | 4 ++--
 hw/s390x/ap-device.c | 2 +-
 hw/vfio/ap.c | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/hw/s390x/ap-device.h b/include/hw/s390x/ap-device.h
index fb250a20f3..e502745de5 100644
--- a/include/hw/s390x/ap-device.h
+++ b/include/hw/s390x/ap-device.h
@@ -14,7 +14,7 @@
 #include "hw/qdev-core.h"
 #include "qom/object.h"
 
-#define AP_DEVICE_TYPE   "ap-device"
+#define TYPE_AP_DEVICE   "ap-device"
 
 struct APDevice {
 DeviceState parent_obj;
@@ -22,6 +22,6 @@ struct APDevice {
 typedef struct APDevice APDevice;
 
 DECLARE_INSTANCE_CHECKER(APDevice, AP_DEVICE,
- AP_DEVICE_TYPE)
+ TYPE_AP_DEVICE)
 
 #endif /* HW_S390X_AP_DEVICE_H */
diff --git a/hw/s390x/ap-device.c b/hw/s390x/ap-device.c
index fc0b41e937..237d1f19c5 100644
--- a/hw/s390x/ap-device.c
+++ b/hw/s390x/ap-device.c
@@ -21,7 +21,7 @@ static void ap_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo ap_device_info = {
-.name = AP_DEVICE_TYPE,
+.name = TYPE_AP_DEVICE,
 .parent = TYPE_DEVICE,
 .instance_size = sizeof(APDevice),
 .class_size = sizeof(DeviceClass),
diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c
index f399ec0a31..68ed059b39 100644
--- a/hw/vfio/ap.c
+++ b/hw/vfio/ap.c
@@ -177,7 +177,7 @@ static void vfio_ap_class_init(ObjectClass *klass, void 
*data)
 
 static const TypeInfo vfio_ap_info = {
 .name = VFIO_AP_DEVICE_TYPE,
-.parent = AP_DEVICE_TYPE,
+.parent = TYPE_AP_DEVICE,
 .instance_size = sizeof(VFIOAPDevice),
 .class_init = vfio_ap_class_init,
 };
-- 
2.26.2




[PULL 06/34] qom: Make type checker functions accept const pointers

2020-09-08 Thread Eduardo Habkost
The existing type check macros all unconditionally drop const
qualifiers from their arguments.  Keep this behavior in the
macros generated by DECLARE_*CHECKER* by now.

Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Daniel P. Berrangé 
Signed-off-by: Eduardo Habkost 
Message-Id: <20200831210740.126168-6-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 include/qom/object.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/qom/object.h b/include/qom/object.h
index 4cd84998c2..3626ae3c65 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -567,7 +567,7 @@ struct Object
  */
 #define DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \
 static inline G_GNUC_UNUSED InstanceType * \
-OBJ_NAME(void *obj) \
+OBJ_NAME(const void *obj) \
 { return OBJECT_CHECK(InstanceType, obj, TYPENAME); }
 
 /**
@@ -584,11 +584,11 @@ struct Object
  */
 #define DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME) \
 static inline G_GNUC_UNUSED ClassType * \
-OBJ_NAME##_GET_CLASS(void *obj) \
+OBJ_NAME##_GET_CLASS(const void *obj) \
 { return OBJECT_GET_CLASS(ClassType, obj, TYPENAME); } \
 \
 static inline G_GNUC_UNUSED ClassType * \
-OBJ_NAME##_CLASS(void *klass) \
+OBJ_NAME##_CLASS(const void *klass) \
 { return OBJECT_CLASS_CHECK(ClassType, klass, TYPENAME); }
 
 /**
-- 
2.26.2




[PULL 20/34] ahci: Rename ICH_AHCI to ICH9_AHCI

2020-09-08 Thread Eduardo Habkost
Make the type checking macro name consistent with the TYPE_*
constant.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20200902224311.1321159-33-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 include/hw/ide/ahci.h | 2 +-
 hw/ide/ahci.c | 4 ++--
 hw/ide/ich.c  | 8 
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/hw/ide/ahci.h b/include/hw/ide/ahci.h
index 4cf6813d80..da3cddcc65 100644
--- a/include/hw/ide/ahci.h
+++ b/include/hw/ide/ahci.h
@@ -54,7 +54,7 @@ typedef struct AHCIState {
 typedef struct AHCIPCIState AHCIPCIState;
 
 #define TYPE_ICH9_AHCI "ich9-ahci"
-DECLARE_INSTANCE_CHECKER(AHCIPCIState, ICH_AHCI,
+DECLARE_INSTANCE_CHECKER(AHCIPCIState, ICH9_AHCI,
  TYPE_ICH9_AHCI)
 
 int32_t ahci_get_num_ports(PCIDevice *dev);
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index b696c6291a..ee1d47ff75 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1819,7 +1819,7 @@ type_init(sysbus_ahci_register_types)
 
 int32_t ahci_get_num_ports(PCIDevice *dev)
 {
-AHCIPCIState *d = ICH_AHCI(dev);
+AHCIPCIState *d = ICH9_AHCI(dev);
 AHCIState *ahci = >ahci;
 
 return ahci->ports;
@@ -1827,7 +1827,7 @@ int32_t ahci_get_num_ports(PCIDevice *dev)
 
 void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd)
 {
-AHCIPCIState *d = ICH_AHCI(dev);
+AHCIPCIState *d = ICH9_AHCI(dev);
 AHCIState *ahci = >ahci;
 int i;
 
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index eff3188fff..51cd2f38b7 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -91,14 +91,14 @@ static const VMStateDescription vmstate_ich9_ahci = {
 
 static void pci_ich9_reset(DeviceState *dev)
 {
-AHCIPCIState *d = ICH_AHCI(dev);
+AHCIPCIState *d = ICH9_AHCI(dev);
 
 ahci_reset(>ahci);
 }
 
 static void pci_ich9_ahci_init(Object *obj)
 {
-struct AHCIPCIState *d = ICH_AHCI(obj);
+struct AHCIPCIState *d = ICH9_AHCI(obj);
 
 ahci_init(>ahci, DEVICE(obj));
 }
@@ -108,7 +108,7 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error 
**errp)
 struct AHCIPCIState *d;
 int sata_cap_offset;
 uint8_t *sata_cap;
-d = ICH_AHCI(dev);
+d = ICH9_AHCI(dev);
 int ret;
 
 ahci_realize(>ahci, DEVICE(dev), pci_get_address_space(dev), 6);
@@ -154,7 +154,7 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error 
**errp)
 static void pci_ich9_uninit(PCIDevice *dev)
 {
 struct AHCIPCIState *d;
-d = ICH_AHCI(dev);
+d = ICH9_AHCI(dev);
 
 msi_uninit(dev);
 ahci_uninit(>ahci);
-- 
2.26.2




[PULL 17/34] dev-smartcard-reader: Rename CCID_DEV_NAME to TYPE_USB_CCID_DEV

2020-09-08 Thread Eduardo Habkost
This will make the type name constant consistent with the name of
the type checking macro.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20200902224311.1321159-7-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 hw/usb/dev-smartcard-reader.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 432508c478..59b2248f34 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -60,10 +60,10 @@ do { \
 #define D_MORE_INFO 3
 #define D_VERBOSE 4
 
-#define CCID_DEV_NAME "usb-ccid"
+#define TYPE_USB_CCID_DEV "usb-ccid"
 typedef struct USBCCIDState USBCCIDState;
 DECLARE_INSTANCE_CHECKER(USBCCIDState, USB_CCID_DEV,
- CCID_DEV_NAME)
+ TYPE_USB_CCID_DEV)
 /*
  * The two options for variable sized buffers:
  * make them constant size, for large enough constant,
@@ -1462,7 +1462,7 @@ static void ccid_class_initfn(ObjectClass *klass, void 
*data)
 }
 
 static const TypeInfo ccid_info = {
-.name  = CCID_DEV_NAME,
+.name  = TYPE_USB_CCID_DEV,
 .parent= TYPE_USB_DEVICE,
 .instance_size = sizeof(USBCCIDState),
 .class_init= ccid_class_initfn,
@@ -1495,7 +1495,7 @@ static void ccid_register_types(void)
 type_register_static(_bus_info);
 type_register_static(_card_type_info);
 type_register_static(_info);
-usb_legacy_register(CCID_DEV_NAME, "ccid", NULL);
+usb_legacy_register(TYPE_USB_CCID_DEV, "ccid", NULL);
 }
 
 type_init(ccid_register_types)
-- 
2.26.2




[PULL 15/34] chardev: Rename TYPE_CHARDEV_* to TYPE_*_CHARDEV

2020-09-08 Thread Eduardo Habkost
This will make the TYPE_* constants consistent with the name of
most type checking macros we have today.

Signed-off-by: Eduardo Habkost 
Reviewed-by: Philippe Mathieu-Daudé 
Message-Id: <20200902224311.1321159-3-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 chardev/chardev-internal.h   |  4 ++--
 include/chardev/char-fd.h|  4 ++--
 include/chardev/char-win-stdio.h |  2 +-
 include/chardev/char-win.h   |  4 ++--
 include/chardev/char.h   | 30 +++---
 include/chardev/spice.h  |  8 
 chardev/baum.c   |  6 +++---
 chardev/char-console.c   |  4 ++--
 chardev/char-fd.c|  2 +-
 chardev/char-file.c  |  6 +++---
 chardev/char-mux.c   |  2 +-
 chardev/char-null.c  |  2 +-
 chardev/char-parallel.c  |  4 ++--
 chardev/char-pipe.c  |  6 +++---
 chardev/char-pty.c   |  4 ++--
 chardev/char-ringbuf.c   |  8 
 chardev/char-serial.c|  6 +++---
 chardev/char-socket.c|  4 ++--
 chardev/char-stdio.c |  6 +++---
 chardev/char-udp.c   |  4 ++--
 chardev/char-win-stdio.c |  4 ++--
 chardev/char-win.c   |  2 +-
 chardev/char.c   |  2 +-
 chardev/msmouse.c|  6 +++---
 chardev/spice.c  | 10 +-
 chardev/testdev.c|  6 +++---
 chardev/wctablet.c   |  6 +++---
 gdbstub.c|  6 +++---
 hw/display/vhost-user-gpu.c  |  2 +-
 tests/test-char.c|  4 ++--
 ui/console.c |  8 
 ui/gtk.c |  6 +++---
 ui/spice-app.c   | 10 +-
 33 files changed, 94 insertions(+), 94 deletions(-)

diff --git a/chardev/chardev-internal.h b/chardev/chardev-internal.h
index aba0240759..832dc10a95 100644
--- a/chardev/chardev-internal.h
+++ b/chardev/chardev-internal.h
@@ -55,9 +55,9 @@ struct MuxChardev {
 typedef struct MuxChardev MuxChardev;
 
 DECLARE_INSTANCE_CHECKER(MuxChardev, MUX_CHARDEV,
- TYPE_CHARDEV_MUX)
+ TYPE_MUX_CHARDEV)
 #define CHARDEV_IS_MUX(chr) \
-object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX)
+object_dynamic_cast(OBJECT(chr), TYPE_MUX_CHARDEV)
 
 void mux_set_focus(Chardev *chr, int focus);
 void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event);
diff --git a/include/chardev/char-fd.h b/include/chardev/char-fd.h
index 9de0e440de..14c664fc83 100644
--- a/include/chardev/char-fd.h
+++ b/include/chardev/char-fd.h
@@ -36,10 +36,10 @@ struct FDChardev {
 };
 typedef struct FDChardev FDChardev;
 
-#define TYPE_CHARDEV_FD "chardev-fd"
+#define TYPE_FD_CHARDEV "chardev-fd"
 
 DECLARE_INSTANCE_CHECKER(FDChardev, FD_CHARDEV,
- TYPE_CHARDEV_FD)
+ TYPE_FD_CHARDEV)
 
 void qemu_chr_open_fd(Chardev *chr, int fd_in, int fd_out);
 int qmp_chardev_open_file_source(char *src, int flags, Error **errp);
diff --git a/include/chardev/char-win-stdio.h b/include/chardev/char-win-stdio.h
index d7314f734d..139dfbe92f 100644
--- a/include/chardev/char-win-stdio.h
+++ b/include/chardev/char-win-stdio.h
@@ -24,6 +24,6 @@
 #ifndef CHAR_WIN_STDIO_H
 #define CHAR_WIN_STDIO_H
 
-#define TYPE_CHARDEV_WIN_STDIO "chardev-win-stdio"
+#define TYPE_WIN_STDIO_CHARDEV "chardev-win-stdio"
 
 #endif /* CHAR_WIN_STDIO_H */
diff --git a/include/chardev/char-win.h b/include/chardev/char-win.h
index 485521469c..a1745ba267 100644
--- a/include/chardev/char-win.h
+++ b/include/chardev/char-win.h
@@ -43,9 +43,9 @@ typedef struct WinChardev WinChardev;
 #define NSENDBUF 2048
 #define NRECVBUF 2048
 
-#define TYPE_CHARDEV_WIN "chardev-win"
+#define TYPE_WIN_CHARDEV "chardev-win"
 DECLARE_INSTANCE_CHECKER(WinChardev, WIN_CHARDEV,
- TYPE_CHARDEV_WIN)
+ TYPE_WIN_CHARDEV)
 
 void win_chr_set_file(Chardev *chr, HANDLE file, bool keep_open);
 int win_chr_serial_init(Chardev *chr, const char *filename, Error **errp);
diff --git a/include/chardev/char.h b/include/chardev/char.h
index 5874de57ea..0f358a4eee 100644
--- a/include/chardev/char.h
+++ b/include/chardev/char.h
@@ -230,24 +230,24 @@ typedef struct ChardevClass ChardevClass;
 DECLARE_OBJ_CHECKERS(Chardev, ChardevClass,
  CHARDEV, TYPE_CHARDEV)
 
-#define TYPE_CHARDEV_NULL "chardev-null"
-#define TYPE_CHARDEV_MUX "chardev-mux"
-#define TYPE_CHARDEV_RINGBUF "chardev-ringbuf"
-#define TYPE_CHARDEV_PTY "chardev-pty"
-#define TYPE_CHARDEV_CONSOLE "chardev-console"
-#define TYPE_CHARDEV_STDIO "chardev-stdio"
-#define TYPE_CHARDEV_PIPE "chardev-pipe"
-#define TYPE_CHARDEV_MEMORY "chardev-memory"
-#define TYPE_CHARDEV_PARALLEL "chardev-parallel"
-#define TYPE_CHARDEV_FILE "chardev-file"
-#define TYPE_CHARDEV_SERIAL "chardev-serial"
-#define TYPE_CHARDEV_SOCKET "chardev-socket"
-#define 

[PULL 00/34] QOM boilerplate cleanup (v3)

2020-09-08 Thread Eduardo Habkost
Changes v2 -> v3:
* Fix build errors: dropped all changes in
  include/hw/riscv/sifive* and include/accel/accel.h

The following changes since commit 6779038537360e957dbded830f76b08ef5070161:

  Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2020-09-08' int=
o staging (2020-09-08 17:23:31 +0100)

are available in the Git repository at:

  git://github.com/ehabkost/qemu.git tags/machine-next-pull-request

for you to fetch changes up to 7661577c45301bf37a56988eeb084e01bd119de7:

  virtio-vga: Use typedef name for instance_size (2020-09-08 17:32:01 -0400)


QOM boilerplate cleanup

Documentation build fix:
* memory: Remove kernel-doc comment marker (Eduardo Habkost)

QOM cleanups:
* Rename QOM macros for consistency between
  TYPE_* and type checking constants (Eduardo Habkost)

QOM new macros:
* OBJECT_DECLARE_* and OBJECT_DEFINE_* macros (Daniel P. Berrang=C3=A9)
* DECLARE_*_CHECKER macros (Eduardo Habkost)

Automated QOM boilerplate changes:
* Automated changes to use DECLARE_*_CHECKER (Eduardo Habkost
* Automated changes to use OBJECT_DECLARE* (Eduardo Habkost)



Daniel P. Berrang=C3=A9 (2):
  qom: make object_ref/unref use a void * instead of Object *.
  qom: provide convenient macros for declaring and defining types

Eduardo Habkost (32):
  memory: Remove kernel-doc comment marker
  qom: Allow class type name to be specified in OBJECT_DECLARE*
  qom: DECLARE_*_CHECKERS macros
  qom: Make type checker functions accept const pointers
  codeconverter: script for automating QOM code cleanups
  Delete duplicate QOM typedefs
  Move QOM typedefs and add missing includes
  Use DECLARE_*CHECKER* macros
  Use DECLARE_*CHECKER* when possible (--force mode)
  Use OBJECT_DECLARE_TYPE where possible
  Use OBJECT_DECLARE_SIMPLE_TYPE when possible
  gpex: Fix type checking function name
  chardev: Rename TYPE_CHARDEV_* to TYPE_*_CHARDEV
  ap-device: Rename AP_DEVICE_TYPE to TYPE_AP_DEVICE
  dev-smartcard-reader: Rename CCID_DEV_NAME to TYPE_USB_CCID_DEV
  vfio: Rename VFIO_AP_DEVICE_TYPE to TYPE_VFIO_AP_DEVICE
  vmgenid: Rename VMGENID_DEVICE to TYPE_VMGENID
  ahci: Rename ICH_AHCI to ICH9_AHCI
  esp: Rename ESP_STATE to ESP
  filter-rewriter: Rename FILTER_COLO_REWRITER to FILTER_REWRITER
  rs6000_mc: Rename RS6000MC_DEVICE to RS6000MC
  sabre: Rename SABRE_DEVICE to SABRE
  usb: Rename USB_SERIAL_DEV to USB_SERIAL
  vfio: Rename PCI_VFIO to VFIO_PCI
  pc87312: Rename TYPE_PC87312_SUPERIO to TYPE_PC87312
  tusb6010: Rename TUSB to TUSB6010
  xilinx_axidma: Use typedef name for instance_size
  omap_intc: Use typedef name for instance_size
  lpc_ich9: Use typedef name for instance_size
  xilinx_axienet: Use typedef name for instance_size
  vhost-user-vga: Use typedef name for instance_size
  virtio-vga: Use typedef name for instance_size

 .../codeconverter/codeconverter/__init__.py   |   0
 .../codeconverter/codeconverter/patching.py   | 397 +++
 .../codeconverter/codeconverter/qom_macros.py | 652 ++
 .../codeconverter/qom_type_info.py| 434 
 .../codeconverter/codeconverter/regexps.py| 118 
 .../codeconverter/test_patching.py| 105 +++
 .../codeconverter/test_regexps.py | 282 
 scripts/codeconverter/codeconverter/utils.py  |  72 ++
 scripts/codeconverter/converter.py| 123 
 chardev/chardev-internal.h|  10 +-
 hw/9pfs/virtio-9p.h   |  11 +-
 hw/audio/intel-hda.h  |  20 +-
 hw/avr/atmega.h   |   9 +-
 hw/display/ati_int.h  |   9 +-
 hw/display/qxl.h  |   9 +-
 hw/display/virtio-vga.h   |  17 +-
 hw/i386/amd_iommu.h   |  10 +-
 hw/misc/tmp105.h  |   9 +-
 hw/net/fsl_etsec/etsec.h  |  10 +-
 hw/net/rocker/rocker.h|   5 +-
 hw/net/tulip.h|   4 +-
 hw/net/vmxnet3_defs.h |   9 +-
 hw/ppc/e500-ccsr.h|   9 +-
 hw/ppc/e500.h |  19 +-
 hw/ppc/mac.h  |  19 +-
 hw/rdma/vmw/pvrdma.h  |   9 +-
 hw/s390x/ccw-device.h |  17 +-
 hw/s390x/ipl.h|   6 +-
 hw/s390x/s390-pci-bus.h   |  34 +-
 hw/s390x/virtio-ccw.h | 141 ++--
 hw/scsi/mptsas.h  |   5 +-
 hw/usb/ccid.h |  14 +-
 hw/usb/hcd-dwc2.h |   9 +-
 hw/usb/hcd-ehci.h |  36 +-
 hw/usb/hcd-ohci.h |   9 +-
 hw/usb/hcd-xhci.h |   7 +-
 hw/vfio/pci.h   

[PULL 11/34] Use DECLARE_*CHECKER* when possible (--force mode)

2020-09-08 Thread Eduardo Habkost
Separate run of the TypeCheckMacro converter using the --force
flag, for the cases where typedefs weren't found in the same
header nor in typedefs.h.

Generated initially using:

 $ ./scripts/codeconverter/converter.py --force -i \
   --pattern=TypeCheckMacro $(git grep -l '' -- '*.[ch]')

Then each case was manually reviewed, and a comment was added
indicating what's unusual about those type checking
macros/functions.  Despite not following the usual pattern, the
changes in this patch were found to be safe.

Reviewed-by: Daniel P. Berrangé 
Signed-off-by: Eduardo Habkost 
Message-Id: <20200831210740.126168-15-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 include/hw/intc/arm_gic.h   | 9 +++--
 include/hw/intc/arm_gicv3.h | 8 +++-
 include/hw/ppc/xics_spapr.h | 4 +++-
 include/hw/virtio/virtio-mmio.h | 9 +++--
 hw/intc/apic.c  | 5 +++--
 hw/intc/arm_gic_kvm.c   | 9 +++--
 hw/intc/arm_gicv3_its_kvm.c | 8 +++-
 hw/intc/arm_gicv3_kvm.c | 9 +++--
 hw/sd/allwinner-sdhost.c| 5 +++--
 hw/sd/bcm2835_sdhost.c  | 5 +++--
 hw/sd/pxa2xx_mmci.c | 4 +++-
 hw/sd/sdhci.c   | 4 +++-
 12 files changed, 36 insertions(+), 43 deletions(-)

diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h
index 704ef2b751..116ccbb5a9 100644
--- a/include/hw/intc/arm_gic.h
+++ b/include/hw/intc/arm_gic.h
@@ -74,12 +74,9 @@
 
 #define TYPE_ARM_GIC "arm_gic"
 typedef struct ARMGICClass ARMGICClass;
-#define ARM_GIC(obj) \
- OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC)
-#define ARM_GIC_CLASS(klass) \
- OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC)
-#define ARM_GIC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC)
+/* This is reusing the GICState typedef from TYPE_ARM_GIC_COMMON */
+DECLARE_OBJ_CHECKERS(GICState, ARMGICClass,
+ ARM_GIC, TYPE_ARM_GIC)
 
 struct ARMGICClass {
 /*< private >*/
diff --git a/include/hw/intc/arm_gicv3.h b/include/hw/intc/arm_gicv3.h
index 58e9131a33..a81a6ae7ec 100644
--- a/include/hw/intc/arm_gicv3.h
+++ b/include/hw/intc/arm_gicv3.h
@@ -17,11 +17,9 @@
 
 #define TYPE_ARM_GICV3 "arm-gicv3"
 typedef struct ARMGICv3Class ARMGICv3Class;
-#define ARM_GICV3(obj) OBJECT_CHECK(GICv3State, (obj), TYPE_ARM_GICV3)
-#define ARM_GICV3_CLASS(klass) \
- OBJECT_CLASS_CHECK(ARMGICv3Class, (klass), TYPE_ARM_GICV3)
-#define ARM_GICV3_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ARMGICv3Class, (obj), TYPE_ARM_GICV3)
+/* This is reusing the GICState typedef from TYPE_ARM_GICV3_COMMON */
+DECLARE_OBJ_CHECKERS(GICv3State, ARMGICv3Class,
+ ARM_GICV3, TYPE_ARM_GICV3)
 
 struct ARMGICv3Class {
 /*< private >*/
diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h
index 09e428de4e..0b8182e40b 100644
--- a/include/hw/ppc/xics_spapr.h
+++ b/include/hw/ppc/xics_spapr.h
@@ -31,7 +31,9 @@
 #include "qom/object.h"
 
 #define TYPE_ICS_SPAPR "ics-spapr"
-#define ICS_SPAPR(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_SPAPR)
+/* This is reusing the ICSState typedef from TYPE_ICS */
+DECLARE_INSTANCE_CHECKER(ICSState, ICS_SPAPR,
+ TYPE_ICS_SPAPR)
 
 int xics_kvm_connect(SpaprInterruptController *intc, uint32_t nr_servers,
  Error **errp);
diff --git a/include/hw/virtio/virtio-mmio.h b/include/hw/virtio/virtio-mmio.h
index dca651fd14..6a1c2c20d4 100644
--- a/include/hw/virtio/virtio-mmio.h
+++ b/include/hw/virtio/virtio-mmio.h
@@ -28,12 +28,9 @@
 /* QOM macros */
 /* virtio-mmio-bus */
 #define TYPE_VIRTIO_MMIO_BUS "virtio-mmio-bus"
-#define VIRTIO_MMIO_BUS(obj) \
-OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_MMIO_BUS)
-#define VIRTIO_MMIO_BUS_GET_CLASS(obj) \
-OBJECT_GET_CLASS(VirtioBusClass, (obj), TYPE_VIRTIO_MMIO_BUS)
-#define VIRTIO_MMIO_BUS_CLASS(klass) \
-OBJECT_CLASS_CHECK(VirtioBusClass, (klass), TYPE_VIRTIO_MMIO_BUS)
+/* This is reusing the VirtioBusState typedef from TYPE_VIRTIO_BUS */
+DECLARE_OBJ_CHECKERS(VirtioBusState, VirtioBusClass,
+ VIRTIO_MMIO_BUS, TYPE_VIRTIO_MMIO_BUS)
 
 /* virtio-mmio */
 #define TYPE_VIRTIO_MMIO "virtio-mmio"
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index e055bb3af2..b6a05e5439 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -40,8 +40,9 @@
 static APICCommonState *local_apics[MAX_APICS + 1];
 
 #define TYPE_APIC "apic"
-#define APIC(obj) \
-OBJECT_CHECK(APICCommonState, (obj), TYPE_APIC)
+/*This is reusing the APICCommonState typedef from APIC_COMMON */
+DECLARE_INSTANCE_CHECKER(APICCommonState, APIC,
+ TYPE_APIC)
 
 static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode);
 static void apic_update_irq(APICCommonState *s);
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index 6e5a2b8fe0..9494185cf4 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -33,12 +33,9 @@
 
 #define TYPE_KVM_ARM_GIC 

[PULL 07/34] codeconverter: script for automating QOM code cleanups

2020-09-08 Thread Eduardo Habkost
This started as a simple script that scanned for regular
expressions, but became more and more complex when exceptions to
the rules were found.

I don't know if this should be maintained in the QEMU source tree
long term (maybe it can be reused for other code transformations
that Coccinelle can't handle).  In either case, this is included
as part of the patch series to document how exactly the automated
code transformations in the next patches were done.

Signed-off-by: Eduardo Habkost 
Message-Id: <20200831210740.126168-7-ehabk...@redhat.com>
Signed-off-by: Eduardo Habkost 
---
 .../codeconverter/codeconverter/__init__.py   |   0
 .../codeconverter/codeconverter/patching.py   | 397 +++
 .../codeconverter/codeconverter/qom_macros.py | 652 ++
 .../codeconverter/qom_type_info.py| 434 
 .../codeconverter/codeconverter/regexps.py| 118 
 .../codeconverter/test_patching.py| 105 +++
 .../codeconverter/test_regexps.py | 282 
 scripts/codeconverter/codeconverter/utils.py  |  72 ++
 scripts/codeconverter/converter.py| 123 
 MAINTAINERS   |   5 +
 10 files changed, 2188 insertions(+)
 create mode 100644 scripts/codeconverter/codeconverter/__init__.py
 create mode 100644 scripts/codeconverter/codeconverter/patching.py
 create mode 100644 scripts/codeconverter/codeconverter/qom_macros.py
 create mode 100644 scripts/codeconverter/codeconverter/qom_type_info.py
 create mode 100644 scripts/codeconverter/codeconverter/regexps.py
 create mode 100644 scripts/codeconverter/codeconverter/test_patching.py
 create mode 100644 scripts/codeconverter/codeconverter/test_regexps.py
 create mode 100644 scripts/codeconverter/codeconverter/utils.py
 create mode 100755 scripts/codeconverter/converter.py

diff --git a/scripts/codeconverter/codeconverter/__init__.py 
b/scripts/codeconverter/codeconverter/__init__.py
new file mode 100644
index 00..e69de29bb2
diff --git a/scripts/codeconverter/codeconverter/patching.py 
b/scripts/codeconverter/codeconverter/patching.py
new file mode 100644
index 00..627a1a1b04
--- /dev/null
+++ b/scripts/codeconverter/codeconverter/patching.py
@@ -0,0 +1,397 @@
+# Copyright (C) 2020 Red Hat Inc.
+#
+# Authors:
+#  Eduardo Habkost 
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+from typing import IO, Match, NamedTuple, Optional, Literal, Iterable, Type, 
Dict, List, Any, TypeVar, NewType, Tuple
+from pathlib import Path
+from itertools import chain
+from tempfile import NamedTemporaryFile
+import os
+import re
+import subprocess
+from io import StringIO
+
+import logging
+logger = logging.getLogger(__name__)
+DBG = logger.debug
+INFO = logger.info
+WARN = logger.warning
+ERROR = logger.error
+
+from .utils import *
+
+T = TypeVar('T')
+
+class Patch(NamedTuple):
+# start inside file.original_content
+start: int
+# end position inside file.original_content
+end: int
+# replacement string for file.original_content[start:end]
+replacement: str
+
+IdentifierType = Literal['type', 'symbol', 'include', 'constant']
+class RequiredIdentifier(NamedTuple):
+type: IdentifierType
+name: str
+
+class FileMatch:
+"""Base class for regex matches
+
+Subclasses just need to set the `regexp` class attribute
+"""
+regexp: Optional[str] = None
+
+def __init__(self, f: 'FileInfo', m: Match) -> None:
+self.file: 'FileInfo' = f
+self.match: Match = m
+
+@property
+def name(self) -> str:
+if 'name' not in self.match.groupdict():
+return '[no name]'
+return self.group('name')
+
+@classmethod
+def compiled_re(klass):
+return re.compile(klass.regexp, re.MULTILINE)
+
+def start(self) -> int:
+return self.match.start()
+
+def end(self) -> int:
+return self.match.end()
+
+def line_col(self) -> LineAndColumn:
+return self.file.line_col(self.start())
+
+def group(self, *args):
+return self.match.group(*args)
+
+def log(self, level, fmt, *args) -> None:
+pos = self.line_col()
+logger.log(level, '%s:%d:%d: '+fmt, self.file.filename, pos.line, 
pos.col, *args)
+
+def debug(self, fmt, *args) -> None:
+self.log(logging.DEBUG, fmt, *args)
+
+def info(self, fmt, *args) -> None:
+self.log(logging.INFO, fmt, *args)
+
+def warn(self, fmt, *args) -> None:
+self.log(logging.WARNING, fmt, *args)
+
+def error(self, fmt, *args) -> None:
+self.log(logging.ERROR, fmt, *args)
+
+def sub(self, original: str, replacement: str) -> str:
+"""Replace content
+
+XXX: this won't use the match position, but will just
+replace all strings that look like the original match.
+This should be enough for all the patterns used in this
+script.
+"""
+return 

  1   2   3   4   5   6   >