[Qemu-devel] [PULL 09/22] target/arm: Implement ARMv8.5-CondM

Maintainers: Eduardo Habkost <ehabkost@redhat.com>, Peter Maydell <peter.maydell@linaro.org>, Shannon Zhao <shannon.zhaosl@gmail.com>, Laurent Vivier <laurent@vivier.eu>, Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>, David Gibson <david@gibson.dropbear.id.au>, Riku Voipio <riku.voipio@iki.fi>, Paolo Bonzini <pbonzini@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, "Michael S. Tsirkin" <mst@redhat.com>, Igor Mammedov <imammedo@redhat.com>
There is a newer version of this series
[Qemu-devel] [PULL 09/22] target/arm: Implement ARMv8.5-CondM
Posted by Peter Maydell 6 years, 2 months ago
From: Richard Henderson <richard.henderson@linaro.org>

Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190301200501.16533-9-richard.henderson@linaro.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.h           |  5 ++++
 target/arm/cpu64.c         |  2 +-
 target/arm/translate-a64.c | 58 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index fc2909ea6dc..a7aaec63d74 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3436,6 +3436,11 @@ static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id)
     return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0;
 }
 
+static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2;
+}
+
 static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
 {
     return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index fcf79321e2f..9fe0844a828 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -309,7 +309,7 @@ static void aarch64_max_initfn(Object *obj)
         t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1);
         t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1);
         t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1);
-        t = FIELD_DP64(t, ID_AA64ISAR0, TS, 1);
+        t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */
         cpu->isar.id_aa64isar0 = t;
 
         t = cpu->isar.id_aa64isar1;
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 3cc9a99a9cb..0cfd07d3abd 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1646,6 +1646,48 @@ static void handle_sync(DisasContext *s, uint32_t insn,
     }
 }
 
+static void gen_xaflag(void)
+{
+    TCGv_i32 z = tcg_temp_new_i32();
+
+    tcg_gen_setcondi_i32(TCG_COND_EQ, z, cpu_ZF, 0);
+
+    /*
+     * (!C & !Z) << 31
+     * (!(C | Z)) << 31
+     * ~((C | Z) << 31)
+     * ~-(C | Z)
+     * (C | Z) - 1
+     */
+    tcg_gen_or_i32(cpu_NF, cpu_CF, z);
+    tcg_gen_subi_i32(cpu_NF, cpu_NF, 1);
+
+    /* !(Z & C) */
+    tcg_gen_and_i32(cpu_ZF, z, cpu_CF);
+    tcg_gen_xori_i32(cpu_ZF, cpu_ZF, 1);
+
+    /* (!C & Z) << 31 -> -(Z & ~C) */
+    tcg_gen_andc_i32(cpu_VF, z, cpu_CF);
+    tcg_gen_neg_i32(cpu_VF, cpu_VF);
+
+    /* C | Z */
+    tcg_gen_or_i32(cpu_CF, cpu_CF, z);
+
+    tcg_temp_free_i32(z);
+}
+
+static void gen_axflag(void)
+{
+    tcg_gen_sari_i32(cpu_VF, cpu_VF, 31);         /* V ? -1 : 0 */
+    tcg_gen_andc_i32(cpu_CF, cpu_CF, cpu_VF);     /* C & !V */
+
+    /* !(Z | V) -> !(!ZF | V) -> ZF & !V -> ZF & ~VF */
+    tcg_gen_andc_i32(cpu_ZF, cpu_ZF, cpu_VF);
+
+    tcg_gen_movi_i32(cpu_NF, 0);
+    tcg_gen_movi_i32(cpu_VF, 0);
+}
+
 /* MSR (immediate) - move immediate to processor state field */
 static void handle_msr_i(DisasContext *s, uint32_t insn,
                          unsigned int op1, unsigned int op2, unsigned int crm)
@@ -1665,6 +1707,22 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
         s->base.is_jmp = DISAS_NEXT;
         break;
 
+    case 0x01: /* XAFlag */
+        if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
+            goto do_unallocated;
+        }
+        gen_xaflag();
+        s->base.is_jmp = DISAS_NEXT;
+        break;
+
+    case 0x02: /* AXFlag */
+        if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
+            goto do_unallocated;
+        }
+        gen_axflag();
+        s->base.is_jmp = DISAS_NEXT;
+        break;
+
     case 0x05: /* SPSel */
         if (s->current_el == 0) {
             goto do_unallocated;
-- 
2.20.1


Re: [Qemu-devel] [PULL 09/22] target/arm: Implement ARMv8.5-CondM
Posted by Peter Maydell 5 years, 9 months ago
On Tue, 5 Mar 2019 at 16:51, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> From: Richard Henderson <richard.henderson@linaro.org>
>
> Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> Message-id: 20190301200501.16533-9-richard.henderson@linaro.org
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

> diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
> index fcf79321e2f..9fe0844a828 100644
> --- a/target/arm/cpu64.c
> +++ b/target/arm/cpu64.c
> @@ -309,7 +309,7 @@ static void aarch64_max_initfn(Object *obj)
>          t = FIELD_DP64(t, ID_AA64ISAR0, SM4, 1);
>          t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1);
>          t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1);
> -        t = FIELD_DP64(t, ID_AA64ISAR0, TS, 1);
> +        t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */
>          cpu->isar.id_aa64isar0 = t;
>
>          t = cpu->isar.id_aa64isar1;

Hi -- it's just been pointed out to me that if our 'max' CPU
supports v8.5-CondM then we ought to be setting the HWCAP2_FLAGM2
bit in the hwcaps for linux-user mode. (Maybe we implemented this
before the kernel defined the hwcap bit?)

I guess we should also cross check whether there are any other
recently introduced hwcap bits we now should be setting.

thanks
-- PMM

Re: [Qemu-devel] [PULL 09/22] target/arm: Implement ARMv8.5-CondM
Posted by Richard Henderson 5 years, 9 months ago
On 8/9/19 2:53 AM, Peter Maydell wrote:
> Hi -- it's just been pointed out to me that if our 'max' CPU
> supports v8.5-CondM then we ought to be setting the HWCAP2_FLAGM2
> bit in the hwcaps for linux-user mode. (Maybe we implemented this
> before the kernel defined the hwcap bit?)

Yep.  We added CondM in March and this hwcap bit was added in June.

I keep thinking that they'll stop adding hwcap bits that can now just as easily
be "read" (trap and emulated) from id registers.  They've filled up HWCAP, and
only have 23 left in HWCAP2.

> I guess we should also cross check whether there are any other
> recently introduced hwcap bits we now should be setting.

I'll have a look.


r~

Re: [Qemu-devel] [PULL 09/22] target/arm: Implement ARMv8.5-CondM
Posted by Alex Bennée 5 years, 9 months ago
Richard Henderson <richard.henderson@linaro.org> writes:

> On 8/9/19 2:53 AM, Peter Maydell wrote:
>> Hi -- it's just been pointed out to me that if our 'max' CPU
>> supports v8.5-CondM then we ought to be setting the HWCAP2_FLAGM2
>> bit in the hwcaps for linux-user mode. (Maybe we implemented this
>> before the kernel defined the hwcap bit?)
>
> Yep.  We added CondM in March and this hwcap bit was added in June.
>
> I keep thinking that they'll stop adding hwcap bits that can now just as easily
> be "read" (trap and emulated) from id registers.  They've filled up HWCAP, and
> only have 23 left in HWCAP2.

It's impressive on our modern hardware that bits are getting so scarce
;-)

We haven't yet started on filling up cs_base for our own flags but where
does it all end?

--
Alex Bennée