diff mbox series

[01/39] target/hexagon: Implement ciad helper

Message ID 20250301052845.1012069-2-brian.cain@oss.qualcomm.com (mailing list archive)
State New
Headers show
Series hexagon system emu, part 2/3 | expand

Commit Message

Brian Cain March 1, 2025, 5:28 a.m. UTC
From: Brian Cain <bcain@quicinc.com>

ciad is the clear interrupt auto disable instruction.

This instruction is defined in the Qualcomm Hexagon V71 Programmer's Reference
Manual -
https://docs.qualcomm.com/bundle/publicresource/80-N2040-51_REV_AB_Hexagon_V71_ProgrammerS_Reference_Manual.pdf
See ยง11.9.2 SYSTEM MONITOR.

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/op_helper.c | 39 ++++++++++++++++++++++++++++++++------
 1 file changed, 33 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index fd9caafefc..b28a18adf6 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -34,6 +34,11 @@ 
 #include "op_helper.h"
 #include "cpu_helper.h"
 #include "translate.h"
+#ifndef CONFIG_USER_ONLY
+#include "hex_mmu.h"
+#include "hw/intc/l2vic.h"
+#include "hex_interrupts.h"
+#endif
 
 #define SF_BIAS        127
 #define SF_MANTBITS    23
@@ -1338,9 +1343,36 @@  void HELPER(vwhist128qm)(CPUHexagonState *env, int32_t uiV)
 }
 
 #ifndef CONFIG_USER_ONLY
+static void hexagon_set_vid(CPUHexagonState *env, uint32_t offset, int val)
+{
+    g_assert((offset == L2VIC_VID_0) || (offset == L2VIC_VID_1));
+    CPUState *cs = env_cpu(env);
+    HexagonCPU *cpu = HEXAGON_CPU(cs);
+    const hwaddr pend_mem = cpu->l2vic_base_addr + offset;
+    cpu_physical_memory_write(pend_mem, &val, sizeof(val));
+}
+
+static void hexagon_clear_last_irq(CPUHexagonState *env, uint32_t offset)
+{
+    /*
+     * currently only l2vic is the only attached it uses vid0, remove
+     * the assert below if anther is added
+     */
+    hexagon_set_vid(env, offset, L2VIC_CIAD_INSTRUCTION);
+}
+
 void HELPER(ciad)(CPUHexagonState *env, uint32_t mask)
 {
-    g_assert_not_reached();
+    uint32_t ipendad;
+    uint32_t iad;
+
+    BQL_LOCK_GUARD();
+    ipendad = READ_SREG(HEX_SREG_IPENDAD);
+    iad = fGET_FIELD(ipendad, IPENDAD_IAD);
+    fSET_FIELD(ipendad, IPENDAD_IAD, iad & ~(mask));
+    arch_set_system_reg(env, HEX_SREG_IPENDAD, ipendad);
+    hexagon_clear_last_irq(env, L2VIC_VID_0);
+    hex_interrupt_update(env);
 }
 
 void HELPER(siad)(CPUHexagonState *env, uint32_t mask)
@@ -1416,11 +1448,6 @@  static void modify_syscfg(CPUHexagonState *env, uint32_t val)
     g_assert_not_reached();
 }
 
-static void hexagon_set_vid(CPUHexagonState *env, uint32_t offset, int val)
-{
-    g_assert_not_reached();
-}
-
 static uint32_t hexagon_find_last_irq(CPUHexagonState *env, uint32_t vid)
 {
     g_assert_not_reached();