All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] target/arm: More v8.1M features
@ 2020-11-16 16:08 Peter Maydell
  2020-11-16 16:08 ` [PATCH 01/15] hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault Peter Maydell
                   ` (14 more replies)
  0 siblings, 15 replies; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

This patchset implements a somewhat miscellaneous collection of
new-in-v8.1M features, as well as some bugfixes. It's for-6.0
material.

In the bugfix category:
 * RAZWI (or BusFault for unprivileged accesses) the whole of the
   system PPB address range, not just the SCS
 * Don't clobber ID_PFR1.Security on M-profile
 * Don't allow VMRS/VMSR to fp sysregs that don't exist on M-profile

In the features category:
 * v8.1M PXN extension
 * VSCCLRM and CLRM insns
 * VLDR/VSTR (sysreg) insns
 * new M-profile fp sysregs: FPSCR_nzcvqc, FPCXT_S, FPCXT_NS
 * update FPDSCR masking to allow new-in-v8.1M bits in that register

As usual, none of this will be enabled until we eventually get
to the point of a complete v8.1M implementation and can define
a Cortex-M55 CPU model.

thanks
-- PMM

Peter Maydell (15):
  hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
  target/arm: Implement v8.1M PXN extension
  target/arm: Don't clobber ID_PFR1.Security on M-profile cores
  target/arm: Implement VSCCLRM insn
  target/arm: Implement CLRM instruction
  target/arm: Enforce M-profile VMRS/VMSR register restrictions
  target/arm: Refactor M-profile VMSR/VMRS handling
  target/arm: Move general-use constant expanders up in translate.c
  target/arm: Implement VLDR/VSTR system register
  target/arm: Implement M-profile FPSCR_nzcvqc
  target/arm: Use new FPCR_NZCV_MASK constant
  target/arm: Factor out preserve-fp-state from full_vfp_access_check()
  target/arm: Implement FPCXT_S fp system register
  target/arm: Implement FPCXT_NS fp system register
  hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M

 include/hw/intc/armv7m_nvic.h  |   1 +
 target/arm/cpu.h               |  30 ++
 target/arm/m-nocp.decode       |   8 +-
 target/arm/t32.decode          |   6 +-
 target/arm/vfp.decode          |  14 +
 hw/arm/armv7m.c                |   2 +-
 hw/intc/armv7m_nvic.c          |  87 ++++-
 target/arm/cpu.c               |   5 +-
 target/arm/helper.c            |   7 +-
 target/arm/translate.c         | 102 ++++--
 target/arm/translate-vfp.c.inc | 581 +++++++++++++++++++++++++++++++--
 11 files changed, 765 insertions(+), 78 deletions(-)

-- 
2.20.1



^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 01/15] hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-17 19:07   ` Richard Henderson
  2020-11-16 16:08 ` [PATCH 02/15] target/arm: Implement v8.1M PXN extension Peter Maydell
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

For M-profile CPUs, the range from 0xe0000000 to 0xe00fffff is the
Private Peripheral Bus range, which includes all of the memory mapped
devices and registers that are part of the CPU itself, including the
NVIC, systick timer, and debug and trace components like the Data
Watchpoint and Trace unit (DWT).  Within this large region, the range
0xe000e000 to 0xe000efff is the System Control Space (NVIC, system
registers, systick) and 0xe002e000 to 0exe002efff is its Non-secure
alias.

The architecture is clear that within the SCS unimplemented registers
should be RES0 for privileged accesses and generate BusFault for
unprivileged accesses, and we currently implement this.

It is less clear about how to handle accesses to unimplemented
regions of the wider PPB.  Unprivileged accesses should definitely
cause BusFaults (R_DQQS), but the behaviour of privileged accesses is
not given as a general rule.  However, the register definitions of
individual registers for components like the DWT all state that they
are RES0 if the relevant component is not implemented, so the
simplest way to provide that is to provide RAZ/WI for the whole range
for privileged accesses.  (The v7M Arm ARM does say that reserved
registers should be UNK/SBZP.)

Expand the container MemoryRegion that the NVIC exposes so that
it covers the whole PPB space. This means:
 * moving the address that the ARMV7M device maps it to down by
   0xe000 bytes
 * moving the off and the offsets within the container of all the
   subregions forward by 0xe000 bytes
 * adding a new default MemoryRegion that covers the whole container
   at a lower priority than anything else and which provides the
   RAZWI/BusFault behaviour

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/intc/armv7m_nvic.h |  1 +
 hw/arm/armv7m.c               |  2 +-
 hw/intc/armv7m_nvic.c         | 78 ++++++++++++++++++++++++++++++-----
 3 files changed, 69 insertions(+), 12 deletions(-)

diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
index bb087b23c35..33b6d8810c7 100644
--- a/include/hw/intc/armv7m_nvic.h
+++ b/include/hw/intc/armv7m_nvic.h
@@ -84,6 +84,7 @@ struct NVICState {
     MemoryRegion systickmem;
     MemoryRegion systick_ns_mem;
     MemoryRegion container;
+    MemoryRegion defaultmem;
 
     uint32_t num_irq;
     qemu_irq excpout;
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 8113b29f1fd..944f261dd05 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -225,7 +225,7 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
     sysbus_connect_irq(sbd, 0,
                        qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
 
-    memory_region_add_subregion(&s->container, 0xe000e000,
+    memory_region_add_subregion(&s->container, 0xe0000000,
                                 sysbus_mmio_get_region(sbd, 0));
 
     for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 42b1ad59e65..9628ce876e0 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -2479,6 +2479,43 @@ static const MemoryRegionOps nvic_systick_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
+/*
+ * Unassigned portions of the PPB space are RAZ/WI for privileged
+ * accesses, and fault for non-privileged accesses.
+ */
+static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
+                                    uint64_t *data, unsigned size,
+                                    MemTxAttrs attrs)
+{
+    qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
+                  (uint32_t)addr);
+    if (attrs.user) {
+        return MEMTX_ERROR;
+    }
+    *data = 0;
+    return MEMTX_OK;
+}
+
+static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
+                                     uint64_t value, unsigned size,
+                                     MemTxAttrs attrs)
+{
+    qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n",
+                  (uint32_t)addr);
+    if (attrs.user) {
+        return MEMTX_ERROR;
+    }
+    return MEMTX_OK;
+}
+
+static const MemoryRegionOps ppb_default_ops = {
+    .read_with_attrs = ppb_default_read,
+    .write_with_attrs = ppb_default_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 8,
+};
+
 static int nvic_post_load(void *opaque, int version_id)
 {
     NVICState *s = opaque;
@@ -2675,7 +2712,6 @@ static void nvic_systick_trigger(void *opaque, int n, int level)
 static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
 {
     NVICState *s = NVIC(dev);
-    int regionlen;
 
     /* The armv7m container object will have set our CPU pointer */
     if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
@@ -2718,7 +2754,20 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
                                                   M_REG_S));
     }
 
-    /* The NVIC and System Control Space (SCS) starts at 0xe000e000
+    /*
+     * This device provides a single sysbus memory region which
+     * represents the whole of the "System PPB" space. This is the
+     * range from 0xe0000000 to 0xe00fffff and includes the NVIC,
+     * the System Control Space (system registers), the systick timer,
+     * and for CPUs with the Security extension an NS banked version
+     * of all of these.
+     *
+     * The default behaviour for unimplemented registers/ranges
+     * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
+     * is to RAZ/WI for privileged access and BusFault for non-privileged
+     * access.
+     *
+     * The NVIC and System Control Space (SCS) starts at 0xe000e000
      * and looks like this:
      *  0x004 - ICTR
      *  0x010 - 0xff - systick
@@ -2741,32 +2790,39 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
      * generally code determining which banked register to use should
      * use attrs.secure; code determining actual behaviour of the system
      * should use env->v7m.secure.
+     *
+     * The container covers the whole PPB space. Within it the priority
+     * of overlapping regions is:
+     *  - default region (for RAZ/WI and BusFault) : -1
+     *  - system register regions : 0
+     *  - systick : 1
+     * This is because the systick device is a small block of registers
+     * in the middle of the other system control registers.
      */
-    regionlen = arm_feature(&s->cpu->env, ARM_FEATURE_V8) ? 0x21000 : 0x1000;
-    memory_region_init(&s->container, OBJECT(s), "nvic", regionlen);
-    /* The system register region goes at the bottom of the priority
-     * stack as it covers the whole page.
-     */
+    memory_region_init(&s->container, OBJECT(s), "nvic", 0x100000);
+    memory_region_init_io(&s->defaultmem, OBJECT(s), &ppb_default_ops, s,
+                          "nvic-default", 0x100000);
+    memory_region_add_subregion_overlap(&s->container, 0, &s->defaultmem, -1);
     memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
                           "nvic_sysregs", 0x1000);
-    memory_region_add_subregion(&s->container, 0, &s->sysregmem);
+    memory_region_add_subregion(&s->container, 0xe000, &s->sysregmem);
 
     memory_region_init_io(&s->systickmem, OBJECT(s),
                           &nvic_systick_ops, s,
                           "nvic_systick", 0xe0);
 
-    memory_region_add_subregion_overlap(&s->container, 0x10,
+    memory_region_add_subregion_overlap(&s->container, 0xe010,
                                         &s->systickmem, 1);
 
     if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
         memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
                               &nvic_sysreg_ns_ops, &s->sysregmem,
                               "nvic_sysregs_ns", 0x1000);
-        memory_region_add_subregion(&s->container, 0x20000, &s->sysreg_ns_mem);
+        memory_region_add_subregion(&s->container, 0x2e000, &s->sysreg_ns_mem);
         memory_region_init_io(&s->systick_ns_mem, OBJECT(s),
                               &nvic_sysreg_ns_ops, &s->systickmem,
                               "nvic_systick_ns", 0xe0);
-        memory_region_add_subregion_overlap(&s->container, 0x20010,
+        memory_region_add_subregion_overlap(&s->container, 0x2e010,
                                             &s->systick_ns_mem, 1);
     }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 02/15] target/arm: Implement v8.1M PXN extension
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
  2020-11-16 16:08 ` [PATCH 01/15] hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-17 19:10   ` Richard Henderson
  2020-11-16 16:08 ` [PATCH 03/15] target/arm: Don't clobber ID_PFR1.Security on M-profile cores Peter Maydell
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

In v8.1M the PXN architecture extension adds a new PXN bit to the
MPU_RLAR registers, which forbids execution of code in the region
from a privileged mode.

This is another feature which is just in the generic "in v8.1M" set
and has no ID register field indicating its presence.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/helper.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 11b0803df72..abc470d9f17 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11754,6 +11754,11 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
     } else {
         uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
         uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
+        bool pxn = false;
+
+        if (arm_feature(env, ARM_FEATURE_V8_1M)) {
+            pxn = extract32(env->pmsav8.rlar[secure][matchregion], 4, 1);
+        }
 
         if (m_is_system_region(env, address)) {
             /* System space is always execute never */
@@ -11761,7 +11766,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
         }
 
         *prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
-        if (*prot && !xn) {
+        if (*prot && !xn && !(pxn && !is_user)) {
             *prot |= PAGE_EXEC;
         }
         /* We don't need to look the attribute up in the MAIR0/MAIR1
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 03/15] target/arm: Don't clobber ID_PFR1.Security on M-profile cores
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
  2020-11-16 16:08 ` [PATCH 01/15] hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault Peter Maydell
  2020-11-16 16:08 ` [PATCH 02/15] target/arm: Implement v8.1M PXN extension Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-17 19:12   ` Richard Henderson
  2020-11-16 16:08 ` [PATCH 04/15] target/arm: Implement VSCCLRM insn Peter Maydell
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

In arm_cpu_realizefn() we check whether the board code disabled EL3
via the has_el3 CPU object property, which we create if the CPU
starts with the ARM_FEATURE_EL3 feature bit.  If it is disabled, then
we turn off ARM_FEATURE_EL3 and also zero out the relevant fields in
the ID_PFR1 and ID_AA64PFR0 registers.

This codepath was incorrectly being taken for M-profile CPUs, which
do not have an EL3 and don't set ARM_FEATURE_EL3, but which may have
the M-profile Security extension and so should have non-zero values
in the ID_PFR1.Security field.

Restrict the handling of the feature flag to A/R-profile cores.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 07492e9f9a4..40f3f798b2b 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1674,7 +1674,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         }
     }
 
-    if (!cpu->has_el3) {
+    if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) {
         /* If the has_el3 CPU property is disabled then we need to disable the
          * feature.
          */
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 04/15] target/arm: Implement VSCCLRM insn
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
                   ` (2 preceding siblings ...)
  2020-11-16 16:08 ` [PATCH 03/15] target/arm: Don't clobber ID_PFR1.Security on M-profile cores Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-17 19:31   ` Richard Henderson
  2020-11-16 16:08 ` [PATCH 05/15] target/arm: Implement CLRM instruction Peter Maydell
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

Implement the v8.1M VSCCLRM insn, which zeros floating point
registers if there is an active floating point context.

Because we want to use arm_gen_condlabel(), we need to move
the definition of that function up in translate.c so it is
before the #include of translate-vfp.c.inc.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.h               |  9 ++++
 target/arm/m-nocp.decode       |  8 +++-
 target/arm/translate.c         | 18 +++----
 target/arm/translate-vfp.c.inc | 86 ++++++++++++++++++++++++++++++++++
 4 files changed, 110 insertions(+), 11 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index c18a9167665..806c18a499f 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3555,6 +3555,15 @@ static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
     return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
 }
 
+static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
+{
+    /*
+     * Return true if M-profile state handling insns
+     * (VSCCLRM, CLRM, FPCTX access insns) are implemented
+     */
+    return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3;
+}
+
 static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
 {
     /* Sadly this is encoded differently for A-profile and M-profile */
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
index 28c8ac6b94c..ccd62e8739a 100644
--- a/target/arm/m-nocp.decode
+++ b/target/arm/m-nocp.decode
@@ -29,13 +29,17 @@
 # If the coprocessor is not present or disabled then we will generate
 # the NOCP exception; otherwise we let the insn through to the main decode.
 
+%vd_dp  22:1 12:4
+%vd_sp  12:4 22:1
+
 &nocp cp
 
 {
   # Special cases which do not take an early NOCP: VLLDM and VLSTM
   VLLDM_VLSTM  1110 1100 001 l:1 rn:4 0000 1010 0000 0000
-  # TODO: VSCCLRM (new in v8.1M) is similar:
-  #VSCCLRM      1110 1100 1-01 1111 ---- 1011 ---- ---0
+  # VSCCLRM (new in v8.1M) is similar:
+  VSCCLRM      1110 1100 1.01 1111 .... 1011 imm:7 0   vd=%vd_dp size=3
+  VSCCLRM      1110 1100 1.01 1111 .... 1010 imm:8     vd=%vd_sp size=2
 
   NOCP         111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
   NOCP         111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
diff --git a/target/arm/translate.c b/target/arm/translate.c
index f7d4ee393b7..4b17b2e0d46 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -100,6 +100,15 @@ void arm_translate_init(void)
     a64_translate_init();
 }
 
+/* Generate a label used for skipping this instruction */
+static void arm_gen_condlabel(DisasContext *s)
+{
+    if (!s->condjmp) {
+        s->condlabel = gen_new_label();
+        s->condjmp = 1;
+    }
+}
+
 /* Flags for the disas_set_da_iss info argument:
  * lower bits hold the Rt register number, higher bits are flags.
  */
@@ -5156,15 +5165,6 @@ static void gen_srs(DisasContext *s,
     s->base.is_jmp = DISAS_UPDATE_EXIT;
 }
 
-/* Generate a label used for skipping this instruction */
-static void arm_gen_condlabel(DisasContext *s)
-{
-    if (!s->condjmp) {
-        s->condlabel = gen_new_label();
-        s->condjmp = 1;
-    }
-}
-
 /* Skip this instruction if the ARM condition is false */
 static void arm_skip_unless(DisasContext *s, uint32_t cond)
 {
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
index f966de5b1f8..daf39306d04 100644
--- a/target/arm/translate-vfp.c.inc
+++ b/target/arm/translate-vfp.c.inc
@@ -3406,6 +3406,92 @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
     return true;
 }
 
+static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
+{
+    int btmreg, topreg;
+    TCGv_i64 zero64;
+    TCGv_i32 zero32;
+    TCGv_i32 aspen, sfpa;
+
+    if (!dc_isar_feature(aa32_m_sec_state, s)) {
+        /* Before v8.1M, fall through in decode to NOCP check */
+        return false;
+    }
+
+    /* Explicitly UNDEF because this takes precedence over NOCP */
+    if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) {
+        unallocated_encoding(s);
+        return true;
+    }
+
+    if (!dc_isar_feature(aa32_vfp_simd, s)) {
+        /* NOP if we have neither FP nor MVE */
+        return true;
+    }
+
+    /*
+     * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no
+     * active floating point context so we must NOP (without doing
+     * any lazy state preservation or the NOCP check).
+     */
+    aspen = load_cpu_field(v7m.fpccr[M_REG_S]);
+    sfpa = load_cpu_field(v7m.control[M_REG_S]);
+    tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
+    tcg_gen_subi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
+    tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
+    tcg_gen_or_i32(sfpa, sfpa, aspen);
+    arm_gen_condlabel(s);
+    tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
+
+    if (s->fp_excp_el != 0) {
+        gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
+                           syn_uncategorized(), s->fp_excp_el);
+        return true;
+    }
+
+    topreg = a->vd + a->imm - 1;
+    btmreg = a->vd;
+
+    /* Convert to Sreg numbers if the insn specified in Dregs */
+    if (a->size == 3) {
+        topreg = topreg * 2 + 1;
+        btmreg *= 2;
+    }
+
+    if (topreg > 63 || (topreg > 31 && !(topreg & 1))) {
+        /* UNPREDICTABLE: we choose to undef */
+        unallocated_encoding(s);
+        return true;
+    }
+
+    /* Silently ignore requests to clear D16-D31 if they don't exist */
+    if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) {
+        topreg = 31;
+    }
+
+    if (!vfp_access_check(s)) {
+        return true;
+    }
+
+    /* Zero the Sregs from btmreg to topreg inclusive. */
+    zero64 = tcg_const_i64(0);
+    zero32 = tcg_const_i32(0);
+    if (btmreg & 1) {
+        write_neon_element32(zero32, btmreg >> 1, 1, MO_32);
+        btmreg++;
+    }
+    for (; btmreg + 1 <= topreg; btmreg += 2) {
+        write_neon_element64(zero64, btmreg >> 1, 0, MO_64);
+    }
+    if (btmreg == topreg) {
+        write_neon_element32(zero32, btmreg >> 1, 0, MO_32);
+        btmreg++;
+    }
+    assert(btmreg == topreg + 1);
+    /* TODO: when MVE is implemented, zero VPR here */
+    return true;
+}
+
 static bool trans_NOCP(DisasContext *s, arg_nocp *a)
 {
     /*
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 05/15] target/arm: Implement CLRM instruction
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
                   ` (3 preceding siblings ...)
  2020-11-16 16:08 ` [PATCH 04/15] target/arm: Implement VSCCLRM insn Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-17 19:38   ` Richard Henderson
  2020-11-16 16:08 ` [PATCH 06/15] target/arm: Enforce M-profile VMRS/VMSR register restrictions Peter Maydell
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

In v8.1M the new CLRM instruction allows zeroing an arbitrary set of
the general-purpose registers and APSR.  Implement this.

The encoding is a subset of the LDMIA T2 encoding, using what would
be Rn=0b1111 (which UNDEFs for LDMIA).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/t32.decode  |  6 +++++-
 target/arm/translate.c | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/target/arm/t32.decode b/target/arm/t32.decode
index 8152739b52b..59ab974c661 100644
--- a/target/arm/t32.decode
+++ b/target/arm/t32.decode
@@ -609,7 +609,11 @@ UXTAB            1111 1010 0101 .... 1111 .... 10.. ....      @rrr_rot
 
 STM_t32          1110 1000 10.0 .... ................         @ldstm i=1 b=0
 STM_t32          1110 1001 00.0 .... ................         @ldstm i=0 b=1
-LDM_t32          1110 1000 10.1 .... ................         @ldstm i=1 b=0
+{
+  # Rn=15 UNDEFs for LDM; M-profile CLRM uses that encoding
+  CLRM           1110 1000 1001 1111 list:16
+  LDM_t32        1110 1000 10.1 .... ................         @ldstm i=1 b=0
+}
 LDM_t32          1110 1001 00.1 .... ................         @ldstm i=0 b=1
 
 &rfe             !extern rn w pu
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 4b17b2e0d46..ac8c118427f 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7965,6 +7965,44 @@ static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
     return do_ldm(s, a, 1);
 }
 
+static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
+{
+    int i;
+    TCGv_i32 zero;
+
+    if (!dc_isar_feature(aa32_m_sec_state, s)) {
+        return false;
+    }
+
+    if (extract32(a->list, 13, 1)) {
+        return false;
+    }
+
+    if (!a->list) {
+        /* UNPREDICTABLE; we choose to UNDEF */
+        return false;
+    }
+
+    zero = tcg_const_i32(0);
+    for (i = 0; i < 15; i++) {
+        if (extract32(a->list, i, 1)) {
+            /* Clear R[i] */
+            tcg_gen_mov_i32(cpu_R[i], zero);
+        }
+    }
+    if (extract32(a->list, 15, 1)) {
+        /*
+         * Clear APSR (by calling the MSR helper with the same argument
+         * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
+         */
+        TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
+        gen_helper_v7m_msr(cpu_env, maskreg, zero);
+        tcg_temp_free_i32(maskreg);
+    }
+    tcg_temp_free_i32(zero);
+    return true;
+}
+
 /*
  * Branch, branch with link
  */
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 06/15] target/arm: Enforce M-profile VMRS/VMSR register restrictions
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
                   ` (4 preceding siblings ...)
  2020-11-16 16:08 ` [PATCH 05/15] target/arm: Implement CLRM instruction Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-17 19:42   ` Richard Henderson
  2020-11-16 16:08 ` [PATCH 07/15] target/arm: Refactor M-profile VMSR/VMRS handling Peter Maydell
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

For M-profile before v8.1M, the only valid register for VMSR/VMRS is
the FPSCR.  We have a comment that states this, but the actual logic
to forbid accesses for any other register value is missing, so we
would end up with A-profile style behaviour.  Add the missing check.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/translate-vfp.c.inc | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
index daf39306d04..aee60ff98b3 100644
--- a/target/arm/translate-vfp.c.inc
+++ b/target/arm/translate-vfp.c.inc
@@ -622,7 +622,10 @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
          * Accesses to R15 are UNPREDICTABLE; we choose to undef.
          * (FPSCR -> r15 is a special case which writes to the PSR flags.)
          */
-        if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
+        if (a->reg != ARM_VFP_FPSCR) {
+            return false;
+        }
+        if (a->rt == 15 && !a->l) {
             return false;
         }
     }
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 07/15] target/arm: Refactor M-profile VMSR/VMRS handling
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
                   ` (5 preceding siblings ...)
  2020-11-16 16:08 ` [PATCH 06/15] target/arm: Enforce M-profile VMRS/VMSR register restrictions Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-16 16:08 ` [PATCH 08/15] target/arm: Move general-use constant expanders up in translate.c Peter Maydell
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

Currently M-profile borrows the A-profile code for VMSR and VMRS
(access to the FP system registers), because all it needs to support
is the FPSCR.  In v8.1M things become significantly more complicated
in two ways:

 * there are several new FP system registers; some have side effects
   on read, and one (FPCXT_NS) needs to avoid the usual
   vfp_access_check() and the "only if FPU implemented" check

 * all sysregs are now accessible both by VMRS/VMSR (which
   reads/writes a general purpose register) and also by VLDR/VSTR
   (which reads/writes them directly to memory)

Refactor the structure of how we handle VMSR/VMRS to cope with this:

 * keep the M-profile code entirely separate from the A-profile code

 * abstract out the "read or write the general purpose register" part
   of the code into a loadfn or storefn function pointer, so we can
   reuse it for VLDR/VSTR.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.h               |   3 +
 target/arm/translate-vfp.c.inc | 181 ++++++++++++++++++++++++++++++---
 2 files changed, 170 insertions(+), 14 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 806c18a499f..3b20f935174 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1569,6 +1569,9 @@ enum arm_cpu_mode {
 #define ARM_VFP_FPINST  9
 #define ARM_VFP_FPINST2 10
 
+/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
+#define QEMU_VFP_FPSCR_NZCV 0xffff
+
 /* iwMMXt coprocessor control registers.  */
 #define ARM_IWMMXT_wCID  0
 #define ARM_IWMMXT_wCon  1
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
index aee60ff98b3..5d880d12116 100644
--- a/target/arm/translate-vfp.c.inc
+++ b/target/arm/translate-vfp.c.inc
@@ -607,27 +607,180 @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
     return true;
 }
 
+/*
+ * M-profile provides two different sets of instructions that can
+ * access floating point system registers: VMSR/VMRS (which move
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
+ * move directly to/from memory). In some cases there are also side
+ * effects which must happen after any write to memory (which could
+ * cause an exception). So we implement the common logic for the
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
+ * which take pointers to callback functions which will perform the
+ * actual "read/write general purpose register" and "read/write
+ * memory" operations.
+ */
+
+/*
+ * Emit code to store the sysreg to its final destination; frees the
+ * TCG temp 'value' it is passed.
+ */
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
+/*
+ * Emit code to load the value to be copied to the sysreg; returns
+ * a new TCG temporary
+ */
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
+
+/* Common decode/access checks for fp sysreg read/write */
+typedef enum fp_sysreg_check_result {
+    fp_sysreg_check_failed, /* caller should return false */
+    fp_sysreg_check_done, /* caller should return true */
+    fp_sysreg_check_continue, /* caller should continue generating code */
+} fp_sysreg_check_result;
+
+static fp_sysreg_check_result fp_sysreg_checks(DisasContext *s, int regno)
+{
+    if (!dc_isar_feature(aa32_fpsp_v2, s)) {
+        return fp_sysreg_check_failed;
+    }
+
+    switch (regno) {
+    case ARM_VFP_FPSCR:
+    case QEMU_VFP_FPSCR_NZCV:
+        break;
+    default:
+        return fp_sysreg_check_failed;
+    }
+
+    if (!vfp_access_check(s)) {
+        return fp_sysreg_check_done;
+    }
+
+    return fp_sysreg_check_continue;
+}
+
+static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
+                                 fp_sysreg_loadfn *loadfn,
+                                 void *opaque)
+{
+    /* Do a write to an M-profile floating point system register */
+    TCGv_i32 tmp;
+
+    switch (fp_sysreg_checks(s, regno)) {
+    case fp_sysreg_check_failed:
+        return false;
+    case fp_sysreg_check_done:
+        return true;
+    case fp_sysreg_check_continue:
+        break;
+    }
+
+    switch (regno) {
+    case ARM_VFP_FPSCR:
+        tmp = loadfn(s, opaque);
+        gen_helper_vfp_set_fpscr(cpu_env, tmp);
+        tcg_temp_free_i32(tmp);
+        gen_lookup_tb(s);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    return true;
+}
+
+static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
+                                fp_sysreg_storefn *storefn,
+                                void *opaque)
+{
+    /* Do a read from an M-profile floating point system register */
+    TCGv_i32 tmp;
+
+    switch (fp_sysreg_checks(s, regno)) {
+    case fp_sysreg_check_failed:
+        return false;
+    case fp_sysreg_check_done:
+        return true;
+    case fp_sysreg_check_continue:
+        break;
+    }
+
+    switch (regno) {
+    case ARM_VFP_FPSCR:
+        tmp = tcg_temp_new_i32();
+        gen_helper_vfp_get_fpscr(tmp, cpu_env);
+        storefn(s, opaque, tmp);
+        break;
+    case QEMU_VFP_FPSCR_NZCV:
+        /*
+         * Read just NZCV; this is a special case to avoid the
+         * helper call for the "VMRS to CPSR.NZCV" insn.
+         */
+        tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
+        tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
+        storefn(s, opaque, tmp);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    return true;
+}
+
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
+{
+    arg_VMSR_VMRS *a = opaque;
+
+    if (a->rt == 15) {
+        /* Set the 4 flag bits in the CPSR */
+        gen_set_nzcv(value);
+        tcg_temp_free_i32(value);
+    } else {
+        store_reg(s, a->rt, value);
+    }
+}
+
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
+{
+    arg_VMSR_VMRS *a = opaque;
+
+    return load_reg(s, a->rt);
+}
+
+static bool gen_M_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
+{
+    /*
+     * Accesses to R15 are UNPREDICTABLE; we choose to undef.
+     * FPSCR -> r15 is a special case which writes to the PSR flags;
+     * set a->reg to a special value to tell gen_M_fp_sysreg_read()
+     * we only care about the top 4 bits of FPSCR there.
+     */
+    if (a->rt == 15) {
+        if (a->l && a->reg == ARM_VFP_FPSCR) {
+            a->reg = QEMU_VFP_FPSCR_NZCV;
+        } else {
+            return false;
+        }
+    }
+
+    if (a->l) {
+        /* VMRS, move FP system register to gp register */
+        return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
+    } else {
+        /* VMSR, move gp register to FP system register */
+        return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
+    }
+}
+
 static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
 {
     TCGv_i32 tmp;
     bool ignore_vfp_enabled = false;
 
-    if (!dc_isar_feature(aa32_fpsp_v2, s)) {
-        return false;
+    if (arm_dc_feature(s, ARM_FEATURE_M)) {
+        return gen_M_VMSR_VMRS(s, a);
     }
 
-    if (arm_dc_feature(s, ARM_FEATURE_M)) {
-        /*
-         * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
-         * Accesses to R15 are UNPREDICTABLE; we choose to undef.
-         * (FPSCR -> r15 is a special case which writes to the PSR flags.)
-         */
-        if (a->reg != ARM_VFP_FPSCR) {
-            return false;
-        }
-        if (a->rt == 15 && !a->l) {
-            return false;
-        }
+    if (!dc_isar_feature(aa32_fpsp_v2, s)) {
+        return false;
     }
 
     switch (a->reg) {
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 08/15] target/arm: Move general-use constant expanders up in translate.c
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
                   ` (6 preceding siblings ...)
  2020-11-16 16:08 ` [PATCH 07/15] target/arm: Refactor M-profile VMSR/VMRS handling Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-17 19:47   ` Richard Henderson
  2020-11-16 16:08 ` [PATCH 09/15] target/arm: Implement VLDR/VSTR system register Peter Maydell
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

The constant-expander functions like negate, plus_2, etc, are
generally useful; move them up in translate.c so we can use them in
the VFP/Neon decoders as well as in the A32/T32/T16 decoders.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/translate.c | 46 +++++++++++++++++++++++-------------------
 1 file changed, 25 insertions(+), 21 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index ac8c118427f..3e5bcab0a62 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -109,6 +109,30 @@ static void arm_gen_condlabel(DisasContext *s)
     }
 }
 
+/*
+ * Constant expanders for the decoders.
+ */
+
+static int negate(DisasContext *s, int x)
+{
+    return -x;
+}
+
+static int plus_2(DisasContext *s, int x)
+{
+    return x + 2;
+}
+
+static int times_2(DisasContext *s, int x)
+{
+    return x * 2;
+}
+
+static int times_4(DisasContext *s, int x)
+{
+    return x * 4;
+}
+
 /* Flags for the disas_set_da_iss info argument:
  * lower bits hold the Rt register number, higher bits are flags.
  */
@@ -5174,29 +5198,9 @@ static void arm_skip_unless(DisasContext *s, uint32_t cond)
 
 
 /*
- * Constant expanders for the decoders.
+ * Constant expanders used by T16/T32 decode
  */
 
-static int negate(DisasContext *s, int x)
-{
-    return -x;
-}
-
-static int plus_2(DisasContext *s, int x)
-{
-    return x + 2;
-}
-
-static int times_2(DisasContext *s, int x)
-{
-    return x * 2;
-}
-
-static int times_4(DisasContext *s, int x)
-{
-    return x * 4;
-}
-
 /* Return only the rotation part of T32ExpandImm.  */
 static int t32_expandimm_rot(DisasContext *s, int x)
 {
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 09/15] target/arm: Implement VLDR/VSTR system register
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
                   ` (7 preceding siblings ...)
  2020-11-16 16:08 ` [PATCH 08/15] target/arm: Move general-use constant expanders up in translate.c Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-16 16:08 ` [PATCH 10/15] target/arm: Implement M-profile FPSCR_nzcvqc Peter Maydell
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

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(+)

diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
index 51f143b4a51..45e3023840b 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 5d880d12116..cc115f1d35d 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;
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 10/15] target/arm: Implement M-profile FPSCR_nzcvqc
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
                   ` (8 preceding siblings ...)
  2020-11-16 16:08 ` [PATCH 09/15] target/arm: Implement VLDR/VSTR system register Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-16 16:08 ` [PATCH 11/15] target/arm: Use new FPCR_NZCV_MASK constant Peter Maydell
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

v8.1M defines a new FP system register FPSCR_nzcvqc; this behaves
like the existing FPSCR, except that it reads and writes only bits
[31:27] of the FPSCR (the N, Z, C, V and QC flag bits).  (Unlike the
FPSCR, the special case for Rt=15 of writing the CPSR.NZCV is not
permitted.)

Implement the register.  Since we don't yet implement MVE, we handle
the QC bit as RES0, with todo comments for where we will need to add
support later.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.h               | 13 +++++++++++++
 target/arm/translate-vfp.c.inc | 27 +++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 3b20f935174..34f8f4afe18 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1524,6 +1524,13 @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
 #define FPCR_FZ     (1 << 24)   /* Flush-to-zero enable bit */
 #define FPCR_DN     (1 << 25)   /* Default NaN enable bit */
 #define FPCR_QC     (1 << 27)   /* Cumulative saturation bit */
+#define FPCR_V      (1 << 28)   /* FP overflow flag */
+#define FPCR_C      (1 << 29)   /* FP carry flag */
+#define FPCR_Z      (1 << 30)   /* FP zero flag */
+#define FPCR_N      (1 << 31)   /* FP negative flag */
+
+#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
+#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
 
 static inline uint32_t vfp_get_fpsr(CPUARMState *env)
 {
@@ -1568,6 +1575,12 @@ enum arm_cpu_mode {
 #define ARM_VFP_FPEXC   8
 #define ARM_VFP_FPINST  9
 #define ARM_VFP_FPINST2 10
+/* These ones are M-profile only */
+#define ARM_VFP_FPSCR_NZCVQC 2
+#define ARM_VFP_VPR 12
+#define ARM_VFP_P0 13
+#define ARM_VFP_FPCXT_NS 14
+#define ARM_VFP_FPCXT_S 15
 
 /* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
 #define QEMU_VFP_FPSCR_NZCV 0xffff
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
index cc115f1d35d..84e806004e4 100644
--- a/target/arm/translate-vfp.c.inc
+++ b/target/arm/translate-vfp.c.inc
@@ -648,6 +648,11 @@ static fp_sysreg_check_result fp_sysreg_checks(DisasContext *s, int regno)
     case ARM_VFP_FPSCR:
     case QEMU_VFP_FPSCR_NZCV:
         break;
+    case ARM_VFP_FPSCR_NZCVQC:
+        if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
+            return false;
+        }
+        break;
     default:
         return fp_sysreg_check_failed;
     }
@@ -682,6 +687,22 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
         tcg_temp_free_i32(tmp);
         gen_lookup_tb(s);
         break;
+    case ARM_VFP_FPSCR_NZCVQC:
+    {
+        TCGv_i32 fpscr;
+        tmp = loadfn(s, opaque);
+        /*
+         * TODO: when we implement MVE, write the QC bit.
+         * For non-MVE, QC is RES0.
+         */
+        tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
+        fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
+        tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
+        tcg_gen_or_i32(fpscr, fpscr, tmp);
+        store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
+        tcg_temp_free_i32(tmp);
+        break;
+    }
     default:
         g_assert_not_reached();
     }
@@ -710,6 +731,12 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
         gen_helper_vfp_get_fpscr(tmp, cpu_env);
         storefn(s, opaque, tmp);
         break;
+    case ARM_VFP_FPSCR_NZCVQC:
+        /*
+         * TODO: MVE has a QC bit, which we probably won't store
+         * in the xregs[] field. For non-MVE, where QC is RES0,
+         * we can just fall through to the FPSCR_NZCV case.
+         */
     case QEMU_VFP_FPSCR_NZCV:
         /*
          * Read just NZCV; this is a special case to avoid the
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 11/15] target/arm: Use new FPCR_NZCV_MASK constant
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
                   ` (9 preceding siblings ...)
  2020-11-16 16:08 ` [PATCH 10/15] target/arm: Implement M-profile FPSCR_nzcvqc Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-17 19:49   ` Richard Henderson
  2020-11-16 16:08 ` [PATCH 12/15] target/arm: Factor out preserve-fp-state from full_vfp_access_check() Peter Maydell
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

We defined a constant name for the mask of NZCV bits in the FPCR/FPSCR
in the previous commit; use it in a couple of places in existing code,
where we're masking out everything except NZCV for the "load to Rt=15
sets CPSR.NZCV" special case.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/translate-vfp.c.inc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
index 84e806004e4..1ccaccbc834 100644
--- a/target/arm/translate-vfp.c.inc
+++ b/target/arm/translate-vfp.c.inc
@@ -743,7 +743,7 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
          * helper call for the "VMRS to CPSR.NZCV" insn.
          */
         tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
-        tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
+        tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
         storefn(s, opaque, tmp);
         break;
     default:
@@ -884,7 +884,7 @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
         case ARM_VFP_FPSCR:
             if (a->rt == 15) {
                 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
-                tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
+                tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
             } else {
                 tmp = tcg_temp_new_i32();
                 gen_helper_vfp_get_fpscr(tmp, cpu_env);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 12/15] target/arm: Factor out preserve-fp-state from full_vfp_access_check()
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
                   ` (10 preceding siblings ...)
  2020-11-16 16:08 ` [PATCH 11/15] target/arm: Use new FPCR_NZCV_MASK constant Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-17 19:50   ` Richard Henderson
  2020-11-16 16:08 ` [PATCH 13/15] target/arm: Implement FPCXT_S fp system register Peter Maydell
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

Factor out the code which handles M-profile lazy FP state preservation
from full_vfp_access_check(); accesses to the FPCXT_NS register are
a special case which need to do just this part (corresponding in the
pseudocode to the PreserveFPState() function), and not the full
set of actions matching the pseudocode ExecuteFPCheck() which
normal FP instructions need to do.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/translate-vfp.c.inc | 45 ++++++++++++++++++++--------------
 1 file changed, 27 insertions(+), 18 deletions(-)

diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
index 1ccaccbc834..6bc07992eb4 100644
--- a/target/arm/translate-vfp.c.inc
+++ b/target/arm/translate-vfp.c.inc
@@ -83,6 +83,32 @@ static inline long vfp_f16_offset(unsigned reg, bool top)
     return offs;
 }
 
+/*
+ * Generate code for M-profile lazy FP state preservation if needed;
+ * this corresponds to the pseudocode PreserveFPState() function.
+ */
+static void gen_preserve_fp_state(DisasContext *s)
+{
+    if (s->v7m_lspact) {
+        /*
+         * Lazy state saving affects external memory and also the NVIC,
+         * so we must mark it as an IO operation for icount (and cause
+         * this to be the last insn in the TB).
+         */
+        if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
+            s->base.is_jmp = DISAS_UPDATE_EXIT;
+            gen_io_start();
+        }
+        gen_helper_v7m_preserve_fp_state(cpu_env);
+        /*
+         * If the preserve_fp_state helper doesn't throw an exception
+         * then it will clear LSPACT; we don't need to repeat this for
+         * any further FP insns in this TB.
+         */
+        s->v7m_lspact = false;
+    }
+}
+
 /*
  * Check that VFP access is enabled. If it is, do the necessary
  * M-profile lazy-FP handling and then return true.
@@ -113,24 +139,7 @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
         /* Handle M-profile lazy FP state mechanics */
 
         /* Trigger lazy-state preservation if necessary */
-        if (s->v7m_lspact) {
-            /*
-             * Lazy state saving affects external memory and also the NVIC,
-             * so we must mark it as an IO operation for icount (and cause
-             * this to be the last insn in the TB).
-             */
-            if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
-                s->base.is_jmp = DISAS_UPDATE_EXIT;
-                gen_io_start();
-            }
-            gen_helper_v7m_preserve_fp_state(cpu_env);
-            /*
-             * If the preserve_fp_state helper doesn't throw an exception
-             * then it will clear LSPACT; we don't need to repeat this for
-             * any further FP insns in this TB.
-             */
-            s->v7m_lspact = false;
-        }
+        gen_preserve_fp_state(s);
 
         /* Update ownership of FP context: set FPCCR.S to match current state */
         if (s->v8m_fpccr_s_wrong) {
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 13/15] target/arm: Implement FPCXT_S fp system register
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
                   ` (11 preceding siblings ...)
  2020-11-16 16:08 ` [PATCH 12/15] target/arm: Factor out preserve-fp-state from full_vfp_access_check() Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-16 16:08 ` [PATCH 14/15] target/arm: Implement FPCXT_NS " Peter Maydell
  2020-11-16 16:08 ` [PATCH 15/15] hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M Peter Maydell
  14 siblings, 0 replies; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

Implement the new-in-v8.1M FPCXT_S floating point system register.
This is for saving and restoring the secure floating point context,
and it reads and writes bits [27:0] from the FPSCR and the
CONTROL.SFPA bit in bit [31].

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/translate-vfp.c.inc | 58 ++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
index 6bc07992eb4..c7ae306f12f 100644
--- a/target/arm/translate-vfp.c.inc
+++ b/target/arm/translate-vfp.c.inc
@@ -662,6 +662,14 @@ static fp_sysreg_check_result fp_sysreg_checks(DisasContext *s, int regno)
             return false;
         }
         break;
+    case ARM_VFP_FPCXT_S:
+        if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
+            return false;
+        }
+        if (!s->v8m_secure) {
+            return false;
+        }
+        break;
     default:
         return fp_sysreg_check_failed;
     }
@@ -712,6 +720,26 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
         tcg_temp_free_i32(tmp);
         break;
     }
+    case ARM_VFP_FPCXT_S:
+    {
+        TCGv_i32 sfpa, control, fpscr;
+        /* Set FPSCR[27:0] and CONTROL.SFPA from value */
+        tmp = loadfn(s, opaque);
+        sfpa = tcg_temp_new_i32();
+        tcg_gen_shri_i32(sfpa, tmp, 31);
+        control = load_cpu_field(v7m.control[M_REG_S]);
+        tcg_gen_deposit_i32(control, control, sfpa,
+                            R_V7M_CONTROL_SFPA_SHIFT, 1);
+        store_cpu_field(control, v7m.control[M_REG_S]);
+        fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
+        tcg_gen_andi_i32(fpscr, fpscr, FPCR_NZCV_MASK);
+        tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
+        tcg_gen_or_i32(fpscr, fpscr, tmp);
+        store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
+        tcg_temp_free_i32(tmp);
+        tcg_temp_free_i32(sfpa);
+        break;
+    }
     default:
         g_assert_not_reached();
     }
@@ -755,6 +783,36 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
         tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
         storefn(s, opaque, tmp);
         break;
+    case ARM_VFP_FPCXT_S:
+    {
+        TCGv_i32 control, sfpa, fpscr;
+        /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
+        tmp = tcg_temp_new_i32();
+        sfpa = tcg_temp_new_i32();
+        gen_helper_vfp_get_fpscr(tmp, cpu_env);
+        tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
+        control = load_cpu_field(v7m.control[M_REG_S]);
+        tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
+        tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
+        tcg_gen_or_i32(tmp, tmp, sfpa);
+        tcg_temp_free_i32(sfpa);
+        /*
+         * Store result before updating FPSCR etc, in case
+         * it is a memory write which causes an exception.
+         */
+        storefn(s, opaque, tmp);
+        /*
+         * Now we must reset FPSCR from FPDSCR_NS, and clear
+         * CONTROL.SFPA; so we'll end the TB here.
+         */
+        tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
+        store_cpu_field(control, v7m.control[M_REG_S]);
+        fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
+        gen_helper_vfp_set_fpscr(cpu_env, fpscr);
+        tcg_temp_free_i32(fpscr);
+        gen_lookup_tb(s);
+        break;
+    }
     default:
         g_assert_not_reached();
     }
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 14/15] target/arm: Implement FPCXT_NS fp system register
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
                   ` (12 preceding siblings ...)
  2020-11-16 16:08 ` [PATCH 13/15] target/arm: Implement FPCXT_S fp system register Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  2020-11-16 16:08 ` [PATCH 15/15] hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M Peter Maydell
  14 siblings, 0 replies; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

Implement the v8.1M FPCXT_NS floating-point system register.  This is
a little more complicated than FPCXT_S, because it has specific
handling for "current FP state is inactive", and it only wants to do
PreserveFPState(), not the full set of actions done by
ExecuteFPCheck() which vfp_access_check() implements.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/translate-vfp.c.inc | 110 ++++++++++++++++++++++++++++++---
 1 file changed, 103 insertions(+), 7 deletions(-)

diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
index c7ae306f12f..d0c3a464a21 100644
--- a/target/arm/translate-vfp.c.inc
+++ b/target/arm/translate-vfp.c.inc
@@ -647,8 +647,20 @@ typedef enum fp_sysreg_check_result {
     fp_sysreg_check_continue, /* caller should continue generating code */
 } fp_sysreg_check_result;
 
-static fp_sysreg_check_result fp_sysreg_checks(DisasContext *s, int regno)
+/*
+ * Emit code to check common UNDEF cases and handle lazy state preservation
+ * including the special casing for FPCXT_NS. For reads of sysregs, caller
+ * should provide storefn and opaque; for writes to sysregs these can be NULL.
+ * On return, if *insn_end_label is not NULL the caller needs to gen_set_label()
+ * it at the end of the other code generated for the insn.
+ */
+static fp_sysreg_check_result fp_sysreg_checks(DisasContext *s, int regno,
+                                               fp_sysreg_storefn *storefn,
+                                               void *opaque,
+                                               TCGLabel **insn_end_label)
 {
+    *insn_end_label = NULL;
+
     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
         return fp_sysreg_check_failed;
     }
@@ -663,6 +675,7 @@ static fp_sysreg_check_result fp_sysreg_checks(DisasContext *s, int regno)
         }
         break;
     case ARM_VFP_FPCXT_S:
+    case ARM_VFP_FPCXT_NS:
         if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
             return false;
         }
@@ -674,8 +687,46 @@ static fp_sysreg_check_result fp_sysreg_checks(DisasContext *s, int regno)
         return fp_sysreg_check_failed;
     }
 
-    if (!vfp_access_check(s)) {
-        return fp_sysreg_check_done;
+    /*
+     * FPCXT_NS is a special case: it has specific handling for
+     * "current FP state is inactive", and must do the PreserveFPState()
+     * but not the usual full set of actions done by ExecuteFPCheck().
+     * We don't have a TB flag that matches the fpInactive check, so we
+     * do it at runtime as we don't expect FPCXT_NS accesses to be frequent.
+     * The code emitted here handles the fpInactive special case;
+     * the caller just has to do the codegen for the normal (!fpInactive)
+     * special case, and then set the label at the end.
+     */
+    if (regno == ARM_VFP_FPCXT_NS) {
+        /* fpInactive = FPCCR_NS.ASPEN == 1 && CONTROL.FPCA == 0 */
+        TCGLabel *fp_active_label = gen_new_label();
+        TCGv_i32 aspen, fpca;
+        aspen = load_cpu_field(v7m.fpccr[M_REG_NS]);
+        fpca = load_cpu_field(v7m.control[M_REG_S]);
+        tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
+        tcg_gen_subi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
+        tcg_gen_andi_i32(fpca, fpca, R_V7M_CONTROL_FPCA_MASK);
+        tcg_gen_or_i32(fpca, fpca, aspen);
+        tcg_gen_brcondi_i32(TCG_COND_NE, fpca, 0, fp_active_label);
+        tcg_temp_free_i32(aspen);
+        tcg_temp_free_i32(fpca);
+
+        /* fpInactive case: FPCXT_NS reads as FPDSCR_NS, write is NOP */
+        if (storefn) {
+            TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
+            storefn(s, opaque, tmp);
+        }
+        /* jump to end of insn */
+        *insn_end_label = gen_new_label();
+        tcg_gen_br(*insn_end_label);
+
+        gen_set_label(fp_active_label);
+        /* !fpInactive: PreserveFPState() and handle register as normal */
+        gen_preserve_fp_state(s);
+    } else {
+        if (!vfp_access_check(s)) {
+            return fp_sysreg_check_done;
+        }
     }
 
     return fp_sysreg_check_continue;
@@ -687,8 +738,10 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
 {
     /* Do a write to an M-profile floating point system register */
     TCGv_i32 tmp;
+    TCGLabel *insn_end_label;
+    bool lookup_tb = false;
 
-    switch (fp_sysreg_checks(s, regno)) {
+    switch (fp_sysreg_checks(s, regno, NULL, NULL, &insn_end_label)) {
     case fp_sysreg_check_failed:
         return false;
     case fp_sysreg_check_done:
@@ -702,7 +755,7 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
         tmp = loadfn(s, opaque);
         gen_helper_vfp_set_fpscr(cpu_env, tmp);
         tcg_temp_free_i32(tmp);
-        gen_lookup_tb(s);
+        lookup_tb = true;
         break;
     case ARM_VFP_FPSCR_NZCVQC:
     {
@@ -721,6 +774,7 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
         break;
     }
     case ARM_VFP_FPCXT_S:
+    case ARM_VFP_FPCXT_NS:
     {
         TCGv_i32 sfpa, control, fpscr;
         /* Set FPSCR[27:0] and CONTROL.SFPA from value */
@@ -743,6 +797,12 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
     default:
         g_assert_not_reached();
     }
+    if (insn_end_label) {
+        gen_set_label(insn_end_label);
+    }
+    if (lookup_tb) {
+        gen_lookup_tb(s);
+    }
     return true;
 }
 
@@ -752,8 +812,10 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
 {
     /* Do a read from an M-profile floating point system register */
     TCGv_i32 tmp;
+    TCGLabel *insn_end_label;
+    bool lookup_tb = false;
 
-    switch (fp_sysreg_checks(s, regno)) {
+    switch (fp_sysreg_checks(s, regno, storefn, opaque, &insn_end_label)) {
     case fp_sysreg_check_failed:
         return false;
     case fp_sysreg_check_done:
@@ -810,12 +872,46 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
         fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
         gen_helper_vfp_set_fpscr(cpu_env, fpscr);
         tcg_temp_free_i32(fpscr);
-        gen_lookup_tb(s);
+        lookup_tb = true;
+        break;
+    }
+    case ARM_VFP_FPCXT_NS:
+    {
+        TCGv_i32 control, sfpa, fpscr, fpdscr, zero;
+        /* Reads the same as FPCXT_S, but side effects differ */
+        tmp = tcg_temp_new_i32();
+        sfpa = tcg_temp_new_i32();
+        fpscr = tcg_temp_new_i32();
+        gen_helper_vfp_get_fpscr(fpscr, cpu_env);
+        tcg_gen_andi_i32(tmp, fpscr, ~FPCR_NZCV_MASK);
+        control = load_cpu_field(v7m.control[M_REG_S]);
+        tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
+        tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
+        tcg_gen_or_i32(tmp, tmp, sfpa);
+        tcg_temp_free_i32(control);
+        /* Store result before updating FPSCR, in case it faults */
+        storefn(s, opaque, tmp);
+        /* If SFPA is zero then set FPSCR from FPDSCR_NS */
+        fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
+        zero = tcg_const_i32(0);
+        tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, zero, fpdscr, fpscr);
+        gen_helper_vfp_set_fpscr(cpu_env, fpscr);
+        tcg_temp_free_i32(zero);
+        tcg_temp_free_i32(sfpa);
+        tcg_temp_free_i32(fpdscr);
+        tcg_temp_free_i32(fpscr);
+        lookup_tb = true;
         break;
     }
     default:
         g_assert_not_reached();
     }
+    if (insn_end_label) {
+        gen_set_label(insn_end_label);
+    }
+    if (lookup_tb) {
+        gen_lookup_tb(s);
+    }
     return true;
 }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 15/15] hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M
  2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
                   ` (13 preceding siblings ...)
  2020-11-16 16:08 ` [PATCH 14/15] target/arm: Implement FPCXT_NS " Peter Maydell
@ 2020-11-16 16:08 ` Peter Maydell
  14 siblings, 0 replies; 26+ messages in thread
From: Peter Maydell @ 2020-11-16 16:08 UTC (permalink / raw)
  To: qemu-arm, qemu-devel

The FPDSCR register has a similar layout to the FPSCR.  In v8.1M it
gains new fields FZ16 (if half-precision floating point is supported)
and LTPSIZE (always reads as 4).  Update the reset value and the code
that handles writes to this register accordingly.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.h      | 5 +++++
 hw/intc/armv7m_nvic.c | 9 ++++++++-
 target/arm/cpu.c      | 3 +++
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 34f8f4afe18..2bc25b65ab0 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1521,14 +1521,19 @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
 #define FPCR_IXE    (1 << 12)   /* Inexact exception trap enable */
 #define FPCR_IDE    (1 << 15)   /* Input Denormal exception trap enable */
 #define FPCR_FZ16   (1 << 19)   /* ARMv8.2+, FP16 flush-to-zero */
+#define FPCR_RMODE_MASK (3 << 22) /* Rounding mode */
 #define FPCR_FZ     (1 << 24)   /* Flush-to-zero enable bit */
 #define FPCR_DN     (1 << 25)   /* Default NaN enable bit */
+#define FPCR_AHP    (1 << 26)   /* Alternative half-precision */
 #define FPCR_QC     (1 << 27)   /* Cumulative saturation bit */
 #define FPCR_V      (1 << 28)   /* FP overflow flag */
 #define FPCR_C      (1 << 29)   /* FP carry flag */
 #define FPCR_Z      (1 << 30)   /* FP zero flag */
 #define FPCR_N      (1 << 31)   /* FP negative flag */
 
+#define FPCR_LTPSIZE_SHIFT 16   /* LTPSIZE, M-profile only */
+#define FPCR_LTPSIZE_MASK (7 << FPCR_LTPSIZE_SHIFT)
+
 #define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
 #define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
 
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 9628ce876e0..be3bc1f1f45 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -2068,7 +2068,14 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
         break;
     case 0xf3c: /* FPDSCR */
         if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
-            value &= 0x07c00000;
+            uint32_t mask = FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK;
+            if (cpu_isar_feature(any_fp16, cpu)) {
+                mask |= FPCR_FZ16;
+            }
+            value &= mask;
+            if (cpu_isar_feature(aa32_lob, cpu)) {
+                value |= 4 << FPCR_LTPSIZE_SHIFT;
+            }
             cpu->env.v7m.fpdscr[attrs.secure] = value;
         }
         break;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 40f3f798b2b..d6188f6566a 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -262,6 +262,9 @@ static void arm_cpu_reset(DeviceState *dev)
              * always reset to 4.
              */
             env->v7m.ltpsize = 4;
+            /* The LTPSIZE field in FPDSCR is constant and reads as 4. */
+            env->v7m.fpdscr[M_REG_NS] = 4 << FPCR_LTPSIZE_SHIFT;
+            env->v7m.fpdscr[M_REG_S] = 4 << FPCR_LTPSIZE_SHIFT;
         }
 
         if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/15] hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
  2020-11-16 16:08 ` [PATCH 01/15] hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault Peter Maydell
@ 2020-11-17 19:07   ` Richard Henderson
  0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2020-11-17 19:07 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 11/16/20 8:08 AM, Peter Maydell wrote:
> For M-profile CPUs, the range from 0xe0000000 to 0xe00fffff is the
> Private Peripheral Bus range, which includes all of the memory mapped
> devices and registers that are part of the CPU itself, including the
> NVIC, systick timer, and debug and trace components like the Data
> Watchpoint and Trace unit (DWT).  Within this large region, the range
> 0xe000e000 to 0xe000efff is the System Control Space (NVIC, system
> registers, systick) and 0xe002e000 to 0exe002efff is its Non-secure
> alias.
> 
> The architecture is clear that within the SCS unimplemented registers
> should be RES0 for privileged accesses and generate BusFault for
> unprivileged accesses, and we currently implement this.
> 
> It is less clear about how to handle accesses to unimplemented
> regions of the wider PPB.  Unprivileged accesses should definitely
> cause BusFaults (R_DQQS), but the behaviour of privileged accesses is
> not given as a general rule.  However, the register definitions of
> individual registers for components like the DWT all state that they
> are RES0 if the relevant component is not implemented, so the
> simplest way to provide that is to provide RAZ/WI for the whole range
> for privileged accesses.  (The v7M Arm ARM does say that reserved
> registers should be UNK/SBZP.)
> 
> Expand the container MemoryRegion that the NVIC exposes so that
> it covers the whole PPB space. This means:
>  * moving the address that the ARMV7M device maps it to down by
>    0xe000 bytes
>  * moving the off and the offsets within the container of all the
>    subregions forward by 0xe000 bytes
>  * adding a new default MemoryRegion that covers the whole container
>    at a lower priority than anything else and which provides the
>    RAZWI/BusFault behaviour
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---

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

r~


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 02/15] target/arm: Implement v8.1M PXN extension
  2020-11-16 16:08 ` [PATCH 02/15] target/arm: Implement v8.1M PXN extension Peter Maydell
@ 2020-11-17 19:10   ` Richard Henderson
  0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2020-11-17 19:10 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 11/16/20 8:08 AM, Peter Maydell wrote:
> In v8.1M the PXN architecture extension adds a new PXN bit to the
> MPU_RLAR registers, which forbids execution of code in the region
> from a privileged mode.
> 
> This is another feature which is just in the generic "in v8.1M" set
> and has no ID register field indicating its presence.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/helper.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)

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

r~



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 03/15] target/arm: Don't clobber ID_PFR1.Security on M-profile cores
  2020-11-16 16:08 ` [PATCH 03/15] target/arm: Don't clobber ID_PFR1.Security on M-profile cores Peter Maydell
@ 2020-11-17 19:12   ` Richard Henderson
  0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2020-11-17 19:12 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 11/16/20 8:08 AM, Peter Maydell wrote:
> In arm_cpu_realizefn() we check whether the board code disabled EL3
> via the has_el3 CPU object property, which we create if the CPU
> starts with the ARM_FEATURE_EL3 feature bit.  If it is disabled, then
> we turn off ARM_FEATURE_EL3 and also zero out the relevant fields in
> the ID_PFR1 and ID_AA64PFR0 registers.
> 
> This codepath was incorrectly being taken for M-profile CPUs, which
> do not have an EL3 and don't set ARM_FEATURE_EL3, but which may have
> the M-profile Security extension and so should have non-zero values
> in the ID_PFR1.Security field.
> 
> Restrict the handling of the feature flag to A/R-profile cores.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/cpu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

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

r~



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 04/15] target/arm: Implement VSCCLRM insn
  2020-11-16 16:08 ` [PATCH 04/15] target/arm: Implement VSCCLRM insn Peter Maydell
@ 2020-11-17 19:31   ` Richard Henderson
  0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2020-11-17 19:31 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 11/16/20 8:08 AM, Peter Maydell wrote:
> +    aspen = load_cpu_field(v7m.fpccr[M_REG_S]);
> +    sfpa = load_cpu_field(v7m.control[M_REG_S]);
> +    tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
> +    tcg_gen_subi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);

xori would be clearer, i think.

> +    /* Zero the Sregs from btmreg to topreg inclusive. */
> +    zero64 = tcg_const_i64(0);
> +    zero32 = tcg_const_i32(0);
> +    if (btmreg & 1) {
> +        write_neon_element32(zero32, btmreg >> 1, 1, MO_32);
> +        btmreg++;
> +    }
> +    for (; btmreg + 1 <= topreg; btmreg += 2) {
> +        write_neon_element64(zero64, btmreg >> 1, 0, MO_64);
> +    }
> +    if (btmreg == topreg) {
> +        write_neon_element32(zero32, btmreg >> 1, 0, MO_32);
> +        btmreg++;
> +    }

I hadn't implemented MO_32 for write_neon_element64 because there were no
users.  Better to just add the case there using tcg_gen_st32_i64, then you
don't need a 32-bit zero.

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


r~


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 05/15] target/arm: Implement CLRM instruction
  2020-11-16 16:08 ` [PATCH 05/15] target/arm: Implement CLRM instruction Peter Maydell
@ 2020-11-17 19:38   ` Richard Henderson
  0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2020-11-17 19:38 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 11/16/20 8:08 AM, Peter Maydell wrote:
> In v8.1M the new CLRM instruction allows zeroing an arbitrary set of
> the general-purpose registers and APSR.  Implement this.
> 
> The encoding is a subset of the LDMIA T2 encoding, using what would
> be Rn=0b1111 (which UNDEFs for LDMIA).
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/t32.decode  |  6 +++++-
>  target/arm/translate.c | 38 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 43 insertions(+), 1 deletion(-)

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

r~


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 06/15] target/arm: Enforce M-profile VMRS/VMSR register restrictions
  2020-11-16 16:08 ` [PATCH 06/15] target/arm: Enforce M-profile VMRS/VMSR register restrictions Peter Maydell
@ 2020-11-17 19:42   ` Richard Henderson
  2020-11-17 21:18     ` Peter Maydell
  0 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2020-11-17 19:42 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 11/16/20 8:08 AM, Peter Maydell wrote:
> -        if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
> +        if (a->reg != ARM_VFP_FPSCR) {
> +            return false;
> +        }
> +        if (a->rt == 15 && !a->l) {

Alternately, the parenthesis are just off:

  if ((a->rt == 15 && !a->l) || a->reg != ARM_VFP_FPSCR)

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

r~


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 08/15] target/arm: Move general-use constant expanders up in translate.c
  2020-11-16 16:08 ` [PATCH 08/15] target/arm: Move general-use constant expanders up in translate.c Peter Maydell
@ 2020-11-17 19:47   ` Richard Henderson
  0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2020-11-17 19:47 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 11/16/20 8:08 AM, Peter Maydell wrote:
> The constant-expander functions like negate, plus_2, etc, are
> generally useful; move them up in translate.c so we can use them in
> the VFP/Neon decoders as well as in the A32/T32/T16 decoders.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/translate.c | 46 +++++++++++++++++++++++-------------------
>  1 file changed, 25 insertions(+), 21 deletions(-)

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

r~



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 11/15] target/arm: Use new FPCR_NZCV_MASK constant
  2020-11-16 16:08 ` [PATCH 11/15] target/arm: Use new FPCR_NZCV_MASK constant Peter Maydell
@ 2020-11-17 19:49   ` Richard Henderson
  0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2020-11-17 19:49 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 11/16/20 8:08 AM, Peter Maydell wrote:
> We defined a constant name for the mask of NZCV bits in the FPCR/FPSCR
> in the previous commit; use it in a couple of places in existing code,
> where we're masking out everything except NZCV for the "load to Rt=15
> sets CPSR.NZCV" special case.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/translate-vfp.c.inc | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

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

r~



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 12/15] target/arm: Factor out preserve-fp-state from full_vfp_access_check()
  2020-11-16 16:08 ` [PATCH 12/15] target/arm: Factor out preserve-fp-state from full_vfp_access_check() Peter Maydell
@ 2020-11-17 19:50   ` Richard Henderson
  0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2020-11-17 19:50 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel

On 11/16/20 8:08 AM, Peter Maydell wrote:
> Factor out the code which handles M-profile lazy FP state preservation
> from full_vfp_access_check(); accesses to the FPCXT_NS register are
> a special case which need to do just this part (corresponding in the
> pseudocode to the PreserveFPState() function), and not the full
> set of actions matching the pseudocode ExecuteFPCheck() which
> normal FP instructions need to do.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/translate-vfp.c.inc | 45 ++++++++++++++++++++--------------
>  1 file changed, 27 insertions(+), 18 deletions(-)

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

r~



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 06/15] target/arm: Enforce M-profile VMRS/VMSR register restrictions
  2020-11-17 19:42   ` Richard Henderson
@ 2020-11-17 21:18     ` Peter Maydell
  0 siblings, 0 replies; 26+ messages in thread
From: Peter Maydell @ 2020-11-17 21:18 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-arm, QEMU Developers

On Tue, 17 Nov 2020 at 19:42, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 11/16/20 8:08 AM, Peter Maydell wrote:
> > -        if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
> > +        if (a->reg != ARM_VFP_FPSCR) {
> > +            return false;
> > +        }
> > +        if (a->rt == 15 && !a->l) {
>
> Alternately, the parenthesis are just off:
>
>   if ((a->rt == 15 && !a->l) || a->reg != ARM_VFP_FPSCR)

Mmm. As you've probably discovered by now, the refactoring
in the subsequent patches means that this code gets moved
and changed anyway; I just wanted it in this separate
patch so the bugfix wasn't hidden in the refactoring.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2020-11-17 21:20 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-16 16:08 [PATCH 00/15] target/arm: More v8.1M features Peter Maydell
2020-11-16 16:08 ` [PATCH 01/15] hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault Peter Maydell
2020-11-17 19:07   ` Richard Henderson
2020-11-16 16:08 ` [PATCH 02/15] target/arm: Implement v8.1M PXN extension Peter Maydell
2020-11-17 19:10   ` Richard Henderson
2020-11-16 16:08 ` [PATCH 03/15] target/arm: Don't clobber ID_PFR1.Security on M-profile cores Peter Maydell
2020-11-17 19:12   ` Richard Henderson
2020-11-16 16:08 ` [PATCH 04/15] target/arm: Implement VSCCLRM insn Peter Maydell
2020-11-17 19:31   ` Richard Henderson
2020-11-16 16:08 ` [PATCH 05/15] target/arm: Implement CLRM instruction Peter Maydell
2020-11-17 19:38   ` Richard Henderson
2020-11-16 16:08 ` [PATCH 06/15] target/arm: Enforce M-profile VMRS/VMSR register restrictions Peter Maydell
2020-11-17 19:42   ` Richard Henderson
2020-11-17 21:18     ` Peter Maydell
2020-11-16 16:08 ` [PATCH 07/15] target/arm: Refactor M-profile VMSR/VMRS handling Peter Maydell
2020-11-16 16:08 ` [PATCH 08/15] target/arm: Move general-use constant expanders up in translate.c Peter Maydell
2020-11-17 19:47   ` Richard Henderson
2020-11-16 16:08 ` [PATCH 09/15] target/arm: Implement VLDR/VSTR system register Peter Maydell
2020-11-16 16:08 ` [PATCH 10/15] target/arm: Implement M-profile FPSCR_nzcvqc Peter Maydell
2020-11-16 16:08 ` [PATCH 11/15] target/arm: Use new FPCR_NZCV_MASK constant Peter Maydell
2020-11-17 19:49   ` Richard Henderson
2020-11-16 16:08 ` [PATCH 12/15] target/arm: Factor out preserve-fp-state from full_vfp_access_check() Peter Maydell
2020-11-17 19:50   ` Richard Henderson
2020-11-16 16:08 ` [PATCH 13/15] target/arm: Implement FPCXT_S fp system register Peter Maydell
2020-11-16 16:08 ` [PATCH 14/15] target/arm: Implement FPCXT_NS " Peter Maydell
2020-11-16 16:08 ` [PATCH 15/15] hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.