aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-04-29 17:36:00 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-04-29 17:36:00 +0100
commitb593c2b81287040ab6f452afec6281e2f7ee487b (patch)
treec5fccb99d4806afe49a25d6728e383c5ad6cfbb6 /hw
parent0ed377a8013f40653a83f6ad2c9693897522d7dc (diff)
target/arm: Implement v7m_update_fpccr()
Implement the code which updates the FPCCR register on an exception entry where we are going to use lazy FP stacking. We have to defer to the NVIC to determine whether the various exceptions are currently ready or not. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20190416125744.27770-12-peter.maydell@linaro.org
Diffstat (limited to 'hw')
-rw-r--r--hw/intc/armv7m_nvic.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 5eb438f540..53b4631dac 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -746,6 +746,40 @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
return ret;
}
+bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
+{
+ /*
+ * Return whether an exception is "ready", i.e. it is enabled and is
+ * configured at a priority which would allow it to interrupt the
+ * current execution priority.
+ *
+ * irq and secure have the same semantics as for armv7m_nvic_set_pending():
+ * for non-banked exceptions secure is always false; for banked exceptions
+ * it indicates which of the exceptions is required.
+ */
+ NVICState *s = (NVICState *)opaque;
+ bool banked = exc_is_banked(irq);
+ VecInfo *vec;
+ int running = nvic_exec_prio(s);
+
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
+ assert(!secure || banked);
+
+ /*
+ * HardFault is an odd special case: we always check against -1,
+ * even if we're secure and HardFault has priority -3; we never
+ * need to check for enabled state.
+ */
+ if (irq == ARMV7M_EXCP_HARD) {
+ return running > -1;
+ }
+
+ vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
+
+ return vec->enabled &&
+ exc_group_prio(s, vec->prio, secure) < running;
+}
+
/* callback when external interrupt line is changed */
static void set_irq_level(void *opaque, int n, int level)
{