aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--accel/tcg/user-exec.c43
-rw-r--r--docs/devel/qom.rst91
-rw-r--r--hw/core/cpu.c1
-rw-r--r--hw/core/numa.c8
-rw-r--r--hw/core/qdev-prop-internal.h30
-rw-r--r--hw/core/qdev-properties-system.c687
-rw-r--r--hw/core/qdev-properties.c735
-rw-r--r--include/exec/memory.h6
-rw-r--r--include/hw/qdev-properties.h1
-rw-r--r--include/qom/object.h38
-rw-r--r--include/tcg/tcg-gvec-desc.h36
-rw-r--r--include/tcg/tcg.h22
-rw-r--r--qom/object.c3
-rwxr-xr-xscripts/kernel-doc16
-rw-r--r--tcg/aarch64/tcg-target.c.inc17
-rw-r--r--tcg/aarch64/tcg-target.h1
-rw-r--r--tcg/arm/tcg-target.c.inc29
-rw-r--r--tcg/i386/tcg-target.c.inc39
-rw-r--r--tcg/i386/tcg-target.h1
-rw-r--r--tcg/mips/tcg-target.c.inc21
-rw-r--r--tcg/optimize.c15
-rw-r--r--tcg/ppc/tcg-target.c.inc29
-rw-r--r--tcg/ppc/tcg-target.h1
-rw-r--r--tcg/riscv/tcg-target.c.inc16
-rw-r--r--tcg/s390/tcg-target.c.inc22
-rw-r--r--tcg/sparc/tcg-target.c.inc21
-rw-r--r--tcg/tcg-op-gvec.c35
-rw-r--r--tcg/tcg-op-vec.c12
-rw-r--r--tcg/tcg.c96
-rw-r--r--tcg/tci/tcg-target.c.inc3
30 files changed, 1074 insertions, 1001 deletions
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 5c96819ded..4ebe25461a 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -702,16 +702,51 @@ int cpu_signal_handler(int host_signum, void *pinfo,
#elif defined(__mips__)
+#if defined(__misp16) || defined(__mips_micromips)
+#error "Unsupported encoding"
+#endif
+
int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
ucontext_t *uc = puc;
- greg_t pc = uc->uc_mcontext.pc;
- int is_write;
+ uintptr_t pc = uc->uc_mcontext.pc;
+ uint32_t insn = *(uint32_t *)pc;
+ int is_write = 0;
+
+ /* Detect all store instructions at program counter. */
+ switch((insn >> 26) & 077) {
+ case 050: /* SB */
+ case 051: /* SH */
+ case 052: /* SWL */
+ case 053: /* SW */
+ case 054: /* SDL */
+ case 055: /* SDR */
+ case 056: /* SWR */
+ case 070: /* SC */
+ case 071: /* SWC1 */
+ case 074: /* SCD */
+ case 075: /* SDC1 */
+ case 077: /* SD */
+#if !defined(__mips_isa_rev) || __mips_isa_rev < 6
+ case 072: /* SWC2 */
+ case 076: /* SDC2 */
+#endif
+ is_write = 1;
+ break;
+ case 023: /* COP1X */
+ /* Required in all versions of MIPS64 since
+ MIPS64r1 and subsequent versions of MIPS32r2. */
+ switch (insn & 077) {
+ case 010: /* SWXC1 */
+ case 011: /* SDXC1 */
+ case 015: /* SUXC1 */
+ is_write = 1;
+ }
+ break;
+ }
- /* XXX: compute is_write */
- is_write = 0;
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
}
diff --git a/docs/devel/qom.rst b/docs/devel/qom.rst
index 0b943b2a1a..42d0dc4f4d 100644
--- a/docs/devel/qom.rst
+++ b/docs/devel/qom.rst
@@ -8,9 +8,9 @@ The QEMU Object Model provides a framework for registering user creatable
types and instantiating objects from those types. QOM provides the following
features:
- - System for dynamically registering types
- - Support for single-inheritance of types
- - Multiple inheritance of stateless interfaces
+- System for dynamically registering types
+- Support for single-inheritance of types
+- Multiple inheritance of stateless interfaces
.. code-block:: c
:caption: Creating a minimal type
@@ -174,17 +174,17 @@ dynamically cast it to an object that implements the interface.
Methods
=======
-A <emphasis>method</emphasis> is a function within the namespace scope of
+A *method* is a function within the namespace scope of
a class. It usually operates on the object instance by passing it as a
strongly-typed first argument.
If it does not operate on an object instance, it is dubbed
-<emphasis>class method</emphasis>.
+*class method*.
Methods cannot be overloaded. That is, the #ObjectClass and method name
uniquely identity the function to be called; the signature does not vary
except for trailing varargs.
-Methods are always <emphasis>virtual</emphasis>. Overriding a method in
+Methods are always *virtual*. Overriding a method in
#TypeInfo.class_init of a subclass leads to any user of the class obtained
via OBJECT_GET_CLASS() accessing the overridden function.
The original function is not automatically invoked. It is the responsibility
@@ -284,28 +284,29 @@ in the header file:
.. code-block:: c
:caption: Declaring a simple type
- OBJECT_DECLARE_SIMPLE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)
+ OBJECT_DECLARE_SIMPLE_TYPE(MyDevice, my_device,
+ MY_DEVICE, DEVICE)
This is equivalent to the following:
.. code-block:: c
:caption: Expansion from declaring a simple type
- typedef struct MyDevice MyDevice;
- typedef struct MyDeviceClass MyDeviceClass;
+ typedef struct MyDevice MyDevice;
+ typedef struct MyDeviceClass MyDeviceClass;
- G_DEFINE_AUTOPTR_CLEANUP_FUNC(MyDeviceClass, object_unref)
+ 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)
+ #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;
- };
+ struct MyDeviceClass {
+ DeviceClass parent_class;
+ };
The 'struct MyDevice' needs to be declared separately.
If the type requires virtual functions to be declared in the class
@@ -319,33 +320,33 @@ In the simple case the OBJECT_DEFINE_TYPE macro is suitable:
.. code-block:: c
:caption: Defining a simple type
- OBJECT_DEFINE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)
+ OBJECT_DEFINE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)
This is equivalent to the following:
.. code-block:: c
:caption: Expansion from defining a simple type
- 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(&my_device_info);
- }
- type_init(my_device_register_types);
+ 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(&my_device_info);
+ }
+ type_init(my_device_register_types);
This is sufficient to get the type registered with the type
system, and the three standard methods now need to be implemented
@@ -358,9 +359,10 @@ This accepts an array of interface type names.
.. code-block:: c
:caption: Defining a simple type implementing interfaces
- OBJECT_DEFINE_TYPE_WITH_INTERFACES(MyDevice, my_device,
- MY_DEVICE, DEVICE,
- { TYPE_USER_CREATABLE }, { NULL })
+ OBJECT_DEFINE_TYPE_WITH_INTERFACES(MyDevice, my_device,
+ MY_DEVICE, DEVICE,
+ { TYPE_USER_CREATABLE },
+ { NULL })
If the type is not intended to be instantiated, then then
the OBJECT_DEFINE_ABSTRACT_TYPE() macro can be used instead:
@@ -368,7 +370,8 @@ the OBJECT_DEFINE_ABSTRACT_TYPE() macro can be used instead:
.. code-block:: c
:caption: Defining a simple abstract type
- OBJECT_DEFINE_ABSTRACT_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)
+ OBJECT_DEFINE_ABSTRACT_TYPE(MyDevice, my_device,
+ MY_DEVICE, DEVICE)
diff --git a/hw/core/cpu.c b/hw/core/cpu.c
index 8654550d39..576fa1d7ba 100644
--- a/hw/core/cpu.c
+++ b/hw/core/cpu.c
@@ -26,6 +26,7 @@
#include "qemu/log.h"
#include "qemu/main-loop.h"
#include "exec/log.h"
+#include "exec/cpu-common.h"
#include "qemu/error-report.h"
#include "qemu/qemu-print.h"
#include "sysemu/tcg.h"
diff --git a/hw/core/numa.c b/hw/core/numa.c
index 7d5d413001..7c4dd4e68e 100644
--- a/hw/core/numa.c
+++ b/hw/core/numa.c
@@ -424,7 +424,13 @@ void parse_numa_hmat_cache(MachineState *ms, NumaHmatCacheOptions *node,
}
if ((node->level > 1) &&
- ms->numa_state->hmat_cache[node->node_id][node->level - 1] &&
+ ms->numa_state->hmat_cache[node->node_id][node->level - 1] == NULL) {
+ error_setg(errp, "Cache level=%u shall be defined first",
+ node->level - 1);
+ return;
+ }
+
+ if ((node->level > 1) &&
(node->size <=
ms->numa_state->hmat_cache[node->node_id][node->level - 1]->size)) {
error_setg(errp, "Invalid size=%" PRIu64 ", the size of level=%" PRIu8
diff --git a/hw/core/qdev-prop-internal.h b/hw/core/qdev-prop-internal.h
new file mode 100644
index 0000000000..9cf5cc1d51
--- /dev/null
+++ b/hw/core/qdev-prop-internal.h
@@ -0,0 +1,30 @@
+/*
+ * qdev property parsing
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_CORE_QDEV_PROP_INTERNAL_H
+#define HW_CORE_QDEV_PROP_INTERNAL_H
+
+void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp);
+void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp);
+
+void qdev_propinfo_set_default_value_enum(ObjectProperty *op,
+ const Property *prop);
+void qdev_propinfo_set_default_value_int(ObjectProperty *op,
+ const Property *prop);
+void qdev_propinfo_set_default_value_uint(ObjectProperty *op,
+ const Property *prop);
+
+void qdev_propinfo_get_uint16(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp);
+void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp);
+void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp);
+
+#endif
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index b29daf4fb5..49bdd12581 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -11,19 +11,25 @@
*/
#include "qemu/osdep.h"
-#include "audio/audio.h"
-#include "net/net.h"
#include "hw/qdev-properties.h"
#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "qapi/qapi-types-block.h"
+#include "qapi/qapi-types-machine.h"
+#include "qapi/qapi-types-migration.h"
#include "qapi/qmp/qerror.h"
+#include "qemu/ctype.h"
+#include "qemu/cutils.h"
+#include "qemu/units.h"
+#include "qemu/error-report.h"
+#include "qdev-prop-internal.h"
+
+#include "audio/audio.h"
+#include "chardev/char-fe.h"
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
-#include "hw/block/block.h"
-#include "net/hub.h"
-#include "qapi/visitor.h"
-#include "chardev/char-fe.h"
-#include "sysemu/iothread.h"
-#include "sysemu/tpm_backend.h"
+#include "net/net.h"
+#include "hw/pci/pci.h"
static bool check_prop_still_unset(DeviceState *dev, const char *name,
const void *old_val, const char *new_val,
@@ -280,6 +286,96 @@ const PropertyInfo qdev_prop_chr = {
.release = release_chr,
};
+/* --- mac address --- */
+
+/*
+ * accepted syntax versions:
+ * 01:02:03:04:05:06
+ * 01-02-03-04-05-06
+ */
+static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
+ Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ MACAddr *mac = qdev_get_prop_ptr(dev, prop);
+ char buffer[2 * 6 + 5 + 1];
+ char *p = buffer;
+
+ snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
+ mac->a[0], mac->a[1], mac->a[2],
+ mac->a[3], mac->a[4], mac->a[5]);
+
+ visit_type_str(v, name, &p, errp);
+}
+
+static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
+ Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ MACAddr *mac = qdev_get_prop_ptr(dev, prop);
+ int i, pos;
+ char *str;
+ const char *p;
+
+ if (dev->realized) {
+ qdev_prop_set_after_realize(dev, name, errp);
+ return;
+ }
+
+ if (!visit_type_str(v, name, &str, errp)) {
+ return;
+ }
+
+ for (i = 0, pos = 0; i < 6; i++, pos += 3) {
+ long val;
+
+ if (!qemu_isxdigit(str[pos])) {
+ goto inval;
+ }
+ if (!qemu_isxdigit(str[pos + 1])) {
+ goto inval;
+ }
+ if (i == 5) {
+ if (str[pos + 2] != '\0') {
+ goto inval;
+ }
+ } else {
+ if (str[pos + 2] != ':' && str[pos + 2] != '-') {
+ goto inval;
+ }
+ }
+ if (qemu_strtol(str + pos, &p, 16, &val) < 0 || val > 0xff) {
+ goto inval;
+ }
+ mac->a[i] = val;
+ }
+ g_free(str);
+ return;
+
+inval:
+ error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+ g_free(str);
+}
+
+const PropertyInfo qdev_prop_macaddr = {
+ .name = "str",
+ .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
+ .get = get_mac,
+ .set = set_mac,
+};
+
+void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
+ const uint8_t *value)
+{
+ char str[2 * 6 + 5 + 1];
+ snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
+ value[0], value[1], value[2], value[3], value[4], value[5]);
+
+ object_property_set_str(OBJECT(dev), name, str, &error_abort);
+}
+
/* --- netdev device --- */
static void get_netdev(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
@@ -465,3 +561,578 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
}
nd->instantiated = 1;
}
+
+/* --- lost tick policy --- */
+
+QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
+
+const PropertyInfo qdev_prop_losttickpolicy = {
+ .name = "LostTickPolicy",
+ .enum_table = &LostTickPolicy_lookup,
+ .get = qdev_propinfo_get_enum,
+ .set = qdev_propinfo_set_enum,
+ .set_default_value = qdev_propinfo_set_default_value_enum,
+};
+
+/* --- blocksize --- */
+
+/* lower limit is sector size */
+#define MIN_BLOCK_SIZE 512
+#define MIN_BLOCK_SIZE_STR "512 B"
+/*
+ * upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and
+ * matches qcow2 cluster size limit
+ */
+#define MAX_BLOCK_SIZE (2 * MiB)
+#define MAX_BLOCK_SIZE_STR "2 MiB"
+
+static void set_blocksize(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
+ uint64_t value;
+
+ if (dev->realized) {
+ qdev_prop_set_after_realize(dev, name, errp);
+ return;
+ }
+
+ if (!visit_type_size(v, name, &value, errp)) {
+ return;
+ }
+ /* value of 0 means "unset" */
+ if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) {
+ error_setg(errp,
+ "Property %s.%s doesn't take value %" PRIu64
+ " (minimum: " MIN_BLOCK_SIZE_STR
+ ", maximum: " MAX_BLOCK_SIZE_STR ")",
+ dev->id ? : "", name, value);
+ return;
+ }
+
+ /* We rely on power-of-2 blocksizes for bitmasks */
+ if ((value & (value - 1)) != 0) {
+ error_setg(errp,
+ "Property %s.%s doesn't take value '%" PRId64 "', "
+ "it's not a power of 2", dev->id ?: "", name, (int64_t)value);
+ return;
+ }
+
+ *ptr = value;
+}
+
+const PropertyInfo qdev_prop_blocksize = {
+ .name = "size",
+ .description = "A power of two between " MIN_BLOCK_SIZE_STR
+ " and " MAX_BLOCK_SIZE_STR,
+ .get = qdev_propinfo_get_size32,
+ .set = set_blocksize,
+ .set_default_value = qdev_propinfo_set_default_value_uint,
+};
+
+/* --- Block device error handling policy --- */
+
+QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));
+
+const PropertyInfo qdev_prop_blockdev_on_error = {
+ .name = "BlockdevOnError",
+ .description = "Error handling policy, "
+ "report/ignore/enospc/stop/auto",
+ .enum_table = &BlockdevOnError_lookup,
+ .get = qdev_propinfo_get_enum,
+ .set = qdev_propinfo_set_enum,
+ .set_default_value = qdev_propinfo_set_default_value_enum,
+};
+
+/* --- BIOS CHS translation */
+
+QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
+
+const PropertyInfo qdev_prop_bios_chs_trans = {
+ .name = "BiosAtaTranslation",
+ .description = "Logical CHS translation algorithm, "
+ "auto/none/lba/large/rechs",
+ .enum_table = &BiosAtaTranslation_lookup,
+ .get = qdev_propinfo_get_enum,
+ .set = qdev_propinfo_set_enum,
+ .set_default_value = qdev_propinfo_set_default_value_enum,
+};
+
+/* --- FDC default drive types */
+
+const PropertyInfo qdev_prop_fdc_drive_type = {
+ .name = "FdcDriveType",
+ .description = "FDC drive type, "
+ "144/288/120/none/auto",
+ .enum_table = &FloppyDriveType_lookup,
+ .get = qdev_propinfo_get_enum,
+ .set = qdev_propinfo_set_enum,
+ .set_default_value = qdev_propinfo_set_default_value_enum,
+};
+
+/* --- MultiFDCompression --- */
+
+const PropertyInfo qdev_prop_multifd_compression = {
+ .name = "MultiFDCompression",
+ .description = "multifd_compression values, "
+ "none/zlib/zstd",
+ .enum_table = &MultiFDCompression_lookup,
+ .get = qdev_propinfo_get_enum,
+ .set = qdev_propinfo_set_enum,
+ .set_default_value = qdev_propinfo_set_default_value_enum,
+};
+
+/* --- Reserved Region --- */
+
+/*
+ * Accepted syntax:
+ * <low address>:<high address>:<type>
+ * where low/high addresses are uint64_t in hexadecimal
+ * and type is a non-negative decimal integer
+ */
+static void get_reserved_region(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
+ char buffer[64];
+ char *p = buffer;
+ int rc;
+
+ rc = snprintf(buffer, sizeof(buffer), "0x%"PRIx64":0x%"PRIx64":%u",
+ rr->low, rr->high, rr->type);
+ assert(rc < sizeof(buffer));
+
+ visit_type_str(v, name, &p, errp);
+}
+
+static void set_reserved_region(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
+ Error *local_err = NULL;
+ const char *endptr;
+ char *str;
+ int ret;
+
+ if (dev->realized) {
+ qdev_prop_set_after_realize(dev, name, errp);
+ return;
+ }
+
+ visit_type_str(v, name, &str, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ ret = qemu_strtou64(str, &endptr, 16, &rr->low);
+ if (ret) {
+ error_setg(errp, "start address of '%s'"
+ " must be a hexadecimal integer", name);
+ goto out;
+ }
+ if (*endptr != ':') {
+ goto separator_error;
+ }
+
+ ret = qemu_strtou64(endptr + 1, &endptr, 16, &rr->high);
+ if (ret) {
+ error_setg(errp, "end address of '%s'"
+ " must be a hexadecimal integer", name);
+ goto out;
+ }
+ if (*endptr != ':') {
+ goto separator_error;
+ }
+
+ ret = qemu_strtoui(endptr + 1, &endptr, 10, &rr->type);
+ if (ret) {
+ error_setg(errp, "type of '%s'"
+ " must be a non-negative decimal integer", name);
+ }
+ goto out;
+
+separator_error:
+ error_setg(errp, "reserved region fields must be separated with ':'");
+out:
+ g_free(str);
+ return;
+}
+
+const PropertyInfo qdev_prop_reserved_region = {
+ .name = "reserved_region",
+ .description = "Reserved Region, example: 0xFEE00000:0xFEEFFFFF:0",
+ .get = get_reserved_region,
+ .set = set_reserved_region,
+};
+
+/* --- pci address --- */
+
+/*
+ * bus-local address, i.e. "$slot" or "$slot.$fn"
+ */
+static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
+ unsigned int slot, fn, n;
+ char *str;
+
+ if (dev->realized) {
+ qdev_prop_set_after_realize(dev, name, errp);
+ return;
+ }
+
+ if (!visit_type_str(v, name, &str, NULL)) {
+ if (!visit_type_int32(v, name, &value, errp)) {
+ return;
+ }
+ if (value < -1 || value > 255) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", "pci_devfn");
+ return;
+ }
+ *ptr = value;
+ return;
+ }
+
+ if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
+ fn = 0;
+ if (sscanf(str, "%x%n", &slot, &n) != 1) {
+ goto invalid;
+ }
+ }
+ if (str[n] != '\0' || fn > 7 || slot > 31) {
+ goto invalid;
+ }
+ *ptr = slot << 3 | fn;
+ g_free(str);
+ return;
+
+invalid:
+ error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+ g_free(str);
+}
+
+static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
+ size_t len)
+{
+ int32_t *ptr = qdev_get_prop_ptr(dev, prop);
+
+ if (*ptr == -1) {
+ return snprintf(dest, len, "<unset>");
+ } else {
+ return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
+ }
+}
+
+const PropertyInfo qdev_prop_pci_devfn = {
+ .name = "int32",
+ .description = "Slot and optional function number, example: 06.0 or 06",
+ .print = print_pci_devfn,
+ .get = qdev_propinfo_get_int32,
+ .set = set_pci_devfn,
+ .set_default_value = qdev_propinfo_set_default_value_int,
+};
+
+/* --- pci host address --- */
+
+static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+ char buffer[] = "ffff:ff:ff.f";
+ char *p = buffer;
+ int rc = 0;
+
+ /*
+ * Catch "invalid" device reference from vfio-pci and allow the
+ * default buffer representing the non-existent device to be used.
+ */
+ if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) {
+ rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d",
+ addr->domain, addr->bus, addr->slot, addr->function);
+ assert(rc == sizeof(buffer) - 1);
+ }
+
+ visit_type_str(v, name, &p, errp);
+}
+
+/*
+ * Parse [<domain>:]<bus>:<slot>.<func>
+ * if <domain> is not supplied, it's assumed to be 0.
+ */
+static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
+ char *str, *p;
+ const char *e;
+ unsigned long val;
+ unsigned long dom = 0, bus = 0;
+ unsigned int slot = 0, func = 0;
+
+ if (dev->realized) {
+ qdev_prop_set_after_realize(dev, name, errp);
+ return;
+ }
+
+ if (!visit_type_str(v, name, &str, errp)) {
+ return;
+ }
+
+ p = str;
+ if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0xffff || e == p) {
+ goto inval;
+ }
+ if (*e != ':') {
+ goto inval;
+ }
+ bus = val;
+
+ p = (char *)e + 1;
+ if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) {
+ goto inval;
+ }
+ if (*e == ':') {
+ dom = bus;
+ bus = val;
+ p = (char *)e + 1;
+ if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) {
+ goto inval;
+ }
+ }
+ slot = val;
+
+ if (*e != '.') {
+ goto inval;
+ }
+ p = (char *)e + 1;
+ if (qemu_strtoul(p, &e, 10, &val) < 0 || val > 7 || e == p) {
+ goto inval;
+ }
+ func = val;
+
+ if (bus > 0xff) {
+ goto inval;
+ }
+
+ if (*e) {
+ goto inval;
+ }
+
+ addr->domain = dom;
+ addr->bus = bus;
+ addr->slot = slot;
+ addr->function = func;
+
+ g_free(str);
+ return;
+
+inval:
+ error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
+ g_free(str);
+}
+
+const PropertyInfo qdev_prop_pci_host_devaddr = {
+ .name = "str",
+ .description = "Address (bus/device/function) of "
+ "the host device, example: 04:10.0",
+ .get = get_pci_host_devaddr,
+ .set = set_pci_host_devaddr,
+};
+
+/* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */
+
+const PropertyInfo qdev_prop_off_auto_pcibar = {
+ .name = "OffAutoPCIBAR",
+ .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5",
+ .enum_table = &OffAutoPCIBAR_lookup,
+ .get = qdev_propinfo_get_enum,
+ .set = qdev_propinfo_set_enum,
+ .set_default_value = qdev_propinfo_set_default_value_enum,
+};
+
+/* --- PCIELinkSpeed 2_5/5/8/16 -- */
+
+static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
+ int speed;
+
+ switch (*p) {
+ case QEMU_PCI_EXP_LNK_2_5GT:
+ speed = PCIE_LINK_SPEED_2_5;
+ break;
+ case QEMU_PCI_EXP_LNK_5GT:
+ speed = PCIE_LINK_SPEED_5;
+ break;
+ case QEMU_PCI_EXP_LNK_8GT:
+ speed = PCIE_LINK_SPEED_8;
+ break;
+ case QEMU_PCI_EXP_LNK_16GT:
+ speed = PCIE_LINK_SPEED_16;
+ break;
+ default:
+ /* Unreachable */
+ abort();
+ }
+
+ visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp);
+}
+
+static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
+ int speed;
+
+ if (dev->realized) {
+ qdev_prop_set_after_realize(dev, name, errp);
+ return;
+ }
+
+ if (!visit_type_enum(v, prop->name, &speed, prop->info->enum_table,
+ errp)) {
+ return;
+ }
+
+ switch (speed) {
+ case PCIE_LINK_SPEED_2_5:
+ *p = QEMU_PCI_EXP_LNK_2_5GT;
+ break;
+ case PCIE_LINK_SPEED_5:
+ *p = QEMU_PCI_EXP_LNK_5GT;
+ break;
+ case PCIE_LINK_SPEED_8:
+ *p = QEMU_PCI_EXP_LNK_8GT;
+ break;
+ case PCIE_LINK_SPEED_16:
+ *p = QEMU_PCI_EXP_LNK_16GT;
+ break;
+ default:
+ /* Unreachable */
+ abort();
+ }
+}
+
+const PropertyInfo qdev_prop_pcie_link_speed = {
+ .name = "PCIELinkSpeed",
+ .description = "2_5/5/8/16",
+ .enum_table = &PCIELinkSpeed_lookup,
+ .get = get_prop_pcielinkspeed,
+ .set = set_prop_pcielinkspeed,
+ .set_default_value = qdev_propinfo_set_default_value_enum,
+};
+
+/* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */
+
+static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
+ int width;
+
+ switch (*p) {
+ case QEMU_PCI_EXP_LNK_X1:
+ width = PCIE_LINK_WIDTH_1;
+ break;
+ case QEMU_PCI_EXP_LNK_X2:
+ width = PCIE_LINK_WIDTH_2;
+ break;
+ case QEMU_PCI_EXP_LNK_X4:
+ width = PCIE_LINK_WIDTH_4;
+ break;
+ case QEMU_PCI_EXP_LNK_X8:
+ width = PCIE_LINK_WIDTH_8;
+ break;
+ case QEMU_PCI_EXP_LNK_X12:
+ width = PCIE_LINK_WIDTH_12;
+ break;
+ case QEMU_PCI_EXP_LNK_X16:
+ width = PCIE_LINK_WIDTH_16;
+ break;
+ case QEMU_PCI_EXP_LNK_X32:
+ width = PCIE_LINK_WIDTH_32;
+ break;
+ default:
+ /* Unreachable */
+ abort();
+ }
+
+ visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp);
+}
+
+static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
+ int width;
+
+ if (dev->realized) {
+ qdev_prop_set_after_realize(dev, name, errp);
+ return;
+ }
+
+ if (!visit_type_enum(v, prop->name, &width, prop->info->enum_table,
+ errp)) {
+ return;
+ }
+
+ switch (width) {
+ case PCIE_LINK_WIDTH_1:
+ *p = QEMU_PCI_EXP_LNK_X1;
+ break;
+ case PCIE_LINK_WIDTH_2:
+ *p = QEMU_PCI_EXP_LNK_X2;
+ break;
+ case PCIE_LINK_WIDTH_4:
+ *p = QEMU_PCI_EXP_LNK_X4;
+ break;
+ case PCIE_LINK_WIDTH_8:
+ *p = QEMU_PCI_EXP_LNK_X8;
+ break;
+ case PCIE_LINK_WIDTH_12:
+ *p = QEMU_PCI_EXP_LNK_X12;
+ break;
+ case PCIE_LINK_WIDTH_16:
+ *p = QEMU_PCI_EXP_LNK_X16;
+ break;
+ case PCIE_LINK_WIDTH_32:
+ *p = QEMU_PCI_EXP_LNK_X32;
+ break;
+ default:
+ /* Unreachable */
+ abort();
+ }
+}
+
+const PropertyInfo qdev_prop_pcie_link_width = {
+ .name = "PCIELinkWidth",
+ .description = "1/2/4/8/12/16/32",
+ .enum_table = &PCIELinkWidth_lookup,
+ .get = get_prop_pcielinkwidth,
+ .set = set_prop_pcielinkwidth,
+ .set_default_value = qdev_propinfo_set_default_value_enum,
+};
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 343c824da0..509cbf155d 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -1,22 +1,15 @@
#include "qemu/osdep.h"
-#include "net/net.h"
#include "hw/qdev-properties.h"
#include "qapi/error.h"
-#include "hw/pci/pci.h"
-#include "qapi/qapi-types-block.h"
-#include "qapi/qapi-types-machine.h"
#include "qapi/qapi-types-misc.h"
#include "qapi/qmp/qerror.h"
#include "qemu/ctype.h"
#include "qemu/error-report.h"
-#include "qapi/qapi-types-migration.h"
-#include "hw/block/block.h"
-#include "net/hub.h"
#include "qapi/visitor.h"
-#include "chardev/char.h"
#include "qemu/uuid.h"
#include "qemu/units.h"
#include "qemu/cutils.h"
+#include "qdev-prop-internal.h"
void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
Error **errp)
@@ -52,8 +45,8 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
return ptr;
}
-static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque,
- Error **errp)
+void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
@@ -62,8 +55,8 @@ static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque,
visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
}
-static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque,
- Error **errp)
+void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
@@ -77,12 +70,20 @@ static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque,
visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
}
-static void set_default_value_enum(ObjectProperty *op, const Property *prop)
+void qdev_propinfo_set_default_value_enum(ObjectProperty *op,
+ const Property *prop)
{
object_property_set_default_str(op,
qapi_enum_lookup(prop->info->enum_table, prop->defval.i));
}
+const PropertyInfo qdev_prop_enum = {
+ .name = "enum",
+ .get = qdev_propinfo_get_enum,
+ .set = qdev_propinfo_set_enum,
+ .set_default_value = qdev_propinfo_set_default_value_enum,
+};
+
/* Bit */
static uint32_t qdev_get_prop_mask(Property *prop)
@@ -261,12 +262,14 @@ static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
visit_type_uint8(v, name, ptr, errp);
}
-static void set_default_value_int(ObjectProperty *op, const Property *prop)
+void qdev_propinfo_set_default_value_int(ObjectProperty *op,
+ const Property *prop)
{
object_property_set_default_int(op, prop->defval.i);
}
-static void set_default_value_uint(ObjectProperty *op, const Property *prop)
+void qdev_propinfo_set_default_value_uint(ObjectProperty *op,
+ const Property *prop)
{
object_property_set_default_uint(op, prop->defval.u);
}
@@ -275,13 +278,13 @@ const PropertyInfo qdev_prop_uint8 = {
.name = "uint8",
.get = get_uint8,
.set = set_uint8,
- .set_default_value = set_default_value_uint,
+ .set_default_value = qdev_propinfo_set_default_value_uint,
};
/* --- 16bit integer --- */
-static void get_uint16(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
+void qdev_propinfo_get_uint16(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
@@ -307,9 +310,9 @@ static void set_uint16(Object *obj, Visitor *v, const char *name,
const PropertyInfo qdev_prop_uint16 = {
.name = "uint16",
- .get = get_uint16,
+ .get = qdev_propinfo_get_uint16,
.set = set_uint16,
- .set_default_value = set_default_value_uint,
+ .set_default_value = qdev_propinfo_set_default_value_uint,
};
/* --- 32bit integer --- */
@@ -339,8 +342,8 @@ static void set_uint32(Object *obj, Visitor *v, const char *name,
visit_type_uint32(v, name, ptr, errp);
}
-static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque,
- Error **errp)
+void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
@@ -368,14 +371,14 @@ const PropertyInfo qdev_prop_uint32 = {
.name = "uint32",
.get = get_uint32,
.set = set_uint32,
- .set_default_value = set_default_value_uint,
+ .set_default_value = qdev_propinfo_set_default_value_uint,
};
const PropertyInfo qdev_prop_int32 = {
.name = "int32",
- .get = get_int32,
+ .get = qdev_propinfo_get_int32,
.set = set_int32,
- .set_default_value = set_default_value_int,
+ .set_default_value = qdev_propinfo_set_default_value_int,
};
/* --- 64bit integer --- */
@@ -434,14 +437,14 @@ const PropertyInfo qdev_prop_uint64 = {
.name = "uint64",
.get = get_uint64,
.set = set_uint64,
- .set_default_value = set_default_value_uint,
+ .set_default_value = qdev_propinfo_set_default_value_uint,
};
const PropertyInfo qdev_prop_int64 = {
.name = "int64",
.get = get_int64,
.set = set_int64,
- .set_default_value = set_default_value_int,
+ .set_default_value = qdev_propinfo_set_default_value_int,
};
/* --- string --- */
@@ -494,318 +497,21 @@ const PropertyInfo qdev_prop_string = {
.set = set_string,
};
-/* --- mac address --- */
-
-/*
- * accepted syntax versions:
- * 01:02:03:04:05:06
- * 01-02-03-04-05-06
- */
-static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
- Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- MACAddr *mac = qdev_get_prop_ptr(dev, prop);
- char buffer[2 * 6 + 5 + 1];
- char *p = buffer;
-
- snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
- mac->a[0], mac->a[1], mac->a[2],
- mac->a[3], mac->a[4], mac->a[5]);
-
- visit_type_str(v, name, &p, errp);
-}
-
-static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
- Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- MACAddr *mac = qdev_get_prop_ptr(dev, prop);
- int i, pos;
- char *str, *p;
-
- if (dev->realized) {
- qdev_prop_set_after_realize(dev, name, errp);
- return;
- }
-
- if (!visit_type_str(v, name, &str, errp)) {
- return;
- }
-
- for (i = 0, pos = 0; i < 6; i++, pos += 3) {
- if (!qemu_isxdigit(str[pos])) {
- goto inval;
- }
- if (!qemu_isxdigit(str[pos+1])) {
- goto inval;
- }
- if (i == 5) {
- if (str[pos+2] != '\0') {
- goto inval;
- }
- } else {
- if (str[pos+2] != ':' && str[pos+2] != '-') {
- goto inval;
- }
- }
- mac->a[i] = strtol(str+pos, &p, 16);
- }
- g_free(str);
- return;
-
-inval:
- error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
- g_free(str);
-}
-
-const PropertyInfo qdev_prop_macaddr = {
- .name = "str",
- .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
- .get = get_mac,
- .set = set_mac,
-};
-
-/* --- Reserved Region --- */
-
-/*
- * Accepted syntax:
- * <low address>:<high address>:<type>
- * where low/high addresses are uint64_t in hexadecimal
- * and type is a non-negative decimal integer
- */
-static void get_reserved_region(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
- char buffer[64];
- char *p = buffer;
- int rc;
-
- rc = snprintf(buffer, sizeof(buffer), "0x%"PRIx64":0x%"PRIx64":%u",
- rr->low, rr->high, rr->type);
- assert(rc < sizeof(buffer));
-
- visit_type_str(v, name, &p, errp);
-}
-
-static void set_reserved_region(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
- Error *local_err = NULL;
- const char *endptr;
- char *str;
- int ret;
-
- if (dev->realized) {
- qdev_prop_set_after_realize(dev, name, errp);
- return;
- }
-
- visit_type_str(v, name, &str, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- ret = qemu_strtou64(str, &endptr, 16, &rr->low);
- if (ret) {
- error_setg(errp, "start address of '%s'"
- " must be a hexadecimal integer", name);
- goto out;
- }
- if (*endptr != ':') {
- goto separator_error;
- }
-
- ret = qemu_strtou64(endptr + 1, &endptr, 16, &rr->high);
- if (ret) {
- error_setg(errp, "end address of '%s'"
- " must be a hexadecimal integer", name);
- goto out;
- }
- if (*endptr != ':') {
- goto separator_error;
- }
-
- ret = qemu_strtoui(endptr + 1, &endptr, 10, &rr->type);
- if (ret) {
- error_setg(errp, "type of '%s'"
- " must be a non-negative decimal integer", name);
- }
- goto out;
-
-separator_error:
- error_setg(errp, "reserved region fields must be separated with ':'");
-out:
- g_free(str);
- return;
-}
-
-const PropertyInfo qdev_prop_reserved_region = {
- .name = "reserved_region",
- .description = "Reserved Region, example: 0xFEE00000:0xFEEFFFFF:0",
- .get = get_reserved_region,
- .set = set_reserved_region,
-};
-
/* --- on/off/auto --- */
const PropertyInfo qdev_prop_on_off_auto = {
.name = "OnOffAuto",
.description = "on/off/auto",
.enum_table = &OnOffAuto_lookup,
- .get = get_enum,
- .set = set_enum,
- .set_default_value = set_default_value_enum,
-};
-
-/* --- lost tick policy --- */
-
-QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
-
-const PropertyInfo qdev_prop_losttickpolicy = {
- .name = "LostTickPolicy",
- .enum_table = &LostTickPolicy_lookup,
- .get = get_enum,
- .set = set_enum,
- .set_default_value = set_default_value_enum,
-};
-
-/* --- Block device error handling policy --- */
-
-QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));
-
-const PropertyInfo qdev_prop_blockdev_on_error = {
- .name = "BlockdevOnError",
- .description = "Error handling policy, "
- "report/ignore/enospc/stop/auto",
- .enum_table = &BlockdevOnError_lookup,
- .get = get_enum,
- .set = set_enum,
- .set_default_value = set_default_value_enum,
-};
-
-/* --- BIOS CHS translation */
-
-QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
-
-const PropertyInfo qdev_prop_bios_chs_trans = {
- .name = "BiosAtaTranslation",
- .description = "Logical CHS translation algorithm, "
- "auto/none/lba/large/rechs",
- .enum_table = &BiosAtaTranslation_lookup,
- .get = get_enum,
- .set = set_enum,
- .set_default_value = set_default_value_enum,
-};
-
-/* --- FDC default drive types */
-
-const PropertyInfo qdev_prop_fdc_drive_type = {
- .name = "FdcDriveType",
- .description = "FDC drive type, "
- "144/288/120/none/auto",
- .enum_table = &FloppyDriveType_lookup,
- .get = get_enum,
- .set = set_enum,
- .set_default_value = set_default_value_enum,
-};
-
-/* --- MultiFDCompression --- */
-
-const PropertyInfo qdev_prop_multifd_compression = {
- .name = "MultiFDCompression",
- .description = "multifd_compression values, "
- "none/zlib/zstd",
- .enum_table = &MultiFDCompression_lookup,
- .get = get_enum,
- .set = set_enum,
- .set_default_value = set_default_value_enum,
-};
-
-/* --- pci address --- */
-
-/*
- * bus-local address, i.e. "$slot" or "$slot.$fn"
- */
-static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
- unsigned int slot, fn, n;
- char *str;
-
- if (dev->realized) {
- qdev_prop_set_after_realize(dev, name, errp);
- return;
- }
-
- if (!visit_type_str(v, name, &str, NULL)) {
- if (!visit_type_int32(v, name, &value, errp)) {
- return;
- }
- if (value < -1 || value > 255) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "pci_devfn");
- return;
- }
- *ptr = value;
- return;
- }
-
- if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
- fn = 0;
- if (sscanf(str, "%x%n", &slot, &n) != 1) {
- goto invalid;
- }
- }
- if (str[n] != '\0' || fn > 7 || slot > 31) {
- goto invalid;
- }
- *ptr = slot << 3 | fn;
- g_free(str);
- return;
-
-invalid:
- error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
- g_free(str);
-}
-
-static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
- size_t len)
-{
- int32_t *ptr = qdev_get_prop_ptr(dev, prop);
-
- if (*ptr == -1) {
- return snprintf(dest, len, "<unset>");
- } else {
- return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
- }
-}
-
-const PropertyInfo qdev_prop_pci_devfn = {
- .name = "int32",
- .description = "Slot and optional function number, example: 06.0 or 06",
- .print = print_pci_devfn,
- .get = get_int32,
- .set = set_pci_devfn,
- .set_default_value = set_default_value_int,
+ .get = qdev_propinfo_get_enum,
+ .set = qdev_propinfo_set_enum,
+ .set_default_value = qdev_propinfo_set_default_value_enum,
};
/* --- 32bit unsigned int 'size' type --- */
-static void get_size32(Object *obj, Visitor *v, const char *name, void *opaque,
- Error **errp)
+void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
@@ -845,179 +551,9 @@ static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,
const PropertyInfo qdev_prop_size32 = {
.name = "size",
- .get = get_size32,
+ .get = qdev_propinfo_get_size32,
.set = set_size32,
- .set_default_value = set_default_value_uint,
-};
-
-/* --- blocksize --- */
-
-/* lower limit is sector size */
-#define MIN_BLOCK_SIZE 512
-#define MIN_BLOCK_SIZE_STR "512 B"
-/*
- * upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and
- * matches qcow2 cluster size limit
- */
-#define MAX_BLOCK_SIZE (2 * MiB)
-#define MAX_BLOCK_SIZE_STR "2 MiB"
-
-static void set_blocksize(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
- uint64_t value;
-
- if (dev->realized) {
- qdev_prop_set_after_realize(dev, name, errp);
- return;
- }
-
- if (!visit_type_size(v, name, &value, errp)) {
- return;
- }
- /* value of 0 means "unset" */
- if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) {
- error_setg(errp,
- "Property %s.%s doesn't take value %" PRIu64
- " (minimum: " MIN_BLOCK_SIZE_STR
- ", maximum: " MAX_BLOCK_SIZE_STR ")",
- dev->id ? : "", name, value);
- return;
- }
-
- /* We rely on power-of-2 blocksizes for bitmasks */
- if ((value & (value - 1)) != 0) {
- error_setg(errp,
- "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
- dev->id ?: "", name, (int64_t)value);
- return;
- }
-
- *ptr = value;
-}
-
-const PropertyInfo qdev_prop_blocksize = {
- .name = "size",
- .description = "A power of two between " MIN_BLOCK_SIZE_STR
- " and " MAX_BLOCK_SIZE_STR,
- .get = get_size32,
- .set = set_blocksize,
- .set_default_value = set_default_value_uint,
-};
-
-/* --- pci host address --- */
-
-static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
- char buffer[] = "ffff:ff:ff.f";
- char *p = buffer;
- int rc = 0;
-
- /*
- * Catch "invalid" device reference from vfio-pci and allow the
- * default buffer representing the non-existent device to be used.
- */
- if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) {
- rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d",
- addr->domain, addr->bus, addr->slot, addr->function);
- assert(rc == sizeof(buffer) - 1);
- }
-
- visit_type_str(v, name, &p, errp);
-}
-
-/*
- * Parse [<domain>:]<bus>:<slot>.<func>
- * if <domain> is not supplied, it's assumed to be 0.
- */
-static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
- char *str, *p;
- char *e;
- unsigned long val;
- unsigned long dom = 0, bus = 0;
- unsigned int slot = 0, func = 0;
-
- if (dev->realized) {
- qdev_prop_set_after_realize(dev, name, errp);
- return;
- }
-
- if (!visit_type_str(v, name, &str, errp)) {
- return;
- }
-
- p = str;
- val = strtoul(p, &e, 16);
- if (e == p || *e != ':') {
- goto inval;
- }
- bus = val;
-
- p = e + 1;
- val = strtoul(p, &e, 16);
- if (e == p) {
- goto inval;
- }
- if (*e == ':') {
- dom = bus;
- bus = val;
- p = e + 1;
- val = strtoul(p, &e, 16);
- if (e == p) {
- goto inval;
- }
- }
- slot = val;
-
- if (*e != '.') {
- goto inval;
- }
- p = e + 1;
- val = strtoul(p, &e, 10);
- if (e == p) {
- goto inval;
- }
- func = val;
-
- if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
- goto inval;
- }
-
- if (*e) {
- goto inval;
- }
-
- addr->domain = dom;
- addr->bus = bus;
- addr->slot = slot;
- addr->function = func;
-
- g_free(str);
- return;
-
-inval:
- error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
- g_free(str);
-}
-
-const PropertyInfo qdev_prop_pci_host_devaddr = {
- .name = "str",
- .description = "Address (bus/device/function) of "
- "the host device, example: 04:10.0",
- .get = get_pci_host_devaddr,
- .set = set_pci_host_devaddr,
+ .set_default_value = qdev_propinfo_set_default_value_uint,
};
/* --- UUID --- */
@@ -1175,7 +711,7 @@ const PropertyInfo qdev_prop_arraylen = {
.name = "uint32",
.get = get_uint32,
.set = set_prop_arraylen,
- .set_default_value = set_default_value_uint,
+ .set_default_value = qdev_propinfo_set_default_value_uint,
};
/* --- public helpers --- */
@@ -1269,16 +805,6 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
object_property_set_str(OBJECT(dev), name, value, &error_abort);
}
-void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
- const uint8_t *value)
-{
- char str[2 * 6 + 5 + 1];
- snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
- value[0], value[1], value[2], value[3], value[4], value[5]);
-
- object_property_set_str(OBJECT(dev), name, str, &error_abort);
-}
-
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
{
Property *prop;
@@ -1386,7 +912,7 @@ const PropertyInfo qdev_prop_size = {
.name = "size",
.get = get_size,
.set = set_size,
- .set_default_value = set_default_value_uint,
+ .set_default_value = qdev_propinfo_set_default_value_uint,
};
/* --- object link property --- */
@@ -1403,186 +929,3 @@ const PropertyInfo qdev_prop_link = {
.name = "link",
.create = create_link_property,
};
-
-/* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */
-
-const PropertyInfo qdev_prop_off_auto_pcibar = {
- .name = "OffAutoPCIBAR",
- .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5",
- .enum_table = &OffAutoPCIBAR_lookup,
- .get = get_enum,
- .set = set_enum,
- .set_default_value = set_default_value_enum,
-};
-
-/* --- PCIELinkSpeed 2_5/5/8/16 -- */
-
-static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
- int speed;
-
- switch (*p) {
- case QEMU_PCI_EXP_LNK_2_5GT:
- speed = PCIE_LINK_SPEED_2_5;
- break;
- case QEMU_PCI_EXP_LNK_5GT:
- speed = PCIE_LINK_SPEED_5;
- break;
- case QEMU_PCI_EXP_LNK_8GT:
- speed = PCIE_LINK_SPEED_8;
- break;
- case QEMU_PCI_EXP_LNK_16GT:
- speed = PCIE_LINK_SPEED_16;
- break;
- default:
- /* Unreachable */
- abort();
- }
-
- visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp);
-}
-
-static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
- int speed;
-
- if (dev->realized) {
- qdev_prop_set_after_realize(dev, name, errp);
- return;
- }
-
- if (!visit_type_enum(v, prop->name, &speed, prop->info->enum_table,
- errp)) {
- return;
- }
-
- switch (speed) {
- case PCIE_LINK_SPEED_2_5:
- *p = QEMU_PCI_EXP_LNK_2_5GT;
- break;
- case PCIE_LINK_SPEED_5:
- *p = QEMU_PCI_EXP_LNK_5GT;
- break;
- case PCIE_LINK_SPEED_8:
- *p = QEMU_PCI_EXP_LNK_8GT;
- break;
- case PCIE_LINK_SPEED_16:
- *p = QEMU_PCI_EXP_LNK_16GT;
- break;
- default:
- /* Unreachable */
- abort();
- }
-}
-
-const PropertyInfo qdev_prop_pcie_link_speed = {
- .name = "PCIELinkSpeed",
- .description = "2_5/5/8/16",
- .enum_table = &PCIELinkSpeed_lookup,
- .get = get_prop_pcielinkspeed,
- .set = set_prop_pcielinkspeed,
- .set_default_value = set_default_value_enum,
-};
-
-/* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */
-
-static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
- int width;
-
- switch (*p) {
- case QEMU_PCI_EXP_LNK_X1:
- width = PCIE_LINK_WIDTH_1;
- break;
- case QEMU_PCI_EXP_LNK_X2:
- width = PCIE_LINK_WIDTH_2;
- break;
- case QEMU_PCI_EXP_LNK_X4:
- width = PCIE_LINK_WIDTH_4;
- break;
- case QEMU_PCI_EXP_LNK_X8:
- width = PCIE_LINK_WIDTH_8;
- break;
- case QEMU_PCI_EXP_LNK_X12:
- width = PCIE_LINK_WIDTH_12;
- break;
- case QEMU_PCI_EXP_LNK_X16:
- width = PCIE_LINK_WIDTH_16;
- break;
- case QEMU_PCI_EXP_LNK_X32:
- width = PCIE_LINK_WIDTH_32;
- break;
- default:
- /* Unreachable */
- abort();
- }
-
- visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp);
-}
-
-static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- DeviceState *dev = DEVICE(obj);
- Property *prop = opaque;
- PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
- int width;
-
- if (dev->realized) {
- qdev_prop_set_after_realize(dev, name, errp);
- return;
- }
-
- if (!visit_type_enum(v, prop->name, &width, prop->info->enum_table,
- errp)) {
- return;
- }
-
- switch (width) {
- case PCIE_LINK_WIDTH_1:
- *p = QEMU_PCI_EXP_LNK_X1;
- break;
- case PCIE_LINK_WIDTH_2:
- *p = QEMU_PCI_EXP_LNK_X2;
- break;
- case PCIE_LINK_WIDTH_4:
- *p = QEMU_PCI_EXP_LNK_X4;
- break;
- case PCIE_LINK_WIDTH_8:
- *p = QEMU_PCI_EXP_LNK_X8;
- break;
- case PCIE_LINK_WIDTH_12:
- *p = QEMU_PCI_EXP_LNK_X12;
- break;
- case PCIE_LINK_WIDTH_16:
- *p = QEMU_PCI_EXP_LNK_X16;
- break;
- case PCIE_LINK_WIDTH_32:
- *p = QEMU_PCI_EXP_LNK_X32;
- break;
- default:
- /* Unreachable */
- abort();
- }
-}
-
-const PropertyInfo qdev_prop_pcie_link_width = {
- .name = "PCIELinkWidth",
- .description = "1/2/4/8/12/16/32",
- .enum_table = &PCIELinkWidth_lookup,
- .get = get_prop_pcielinkwidth,
- .set = set_prop_pcielinkwidth,
- .set_default_value = set_default_value_enum,
-};
diff --git a/include/exec/memory.h b/include/exec/memory.h
index dee0985162..622207bde1 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -443,7 +443,7 @@ struct IOMMUMemoryRegion {
QLIST_FOREACH((n), &(mr)->iommu_notify, node)
/**
- * MemoryListener: callbacks structure for updates to the physical memory map
+ * struct MemoryListener: callbacks structure for updates to the physical memory map
*
* Allows a component to adjust to changes in the guest-visible memory map.
* Use with memory_listener_register() and memory_listener_unregister().
@@ -681,7 +681,7 @@ struct MemoryListener {
};
/**
- * AddressSpace: describes a mapping of addresses to #MemoryRegion objects
+ * struct AddressSpace: describes a mapping of addresses to #MemoryRegion objects
*/
struct AddressSpace {
/* private: */
@@ -721,7 +721,7 @@ static inline FlatView *address_space_to_flatview(AddressSpace *as)
/**
- * MemoryRegionSection: describes a fragment of a #MemoryRegion
+ * struct MemoryRegionSection: describes a fragment of a #MemoryRegion
*
* @mr: the region, or %NULL if empty
* @fv: the flat view of the address space the region is mapped in
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 528310bb22..4437450065 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -8,6 +8,7 @@
extern const PropertyInfo qdev_prop_bit;
extern const PropertyInfo qdev_prop_bit64;
extern const PropertyInfo qdev_prop_bool;
+extern const PropertyInfo qdev_prop_enum;
extern const PropertyInfo qdev_prop_uint8;
extern const PropertyInfo qdev_prop_uint16;
extern const PropertyInfo qdev_prop_uint32;
diff --git a/include/qom/object.h b/include/qom/object.h
index 27aaa67e63..d378f13a11 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -31,7 +31,7 @@ typedef struct InterfaceInfo InterfaceInfo;
typedef struct ObjectProperty ObjectProperty;
/**
- * ObjectPropertyAccessor:
+ * typedef ObjectPropertyAccessor:
* @obj: the object that owns the property
* @v: the visitor that contains the property data
* @name: the name of the property
@@ -47,7 +47,7 @@ typedef void (ObjectPropertyAccessor)(Object *obj,
Error **errp);
/**
- * ObjectPropertyResolve:
+ * typedef ObjectPropertyResolve:
* @obj: the object that owns the property
* @opaque: the opaque registered with the property
* @part: the name of the property
@@ -66,7 +66,7 @@ typedef Object *(ObjectPropertyResolve)(Object *obj,
const char *part);
/**
- * ObjectPropertyRelease:
+ * typedef ObjectPropertyRelease:
* @obj: the object that owns the property
* @name: the name of the property
* @opaque: the opaque registered with the property
@@ -78,7 +78,7 @@ typedef void (ObjectPropertyRelease)(Object *obj,
void *opaque);
/**
- * ObjectPropertyInit:
+ * typedef ObjectPropertyInit:
* @obj: the object that owns the property
* @prop: the property to set
*
@@ -101,7 +101,7 @@ struct ObjectProperty
};
/**
- * ObjectUnparent:
+ * typedef ObjectUnparent:
* @obj: the object that is being removed from the composition tree
*
* Called when an object is being removed from the QOM composition tree.
@@ -110,7 +110,7 @@ struct ObjectProperty
typedef void (ObjectUnparent)(Object *obj);
/**
- * ObjectFree:
+ * typedef ObjectFree:
* @obj: the object being freed
*
* Called when an object's last reference is removed.
@@ -120,7 +120,7 @@ typedef void (ObjectFree)(void *obj);
#define OBJECT_CLASS_CAST_CACHE 4
/**
- * ObjectClass:
+ * struct ObjectClass:
*
* The base for all classes. The only thing that #ObjectClass contains is an
* integer type handle.
@@ -140,7 +140,7 @@ struct ObjectClass
};
/**
- * Object:
+ * struct Object:
*
* The base for all objects. The first member of this object is a pointer to
* a #ObjectClass. Since C guarantees that the first member of a structure
@@ -170,7 +170,7 @@ struct Object
* Direct usage of this macro should be avoided, and the complete
* OBJECT_DECLARE_TYPE macro is recommended instead.
*
- * This macro will provide the three standard type cast functions for a
+ * This macro will provide the instance type cast functions for a
* QOM type.
*/
#define DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \
@@ -187,7 +187,7 @@ struct Object
* Direct usage of this macro should be avoided, and the complete
* OBJECT_DECLARE_TYPE macro is recommended instead.
*
- * This macro will provide the three standard type cast functions for a
+ * This macro will provide the class type cast functions for a
* QOM type.
*/
#define DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME) \
@@ -370,7 +370,7 @@ struct Object
true, { NULL })
/**
- * TypeInfo:
+ * struct TypeInfo:
* @name: The name of the type.
* @parent: The name of the parent type.
* @instance_size: The size of the object (derivative of #Object). If
@@ -496,7 +496,7 @@ struct TypeInfo
OBJECT_CLASS_CHECK(class, object_get_class(OBJECT(obj)), name)
/**
- * InterfaceInfo:
+ * struct InterfaceInfo:
* @type: The name of the interface.
*
* The information associated with an interface.
@@ -506,7 +506,7 @@ struct InterfaceInfo {
};
/**
- * InterfaceClass:
+ * struct InterfaceClass:
* @parent_class: the base class
*
* The class for all interfaces. Subclasses of this class should only add
@@ -1256,7 +1256,7 @@ char *object_property_get_str(Object *obj, const char *name,
* Writes an object's canonical path to a property.
*
* If the link property was created with
- * <code>OBJ_PROP_LINK_STRONG</code> bit, the old target object is
+ * %OBJ_PROP_LINK_STRONG bit, the old target object is
* unreferenced, and a reference is added to the new target object.
*
* Returns: %true on success, %false on failure.
@@ -1603,16 +1603,16 @@ void object_property_allow_set_link(const Object *obj, const char *name,
*
* Links form the graph in the object model.
*
- * The <code>@check()</code> callback is invoked when
+ * The @check() callback is invoked when
* object_property_set_link() is called and can raise an error to prevent the
- * link being set. If <code>@check</code> is NULL, the property is read-only
+ * link being set. If @check is NULL, the property is read-only
* and cannot be set.
*
* Ownership of the pointer that @child points to is transferred to the
- * link property. The reference count for <code>*@child</code> is
+ * link property. The reference count for *@child is
* managed by the property from after the function returns till the
* property is deleted with object_property_del(). If the
- * <code>@flags</code> <code>OBJ_PROP_LINK_STRONG</code> bit is set,
+ * @flags %OBJ_PROP_LINK_STRONG bit is set,
* the reference count is decremented when the property is deleted or
* modified.
*
@@ -1823,7 +1823,7 @@ ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass,
* Add an alias for a property on an object. This function will add a property
* of the same type as the forwarded property.
*
- * The caller must ensure that <code>@target_obj</code> stays alive as long as
+ * The caller must ensure that @target_obj stays alive as long as
* this property exists. In the case of a child object or an alias on the same
* object this will be the case. For aliases to other objects the caller is
* responsible for taking a reference.
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_BITS 5
+/*
+ * 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_BITS 8
-#define SIMD_MAXSZ_SHIFT (SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS)
-#define SIMD_MAXSZ_BITS 5
+#define SIMD_OPRSZ_SHIFT (SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS)
+#define SIMD_OPRSZ_BITS 2
-#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)
+/* Extract the max vector size from a descriptor. */
+static inline intptr_t simd_maxsz(uint32_t desc)
{
- return (extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS) + 1) * 8;
+ return extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) * 8 + 8;
}
-/* Extract the max vector size from a descriptor. */
-static inline intptr_t simd_maxsz(uint32_t desc)
+/* Extract the operation size from a descriptor. */
+static inline intptr_t simd_oprsz(uint32_t desc)
{
- return (extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) + 1) * 8;
+ 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/include/tcg/tcg.h b/include/tcg/tcg.h
index 53ce94c2c5..8804a8c4a2 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -976,18 +976,16 @@ 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_REG 0x01
-#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;
- union {
- TCGRegSet regs;
- } u;
+ unsigned ct : 16;
+ unsigned alias_index : 4;
+ unsigned sort_index : 4;
+ bool oalias : 1;
+ bool ialias : 1;
+ bool newreg : 1;
+ TCGRegSet regs;
} TCGArgConstraint;
#define TCG_MAX_OP_ARGS 16
@@ -1017,10 +1015,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
} TCGOpDef;
extern TCGOpDef tcg_op_defs[];
diff --git a/qom/object.c b/qom/object.c
index c335dce7e4..1065355233 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1291,7 +1291,8 @@ ObjectProperty *object_property_find_err(Object *obj, const char *name,
{
ObjectProperty *prop = object_property_find(obj, name);
if (!prop) {
- error_setg(errp, "Property '.%s' not found", name);
+ error_setg(errp, "Property '%s.%s' not found",
+ object_get_typename(obj), name);
}
return prop;
}
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 40ad782e34..0ff62bb6a2 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1064,14 +1064,6 @@ sub output_blockhead {
sub dump_declaration($$) {
no strict 'refs';
my ($prototype, $file) = @_;
- if ($decl_type eq 'type name') {
- if ($prototype =~ /^(enum|struct|union)\s+/) {
- $decl_type = $1;
- } else {
- return;
- }
- }
-
my $func = "dump_" . $decl_type;
&$func(@_);
}
@@ -1318,8 +1310,8 @@ sub dump_typedef($$) {
$x =~ s@/\*.*?\*/@@gos; # strip comments.
# Parse function prototypes
- if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
- $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) {
+ if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*?\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
+ $x =~ /typedef\s+(\w+\s*\**)\s*(\w\S+)\s*\s*\((.*)\);/) {
# Function typedefs
$return_type = $1;
@@ -1928,9 +1920,7 @@ sub process_name($$) {
++$warnings;
}
- if ($identifier =~ m/^[A-Z]/) {
- $decl_type = 'type name';
- } elsif ($identifier =~ m/^struct\b/) {
+ if ($identifier =~ m/^struct\b/) {
$decl_type = 'struct';
} elsif ($identifier =~ m/^union\b/) {
$decl_type = 'union';
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 2607fe4ab9..26f71cb599 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -128,23 +128,20 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
{
switch (*ct_str++) {
case 'r': /* general registers */
- ct->ct |= TCG_CT_REG;
- ct->u.regs |= 0xffffffffu;
+ ct->regs |= 0xffffffffu;
break;
case 'w': /* advsimd registers */
- ct->ct |= TCG_CT_REG;
- ct->u.regs |= 0xffffffff00000000ull;
+ ct->regs |= 0xffffffff00000000ull;
break;
case 'l': /* qemu_ld / qemu_st address, data_reg */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffffffffu;
+ ct->regs = 0xffffffffu;
#ifdef CONFIG_SOFTMMU
/* x0 and x1 will be overwritten when reading the tlb entry,
and x2, and x3 for helper args, better to avoid using them. */
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_X0);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_X1);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_X2);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_X3);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_X0);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_X1);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_X2);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_X3);
#endif
break;
case 'A': /* Valid for arithmetic immediate (positive or negative). */
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/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index bc1e1b5a71..62c37a954b 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -253,41 +253,38 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
break;
case 'r':
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffff;
+ ct->regs = 0xffff;
break;
/* qemu_ld address */
case 'l':
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffff;
+ ct->regs = 0xffff;
#ifdef CONFIG_SOFTMMU
/* r0-r2,lr will be overwritten when reading the tlb entry,
so don't use these. */
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R0);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R1);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R14);
#endif
break;
/* qemu_st address & data */
case 's':
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffff;
+ ct->regs = 0xffff;
/* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
and r0-r1 doing the byte swapping, so don't use these. */
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R0);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R1);
#if defined(CONFIG_SOFTMMU)
/* Avoid clashes with registers being used for helper args */
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
#if TARGET_LONG_BITS == 64
/* Avoid clashes with registers being used for helper args */
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
#endif
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R14);
#endif
break;
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 0155c0691c..d8797ed398 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -208,43 +208,34 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
{
switch(*ct_str++) {
case 'a':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
+ tcg_regset_set_reg(ct->regs, TCG_REG_EAX);
break;
case 'b':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
+ tcg_regset_set_reg(ct->regs, TCG_REG_EBX);
break;
case 'c':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
+ tcg_regset_set_reg(ct->regs, TCG_REG_ECX);
break;
case 'd':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
+ tcg_regset_set_reg(ct->regs, TCG_REG_EDX);
break;
case 'S':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
+ tcg_regset_set_reg(ct->regs, TCG_REG_ESI);
break;
case 'D':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
+ tcg_regset_set_reg(ct->regs, TCG_REG_EDI);
break;
case 'q':
/* A register that can be used as a byte operand. */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf;
+ ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf;
break;
case 'Q':
/* A register with an addressable second byte (e.g. %ah). */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xf;
+ ct->regs = 0xf;
break;
case 'r':
/* A general register. */
- ct->ct |= TCG_CT_REG;
- ct->u.regs |= ALL_GENERAL_REGS;
+ ct->regs |= ALL_GENERAL_REGS;
break;
case 'W':
/* With TZCNT/LZCNT, we can have operand-size as an input. */
@@ -252,16 +243,14 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
break;
case 'x':
/* A vector register. */
- ct->ct |= TCG_CT_REG;
- ct->u.regs |= ALL_VECTOR_REGS;
+ ct->regs |= ALL_VECTOR_REGS;
break;
/* qemu_ld/st address constraint */
case 'L':
- ct->ct |= TCG_CT_REG;
- ct->u.regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff;
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1);
+ ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff;
+ tcg_regset_reset_reg(ct->regs, TCG_REG_L0);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_L1);
break;
case 'e':
@@ -969,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);
}
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index d2baf796b0..abd4ac7fc0 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/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 7aa2073520..41be574e89 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -195,29 +195,26 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
{
switch(*ct_str++) {
case 'r':
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffffffff;
+ ct->regs = 0xffffffff;
break;
case 'L': /* qemu_ld input arg constraint */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffffffff;
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
+ ct->regs = 0xffffffff;
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
#if defined(CONFIG_SOFTMMU)
if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A2);
}
#endif
break;
case 'S': /* qemu_st constraint */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffffffff;
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
+ ct->regs = 0xffffffff;
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
#if defined(CONFIG_SOFTMMU)
if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A2);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A3);
} else {
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A1);
}
#endif
break;
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):
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 7cb40b0466..18ee989f95 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -224,34 +224,29 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
{
switch (*ct_str++) {
case 'A': case 'B': case 'C': case 'D':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A');
+ tcg_regset_set_reg(ct->regs, 3 + ct_str[0] - 'A');
break;
case 'r':
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffffffff;
+ ct->regs = 0xffffffff;
break;
case 'v':
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffffffff00000000ull;
+ ct->regs = 0xffffffff00000000ull;
break;
case 'L': /* qemu_ld constraint */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffffffff;
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
+ ct->regs = 0xffffffff;
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
#ifdef CONFIG_SOFTMMU
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R5);
#endif
break;
case 'S': /* qemu_st constraint */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffffffff;
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
+ ct->regs = 0xffffffff;
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
#ifdef CONFIG_SOFTMMU
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R5);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R6);
#endif
break;
case 'I':
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
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 2dfb07e247..d536f3ccc1 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -137,20 +137,18 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
{
switch (*ct_str++) {
case 'r':
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffffffff;
+ ct->regs = 0xffffffff;
break;
case 'L':
/* qemu_ld/qemu_st constraint */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffffffff;
+ ct->regs = 0xffffffff;
/* qemu_ld/qemu_st uses TCG_REG_TMP0 */
#if defined(CONFIG_SOFTMMU)
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]);
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]);
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]);
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[3]);
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[4]);
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[0]);
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[1]);
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[2]);
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[3]);
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[4]);
#endif
break;
case 'I':
diff --git a/tcg/s390/tcg-target.c.inc b/tcg/s390/tcg-target.c.inc
index 985115acfb..c5e096449b 100644
--- a/tcg/s390/tcg-target.c.inc
+++ b/tcg/s390/tcg-target.c.inc
@@ -408,25 +408,21 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
{
switch (*ct_str++) {
case 'r': /* all registers */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffff;
+ ct->regs = 0xffff;
break;
case 'L': /* qemu_ld/st constraint */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffff;
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
+ ct->regs = 0xffff;
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
break;
case 'a': /* force R2 for division */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_R2);
+ ct->regs = 0;
+ tcg_regset_set_reg(ct->regs, TCG_REG_R2);
break;
case 'b': /* force R3 for division */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_R3);
+ ct->regs = 0;
+ tcg_regset_set_reg(ct->regs, TCG_REG_R3);
break;
case 'A':
ct->ct |= TCG_CT_CONST_S33;
diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc
index 40bc12290c..6775bd30fc 100644
--- a/tcg/sparc/tcg-target.c.inc
+++ b/tcg/sparc/tcg-target.c.inc
@@ -325,28 +325,23 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
{
switch (*ct_str++) {
case 'r':
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffffffff;
+ ct->regs = 0xffffffff;
break;
case 'R':
- ct->ct |= TCG_CT_REG;
- ct->u.regs = ALL_64;
+ ct->regs = ALL_64;
break;
case 'A': /* qemu_ld/st address constraint */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff;
+ ct->regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff;
reserve_helpers:
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_O0);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_O1);
+ tcg_regset_reset_reg(ct->regs, TCG_REG_O2);
break;
case 's': /* qemu_st data 32-bit constraint */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = 0xffffffff;
+ ct->regs = 0xffffffff;
goto reserve_helpers;
case 'S': /* qemu_st data 64-bit constraint */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = ALL_64;
+ ct->regs = ALL_64;
goto reserve_helpers;
case 'I':
ct->ct |= TCG_CT_CONST_S11;
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);
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)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 164a141d74..a8c28440e2 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));
@@ -959,15 +958,12 @@ void tcg_context_init(TCGContext *s)
total_args += n;
}
- args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
- sorted_args = g_malloc(sizeof(int) * total_args);
+ args_ct = g_new0(TCGArgConstraint, total_args);
for(op = 0; op < NB_OPS; op++) {
def = &tcg_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;
}
@@ -2198,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 = &def->args_ct[k];
+ int n;
- int i, n;
- arg_ct = &def->args_ct[k];
- if (arg_ct->ct & TCG_CT_ALIAS) {
+ if (arg_ct->oalias) {
/* 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->u.regs, i))
- n++;
- }
+ n = ctpop64(arg_ct->regs);
}
return TCG_TARGET_NB_REGS - n + 1;
}
@@ -2220,20 +2209,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;
}
}
}
@@ -2268,8 +2260,6 @@ 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].ct = 0;
while (*ct_str != '\0') {
switch(*ct_str) {
case '0' ... '9':
@@ -2277,19 +2267,19 @@ 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_CT_ALIAS is for the output arguments.
- The input is tagged with TCG_CT_IALIAS. */
+ tcg_debug_assert(def->args_ct[oarg].regs != 0);
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':
@@ -2855,13 +2845,13 @@ static void liveness_pass_1(TCGContext *s)
pset = la_temp_pref(ts);
set = *pset;
- set &= ct->u.regs;
- if (ct->ct & TCG_CT_IALIAS) {
+ set &= ct->regs;
+ if (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 +3541,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) {
@@ -3659,7 +3649,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 = &def->args_ct[i];
ts = arg_temp(arg);
@@ -3673,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
@@ -3695,9 +3685,8 @@ 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];
- if ((def->args_ct[i2].ct & TCG_CT_IALIAS) &&
- reg == new_args[i2]) {
+ i2 = def->args_ct[nb_oargs + k2].sort_index;
+ if (def->args_ct[i2].ialias && reg == new_args[i2]) {
goto allocate_in_reg;
}
}
@@ -3706,10 +3695,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 +3706,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)) {
/*
@@ -3760,7 +3749,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 = &def->args_ct[i];
ts = arg_temp(arg);
@@ -3768,15 +3757,14 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
/* ENV should not be modified. */
tcg_debug_assert(!ts->fixed_reg);
- if ((arg_ct->ct & TCG_CT_ALIAS)
- && !const_args[arg_ct->alias_index]) {
+ if (arg_ct->oalias && !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,
+ } else if (arg_ct->newreg) {
+ 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/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
index 992d50cb1e..231b9b1775 100644
--- a/tcg/tci/tcg-target.c.inc
+++ b/tcg/tci/tcg-target.c.inc
@@ -392,8 +392,7 @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
case 'r':
case 'L': /* qemu_ld constraint */
case 'S': /* qemu_st constraint */
- ct->ct |= TCG_CT_REG;
- ct->u.regs = BIT(TCG_TARGET_NB_REGS) - 1;
+ ct->regs = BIT(TCG_TARGET_NB_REGS) - 1;
break;
default:
return NULL;