diff mbox series

[v2,09/28] target/arm: Implement VLDR/VSTR system register

Message ID 20201119215617.29887-10-peter.maydell@linaro.org
State New
Headers show
Series target/arm: Implement v8.1M and Cortex-M55 | expand

Commit Message

Peter Maydell Nov. 19, 2020, 9:55 p.m. UTC
Implement the new-in-v8.1M VLDR/VSTR variants which directly
read or write FP system registers to memory.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/vfp.decode          | 14 ++++++
 target/arm/translate-vfp.c.inc | 89 ++++++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+)

Comments

Richard Henderson Dec. 1, 2020, 1:11 p.m. UTC | #1
On 11/19/20 3:55 PM, Peter Maydell wrote:
> +    gen_aa32_st32(s, value, addr, get_mem_index(s));

This is MemA, so should use

  gen_aa32_st_i32(s, value, addr, get_mem_index(s),
                  MO_UL | MO_ALIGN);

a-la my patch set from last week fixing other instances.

> +    gen_aa32_ld32u(s, value, addr, get_mem_index(s));

Similarly.

Otherwise,

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

r~
Peter Maydell Dec. 3, 2020, 11:39 a.m. UTC | #2
On Tue, 1 Dec 2020 at 13:11, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 11/19/20 3:55 PM, Peter Maydell wrote:
> > +    gen_aa32_st32(s, value, addr, get_mem_index(s));
>
> This is MemA, so should use
>
>   gen_aa32_st_i32(s, value, addr, get_mem_index(s),
>                   MO_UL | MO_ALIGN);
>
> a-la my patch set from last week fixing other instances.

Also " | s->be_data", right ?

thanks
-- PMM
Richard Henderson Dec. 3, 2020, 4:14 p.m. UTC | #3
On 12/3/20 5:39 AM, Peter Maydell wrote:
> On Tue, 1 Dec 2020 at 13:11, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> On 11/19/20 3:55 PM, Peter Maydell wrote:
>>> +    gen_aa32_st32(s, value, addr, get_mem_index(s));
>>
>> This is MemA, so should use
>>
>>   gen_aa32_st_i32(s, value, addr, get_mem_index(s),
>>                   MO_UL | MO_ALIGN);
>>
>> a-la my patch set from last week fixing other instances.
> 
> Also " | s->be_data", right ?

Ho hum, yes.  I saw your comment on this in the alignment patch set and I'll
think about A Better Way.


r~
diff mbox series

Patch

diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
index 1300ba045dd..6f7f28f9a46 100644
--- a/target/arm/vfp.decode
+++ b/target/arm/vfp.decode
@@ -84,6 +84,20 @@  VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8      vd=%vd_sp
 VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8      vd=%vd_sp
 VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8      vd=%vd_dp
 
+# M-profile VLDR/VSTR to sysreg
+%vldr_sysreg 22:1 13:3
+%imm7_0x4 0:7 !function=times_4
+
+&vldr_sysreg rn reg imm a w p
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
+             reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
+
+# P=0 W=0 is SEE "Related encodings", so split into two patterns
+VLDR_sysreg  ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
+VLDR_sysreg  ---- 110 0 . . 1   1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
+VSTR_sysreg  ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
+VSTR_sysreg  ---- 110 0 . . 1   0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
+
 # We split the load/store multiple up into two patterns to avoid
 # overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
 # grouping:
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
index 2d201ad0888..dc26759ab95 100644
--- a/target/arm/translate-vfp.c.inc
+++ b/target/arm/translate-vfp.c.inc
@@ -912,6 +912,95 @@  static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
     return true;
 }
 
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
+{
+    arg_vldr_sysreg *a = opaque;
+    uint32_t offset = a->imm;
+    TCGv_i32 addr;
+
+    if (!a->a) {
+        offset = - offset;
+    }
+
+    addr = load_reg(s, a->rn);
+    if (a->p) {
+        tcg_gen_addi_i32(addr, addr, offset);
+    }
+
+    if (s->v8m_stackcheck && a->rn == 13 && a->w) {
+        gen_helper_v8m_stackcheck(cpu_env, addr);
+    }
+
+    gen_aa32_st32(s, value, addr, get_mem_index(s));
+    tcg_temp_free_i32(value);
+
+    if (a->w) {
+        /* writeback */
+        if (!a->p) {
+            tcg_gen_addi_i32(addr, addr, offset);
+        }
+        store_reg(s, a->rn, addr);
+    } else {
+        tcg_temp_free_i32(addr);
+    }
+}
+
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
+{
+    arg_vldr_sysreg *a = opaque;
+    uint32_t offset = a->imm;
+    TCGv_i32 addr;
+    TCGv_i32 value = tcg_temp_new_i32();
+
+    if (!a->a) {
+        offset = - offset;
+    }
+
+    addr = load_reg(s, a->rn);
+    if (a->p) {
+        tcg_gen_addi_i32(addr, addr, offset);
+    }
+
+    if (s->v8m_stackcheck && a->rn == 13 && a->w) {
+        gen_helper_v8m_stackcheck(cpu_env, addr);
+    }
+
+    gen_aa32_ld32u(s, value, addr, get_mem_index(s));
+
+    if (a->w) {
+        /* writeback */
+        if (!a->p) {
+            tcg_gen_addi_i32(addr, addr, offset);
+        }
+        store_reg(s, a->rn, addr);
+    } else {
+        tcg_temp_free_i32(addr);
+    }
+    return value;
+}
+
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
+{
+    if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
+        return false;
+    }
+    if (a->rn == 15) {
+        return false;
+    }
+    return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
+}
+
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
+{
+    if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
+        return false;
+    }
+    if (a->rn == 15) {
+        return false;
+    }
+    return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
+}
+
 static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
 {
     TCGv_i32 tmp;