From 6b568e3f1dc22e839cd56b47e22c2aa5ece21367 Mon Sep 17 00:00:00 2001 From: Thomas Huth <thuth@redhat.com> Date: Fri, 19 Apr 2024 10:48:09 +0200 Subject: [PATCH 01/12] target/sparc/cpu: Rename the CPU models with a "+" in their names Commit b447378e12 ("qom/object: Limit type names to alphanumerical ...") cut down the amount of allowed characters for QOM types to a saner set. The "+" character was meant to be included in this set, so we had to add a hack there to still allow the legacy names of POWER and Sparc64 CPUs. However, instead of putting such a hack in the common QOM code, there is a much better place to do this: The sparc_cpu_class_by_name() function which is used to look up the names of all Sparc CPUs. Thus let's finally get rid of the "+" in the Sparc CPU names, and provide backward compatibility for the old names via some simple checks in the sparc_cpu_class_by_name() function. Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Signed-off-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20240419084812.504779-2-thuth@redhat.com> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> --- qom/object.c | 8 -------- target/sparc/cpu.c | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/qom/object.c b/qom/object.c index 44ec8f6460..157a45c5f8 100644 --- a/qom/object.c +++ b/qom/object.c @@ -157,14 +157,6 @@ static bool type_name_is_valid(const char *name) "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789-_."); - /* Allow some legacy names with '+' in it for compatibility reasons */ - if (name[plen] == '+') { - if (plen >= 17 && g_str_has_prefix(name, "Sun-UltraSparc-I")) { - /* Allow "Sun-UltraSparc-IV+" and "Sun-UltraSparc-IIIi+" */ - return true; - } - } - return plen == slen; } diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index 485d416925..7487ae034d 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -314,7 +314,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "Sun UltraSparc IV+", + .name = "Sun UltraSparc IV plus", .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -323,7 +323,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT, }, { - .name = "Sun UltraSparc IIIi+", + .name = "Sun UltraSparc IIIi plus", .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_3, @@ -762,6 +762,16 @@ static ObjectClass *sparc_cpu_class_by_name(const char *cpu_model) char *typename; typename = sparc_cpu_type_name(cpu_model); + + /* Fix up legacy names with '+' in it */ + if (g_str_equal(typename, SPARC_CPU_TYPE_NAME("Sun-UltraSparc-IV+"))) { + g_free(typename); + typename = g_strdup(SPARC_CPU_TYPE_NAME("Sun-UltraSparc-IV-plus")); + } else if (g_str_equal(typename, SPARC_CPU_TYPE_NAME("Sun-UltraSparc-IIIi+"))) { + g_free(typename); + typename = g_strdup(SPARC_CPU_TYPE_NAME("Sun-UltraSparc-IIIi-plus")); + } + oc = object_class_by_name(typename); g_free(typename); return oc; From 4a7bdec3a6f3f6d9f75715e420a4c826135a1065 Mon Sep 17 00:00:00 2001 From: Thomas Huth <thuth@redhat.com> Date: Fri, 19 Apr 2024 10:48:10 +0200 Subject: [PATCH 02/12] target/sparc/cpu: Avoid spaces by default in the CPU names The output of "-cpu help" is currently rather confusing to the users: It might not be fully clear which part of the output defines the CPU names since the CPU names contain white spaces (which we later have to convert into dashes internally). At best it's at least a nuisance since the users might need to specify the CPU names with quoting on the command line if they are not aware of the fact that the CPU names could be written with dashes instead. So let's finally clean up this mess by using dashes instead of white spaces for the CPU names, like we're doing it internally later (and like we're doing it in most other targets of QEMU). Note that it is still possible to pass the CPU names with spaces to the "-cpu" option, since sparc_cpu_type_name() still translates those to "-". Fixes: https://gitlab.com/qemu-project/qemu/-/issues/2141 Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Signed-off-by: Thomas Huth <thuth@redhat.com> Message-Id: <20240419084812.504779-3-thuth@redhat.com> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> --- target/sparc/cpu.c | 56 +++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index 7487ae034d..c2be4a00b6 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -206,7 +206,7 @@ void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu) static const sparc_def_t sparc_defs[] = { #ifdef TARGET_SPARC64 { - .name = "Fujitsu Sparc64", + .name = "Fujitsu-Sparc64", .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -215,7 +215,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "Fujitsu Sparc64 III", + .name = "Fujitsu-Sparc64-III", .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -224,7 +224,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "Fujitsu Sparc64 IV", + .name = "Fujitsu-Sparc64-IV", .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -233,7 +233,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "Fujitsu Sparc64 V", + .name = "Fujitsu-Sparc64-V", .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -242,7 +242,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "TI UltraSparc I", + .name = "TI-UltraSparc-I", .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -251,7 +251,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "TI UltraSparc II", + .name = "TI-UltraSparc-II", .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -260,7 +260,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "TI UltraSparc IIi", + .name = "TI-UltraSparc-IIi", .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -269,7 +269,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "TI UltraSparc IIe", + .name = "TI-UltraSparc-IIe", .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -278,7 +278,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "Sun UltraSparc III", + .name = "Sun-UltraSparc-III", .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -287,7 +287,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "Sun UltraSparc III Cu", + .name = "Sun-UltraSparc-III-Cu", .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_3, @@ -296,7 +296,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "Sun UltraSparc IIIi", + .name = "Sun-UltraSparc-IIIi", .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -305,7 +305,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "Sun UltraSparc IV", + .name = "Sun-UltraSparc-IV", .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_4, @@ -314,7 +314,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "Sun UltraSparc IV plus", + .name = "Sun-UltraSparc-IV-plus", .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -323,7 +323,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT, }, { - .name = "Sun UltraSparc IIIi plus", + .name = "Sun-UltraSparc-IIIi-plus", .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_3, @@ -332,7 +332,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "Sun UltraSparc T1", + .name = "Sun-UltraSparc-T1", /* defined in sparc_ifu_fdp.v and ctu.h */ .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)), .fpu_version = 0x00000000, @@ -343,7 +343,7 @@ static const sparc_def_t sparc_defs[] = { | CPU_FEATURE_GL, }, { - .name = "Sun UltraSparc T2", + .name = "Sun-UltraSparc-T2", /* defined in tlu_asi_ctl.v and n2_revid_cust.v */ .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)), .fpu_version = 0x00000000, @@ -354,7 +354,7 @@ static const sparc_def_t sparc_defs[] = { | CPU_FEATURE_GL, }, { - .name = "NEC UltraSparc I", + .name = "NEC-UltraSparc-I", .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)), .fpu_version = 0x00000000, .mmu_version = mmu_us_12, @@ -364,7 +364,7 @@ static const sparc_def_t sparc_defs[] = { }, #else { - .name = "Fujitsu MB86904", + .name = "Fujitsu-MB86904", .iu_version = 0x04 << 24, /* Impl 0, ver 4 */ .fpu_version = 4 << FSR_VER_SHIFT, /* FPU version 4 (Meiko) */ .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */ @@ -377,7 +377,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "Fujitsu MB86907", + .name = "Fujitsu-MB86907", .iu_version = 0x05 << 24, /* Impl 0, ver 5 */ .fpu_version = 4 << FSR_VER_SHIFT, /* FPU version 4 (Meiko) */ .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */ @@ -390,7 +390,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "TI MicroSparc I", + .name = "TI-MicroSparc-I", .iu_version = 0x41000000, .fpu_version = 4 << FSR_VER_SHIFT, .mmu_version = 0x41000000, @@ -403,7 +403,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_FEATURE_MUL | CPU_FEATURE_DIV, }, { - .name = "TI MicroSparc II", + .name = "TI-MicroSparc-II", .iu_version = 0x42000000, .fpu_version = 4 << FSR_VER_SHIFT, .mmu_version = 0x02000000, @@ -416,7 +416,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "TI MicroSparc IIep", + .name = "TI-MicroSparc-IIep", .iu_version = 0x42000000, .fpu_version = 4 << FSR_VER_SHIFT, .mmu_version = 0x04000000, @@ -429,7 +429,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "TI SuperSparc 40", /* STP1020NPGA */ + .name = "TI-SuperSparc-40", /* STP1020NPGA */ .iu_version = 0x41000000, /* SuperSPARC 2.x */ .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */ @@ -442,7 +442,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "TI SuperSparc 50", /* STP1020PGA */ + .name = "TI-SuperSparc-50", /* STP1020PGA */ .iu_version = 0x40000000, /* SuperSPARC 3.x */ .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */ @@ -455,7 +455,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "TI SuperSparc 51", + .name = "TI-SuperSparc-51", .iu_version = 0x40000000, /* SuperSPARC 3.x */ .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */ @@ -469,7 +469,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "TI SuperSparc 60", /* STP1020APGA */ + .name = "TI-SuperSparc-60", /* STP1020APGA */ .iu_version = 0x40000000, /* SuperSPARC 3.x */ .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */ @@ -482,7 +482,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "TI SuperSparc 61", + .name = "TI-SuperSparc-61", .iu_version = 0x44000000, /* SuperSPARC 3.x */ .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */ @@ -496,7 +496,7 @@ static const sparc_def_t sparc_defs[] = { .features = CPU_DEFAULT_FEATURES, }, { - .name = "TI SuperSparc II", + .name = "TI-SuperSparc-II", .iu_version = 0x40000000, /* SuperSPARC II 1.x */ .fpu_version = 0 << FSR_VER_SHIFT, .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */ From 49ce37e3d024260072bdfa4c5569859d1f338cb2 Mon Sep 17 00:00:00 2001 From: Thomas Huth <thuth@redhat.com> Date: Fri, 19 Apr 2024 10:48:11 +0200 Subject: [PATCH 03/12] docs/system/target-sparc: Improve the Sparc documentation Add some words about how to enable or disable boolean features, and remove the note about a Linux kernel being available on the QEMU website (they have been removed long ago already), and the note about NetBSD and OpenBSD still having issues (they should work fine nowadays). Fixes: https://gitlab.com/qemu-project/qemu/-/issues/2141 Signed-off-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20240419084812.504779-4-thuth@redhat.com> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> --- docs/system/target-sparc.rst | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/system/target-sparc.rst b/docs/system/target-sparc.rst index 9ec8c90c14..4116cac493 100644 --- a/docs/system/target-sparc.rst +++ b/docs/system/target-sparc.rst @@ -27,6 +27,11 @@ architecture machines: The emulation is somewhat complete. SMP up to 16 CPUs is supported, but Linux limits the number of usable CPUs to 4. +The list of available CPUs can be viewed by starting QEMU with ``-cpu help``. +Optional boolean features can be added with a "+" in front of the feature name, +or disabled with a "-" in front of the name, for example +``-cpu TI-SuperSparc-II,+float128``. + QEMU emulates the following sun4m peripherals: - IOMMU @@ -55,8 +60,5 @@ OpenBIOS is a free (GPL v2) portable firmware implementation. The goal is to implement a 100% IEEE 1275-1994 (referred to as Open Firmware) compliant firmware. -A sample Linux 2.6 series kernel and ram disk image are available on the -QEMU web site. There are still issues with NetBSD and OpenBSD, but most -kernel versions work. Please note that currently older Solaris kernels -don't work probably due to interface issues between OpenBIOS and -Solaris. +Please note that currently older Solaris kernels don't work; this is probably +due to interface issues between OpenBIOS and Solaris. From 029171b5d62fe11a0dce52f64efb356f7fea144d Mon Sep 17 00:00:00 2001 From: Thomas Huth <thuth@redhat.com> Date: Fri, 19 Apr 2024 10:48:12 +0200 Subject: [PATCH 04/12] docs/about: Deprecate the old "UltraSparc" CPU names that contain a "+" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency we should drop the names with a "+" in it in the long run. Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Signed-off-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20240419084812.504779-5-thuth@redhat.com> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> --- docs/about/deprecated.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 7b8aafa15b..03f8b1b655 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -194,6 +194,15 @@ in the QEMU object model anymore. ``power5+``, ``power5+_v2.1``, an alias, but for consistency these will get removed in a future release, too. Use ``power5p_v2.1`` and ``power7p_v2.1`` instead. +``Sun-UltraSparc-IIIi+`` and ``Sun-UltraSparc-IV+`` CPU names (since 9.1) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The character "+" in device (and thus also CPU) names is not allowed +in the QEMU object model anymore. ``Sun-UltraSparc-IIIi+`` and +``Sun-UltraSparc-IV+`` are currently still supported via a workaround, +but for consistency these will get removed in a future release, too. +Use ``Sun-UltraSparc-IIIi-plus`` and ``Sun-UltraSparc-IV-plus`` instead. + CRIS CPU architecture (since 9.0) ''''''''''''''''''''''''''''''''' From 7c420a4d7c080002018af20aed56ceb0bf81ad43 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Date: Thu, 18 Apr 2024 21:57:30 +0100 Subject: [PATCH 05/12] hw/sparc64: set iommu_platform=on for virtio devices attached to the sun4u machine The sun4u machine has an IOMMU and therefore it is possible to program it such that the virtio-device IOVA does not map directly to the CPU physical address. This is not a problem with Linux which always maps the IOVA directly to the CPU physical address, however it is required for the NetBSD virtio driver where this is not the case. Set the sun4u machine defaults for all virtio devices so that disable-legacy=on and iommu_platform=on to ensure a default configuration will allow virtio devices to function correctly on both Linux and NetBSD. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Message-Id: <20240418205730.31396-1-mark.cave-ayland@ilande.co.uk> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> --- hw/sparc64/sun4u.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index cff6d5abaf..4ece1ac1ff 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -793,6 +793,12 @@ static void sun4v_init(MachineState *machine) sun4uv_init(get_system_memory(), machine, &hwdefs[1]); } +static GlobalProperty hw_compat_sparc64[] = { + { "virtio-pci", "disable-legacy", "on", .optional = true }, + { "virtio-device", "iommu_platform", "on" }, +}; +static const size_t hw_compat_sparc64_len = G_N_ELEMENTS(hw_compat_sparc64); + static void sun4u_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -810,6 +816,7 @@ static void sun4u_class_init(ObjectClass *oc, void *data) mc->default_nic = "sunhme"; mc->no_parallel = !module_object_class_by_name(TYPE_ISA_PARALLEL); fwc->get_dev_path = sun4u_fw_dev_path; + compat_props_add(mc->compat_props, hw_compat_sparc64, hw_compat_sparc64_len); } static const TypeInfo sun4u_type = { From 1cde1a2a89e7c6ac1c8240b09f9b3d066cd01270 Mon Sep 17 00:00:00 2001 From: Richard Henderson <richard.henderson@linaro.org> Date: Thu, 2 May 2024 09:55:22 -0700 Subject: [PATCH 06/12] linux-user/sparc: Add more hwcap bits for sparc64 Supply HWCAP_SPARC_V8PLUS, HWCAP_SPARC_MUL32, HWCAP_SPARC_DIV32, HWCAP_SPARC_POPC, HWCAP_SPARC_FSMULD, HWCAP_SPARC_VIS, HWCAP_SPARC_VIS2. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20240502165528.244004-2-richard.henderson@linaro.org> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> --- linux-user/elfload.c | 48 +++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index f9461d2844..14f08b64a1 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -968,24 +968,44 @@ const char *elf_hwcap2_str(uint32_t bit) #endif /* TARGET_ARM */ #ifdef TARGET_SPARC -#ifdef TARGET_SPARC64 -#define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \ - | HWCAP_SPARC_MULDIV | HWCAP_SPARC_V9) -#ifndef TARGET_ABI32 -#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS ) +#ifndef TARGET_SPARC64 +# define ELF_CLASS ELFCLASS32 +# define ELF_ARCH EM_SPARC +#elif defined(TARGET_ABI32) +# define ELF_CLASS ELFCLASS32 +# define elf_check_arch(x) ((x) == EM_SPARC32PLUS || (x) == EM_SPARC) #else -#define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC ) +# define ELF_CLASS ELFCLASS64 +# define ELF_ARCH EM_SPARCV9 #endif -#define ELF_CLASS ELFCLASS64 -#define ELF_ARCH EM_SPARCV9 -#else -#define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \ - | HWCAP_SPARC_MULDIV) -#define ELF_CLASS ELFCLASS32 -#define ELF_ARCH EM_SPARC -#endif /* TARGET_SPARC64 */ +#include "elf.h" + +#define ELF_HWCAP get_elf_hwcap() + +static uint32_t get_elf_hwcap(void) +{ + /* There are not many sparc32 hwcap bits -- we have all of them. */ + uint32_t r = HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | + HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV; + +#ifdef TARGET_SPARC64 + CPUSPARCState *env = cpu_env(thread_cpu); + uint32_t features = env->def.features; + + r |= HWCAP_SPARC_V9 | HWCAP_SPARC_V8PLUS; + /* 32x32 multiply and divide are efficient. */ + r |= HWCAP_SPARC_MUL32 | HWCAP_SPARC_DIV32; + /* We don't have an internal feature bit for this. */ + r |= HWCAP_SPARC_POPC; + r |= features & CPU_FEATURE_FSMULD ? HWCAP_SPARC_FSMULD : 0; + r |= features & CPU_FEATURE_VIS1 ? HWCAP_SPARC_VIS : 0; + r |= features & CPU_FEATURE_VIS2 ? HWCAP_SPARC_VIS2 : 0; +#endif + + return r; +} static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) From 7b616f36de0bde126e1ba6b0793ed26fc414a1ff Mon Sep 17 00:00:00 2001 From: Richard Henderson <richard.henderson@linaro.org> Date: Thu, 2 May 2024 09:55:23 -0700 Subject: [PATCH 07/12] target/sparc: Fix FEXPAND MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a 2-operand instruction, not 3-operand. Worse, we took the source from the wrong operand. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20240502165528.244004-3-richard.henderson@linaro.org> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> --- target/sparc/helper.h | 2 +- target/sparc/insns.decode | 2 +- target/sparc/translate.c | 20 +++++++++++++++++++- target/sparc/vis_helper.c | 6 +++--- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/target/sparc/helper.h b/target/sparc/helper.h index b8087d0d2b..57ab755ffd 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -102,7 +102,7 @@ DEF_HELPER_FLAGS_2(fmul8sux16, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(fmul8ulx16, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(fmuld8sux16, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(fmuld8ulx16, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fexpand, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_1(fexpand, TCG_CALL_NO_RWG_SE, i64, i32) DEF_HELPER_FLAGS_3(pdist, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) DEF_HELPER_FLAGS_2(fpack16, TCG_CALL_NO_RWG_SE, i32, i64, i64) DEF_HELPER_FLAGS_3(fpack32, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) diff --git a/target/sparc/insns.decode b/target/sparc/insns.decode index 2d26404cb2..e2d8a07dc4 100644 --- a/target/sparc/insns.decode +++ b/target/sparc/insns.decode @@ -352,7 +352,7 @@ FCMPEq 10 000 cc:2 110101 rs1:5 0 0101 0111 rs2:5 FALIGNDATAg 10 ..... 110110 ..... 0 0100 1000 ..... @r_r_r FPMERGE 10 ..... 110110 ..... 0 0100 1011 ..... @r_r_r BSHUFFLE 10 ..... 110110 ..... 0 0100 1100 ..... @r_r_r - FEXPAND 10 ..... 110110 ..... 0 0100 1101 ..... @r_r_r + FEXPAND 10 ..... 110110 00000 0 0100 1101 ..... @r_r2 FSRCd 10 ..... 110110 ..... 0 0111 0100 00000 @r_r1 # FSRC1d FSRCs 10 ..... 110110 ..... 0 0111 0101 00000 @r_r1 # FSRC1s diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 571b3e3f03..dfcfe855a1 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -4358,6 +4358,25 @@ TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd) TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod) TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox) +static bool do_df(DisasContext *dc, arg_r_r *a, + void (*func)(TCGv_i64, TCGv_i32)) +{ + TCGv_i64 dst; + TCGv_i32 src; + + if (gen_trap_ifnofpu(dc)) { + return true; + } + + dst = tcg_temp_new_i64(); + src = gen_load_fpr_F(dc, a->rs); + func(dst, src); + gen_store_fpr_D(dc, a->rd, dst); + return advance_pc(dc); +} + +TRANS(FEXPAND, VIS1, do_df, a, gen_helper_fexpand) + static bool do_env_df(DisasContext *dc, arg_r_r *a, void (*func)(TCGv_i64, TCGv_env, TCGv_i32)) { @@ -4589,7 +4608,6 @@ TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) TRANS(FMULD8SUx16, VIS1, do_ddd, a, gen_helper_fmuld8sux16) TRANS(FMULD8ULx16, VIS1, do_ddd, a, gen_helper_fmuld8ulx16) TRANS(FPMERGE, VIS1, do_ddd, a, gen_helper_fpmerge) -TRANS(FEXPAND, VIS1, do_ddd, a, gen_helper_fexpand) TRANS(FPADD16, VIS1, do_ddd, a, tcg_gen_vec_add16_i64) TRANS(FPADD32, VIS1, do_ddd, a, tcg_gen_vec_add32_i64) diff --git a/target/sparc/vis_helper.c b/target/sparc/vis_helper.c index 7763b16c24..db2e6dd6c1 100644 --- a/target/sparc/vis_helper.c +++ b/target/sparc/vis_helper.c @@ -260,13 +260,13 @@ uint64_t helper_fmuld8ulx16(uint64_t src1, uint64_t src2) return d.ll; } -uint64_t helper_fexpand(uint64_t src1, uint64_t src2) +uint64_t helper_fexpand(uint32_t src2) { VIS32 s; VIS64 d; - s.l = (uint32_t)src1; - d.ll = src2; + s.l = src2; + d.ll = 0; d.VIS_W64(0) = s.VIS_B32(0) << 4; d.VIS_W64(1) = s.VIS_B32(1) << 4; d.VIS_W64(2) = s.VIS_B32(2) << 4; From 9157dccc7e71f7c94581c38f38acbef9a21bbe9a Mon Sep 17 00:00:00 2001 From: Richard Henderson <richard.henderson@linaro.org> Date: Thu, 2 May 2024 09:55:24 -0700 Subject: [PATCH 08/12] target/sparc: Fix FMUL8x16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This instruction has f32 as source1, which alters the decoding of the register number, which means we've been passing the wrong data for odd register numbers. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20240502165528.244004-4-richard.henderson@linaro.org> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> --- target/sparc/helper.h | 2 +- target/sparc/translate.c | 21 ++++++++++++++++++++- target/sparc/vis_helper.c | 9 +++++---- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 57ab755ffd..27dc604cac 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -95,7 +95,7 @@ DEF_HELPER_FLAGS_2(fdtox, TCG_CALL_NO_WG, s64, env, f64) DEF_HELPER_FLAGS_2(fqtox, TCG_CALL_NO_WG, s64, env, i128) DEF_HELPER_FLAGS_2(fpmerge, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_NO_RWG_SE, i64, i32, i64) DEF_HELPER_FLAGS_2(fmul8x16al, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(fmul8x16au, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(fmul8sux16, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index dfcfe855a1..c4adc148d2 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -4583,6 +4583,26 @@ TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs) TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls) TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs) +static bool do_dfd(DisasContext *dc, arg_r_r_r *a, + void (*func)(TCGv_i64, TCGv_i32, TCGv_i64)) +{ + TCGv_i64 dst, src2; + TCGv_i32 src1; + + if (gen_trap_ifnofpu(dc)) { + return true; + } + + dst = gen_dest_fpr_D(dc, a->rd); + src1 = gen_load_fpr_F(dc, a->rs1); + src2 = gen_load_fpr_D(dc, a->rs2); + func(dst, src1, src2); + gen_store_fpr_D(dc, a->rd, dst); + return advance_pc(dc); +} + +TRANS(FMUL8x16, VIS1, do_dfd, a, gen_helper_fmul8x16) + static bool do_ddd(DisasContext *dc, arg_r_r_r *a, void (*func)(TCGv_i64, TCGv_i64, TCGv_i64)) { @@ -4600,7 +4620,6 @@ static bool do_ddd(DisasContext *dc, arg_r_r_r *a, return advance_pc(dc); } -TRANS(FMUL8x16, VIS1, do_ddd, a, gen_helper_fmul8x16) TRANS(FMUL8x16AU, VIS1, do_ddd, a, gen_helper_fmul8x16au) TRANS(FMUL8x16AL, VIS1, do_ddd, a, gen_helper_fmul8x16al) TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) diff --git a/target/sparc/vis_helper.c b/target/sparc/vis_helper.c index db2e6dd6c1..7728ffe9c6 100644 --- a/target/sparc/vis_helper.c +++ b/target/sparc/vis_helper.c @@ -94,16 +94,17 @@ uint64_t helper_fpmerge(uint64_t src1, uint64_t src2) return d.ll; } -uint64_t helper_fmul8x16(uint64_t src1, uint64_t src2) +uint64_t helper_fmul8x16(uint32_t src1, uint64_t src2) { - VIS64 s, d; + VIS64 d; + VIS32 s; uint32_t tmp; - s.ll = src1; + s.l = src1; d.ll = src2; #define PMUL(r) \ - tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \ + tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B32(r); \ if ((tmp & 0xff) > 0x7f) { \ tmp += 0x100; \ } \ From a859602c746baf4892cc8ca1ce003e92411d1716 Mon Sep 17 00:00:00 2001 From: Richard Henderson <richard.henderson@linaro.org> Date: Thu, 2 May 2024 09:55:25 -0700 Subject: [PATCH 09/12] target/sparc: Fix FMUL8x16A{U,L} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These instructions have f32 inputs, which changes the decode of the register numbers. While we're fixing things, use a common helper for both insns, extracting the 16-bit scalar in tcg beforehand. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20240502165528.244004-5-richard.henderson@linaro.org> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> --- target/sparc/helper.h | 3 +-- target/sparc/translate.c | 38 +++++++++++++++++++++++++++---- target/sparc/vis_helper.c | 47 +++++++++++---------------------------- 3 files changed, 48 insertions(+), 40 deletions(-) diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 27dc604cac..9cde2b69a5 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -96,8 +96,7 @@ DEF_HELPER_FLAGS_2(fqtox, TCG_CALL_NO_WG, s64, env, i128) DEF_HELPER_FLAGS_2(fpmerge, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_NO_RWG_SE, i64, i32, i64) -DEF_HELPER_FLAGS_2(fmul8x16al, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fmul8x16au, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(fmul8x16a, TCG_CALL_NO_RWG_SE, i64, i32, s32) DEF_HELPER_FLAGS_2(fmul8sux16, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(fmul8ulx16, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(fmuld8sux16, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index c4adc148d2..a8ada6934a 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -45,6 +45,7 @@ # define gen_helper_clear_softint(E, S) qemu_build_not_reached() # define gen_helper_done(E) qemu_build_not_reached() # define gen_helper_flushw(E) qemu_build_not_reached() +# define gen_helper_fmul8x16a(D, S1, S2) qemu_build_not_reached() # define gen_helper_rdccr(D, E) qemu_build_not_reached() # define gen_helper_rdcwp(D, E) qemu_build_not_reached() # define gen_helper_restored(E) qemu_build_not_reached() @@ -72,8 +73,6 @@ # define gen_helper_fexpand ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; }) -# define gen_helper_fmul8x16al ({ qemu_build_not_reached(); NULL; }) -# define gen_helper_fmul8x16au ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fmuld8sux16 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fmuld8ulx16 ({ qemu_build_not_reached(); NULL; }) @@ -719,6 +718,18 @@ static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) #endif } +static void gen_op_fmul8x16al(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) +{ + tcg_gen_ext16s_i32(src2, src2); + gen_helper_fmul8x16a(dst, src1, src2); +} + +static void gen_op_fmul8x16au(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) +{ + tcg_gen_sari_i32(src2, src2, 16); + gen_helper_fmul8x16a(dst, src1, src2); +} + static void finishing_insn(DisasContext *dc) { /* @@ -4583,6 +4594,27 @@ TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs) TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls) TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs) +static bool do_dff(DisasContext *dc, arg_r_r_r *a, + void (*func)(TCGv_i64, TCGv_i32, TCGv_i32)) +{ + TCGv_i64 dst; + TCGv_i32 src1, src2; + + if (gen_trap_ifnofpu(dc)) { + return true; + } + + dst = gen_dest_fpr_D(dc, a->rd); + src1 = gen_load_fpr_F(dc, a->rs1); + src2 = gen_load_fpr_F(dc, a->rs2); + func(dst, src1, src2); + gen_store_fpr_D(dc, a->rd, dst); + return advance_pc(dc); +} + +TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au) +TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al) + static bool do_dfd(DisasContext *dc, arg_r_r_r *a, void (*func)(TCGv_i64, TCGv_i32, TCGv_i64)) { @@ -4620,8 +4652,6 @@ static bool do_ddd(DisasContext *dc, arg_r_r_r *a, return advance_pc(dc); } -TRANS(FMUL8x16AU, VIS1, do_ddd, a, gen_helper_fmul8x16au) -TRANS(FMUL8x16AL, VIS1, do_ddd, a, gen_helper_fmul8x16al) TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) TRANS(FMULD8SUx16, VIS1, do_ddd, a, gen_helper_fmuld8sux16) diff --git a/target/sparc/vis_helper.c b/target/sparc/vis_helper.c index 7728ffe9c6..ff2f43c23f 100644 --- a/target/sparc/vis_helper.c +++ b/target/sparc/vis_helper.c @@ -119,44 +119,23 @@ uint64_t helper_fmul8x16(uint32_t src1, uint64_t src2) return d.ll; } -uint64_t helper_fmul8x16al(uint64_t src1, uint64_t src2) +uint64_t helper_fmul8x16a(uint32_t src1, int32_t src2) { - VIS64 s, d; + VIS32 s; + VIS64 d; uint32_t tmp; - s.ll = src1; - d.ll = src2; + s.l = src1; + d.ll = 0; -#define PMUL(r) \ - tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \ - if ((tmp & 0xff) > 0x7f) { \ - tmp += 0x100; \ - } \ - d.VIS_W64(r) = tmp >> 8; - - PMUL(0); - PMUL(1); - PMUL(2); - PMUL(3); -#undef PMUL - - return d.ll; -} - -uint64_t helper_fmul8x16au(uint64_t src1, uint64_t src2) -{ - VIS64 s, d; - uint32_t tmp; - - s.ll = src1; - d.ll = src2; - -#define PMUL(r) \ - tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \ - if ((tmp & 0xff) > 0x7f) { \ - tmp += 0x100; \ - } \ - d.VIS_W64(r) = tmp >> 8; +#define PMUL(r) \ + do { \ + tmp = src2 * (int32_t)s.VIS_B32(r); \ + if ((tmp & 0xff) > 0x7f) { \ + tmp += 0x100; \ + } \ + d.VIS_W64(r) = tmp >> 8; \ + } while (0) PMUL(0); PMUL(1); From be8998e046c2a7e434494b75cf468ffd9d536025 Mon Sep 17 00:00:00 2001 From: Richard Henderson <richard.henderson@linaro.org> Date: Thu, 2 May 2024 09:55:26 -0700 Subject: [PATCH 10/12] target/sparc: Fix FMULD8*X16 Not only do these instructions have f32 inputs, they also do not perform rounding. Since these are relatively simple, implement them properly inline. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20240502165528.244004-6-richard.henderson@linaro.org> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> --- target/sparc/helper.h | 2 -- target/sparc/translate.c | 48 +++++++++++++++++++++++++++++++++++---- target/sparc/vis_helper.c | 46 ------------------------------------- 3 files changed, 44 insertions(+), 52 deletions(-) diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 9cde2b69a5..fcb9c617b7 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -99,8 +99,6 @@ DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_NO_RWG_SE, i64, i32, i64) DEF_HELPER_FLAGS_2(fmul8x16a, TCG_CALL_NO_RWG_SE, i64, i32, s32) DEF_HELPER_FLAGS_2(fmul8sux16, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(fmul8ulx16, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fmuld8sux16, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(fmuld8ulx16, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_1(fexpand, TCG_CALL_NO_RWG_SE, i64, i32) DEF_HELPER_FLAGS_3(pdist, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) DEF_HELPER_FLAGS_2(fpack16, TCG_CALL_NO_RWG_SE, i32, i64, i64) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index a8ada6934a..8a2894bb9f 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -74,8 +74,6 @@ # define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; }) -# define gen_helper_fmuld8sux16 ({ qemu_build_not_reached(); NULL; }) -# define gen_helper_fmuld8ulx16 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fstox ({ qemu_build_not_reached(); NULL; }) @@ -730,6 +728,48 @@ static void gen_op_fmul8x16au(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) gen_helper_fmul8x16a(dst, src1, src2); } +static void gen_op_fmuld8ulx16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + tcg_gen_ext8u_i32(t0, src1); + tcg_gen_ext16s_i32(t1, src2); + tcg_gen_mul_i32(t0, t0, t1); + + tcg_gen_extract_i32(t1, src1, 16, 8); + tcg_gen_sextract_i32(t2, src2, 16, 16); + tcg_gen_mul_i32(t1, t1, t2); + + tcg_gen_concat_i32_i64(dst, t0, t1); +} + +static void gen_op_fmuld8sux16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + /* + * The insn description talks about extracting the upper 8 bits + * of the signed 16-bit input rs1, performing the multiply, then + * shifting left by 8 bits. Instead, zap the lower 8 bits of + * the rs1 input, which avoids the need for two shifts. + */ + tcg_gen_ext16s_i32(t0, src1); + tcg_gen_andi_i32(t0, t0, ~0xff); + tcg_gen_ext16s_i32(t1, src2); + tcg_gen_mul_i32(t0, t0, t1); + + tcg_gen_sextract_i32(t1, src1, 16, 16); + tcg_gen_andi_i32(t1, t1, ~0xff); + tcg_gen_sextract_i32(t2, src2, 16, 16); + tcg_gen_mul_i32(t1, t1, t2); + + tcg_gen_concat_i32_i64(dst, t0, t1); +} + static void finishing_insn(DisasContext *dc) { /* @@ -4614,6 +4654,8 @@ static bool do_dff(DisasContext *dc, arg_r_r_r *a, TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au) TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al) +TRANS(FMULD8SUx16, VIS1, do_dff, a, gen_op_fmuld8sux16) +TRANS(FMULD8ULx16, VIS1, do_dff, a, gen_op_fmuld8ulx16) static bool do_dfd(DisasContext *dc, arg_r_r_r *a, void (*func)(TCGv_i64, TCGv_i32, TCGv_i64)) @@ -4654,8 +4696,6 @@ static bool do_ddd(DisasContext *dc, arg_r_r_r *a, TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) -TRANS(FMULD8SUx16, VIS1, do_ddd, a, gen_helper_fmuld8sux16) -TRANS(FMULD8ULx16, VIS1, do_ddd, a, gen_helper_fmuld8ulx16) TRANS(FPMERGE, VIS1, do_ddd, a, gen_helper_fpmerge) TRANS(FPADD16, VIS1, do_ddd, a, tcg_gen_vec_add16_i64) diff --git a/target/sparc/vis_helper.c b/target/sparc/vis_helper.c index ff2f43c23f..61c61c7fea 100644 --- a/target/sparc/vis_helper.c +++ b/target/sparc/vis_helper.c @@ -194,52 +194,6 @@ uint64_t helper_fmul8ulx16(uint64_t src1, uint64_t src2) return d.ll; } -uint64_t helper_fmuld8sux16(uint64_t src1, uint64_t src2) -{ - VIS64 s, d; - uint32_t tmp; - - s.ll = src1; - d.ll = src2; - -#define PMUL(r) \ - tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \ - if ((tmp & 0xff) > 0x7f) { \ - tmp += 0x100; \ - } \ - d.VIS_L64(r) = tmp; - - /* Reverse calculation order to handle overlap */ - PMUL(1); - PMUL(0); -#undef PMUL - - return d.ll; -} - -uint64_t helper_fmuld8ulx16(uint64_t src1, uint64_t src2) -{ - VIS64 s, d; - uint32_t tmp; - - s.ll = src1; - d.ll = src2; - -#define PMUL(r) \ - tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \ - if ((tmp & 0xff) > 0x7f) { \ - tmp += 0x100; \ - } \ - d.VIS_L64(r) = tmp; - - /* Reverse calculation order to handle overlap */ - PMUL(1); - PMUL(0); -#undef PMUL - - return d.ll; -} - uint64_t helper_fexpand(uint32_t src2) { VIS32 s; From d3ef26afde77fbdedd5b30282134ff99d0fe5cc5 Mon Sep 17 00:00:00 2001 From: Richard Henderson <richard.henderson@linaro.org> Date: Thu, 2 May 2024 09:55:27 -0700 Subject: [PATCH 11/12] target/sparc: Fix FPMERGE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This instruction has f32 inputs, which changes the decode of the register numbers. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20240502165528.244004-7-richard.henderson@linaro.org> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> --- target/sparc/helper.h | 2 +- target/sparc/translate.c | 2 +- target/sparc/vis_helper.c | 27 ++++++++++++++------------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/target/sparc/helper.h b/target/sparc/helper.h index fcb9c617b7..97fbf6f66c 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -94,7 +94,7 @@ DEF_HELPER_FLAGS_2(fstox, TCG_CALL_NO_WG, s64, env, f32) DEF_HELPER_FLAGS_2(fdtox, TCG_CALL_NO_WG, s64, env, f64) DEF_HELPER_FLAGS_2(fqtox, TCG_CALL_NO_WG, s64, env, i128) -DEF_HELPER_FLAGS_2(fpmerge, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(fpmerge, TCG_CALL_NO_RWG_SE, i64, i32, i32) DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_NO_RWG_SE, i64, i32, i64) DEF_HELPER_FLAGS_2(fmul8x16a, TCG_CALL_NO_RWG_SE, i64, i32, s32) DEF_HELPER_FLAGS_2(fmul8sux16, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 8a2894bb9f..99c6f3cc72 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -4656,6 +4656,7 @@ TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au) TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al) TRANS(FMULD8SUx16, VIS1, do_dff, a, gen_op_fmuld8sux16) TRANS(FMULD8ULx16, VIS1, do_dff, a, gen_op_fmuld8ulx16) +TRANS(FPMERGE, VIS1, do_dff, a, gen_helper_fpmerge) static bool do_dfd(DisasContext *dc, arg_r_r_r *a, void (*func)(TCGv_i64, TCGv_i32, TCGv_i64)) @@ -4696,7 +4697,6 @@ static bool do_ddd(DisasContext *dc, arg_r_r_r *a, TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) -TRANS(FPMERGE, VIS1, do_ddd, a, gen_helper_fpmerge) TRANS(FPADD16, VIS1, do_ddd, a, tcg_gen_vec_add16_i64) TRANS(FPADD32, VIS1, do_ddd, a, tcg_gen_vec_add32_i64) diff --git a/target/sparc/vis_helper.c b/target/sparc/vis_helper.c index 61c61c7fea..14c665cad6 100644 --- a/target/sparc/vis_helper.c +++ b/target/sparc/vis_helper.c @@ -74,22 +74,23 @@ typedef union { float32 f; } VIS32; -uint64_t helper_fpmerge(uint64_t src1, uint64_t src2) +uint64_t helper_fpmerge(uint32_t src1, uint32_t src2) { - VIS64 s, d; + VIS32 s1, s2; + VIS64 d; - s.ll = src1; - d.ll = src2; + s1.l = src1; + s2.l = src2; + d.ll = 0; - /* Reverse calculation order to handle overlap */ - d.VIS_B64(7) = s.VIS_B64(3); - d.VIS_B64(6) = d.VIS_B64(3); - d.VIS_B64(5) = s.VIS_B64(2); - d.VIS_B64(4) = d.VIS_B64(2); - d.VIS_B64(3) = s.VIS_B64(1); - d.VIS_B64(2) = d.VIS_B64(1); - d.VIS_B64(1) = s.VIS_B64(0); - /* d.VIS_B64(0) = d.VIS_B64(0); */ + d.VIS_B64(7) = s1.VIS_B32(3); + d.VIS_B64(6) = s2.VIS_B32(3); + d.VIS_B64(5) = s1.VIS_B32(2); + d.VIS_B64(4) = s2.VIS_B32(2); + d.VIS_B64(3) = s1.VIS_B32(1); + d.VIS_B64(2) = s2.VIS_B32(1); + d.VIS_B64(1) = s1.VIS_B32(0); + d.VIS_B64(0) = s2.VIS_B32(0); return d.ll; } From d6f898cf85c92389182d22f0bcc3a11d7194fc94 Mon Sep 17 00:00:00 2001 From: Richard Henderson <richard.henderson@linaro.org> Date: Thu, 2 May 2024 09:55:28 -0700 Subject: [PATCH 12/12] target/sparc: Split out do_ms16b MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The unit operation for fmul8x16 and friends is described in the manual as "MS16b". Split that out for clarity. Improve rounding with an unconditional addition of 0.5 as a fixed-point integer. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20240502165528.244004-8-richard.henderson@linaro.org> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> --- target/sparc/vis_helper.c | 78 ++++++++++++--------------------------- 1 file changed, 24 insertions(+), 54 deletions(-) diff --git a/target/sparc/vis_helper.c b/target/sparc/vis_helper.c index 14c665cad6..e15c6bb34e 100644 --- a/target/sparc/vis_helper.c +++ b/target/sparc/vis_helper.c @@ -44,6 +44,7 @@ target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize) #if HOST_BIG_ENDIAN #define VIS_B64(n) b[7 - (n)] +#define VIS_SB64(n) sb[7 - (n)] #define VIS_W64(n) w[3 - (n)] #define VIS_SW64(n) sw[3 - (n)] #define VIS_L64(n) l[1 - (n)] @@ -51,6 +52,7 @@ target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize) #define VIS_W32(n) w[1 - (n)] #else #define VIS_B64(n) b[n] +#define VIS_SB64(n) sb[n] #define VIS_W64(n) w[n] #define VIS_SW64(n) sw[n] #define VIS_L64(n) l[n] @@ -60,6 +62,7 @@ target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize) typedef union { uint8_t b[8]; + int8_t sb[8]; uint16_t w[4]; int16_t sw[4]; uint32_t l[2]; @@ -95,27 +98,23 @@ uint64_t helper_fpmerge(uint32_t src1, uint32_t src2) return d.ll; } +static inline int do_ms16b(int x, int y) +{ + return ((x * y) + 0x80) >> 8; +} + uint64_t helper_fmul8x16(uint32_t src1, uint64_t src2) { VIS64 d; VIS32 s; - uint32_t tmp; s.l = src1; d.ll = src2; -#define PMUL(r) \ - tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B32(r); \ - if ((tmp & 0xff) > 0x7f) { \ - tmp += 0x100; \ - } \ - d.VIS_W64(r) = tmp >> 8; - - PMUL(0); - PMUL(1); - PMUL(2); - PMUL(3); -#undef PMUL + d.VIS_W64(0) = do_ms16b(s.VIS_B32(0), d.VIS_SW64(0)); + d.VIS_W64(1) = do_ms16b(s.VIS_B32(1), d.VIS_SW64(1)); + d.VIS_W64(2) = do_ms16b(s.VIS_B32(2), d.VIS_SW64(2)); + d.VIS_W64(3) = do_ms16b(s.VIS_B32(3), d.VIS_SW64(3)); return d.ll; } @@ -124,25 +123,14 @@ uint64_t helper_fmul8x16a(uint32_t src1, int32_t src2) { VIS32 s; VIS64 d; - uint32_t tmp; s.l = src1; d.ll = 0; -#define PMUL(r) \ - do { \ - tmp = src2 * (int32_t)s.VIS_B32(r); \ - if ((tmp & 0xff) > 0x7f) { \ - tmp += 0x100; \ - } \ - d.VIS_W64(r) = tmp >> 8; \ - } while (0) - - PMUL(0); - PMUL(1); - PMUL(2); - PMUL(3); -#undef PMUL + d.VIS_W64(0) = do_ms16b(s.VIS_B32(0), src2); + d.VIS_W64(1) = do_ms16b(s.VIS_B32(1), src2); + d.VIS_W64(2) = do_ms16b(s.VIS_B32(2), src2); + d.VIS_W64(3) = do_ms16b(s.VIS_B32(3), src2); return d.ll; } @@ -150,23 +138,14 @@ uint64_t helper_fmul8x16a(uint32_t src1, int32_t src2) uint64_t helper_fmul8sux16(uint64_t src1, uint64_t src2) { VIS64 s, d; - uint32_t tmp; s.ll = src1; d.ll = src2; -#define PMUL(r) \ - tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \ - if ((tmp & 0xff) > 0x7f) { \ - tmp += 0x100; \ - } \ - d.VIS_W64(r) = tmp >> 8; - - PMUL(0); - PMUL(1); - PMUL(2); - PMUL(3); -#undef PMUL + d.VIS_W64(0) = do_ms16b(s.VIS_SB64(1), d.VIS_SW64(0)); + d.VIS_W64(1) = do_ms16b(s.VIS_SB64(3), d.VIS_SW64(1)); + d.VIS_W64(2) = do_ms16b(s.VIS_SB64(5), d.VIS_SW64(2)); + d.VIS_W64(3) = do_ms16b(s.VIS_SB64(7), d.VIS_SW64(3)); return d.ll; } @@ -174,23 +153,14 @@ uint64_t helper_fmul8sux16(uint64_t src1, uint64_t src2) uint64_t helper_fmul8ulx16(uint64_t src1, uint64_t src2) { VIS64 s, d; - uint32_t tmp; s.ll = src1; d.ll = src2; -#define PMUL(r) \ - tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \ - if ((tmp & 0xff) > 0x7f) { \ - tmp += 0x100; \ - } \ - d.VIS_W64(r) = tmp >> 8; - - PMUL(0); - PMUL(1); - PMUL(2); - PMUL(3); -#undef PMUL + d.VIS_W64(0) = do_ms16b(s.VIS_B64(0), d.VIS_SW64(0)); + d.VIS_W64(1) = do_ms16b(s.VIS_B64(2), d.VIS_SW64(1)); + d.VIS_W64(2) = do_ms16b(s.VIS_B64(4), d.VIS_SW64(2)); + d.VIS_W64(3) = do_ms16b(s.VIS_B64(6), d.VIS_SW64(3)); return d.ll; }