diff mbox series

[3/3] target/arm: Implement v8.4-RCPC

Message ID 20200224172846.13053-4-peter.maydell@linaro.org
State Superseded
Headers show
Series target/arm: Implement v8.3-RCPC and v8.4-RCPC | expand

Commit Message

Peter Maydell Feb. 24, 2020, 5:28 p.m. UTC
The v8.4-RCPC extension implements some new instructions:
 * LDAPUR, LDAPURB, LDAPURH, LDAPRSB, LDAPRSH, LDAPRSW
 * STLUR, STLURB, STLURH

These are all in a new subgroup of encodings that sits below the
top-level "Loads and Stores" group in the Arm ARM.

The STLUR* instructions have standard store-release semantics; the
LDAPUR* have Load-AcquirePC semantics, but (as with LDAPR*) we choose
to implement them as the slightly stronger Load-Acquire.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

---
 target/arm/cpu.h           |  5 +++
 linux-user/elfload.c       |  1 +
 target/arm/cpu64.c         |  2 +-
 target/arm/translate-a64.c | 90 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 97 insertions(+), 1 deletion(-)

-- 
2.20.1

Comments

Richard Henderson Feb. 24, 2020, 6:39 p.m. UTC | #1
On 2/24/20 9:28 AM, Peter Maydell wrote:
> The v8.4-RCPC extension implements some new instructions:

>  * LDAPUR, LDAPURB, LDAPURH, LDAPRSB, LDAPRSH, LDAPRSW

>  * STLUR, STLURB, STLURH

> 

> These are all in a new subgroup of encodings that sits below the

> top-level "Loads and Stores" group in the Arm ARM.

> 

> The STLUR* instructions have standard store-release semantics; the

> LDAPUR* have Load-AcquirePC semantics, but (as with LDAPR*) we choose

> to implement them as the slightly stronger Load-Acquire.

> 

> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

> ---

>  target/arm/cpu.h           |  5 +++

>  linux-user/elfload.c       |  1 +

>  target/arm/cpu64.c         |  2 +-

>  target/arm/translate-a64.c | 90 ++++++++++++++++++++++++++++++++++++++

>  4 files changed, 97 insertions(+), 1 deletion(-)


Reviewed-by: Richard Henderson <richard.henderson@linaro.org>



r~
Peter Maydell Feb. 24, 2020, 6:42 p.m. UTC | #2
On Mon, 24 Feb 2020 at 18:39, Richard Henderson
<richard.henderson@linaro.org> wrote:
>

> On 2/24/20 9:28 AM, Peter Maydell wrote:

> > The v8.4-RCPC extension implements some new instructions:

> >  * LDAPUR, LDAPURB, LDAPURH, LDAPRSB, LDAPRSH, LDAPRSW

> >  * STLUR, STLURB, STLURH

> >

> > These are all in a new subgroup of encodings that sits below the

> > top-level "Loads and Stores" group in the Arm ARM.

> >

> > The STLUR* instructions have standard store-release semantics; the

> > LDAPUR* have Load-AcquirePC semantics, but (as with LDAPR*) we choose

> > to implement them as the slightly stronger Load-Acquire.

> >

> > Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

> > ---

> >  target/arm/cpu.h           |  5 +++

> >  linux-user/elfload.c       |  1 +

> >  target/arm/cpu64.c         |  2 +-

> >  target/arm/translate-a64.c | 90 ++++++++++++++++++++++++++++++++++++++

> >  4 files changed, 97 insertions(+), 1 deletion(-)

>

> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


I guess your memtag series will need to account for the extra
loads/stores added by this series, incidentally.

thanks
-- PMM
diff mbox series

Patch

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 59b467a44bf..3ce453f1e01 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3732,6 +3732,11 @@  static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id)
     return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0;
 }
 
+static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id)
+{
+    return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2;
+}
+
 /*
  * Feature tests for "does this exist in either 32-bit or 64-bit?"
  */
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index a0ffbc8861d..94ec3dcab8f 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -659,6 +659,7 @@  static uint32_t get_elf_hwcap(void)
     GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
     GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
     GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC);
+    GET_FEATURE_ID(aa64_rcpc_8_4, ARM_HWCAP_A64_ILRCPC);
 
     return hwcaps;
 }
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 59b7c574e35..6aace57e4e2 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -657,7 +657,7 @@  static void aarch64_max_initfn(Object *obj)
         t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
         t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
         t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
-        t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 1); /* ARMv8.3-RCPC */
+        t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* ARMv8.4-RCPC */
         cpu->isar.id_aa64isar1 = t;
 
         t = cpu->isar.id_aa64pfr0;
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 7a066fb7cb2..579180af0a9 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -3283,6 +3283,88 @@  static void disas_ldst_pac(DisasContext *s, uint32_t insn,
     }
 }
 
+/*
+ * LDAPR/STLR (unscaled immediate)
+ *
+ *  31  30            24    22  21       12    10    5     0
+ * +------+-------------+-----+---+--------+-----+----+-----+
+ * | size | 0 1 1 0 0 1 | opc | 0 |  imm9  | 0 0 | Rn |  Rt |
+ * +------+-------------+-----+---+--------+-----+----+-----+
+ *
+ * Rt: source or destination register
+ * Rn: base register
+ * imm9: unscaled immediate offset
+ * opc: 00: STLUR*, 01/10/11: various LDAPUR*
+ * size: size of load/store
+ */
+static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
+{
+    int rt = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int offset = sextract32(insn, 12, 9);
+    int opc = extract32(insn, 22, 2);
+    int size = extract32(insn, 30, 2);
+    TCGv_i64 clean_addr, dirty_addr;
+    bool is_store = false;
+    bool is_signed = false;
+    bool extend = false;
+    bool iss_sf;
+
+    if (!dc_isar_feature(aa64_rcpc_8_4, s)) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    switch (opc) {
+    case 0: /* STLURB */
+        is_store = true;
+        break;
+    case 1: /* LDAPUR* */
+        break;
+    case 2: /* LDAPURS* 64-bit variant */
+        if (size == 3) {
+            unallocated_encoding(s);
+            return;
+        }
+        is_signed = true;
+        break;
+    case 3: /* LDAPURS* 32-bit variant */
+        if (size > 1) {
+            unallocated_encoding(s);
+            return;
+        }
+        is_signed = true;
+        extend = true; /* zero-extend 32->64 after signed load */
+        break;
+    default:
+        g_assert_not_reached();
+    }
+
+    iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
+
+    if (rn == 31) {
+        gen_check_sp_alignment(s);
+    }
+
+    dirty_addr = read_cpu_reg_sp(s, rn, 1);
+    tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
+    clean_addr = clean_data_tbi(s, dirty_addr);
+
+    if (is_store) {
+        /* Store-Release semantics */
+        tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
+        do_gpr_st(s, cpu_reg(s, rt), clean_addr, size, true, rt, iss_sf, true);
+    } else {
+        /*
+         * Load-AcquirePC semantics; we implement as the slightly more
+         * restrictive Load-Acquire.
+         */
+        do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, is_signed, extend,
+                  true, rt, iss_sf, true);
+        tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
+    }
+}
+
 /* Load/store register (all forms) */
 static void disas_ldst_reg(DisasContext *s, uint32_t insn)
 {
@@ -3634,6 +3716,14 @@  static void disas_ldst(DisasContext *s, uint32_t insn)
     case 0x0d: /* AdvSIMD load/store single structure */
         disas_ldst_single_struct(s, insn);
         break;
+    case 0x19: /* LDAPR/STLR (unscaled immediate) */
+        if (extract32(insn, 10, 2) != 0 ||
+            extract32(insn, 21, 1) != 0) {
+            unallocated_encoding(s);
+            break;
+        }
+        disas_ldst_ldapr_stlr(s, insn);
+        break;
     default:
         unallocated_encoding(s);
         break;