public inbox for qemu-devel@nongnu.org
 help / color / mirror / Atom feed
* [PATCH v5 00/35] Hexagon system emulation, Part 1/3
@ 2026-03-11  3:48 Brian Cain
  2026-03-11  3:48 ` [PATCH v5 01/35] docs: Add hexagon sysemu docs Brian Cain
                   ` (34 more replies)
  0 siblings, 35 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo

This is Part 1 of the hexagon system emulation (sysemu) patch series,
providing the foundational target infrastructure needed for full-system
emulation of the Qualcomm Hexagon DSP.

Changes since v4:
  - Moved lock infrastructure (hex_lock_state_t enum, lock fields,
    CPU_INTERRUPT_*_UNLOCK) and TLB lock macros into "Add stubs for
    modify_ssr/get_exe_mode" where they are first used
  - Renamed "Add locks, id, next_PC to state" to "Add cpu modes, mmu
    indices, next_PC to state" to reflect remaining content
  - Removed hvx_contexts field and hvx-contexts property from this
    series
  - Used G_GNUC_UNUSED instead of (void) casts to suppress
    unused-variable warnings for sysemu source register numbers
    in hex_common.py

Previous versions:
  v4: https://lore.kernel.org/qemu-devel/20260309144822.877695-1-brian.cain@oss.qualcomm.com/
  v3: https://lore.kernel.org/qemu-devel/20260227203627.932864-1-brian.cain@oss.qualcomm.com/
  v2: https://lore.kernel.org/qemu-devel/20250902034715.1947718-1-brian.cain@oss.qualcomm.com/
  v1: https://lore.kernel.org/qemu-devel/20250301052628.1011210-1-brian.cain@oss.qualcomm.com/

Brian Cain (35):
  docs: Add hexagon sysemu docs
  docs/system: Add hexagon CPU emulation
  target/hexagon: Fix badva reference, delete CAUSE
  target/hexagon: Add missing A_CALL attr, hintjumpr to multi_cof
  target/hexagon: Handle system/guest registers in gen_analyze_funcs.py
    and hex_common.py
  target/hexagon: Suppress unused-variable warnings for sysemu source
    regs
  target/hexagon: Make gen_exception_end_tb non-static
  target/hexagon: Switch to tag_ignore(), generate via
    get_{user,sys}_tags()
  target/hexagon: Add privilege check, use tag_ignore()
  target/hexagon: Add a placeholder fp exception
  target/hexagon: Add guest, system reg number defs
  target/hexagon: Add guest, system reg number state
  target/hexagon: Add TCG values for sreg, greg
  target/hexagon: Add guest/sys reg writes to DisasContext
  target/hexagon: Add imported macro, attr defs for sysemu
  target/hexagon: Add new macro definitions for sysemu
  target/hexagon: Add handlers for guest/sysreg r/w
  target/hexagon: Add placeholder greg/sreg r/w helpers
  target/hexagon: Add vmstate representation
  target/hexagon: Make A_PRIV, "J2_trap*" insts need_env()
  target/hexagon: Define register fields for system regs
  target/hexagon: Implement do_raise_exception()
  target/hexagon: Add system reg insns
  target/hexagon: Add sysemu TCG overrides
  target/hexagon: Add implicit attributes to sysemu macros
  target/hexagon: Add TCG overrides for int handler insts
  target/hexagon: Add TCG overrides for thread ctl
  target/hexagon: Add TCG overrides for rte, nmi
  target/hexagon: Add sreg_{read,write} helpers
  target/hexagon: Add cpu modes, mmu indices, next_PC to state
  hw/hexagon: Introduce hexagon TLB device
  target/hexagon: Add stubs for modify_ssr/get_exe_mode
  target/hexagon: Add clear_wait_mode() definition
  target/hexagon: Define f{S,G}ET_FIELD macros
  target/hexagon: Add hex_interrupts support

 MAINTAINERS                             |   3 +
 docs/devel/hexagon-sys.rst              | 112 ++++++
 docs/devel/index-internals.rst          |   1 +
 docs/system/hexagon/cdsp.rst            |  12 +
 docs/system/hexagon/emulation.rst       |  15 +
 docs/system/target-hexagon.rst          | 103 +++++
 docs/system/targets.rst                 |   1 +
 include/hw/hexagon/hexagon_tlb.h        |  45 +++
 target/hexagon/cpu-param.h              |   4 +
 target/hexagon/cpu.h                    |  72 +++-
 target/hexagon/cpu_bits.h               |  75 +++-
 target/hexagon/cpu_helper.h             |  21 ++
 target/hexagon/gen_tcg.h                |   9 +
 target/hexagon/gen_tcg_sys.h            | 102 +++++
 target/hexagon/helper.h                 |  22 ++
 target/hexagon/hex_interrupts.h         |  15 +
 target/hexagon/hex_mmu.h                |  25 ++
 target/hexagon/hex_regs.h               | 117 ++++++
 target/hexagon/internal.h               |  18 +
 target/hexagon/macros.h                 |  35 +-
 target/hexagon/sys_macros.h             | 240 ++++++++++++
 target/hexagon/translate.h              |  43 +++
 target/hexagon/attribs_def.h.inc        |  49 ++-
 target/hexagon/reg_fields_def.h.inc     |  96 +++++
 hw/hexagon/hexagon_tlb.c                | 463 +++++++++++++++++++++++
 linux-user/hexagon/cpu_loop.c           |  16 +
 target/hexagon/arch.c                   |   5 +
 target/hexagon/cpu.c                    |  56 ++-
 target/hexagon/cpu_helper.c             |  85 +++++
 target/hexagon/genptr.c                 | 151 ++++++++
 target/hexagon/hex_interrupts.c         | 375 ++++++++++++++++++
 target/hexagon/hex_mmu.c                | 277 ++++++++++++++
 target/hexagon/machine.c                |  32 ++
 target/hexagon/op_helper.c              | 144 ++++++-
 target/hexagon/translate.c              |  30 +-
 target/hexagon/gen_analyze_funcs.py     |  14 +-
 target/hexagon/gen_helper_funcs.py      |  26 +-
 target/hexagon/gen_helper_protos.py     |  23 +-
 target/hexagon/gen_idef_parser_funcs.py |   2 +
 target/hexagon/gen_op_attribs.py        |   2 +-
 target/hexagon/gen_opcodes_def.py       |   5 +-
 target/hexagon/gen_tcg_funcs.py         |  35 +-
 target/hexagon/hex_common.py            | 181 ++++++++-
 target/hexagon/imported/encode_pp.def   | 128 ++++++-
 target/hexagon/imported/macros.def      | 482 +++++++++++++++++++++++-
 target/hexagon/imported/system.idef     | 244 +++++++++++-
 target/hexagon/meson.build              |  13 +-
 47 files changed, 3914 insertions(+), 110 deletions(-)
 create mode 100644 docs/devel/hexagon-sys.rst
 create mode 100644 docs/system/hexagon/cdsp.rst
 create mode 100644 docs/system/hexagon/emulation.rst
 create mode 100644 docs/system/target-hexagon.rst
 create mode 100644 include/hw/hexagon/hexagon_tlb.h
 create mode 100644 target/hexagon/cpu_helper.h
 create mode 100644 target/hexagon/gen_tcg_sys.h
 create mode 100644 target/hexagon/hex_interrupts.h
 create mode 100644 target/hexagon/hex_mmu.h
 create mode 100644 target/hexagon/sys_macros.h
 create mode 100644 hw/hexagon/hexagon_tlb.c
 create mode 100644 target/hexagon/cpu_helper.c
 create mode 100644 target/hexagon/hex_interrupts.c
 create mode 100644 target/hexagon/hex_mmu.c
 create mode 100644 target/hexagon/machine.c
 mode change 100755 => 100644 target/hexagon/imported/macros.def

-- 
2.34.1


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

* [PATCH v5 01/35] docs: Add hexagon sysemu docs
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
@ 2026-03-11  3:48 ` Brian Cain
  2026-03-11  3:48 ` [PATCH v5 02/35] docs/system: Add hexagon CPU emulation Brian Cain
                   ` (33 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain,
	Pierrick Bouvier

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 MAINTAINERS                    |   3 +
 docs/devel/hexagon-sys.rst     | 112 +++++++++++++++++++++++++++++++++
 docs/devel/index-internals.rst |   1 +
 docs/system/hexagon/cdsp.rst   |  12 ++++
 docs/system/target-hexagon.rst | 102 ++++++++++++++++++++++++++++++
 docs/system/targets.rst        |   1 +
 6 files changed, 231 insertions(+)
 create mode 100644 docs/devel/hexagon-sys.rst
 create mode 100644 docs/system/hexagon/cdsp.rst
 create mode 100644 docs/system/target-hexagon.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index a53317ff263..17d1d93d595 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -253,6 +253,9 @@ F: disas/hexagon.c
 F: configs/targets/hexagon-linux-user/default.mak
 F: docker/dockerfiles/debian-hexagon-cross.docker
 F: gdb-xml/hexagon*.xml
+F: docs/system/target-hexagon.rst
+F: docs/system/hexagon/
+F: docs/devel/hexagon-sys.rst
 T: git https://github.com/quic/qemu.git hex-next
 
 Hexagon idef-parser
diff --git a/docs/devel/hexagon-sys.rst b/docs/devel/hexagon-sys.rst
new file mode 100644
index 00000000000..92ebc32dce8
--- /dev/null
+++ b/docs/devel/hexagon-sys.rst
@@ -0,0 +1,112 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+.. _Hexagon-System-arch:
+
+Hexagon System Architecture
+===========================
+
+The hexagon architecture has some unique elements which are described here.
+
+Interrupts
+----------
+When interrupts arrive at a Hexagon DSP core, they are priority-steered to
+be handled by an eligible hardware thread with the lowest priority.
+
+Memory
+------
+Each hardware thread has an ``SSR.ASID`` field that contains its Address
+Space Identifier.  This value is catenated with a 32-bit virtual address -
+the MMU can then resolve this extended virtual address to a physical address.
+
+TLBs
+----
+The format of a TLB entry is shown below.
+
+.. note::
+    The Small Core DSPs have a different TLB format which is not yet
+    supported.
+
+.. admonition:: Diagram
+
+ .. code:: text
+
+             6                   5                   4               3
+       3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |v|g|x|A|A|             |                                       |
+      |a|l|P|1|0|     ASID    |             Virtual Page              |
+      |l|b| | | |             |                                       |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+         3                   2                   1                   0
+       1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      | | | | |       |                                             | |
+      |x|w|r|u|Cacheab|               Physical Page                 |S|
+      | | | | |       |                                             | |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+* ASID: the address-space identifier
+* A1, A0: the behavior of these cache line attributes are not modeled by QEMU.
+* xP: the extra-physical bit is the most significant physical address bit.
+* S: the S bit and the LSBs of the physical page indicate the page size
+* val: this is the 'valid' bit, when set it indicates that page matching
+  should consider this entry.
+
+.. list-table:: Page sizes
+   :widths: 25 25 50
+   :header-rows: 1
+
+   * - S-bit
+     - Phys page LSBs
+     - Page size
+   * - 1
+     - N/A
+     - 4kb
+   * - 0
+     - 0b1
+     - 16kb
+   * - 0
+     - 0b10
+     - 64kb
+   * - 0
+     - 0b100
+     - 256kb
+   * - 0
+     - 0b1000
+     - 1MB
+   * - 0
+     - 0b10000
+     - 4MB
+   * - 0
+     - 0b100000
+     - 16MB
+
+* glb: if the global bit is set, the ASID is not considered when matching
+  TLBs.
+* Cacheab: the cacheability attributes of TLBs are not modeled, these bits
+  are ignored.
+* RWX: read-, write-, execute-, enable bits.  Indicates if user programs
+  are permitted to read/write/execute the given page.
+* U: indicates if user programs can access this page.
+
+Scheduler
+---------
+The Hexagon system architecture has a feature to assist the guest OS
+task scheduler.  The guest OS can enable this feature by setting
+``SCHEDCFG.EN``.  The ``BESTWAIT`` register is programmed by the guest OS
+to indicate the priority of the highest priority task waiting to run on a
+hardware thread.  The reschedule interrupt is triggered when any hardware
+thread's priority in ``STID.PRIO`` is worse than the ``BESTWAIT``.  When
+it is triggered, the ``BESTWAIT.PRIO`` value is reset to 0x1ff.
+
+HVX Coprocessor
+---------------
+The Supervisor Status Register field ``SSR.XA`` binds a DSP hardware thread
+to one of the eight possible HVX contexts.  The guest OS is responsible for
+managing this resource.
+
+.. seealso::
+
+    ``target/hexagon/README`` in the QEMU source tree for more info about Hexagon.
diff --git a/docs/devel/index-internals.rst b/docs/devel/index-internals.rst
index 7a0678cbdd3..0471db80645 100644
--- a/docs/devel/index-internals.rst
+++ b/docs/devel/index-internals.rst
@@ -14,6 +14,7 @@ Details about QEMU's various subsystems including how to add features to them.
    block-coroutine-wrapper
    clocks
    ebpf_rss
+   hexagon-sys
    migration/index
    multi-process
    reset
diff --git a/docs/system/hexagon/cdsp.rst b/docs/system/hexagon/cdsp.rst
new file mode 100644
index 00000000000..237529273cb
--- /dev/null
+++ b/docs/system/hexagon/cdsp.rst
@@ -0,0 +1,12 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+Compute DSP
+===========
+
+A Hexagon CDSP is designed as a computation offload device for an SoC.  The
+``V66G_1024`` machine contains:
+
+* L2VIC interrupt controller
+* QTimer timer device
+
+This machine will support any Hexagon CPU, but will default to ``v66``.
diff --git a/docs/system/target-hexagon.rst b/docs/system/target-hexagon.rst
new file mode 100644
index 00000000000..5f7084a6a08
--- /dev/null
+++ b/docs/system/target-hexagon.rst
@@ -0,0 +1,102 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+.. _Hexagon-System-emulator:
+
+Hexagon System emulator
+-----------------------
+
+Use the ``qemu-system-hexagon`` executable to simulate a 32-bit Hexagon
+machine.
+
+Hexagon Machines
+================
+
+Hexagon DSPs are suited to various functions and generally appear in a
+"DSP subsystem" of a larger system-on-chip (SoC).
+
+Hexagon DSPs are often included in a subsystem that looks like the diagram
+below.  Instructions are loaded into DDR before the DSP is brought out of
+reset and the first instructions are fetched from DDR via the EVB/reset vector.
+
+In a real system, a TBU/SMMU would normally arbitrate AXI accesses but
+we don't have a need to model that for QEMU.
+
+Hexagon DSP cores use simultaneous multithreading (SMT) with as many as 8
+hardware threads.
+
+.. admonition:: Diagram
+
+ .. code:: text
+
+              AHB (local) bus                     AXI (global) bus
+                    │                                 │
+                    │                                 │
+       ┌─────────┐  │       ┌─────────────────┐       │
+       │ L2VIC   ├──┤       │                 │       │
+       │         ├──┼───────►                 ├───────┤
+       └─────▲───┘  │       │   Hexagon DSP   │       │
+             │      │       │                 │       │        ┌─────┐
+             │      │       │    N threads    │       │        │ DDR │
+             │      ├───────┤                 │       │        │     │
+        ┌────┴──┐   │       │                 │       ├────────┤     │
+        │QTimer ├───┤       │                 │       │        │     │
+        │       │   │       │                 │       │        │     │
+        └───────┘   │       │   ┌─────────┐   │       │        │     │
+                    │       │  ┌─────────┐│   │       │        │     │
+        ┌───────┐   │       │  │  HVX xM ││   │       │        │     │
+        │QDSP6SS├───┤       │  │         │┘   │       │        │     │
+        └───────┘   │       │  └─────────┘    │       │        └─────┘
+                    │       │                 │       │
+        ┌───────┐   │       └─────────────────┘       │
+        │  CSR  ├───┤
+        └───────┘   │   ┌──────┐   ┌───────────┐
+                    │   │ TCM  │   │   VTCM    │
+                        │      │   │           │
+                        └──────┘   │           │
+                                   │           │
+                                   │           │
+                                   │           │
+                                   └───────────┘
+
+Components
+----------
+Other than l2vic and HVX, the components below are not implemented in QEMU.
+
+* L2VIC: the L2 vectored interrupt controller.  Supports 1024 input
+  interrupts, edge- or level-triggered.  The core ISA has system registers
+  ``VID``, ``VID1`` which read through to the L2VIC device.
+* QTimer: ARMSSE-based programmable timer device. Its interrupts are
+  wired to the L2VIC.  System registers ``TIMER``, ``UTIMER`` read
+  through to the QTimer device.
+* QDSP6SS: DSP subsystem features, accessible to the entire SoC, including
+  DSP NMI, watchdog, reset, etc.
+* CSR: Configuration/Status Registers.
+* TCM: DSP-exclusive tightly-coupled memory.  This memory can be used for
+  DSPs when isolated from DDR and in some bootstrapping modes.
+* VTCM: DSP-exclusive vector tightly-coupled memory.  This memory is accessed
+  by some HVX instructions.
+* HVX: the vector coprocessor supports 64 and 128-byte vector registers.
+  64-byte mode is not implemented in QEMU.
+
+
+Bootstrapping
+-------------
+Hexagon systems do not generally have access to a block device.  So, for
+QEMU the typical use case involves loading a binary or ELF file into memory
+and executing from the indicated start address::
+
+    $ qemu-system-hexagon -kernel ./prog -append 'arg1 arg2'
+
+Semihosting
+-----------
+Hexagon supports a semihosting interface similar to other architectures'.
+The ``trap0`` instruction can activate these semihosting calls so that the
+guest software can access the host console and filesystem.  Semihosting
+is not yet implemented in QEMU hexagon.
+
+
+Hexagon Features
+================
+.. toctree::
+   hexagon/cdsp
+
diff --git a/docs/system/targets.rst b/docs/system/targets.rst
index 5b12858b216..5ebdd0f7fea 100644
--- a/docs/system/targets.rst
+++ b/docs/system/targets.rst
@@ -30,3 +30,4 @@ Contents:
    target-sparc64
    target-i386
    target-xtensa
+   target-hexagon
-- 
2.34.1


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

* [PATCH v5 02/35] docs/system: Add hexagon CPU emulation
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
  2026-03-11  3:48 ` [PATCH v5 01/35] docs: Add hexagon sysemu docs Brian Cain
@ 2026-03-11  3:48 ` Brian Cain
  2026-03-11  3:48 ` [PATCH v5 03/35] target/hexagon: Fix badva reference, delete CAUSE Brian Cain
                   ` (32 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain,
	Pierrick Bouvier

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 docs/system/hexagon/emulation.rst | 15 +++++++++++++++
 docs/system/target-hexagon.rst    |  1 +
 2 files changed, 16 insertions(+)
 create mode 100644 docs/system/hexagon/emulation.rst

diff --git a/docs/system/hexagon/emulation.rst b/docs/system/hexagon/emulation.rst
new file mode 100644
index 00000000000..36f54f058af
--- /dev/null
+++ b/docs/system/hexagon/emulation.rst
@@ -0,0 +1,15 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+.. _Hexagon Emulation:
+
+Hexagon CPU architecture support
+================================
+
+QEMU's TCG emulation includes support for v65, v66, v67, v68, v69, v71, v73.
+It also has support for the following architecture extensions:
+
+- HVX (Hexagon Vector eXtensions)
+
+For information on the specifics of the HVX extension, please refer
+to the `Qualcomm Hexagon V73 HVX Programmer's Reference Manual
+<https://docs.qualcomm.com/bundle/publicresource/80-N2040-53.pdf>`_.
diff --git a/docs/system/target-hexagon.rst b/docs/system/target-hexagon.rst
index 5f7084a6a08..416b8f7be76 100644
--- a/docs/system/target-hexagon.rst
+++ b/docs/system/target-hexagon.rst
@@ -98,5 +98,6 @@ is not yet implemented in QEMU hexagon.
 Hexagon Features
 ================
 .. toctree::
+   hexagon/emulation
    hexagon/cdsp
 
-- 
2.34.1


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

* [PATCH v5 03/35] target/hexagon: Fix badva reference, delete CAUSE
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
  2026-03-11  3:48 ` [PATCH v5 01/35] docs: Add hexagon sysemu docs Brian Cain
  2026-03-11  3:48 ` [PATCH v5 02/35] docs/system: Add hexagon CPU emulation Brian Cain
@ 2026-03-11  3:48 ` Brian Cain
  2026-03-11  3:48 ` [PATCH v5 04/35] target/hexagon: Add missing A_CALL attr, hintjumpr to multi_cof Brian Cain
                   ` (31 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

The BADVA reg is referred to with the wrong identifier.  The
CAUSE reg field of SSR is not yet modeled, we will dump
the SSR in a subsequent commit.

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
---
 target/hexagon/cpu.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 58a22ee41f2..e61ac10fbf3 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -117,6 +117,14 @@ static void print_reg(FILE *f, CPUHexagonState *env, int regnum)
                  hexagon_regnames[regnum], value);
 }
 
+#ifndef CONFIG_USER_ONLY
+static void print_t_sreg(FILE *f, const CPUHexagonState *env, int regnum)
+{
+    qemu_fprintf(f, "  %s = 0x" TARGET_FMT_lx "\n",
+                 hexagon_sregnames[regnum], env->t_sreg[regnum]);
+}
+#endif
+
 static void print_vreg(FILE *f, CPUHexagonState *env, int regnum,
                        bool skip_if_zero)
 {
@@ -216,8 +224,7 @@ static void hexagon_dump(CPUHexagonState *env, FILE *f, int flags)
     qemu_fprintf(f, "  cs0 = 0x00000000\n");
     qemu_fprintf(f, "  cs1 = 0x00000000\n");
 #else
-    print_reg(f, env, HEX_REG_CAUSE);
-    print_reg(f, env, HEX_REG_BADVA);
+    print_t_sreg(f, env, HEX_SREG_BADVA);
     print_reg(f, env, HEX_REG_CS0);
     print_reg(f, env, HEX_REG_CS1);
 #endif
-- 
2.34.1


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

* [PATCH v5 04/35] target/hexagon: Add missing A_CALL attr, hintjumpr to multi_cof
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (2 preceding siblings ...)
  2026-03-11  3:48 ` [PATCH v5 03/35] target/hexagon: Fix badva reference, delete CAUSE Brian Cain
@ 2026-03-11  3:48 ` Brian Cain
  2026-03-11  3:48 ` [PATCH v5 05/35] target/hexagon: Handle system/guest registers in gen_analyze_funcs.py and hex_common.py Brian Cain
                   ` (30 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
---
 target/hexagon/hex_common.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index c0e9f26aebe..002afcdb9e3 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -247,7 +247,9 @@ def need_next_PC(tag):
 
 
 def need_pkt_has_multi_cof(tag):
-    return "A_COF" in attribdict[tag]
+    if attribdict[tag] & {"A_JUMP", "A_CALL"}:
+        return tag != "J4_hintjumpr"
+    return False
 
 
 def need_pkt_need_commit(tag):
-- 
2.34.1


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

* [PATCH v5 05/35] target/hexagon: Handle system/guest registers in gen_analyze_funcs.py and hex_common.py
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (3 preceding siblings ...)
  2026-03-11  3:48 ` [PATCH v5 04/35] target/hexagon: Add missing A_CALL attr, hintjumpr to multi_cof Brian Cain
@ 2026-03-11  3:48 ` Brian Cain
  2026-03-11  3:48 ` [PATCH v5 06/35] target/hexagon: Suppress unused-variable warnings for sysemu source regs Brian Cain
                   ` (29 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Add register classes for guest (G) and system (S) registers to
hex_common.py, and update gen_analyze_funcs.py to handle them.

Guest and system registers can only appear once per packet (one
transfer instruction each), so there is no read-after-write hazard
to detect during the analyze phase.  Source classes (GuestSource,
GuestPairSource, SystemSource, SystemPairSource) provide a no-op
analyze_read() since these register reads do not need tracking.

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/gen_analyze_funcs.py |  14 ++-
 target/hexagon/hex_common.py        | 152 ++++++++++++++++++++++++++++
 2 files changed, 164 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/gen_analyze_funcs.py b/target/hexagon/gen_analyze_funcs.py
index fdefd5b4b36..44bb22ed927 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -22,7 +22,6 @@
 import string
 import hex_common
 
-
 ##
 ## Generate the code to analyze the instruction
 ##     For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
@@ -42,6 +41,13 @@ def gen_analyze_func(f, tag, regs, imms):
     f.write(f"static void analyze_{tag}(DisasContext *ctx)\n")
     f.write("{\n")
 
+    if hex_common.tag_ignore(tag):
+        f.write("}\n\n")
+        return
+
+    if hex_common.is_sysemu_tag(tag):
+        f.write("#ifndef CONFIG_USER_ONLY\n")
+
     f.write("    Insn *insn G_GNUC_UNUSED = ctx->insn;\n")
     if (hex_common.is_hvx_insn(tag)):
         if hex_common.has_hvx_helper(tag):
@@ -58,7 +64,8 @@ def gen_analyze_func(f, tag, regs, imms):
     for regno, register in enumerate(regs):
         reg_type, reg_id = register
         reg = hex_common.get_register(tag, reg_type, reg_id)
-        reg.decl_reg_num(f, regno)
+        if reg.is_read() or reg.is_written():
+            reg.decl_reg_num(f, regno)
 
     ## Analyze the register reads
     for regno, register in enumerate(regs):
@@ -78,6 +85,9 @@ def gen_analyze_func(f, tag, regs, imms):
 
     f.write("    mark_implicit_writes(ctx);\n")
 
+    if hex_common.is_sysemu_tag(tag):
+        f.write("#endif /* !CONFIG_USER_ONLY */\n")
+
     f.write("}\n\n")
 
 
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 002afcdb9e3..ceb4b6812d6 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -33,6 +33,41 @@
 overrides = {}  # tags with helper overrides
 idef_parser_enabled = {}  # tags enabled for idef-parser
 
+
+def is_sysemu_tag(tag):
+    return bool(attribdict[tag] & {"A_PRIV", "A_GUEST"})
+
+
+def tag_ignore(tag):
+    tag_skips = (
+        "Y6_diag",
+        "Y6_diag0",
+        "Y6_diag1",
+    )
+    attr_skips = {
+        "A_FAKEINSN",
+        "A_MAPPING",
+        "A_CONDMAPPING",
+    }
+    return tag in tag_skips or attribdict[tag] & attr_skips
+
+
+def get_sys_tags():
+    return sorted(
+        tag for tag in frozenset(tags) if is_sysemu_tag(tag)
+    )
+
+
+def get_user_tags():
+    return sorted(
+        tag for tag in frozenset(tags) if not is_sysemu_tag(tag)
+    )
+
+
+def get_all_tags():
+    return get_user_tags() + get_sys_tags()
+
+
 # We should do this as a hash for performance,
 # but to keep order let's keep it as a list.
 def uniquify(seq):
@@ -369,12 +404,16 @@ def helper_proto_type(self):
         return "s32"
     def helper_arg_type(self):
         return "int32_t"
+    def is_pair(self):
+        return False
 
 class Pair(Scalar):
     def helper_proto_type(self):
         return "s64"
     def helper_arg_type(self):
         return "int64_t"
+    def is_pair(self):
+        return True
 
 class Hvx:
     def is_scalar_reg(self):
@@ -1010,6 +1049,109 @@ def analyze_write(self, f, tag, regno):
             ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper);
         """))
 
+class GuestRegister(Register):
+    pass
+
+class GuestDest(GuestRegister, Single, Dest):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i32 {self.reg_tcg()} = tcg_temp_new_i32();
+        """))
+    def gen_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_log_greg_write(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+    def analyze_write(self, f, tag, regno):
+        f.write(code_fmt(f"""\
+            ctx_log_greg_write(ctx, {self.reg_num});
+        """))
+
+class GuestSource(GuestRegister, Single, OldSource):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i32 {self.reg_tcg()} = tcg_temp_new_i32();
+            gen_read_greg({self.reg_tcg()}, {self.reg_num});
+        """))
+    def analyze_read(self, f, regno):
+        pass
+
+class GuestPairDest(GuestRegister, Pair, Dest):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
+        """))
+    def gen_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_log_greg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+    def analyze_write(self, f, tag, regno):
+        f.write(code_fmt(f"""\
+            ctx_log_greg_write_pair(ctx, {self.reg_num});
+        """))
+
+class GuestPairSource(GuestRegister, Pair, OldSource):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
+            gen_read_greg_pair({self.reg_tcg()}, {self.reg_num});
+        """))
+    def analyze_read(self, f, regno):
+        pass
+
+class SystemDest(Register, Single, Dest):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i32 {self.reg_tcg()} = tcg_temp_new_i32();
+        """))
+    def gen_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_log_sreg_write(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+    def analyze_write(self, f, tag, regno):
+        f.write(code_fmt(f"""\
+            ctx_log_sreg_write(ctx, {self.reg_num});
+        """))
+
+class SystemSource(Register, Single, OldSource):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i32 {self.reg_tcg()} = tcg_temp_new_i32();
+            gen_read_sreg({self.reg_tcg()}, {self.reg_num});
+        """))
+    def analyze_read(self, f, regno):
+        pass
+
+class SystemPairDest(Register, Pair, Dest):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
+        """))
+    def gen_write(self, f, tag):
+        f.write(code_fmt(f"""\
+            gen_log_sreg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
+        """))
+    def analyze_write(self, f, tag, regno):
+        f.write(code_fmt(f"""\
+            ctx_log_sreg_write_pair(ctx, {self.reg_num});
+        """))
+
+class SystemPairSource(Register, Pair, OldSource):
+    def decl_tcg(self, f, tag, regno):
+        self.decl_reg_num(f, regno)
+        f.write(code_fmt(f"""\
+            TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
+            gen_read_sreg_pair({self.reg_tcg()}, {self.reg_num});
+        """))
+    def analyze_read(self, f, regno):
+        pass
+
 def init_registers():
     regs = {
         GprDest("R", "d"),
@@ -1056,6 +1198,16 @@ def init_registers():
         QRegSource("Q", "u"),
         QRegSource("Q", "v"),
         QRegReadWrite("Q", "x"),
+
+        # system regs
+        GuestDest("G", "d"),
+        GuestSource("G", "s"),
+        GuestPairDest("G", "dd"),
+        GuestPairSource("G", "ss"),
+        SystemDest("S", "d"),
+        SystemSource("S", "s"),
+        SystemPairDest("S", "dd"),
+        SystemPairSource("S", "ss"),
     }
     for reg in regs:
         registers[f"{reg.regtype}{reg.regid}"] = reg
-- 
2.34.1


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

* [PATCH v5 06/35] target/hexagon: Suppress unused-variable warnings for sysemu source regs
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (4 preceding siblings ...)
  2026-03-11  3:48 ` [PATCH v5 05/35] target/hexagon: Handle system/guest registers in gen_analyze_funcs.py and hex_common.py Brian Cain
@ 2026-03-11  3:48 ` Brian Cain
  2026-03-12 21:03   ` Taylor Simpson
  2026-03-11  3:48 ` [PATCH v5 07/35] target/hexagon: Make gen_exception_end_tb non-static Brian Cain
                   ` (28 subsequent siblings)
  34 siblings, 1 reply; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo

The analyze_read() methods on GuestSource, GuestPairSource,
SystemSource, and SystemPairSource were no-ops because these
source registers do not need read-tracking in the analyze phase.
However, gen_analyze_funcs.py unconditionally declares the
register-number variable (e.g. GsN) via decl_reg_num() for all
registers that are read or written.  When building with
hexagon-softmmu, the generated analyze function bodies are
compiled (outside the #ifndef CONFIG_USER_ONLY guard), and the
declared-but-unreferenced register-number variable triggers
-Werror=unused-variable under both gcc and clang.

Emit a (void) cast on the register number from analyze_read() to
suppress the warning.

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/hex_common.py | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index ceb4b6812d6..1daf7239fc4 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -1068,6 +1068,10 @@ def analyze_write(self, f, tag, regno):
         """))
 
 class GuestSource(GuestRegister, Single, OldSource):
+    def decl_reg_num(self, f, regno):
+        f.write(code_fmt(f"""\
+            const int {self.reg_num} G_GNUC_UNUSED = insn->regno[{regno}];
+        """))
     def decl_tcg(self, f, tag, regno):
         self.decl_reg_num(f, regno)
         f.write(code_fmt(f"""\
@@ -1093,6 +1097,10 @@ def analyze_write(self, f, tag, regno):
         """))
 
 class GuestPairSource(GuestRegister, Pair, OldSource):
+    def decl_reg_num(self, f, regno):
+        f.write(code_fmt(f"""\
+            const int {self.reg_num} G_GNUC_UNUSED = insn->regno[{regno}];
+        """))
     def decl_tcg(self, f, tag, regno):
         self.decl_reg_num(f, regno)
         f.write(code_fmt(f"""\
@@ -1118,6 +1126,10 @@ def analyze_write(self, f, tag, regno):
         """))
 
 class SystemSource(Register, Single, OldSource):
+    def decl_reg_num(self, f, regno):
+        f.write(code_fmt(f"""\
+            const int {self.reg_num} G_GNUC_UNUSED = insn->regno[{regno}];
+        """))
     def decl_tcg(self, f, tag, regno):
         self.decl_reg_num(f, regno)
         f.write(code_fmt(f"""\
@@ -1143,6 +1155,10 @@ def analyze_write(self, f, tag, regno):
         """))
 
 class SystemPairSource(Register, Pair, OldSource):
+    def decl_reg_num(self, f, regno):
+        f.write(code_fmt(f"""\
+            const int {self.reg_num} G_GNUC_UNUSED = insn->regno[{regno}];
+        """))
     def decl_tcg(self, f, tag, regno):
         self.decl_reg_num(f, regno)
         f.write(code_fmt(f"""\
-- 
2.34.1


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

* [PATCH v5 07/35] target/hexagon: Make gen_exception_end_tb non-static
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (5 preceding siblings ...)
  2026-03-11  3:48 ` [PATCH v5 06/35] target/hexagon: Suppress unused-variable warnings for sysemu source regs Brian Cain
@ 2026-03-11  3:48 ` Brian Cain
  2026-03-11  3:48 ` [PATCH v5 08/35] target/hexagon: Switch to tag_ignore(), generate via get_{user, sys}_tags() Brian Cain via qemu development
                   ` (27 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/translate.h | 2 ++
 target/hexagon/translate.c | 4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index b37cb492381..2804e08ce57 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -282,6 +282,8 @@ extern TCGv hex_vstore_addr[VSTORES_MAX];
 extern TCGv hex_vstore_size[VSTORES_MAX];
 extern TCGv hex_vstore_pending[VSTORES_MAX];
 
+void hex_gen_exception_end_tb(DisasContext *ctx, int excp);
+
 void process_store(DisasContext *ctx, int slot_num);
 
 FIELD(PROBE_PKT_SCALAR_STORE_S0, MMU_IDX,       0, 2)
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 8a223f6e13e..18b38c285ed 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -189,7 +189,7 @@ static void gen_end_tb(DisasContext *ctx)
     ctx->base.is_jmp = DISAS_NORETURN;
 }
 
-static void gen_exception_end_tb(DisasContext *ctx, int excp)
+void hex_gen_exception_end_tb(DisasContext *ctx, int excp)
 {
     gen_exec_counters(ctx);
     tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->next_PC);
@@ -590,7 +590,7 @@ static void gen_insn(DisasContext *ctx)
         ctx->insn->generate(ctx);
         mark_store_width(ctx);
     } else {
-        gen_exception_end_tb(ctx, HEX_CAUSE_INVALID_OPCODE);
+        hex_gen_exception_end_tb(ctx, HEX_CAUSE_INVALID_OPCODE);
     }
 }
 
-- 
2.34.1


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

* [PATCH v5 08/35] target/hexagon: Switch to tag_ignore(), generate via get_{user, sys}_tags()
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (6 preceding siblings ...)
  2026-03-11  3:48 ` [PATCH v5 07/35] target/hexagon: Make gen_exception_end_tb non-static Brian Cain
@ 2026-03-11  3:48 ` Brian Cain via qemu development
  2026-03-11  3:48 ` [PATCH v5 09/35] target/hexagon: Add privilege check, use tag_ignore() Brian Cain
                   ` (26 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain via qemu development @ 2026-03-11  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/gen_helper_funcs.py      | 26 ++++++++++---------------
 target/hexagon/gen_helper_protos.py     | 23 +++++++++++-----------
 target/hexagon/gen_idef_parser_funcs.py |  2 ++
 target/hexagon/gen_op_attribs.py        |  2 +-
 target/hexagon/gen_opcodes_def.py       |  5 ++++-
 5 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/target/hexagon/gen_helper_funcs.py b/target/hexagon/gen_helper_funcs.py
index 6206104424c..1629ebc0e1a 100755
--- a/target/hexagon/gen_helper_funcs.py
+++ b/target/hexagon/gen_helper_funcs.py
@@ -104,29 +104,23 @@ def main():
     tagimms = hex_common.get_tagimms()
 
     with open(args.out, "w") as f:
-        for tag in hex_common.tags:
-            ## Skip the priv instructions
-            if "A_PRIV" in hex_common.attribdict[tag]:
-                continue
-            ## Skip the guest instructions
-            if "A_GUEST" in hex_common.attribdict[tag]:
-                continue
-            ## Skip the floating point instructions
-            if "A_FPOP" in hex_common.attribdict[tag]:
-                continue
-            ## Skip the diag instructions
-            if tag == "Y6_diag":
-                continue
-            if tag == "Y6_diag0":
-                continue
-            if tag == "Y6_diag1":
+        for tag in hex_common.get_user_tags():
+            if hex_common.tag_ignore(tag):
                 continue
             if hex_common.skip_qemu_helper(tag):
                 continue
             if hex_common.is_idef_parser_enabled(tag):
                 continue
+            gen_helper_function(f, tag, tagregs, tagimms)
 
+        f.write("#if !defined(CONFIG_USER_ONLY)\n")
+        for tag in hex_common.get_sys_tags():
+            if hex_common.skip_qemu_helper(tag):
+                continue
+            if hex_common.is_idef_parser_enabled(tag):
+                continue
             gen_helper_function(f, tag, tagregs, tagimms)
+        f.write("#endif\n")
 
 
 if __name__ == "__main__":
diff --git a/target/hexagon/gen_helper_protos.py b/target/hexagon/gen_helper_protos.py
index 77f8e0a6a32..59c8bdd05c0 100755
--- a/target/hexagon/gen_helper_protos.py
+++ b/target/hexagon/gen_helper_protos.py
@@ -59,27 +59,28 @@ def main():
     tagimms = hex_common.get_tagimms()
 
     with open(args.out, "w") as f:
-        for tag in hex_common.tags:
-            ## Skip the priv instructions
-            if "A_PRIV" in hex_common.attribdict[tag]:
+        for tag in hex_common.get_user_tags():
+            if hex_common.tag_ignore(tag):
                 continue
-            ## Skip the guest instructions
-            if "A_GUEST" in hex_common.attribdict[tag]:
-                continue
-            ## Skip the diag instructions
-            if tag == "Y6_diag":
-                continue
-            if tag == "Y6_diag0":
+
+            if hex_common.skip_qemu_helper(tag):
                 continue
-            if tag == "Y6_diag1":
+            if hex_common.is_idef_parser_enabled(tag):
                 continue
 
+            gen_helper_prototype(f, tag, tagregs, tagimms)
+
+        f.write("#if !defined(CONFIG_USER_ONLY)\n")
+        for tag in hex_common.get_sys_tags():
+            if hex_common.tag_ignore(tag):
+                continue
             if hex_common.skip_qemu_helper(tag):
                 continue
             if hex_common.is_idef_parser_enabled(tag):
                 continue
 
             gen_helper_prototype(f, tag, tagregs, tagimms)
+        f.write("#endif\n")
 
 
 if __name__ == "__main__":
diff --git a/target/hexagon/gen_idef_parser_funcs.py b/target/hexagon/gen_idef_parser_funcs.py
index 2f6e826f76d..32bce9b0028 100644
--- a/target/hexagon/gen_idef_parser_funcs.py
+++ b/target/hexagon/gen_idef_parser_funcs.py
@@ -60,6 +60,8 @@ def main():
         f.write('#include "macros.h.inc"\n\n')
 
         for tag in hex_common.tags:
+            if hex_common.tag_ignore(tag):
+                continue
             ## Skip the priv instructions
             if "A_PRIV" in hex_common.attribdict[tag]:
                 continue
diff --git a/target/hexagon/gen_op_attribs.py b/target/hexagon/gen_op_attribs.py
index bbbb02df3a2..94dd1f876b2 100755
--- a/target/hexagon/gen_op_attribs.py
+++ b/target/hexagon/gen_op_attribs.py
@@ -38,7 +38,7 @@ def main():
     ##     Generate all the attributes associated with each instruction
     ##
     with open(args.out, "w") as f:
-        for tag in hex_common.tags:
+        for tag in hex_common.get_all_tags():
             f.write(
                 f"OP_ATTRIB({tag},ATTRIBS("
                 f'{",".join(sorted(hex_common.attribdict[tag]))}))\n'
diff --git a/target/hexagon/gen_opcodes_def.py b/target/hexagon/gen_opcodes_def.py
index 94a19ff412e..17ba3f9db95 100755
--- a/target/hexagon/gen_opcodes_def.py
+++ b/target/hexagon/gen_opcodes_def.py
@@ -37,7 +37,10 @@ def main():
     ##     Generate a list of all the opcodes
     ##
     with open(args.out, "w") as f:
-        for tag in hex_common.tags:
+        for tag in hex_common.get_user_tags():
+            f.write(f"OPCODE({tag}),\n")
+
+        for tag in hex_common.get_sys_tags():
             f.write(f"OPCODE({tag}),\n")
 
 
-- 
2.34.1


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

* [PATCH v5 09/35] target/hexagon: Add privilege check, use tag_ignore()
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (7 preceding siblings ...)
  2026-03-11  3:48 ` [PATCH v5 08/35] target/hexagon: Switch to tag_ignore(), generate via get_{user, sys}_tags() Brian Cain via qemu development
@ 2026-03-11  3:48 ` Brian Cain
  2026-03-11  3:48 ` [PATCH v5 10/35] target/hexagon: Add a placeholder fp exception Brian Cain
                   ` (25 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo,
	Laurent Vivier, Pierrick Bouvier

Add system event and cause code definitions needed for exception
handling in sysemu mode.  Add privilege checks that raise exceptions
for guest/supervisor-only instructions executed without appropriate
privilege.

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu.h            | 10 +++++
 target/hexagon/cpu_bits.h       | 75 +++++++++++++++++++++++++++++----
 linux-user/hexagon/cpu_loop.c   | 16 +++++++
 target/hexagon/cpu.c            |  1 +
 target/hexagon/translate.c      |  8 ++++
 target/hexagon/gen_tcg_funcs.py | 35 +++++++++------
 6 files changed, 123 insertions(+), 22 deletions(-)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 85afd592778..937194e460e 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -44,6 +44,15 @@
 
 #define MMU_USER_IDX 0
 
+#define HEXAGON_CPU_IRQ_0 0
+#define HEXAGON_CPU_IRQ_1 1
+#define HEXAGON_CPU_IRQ_2 2
+#define HEXAGON_CPU_IRQ_3 3
+#define HEXAGON_CPU_IRQ_4 4
+#define HEXAGON_CPU_IRQ_5 5
+#define HEXAGON_CPU_IRQ_6 6
+#define HEXAGON_CPU_IRQ_7 7
+
 typedef struct {
     target_ulong va;
     uint32_t width;
@@ -76,6 +85,7 @@ typedef struct {
 typedef struct CPUArchState {
     target_ulong gpr[TOTAL_PER_THREAD_REGS];
     target_ulong pred[NUM_PREGS];
+    uint32_t cause_code;
 
     /* For comparing with LLDB on target - see adjust_stack_ptrs function */
     target_ulong last_pc_dumped;
diff --git a/target/hexagon/cpu_bits.h b/target/hexagon/cpu_bits.h
index 19beca81c0c..91e9da09e03 100644
--- a/target/hexagon/cpu_bits.h
+++ b/target/hexagon/cpu_bits.h
@@ -24,20 +24,77 @@
 #define PCALIGN_MASK (PCALIGN - 1)
 
 enum hex_event {
-    HEX_EVENT_NONE           = -1,
-    HEX_EVENT_TRAP0          =  0x008,
+    HEX_EVENT_NONE = -1,
+    HEX_EVENT_RESET = 0x0,
+    HEX_EVENT_IMPRECISE = 0x1,
+    HEX_EVENT_PRECISE = 0x2,
+    HEX_EVENT_TLB_MISS_X = 0x4,
+    HEX_EVENT_TLB_MISS_RW = 0x6,
+    HEX_EVENT_TRAP0 = 0x8,
+    HEX_EVENT_TRAP1 = 0x9,
+    HEX_EVENT_FPTRAP = 0xb,
+    HEX_EVENT_DEBUG = 0xc,
+    HEX_EVENT_INT0 = 0x10,
+    HEX_EVENT_INT1 = 0x11,
+    HEX_EVENT_INT2 = 0x12,
+    HEX_EVENT_INT3 = 0x13,
+    HEX_EVENT_INT4 = 0x14,
+    HEX_EVENT_INT5 = 0x15,
+    HEX_EVENT_INT6 = 0x16,
+    HEX_EVENT_INT7 = 0x17,
+    HEX_EVENT_INT8 = 0x18,
+    HEX_EVENT_INT9 = 0x19,
+    HEX_EVENT_INTA = 0x1a,
+    HEX_EVENT_INTB = 0x1b,
+    HEX_EVENT_INTC = 0x1c,
+    HEX_EVENT_INTD = 0x1d,
+    HEX_EVENT_INTE = 0x1e,
+    HEX_EVENT_INTF = 0x1f,
 };
 
 enum hex_cause {
     HEX_CAUSE_NONE = -1,
-    HEX_CAUSE_TRAP0 = 0x172,
-    HEX_CAUSE_FETCH_NO_UPAGE =  0x012,
-    HEX_CAUSE_INVALID_PACKET =  0x015,
-    HEX_CAUSE_INVALID_OPCODE =  0x015,
+    HEX_CAUSE_RESET = 0x000,
+    HEX_CAUSE_BIU_PRECISE = 0x001,
+    HEX_CAUSE_UNSUPPORTED_HVX_64B = 0x002, /* QEMU-specific */
+    HEX_CAUSE_DOUBLE_EXCEPT = 0x003,
+    HEX_CAUSE_TRAP0 = 0x008,
+    HEX_CAUSE_TRAP1 = 0x009,
+    HEX_CAUSE_FETCH_NO_XPAGE = 0x011,
+    HEX_CAUSE_FETCH_NO_UPAGE = 0x012,
+    HEX_CAUSE_INVALID_PACKET = 0x015,
+    HEX_CAUSE_INVALID_OPCODE = 0x015, /* alias: same cause as INVALID_PACKET */
+    HEX_CAUSE_NO_COPROC_ENABLE = 0x016,
+    HEX_CAUSE_NO_COPROC2_ENABLE = 0x018,
+    HEX_CAUSE_PRIV_USER_NO_GINSN = 0x01a,
+    HEX_CAUSE_PRIV_USER_NO_SINSN = 0x01b,
     HEX_CAUSE_REG_WRITE_CONFLICT = 0x01d,
-    HEX_CAUSE_PC_NOT_ALIGNED =  0x01e,
-    HEX_CAUSE_PRIV_NO_UREAD  =  0x024,
-    HEX_CAUSE_PRIV_NO_UWRITE =  0x025,
+    HEX_CAUSE_PC_NOT_ALIGNED = 0x01e,
+    HEX_CAUSE_MISALIGNED_LOAD = 0x020,
+    HEX_CAUSE_MISALIGNED_STORE = 0x021,
+    HEX_CAUSE_PRIV_NO_READ = 0x022,
+    HEX_CAUSE_PRIV_NO_WRITE = 0x023,
+    HEX_CAUSE_PRIV_NO_UREAD = 0x024,
+    HEX_CAUSE_PRIV_NO_UWRITE = 0x025,
+    HEX_CAUSE_COPROC_LDST = 0x026,
+    HEX_CAUSE_STACK_LIMIT = 0x027,
+    HEX_CAUSE_VWCTRL_WINDOW_MISS = 0x029,
+    HEX_CAUSE_IMPRECISE_NMI = 0x043,
+    HEX_CAUSE_IMPRECISE_MULTI_TLB_MATCH = 0x044,
+    HEX_CAUSE_TLBMISSX_CAUSE_NORMAL = 0x060,
+    HEX_CAUSE_TLBMISSX_CAUSE_NEXTPAGE = 0x061,
+    HEX_CAUSE_TLBMISSRW_CAUSE_READ = 0x070,
+    HEX_CAUSE_TLBMISSRW_CAUSE_WRITE = 0x071,
+    HEX_CAUSE_DEBUG_SINGLESTEP = 0x80,
+    HEX_CAUSE_FPTRAP_CAUSE_BADFLOAT = 0x0bf,
+    HEX_CAUSE_INT0 = 0x0c0,
+    HEX_CAUSE_INT1 = 0x0c1,
+    HEX_CAUSE_INT2 = 0x0c2,
+    HEX_CAUSE_INT3 = 0x0c3,
+    HEX_CAUSE_INT4 = 0x0c4,
+    HEX_CAUSE_INT5 = 0x0c5,
+    HEX_CAUSE_INT6 = 0x0c6,
+    HEX_CAUSE_INT7 = 0x0c7,
 };
 
 #define PACKET_WORDS_MAX         4
diff --git a/linux-user/hexagon/cpu_loop.c b/linux-user/hexagon/cpu_loop.c
index 9464246e9e3..9f54c7b3f96 100644
--- a/linux-user/hexagon/cpu_loop.c
+++ b/linux-user/hexagon/cpu_loop.c
@@ -22,6 +22,7 @@
 #include "qemu.h"
 #include "user-internals.h"
 #include "user/cpu_loop.h"
+#include "target/hexagon/internal.h"
 #include "signal-common.h"
 #include "internal.h"
 
@@ -60,6 +61,21 @@ void cpu_loop(CPUHexagonState *env)
                 env->gpr[0] = ret;
             }
             break;
+        case HEX_EVENT_PRECISE:
+            switch (env->cause_code) {
+            case HEX_CAUSE_PRIV_USER_NO_GINSN:
+            case HEX_CAUSE_PRIV_USER_NO_SINSN:
+            case HEX_CAUSE_INVALID_PACKET:
+            force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC,
+                    env->gpr[HEX_REG_PC]);
+            break;
+            default:
+                EXCP_DUMP(env, "\nqemu: unhandled CPU precise exception "
+                    "cause code 0x%x - aborting\n",
+                    env->cause_code);
+                exit(EXIT_FAILURE);
+            }
+            break;
         case HEX_CAUSE_PC_NOT_ALIGNED:
             force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN,
                             env->gpr[HEX_REG_R31]);
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index e61ac10fbf3..1f172404608 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -306,6 +306,7 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
     set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
     /* Default NaN value: sign bit set, all frac bits set */
     set_float_default_nan_pattern(0b11111111, &env->fp_status);
+    env->cause_code = HEX_EVENT_NONE;
 }
 
 static void hexagon_cpu_disas_set_info(const CPUState *cs,
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 18b38c285ed..571ba9cae41 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -65,6 +65,10 @@ TCGv hex_vstore_addr[VSTORES_MAX];
 TCGv hex_vstore_size[VSTORES_MAX];
 TCGv hex_vstore_pending[VSTORES_MAX];
 
+#ifndef CONFIG_USER_ONLY
+TCGv_i32 hex_cause_code;
+#endif
+
 static const char * const hexagon_prednames[] = {
   "p0", "p1", "p2", "p3"
 };
@@ -1153,4 +1157,8 @@ void hexagon_translate_init(void)
             offsetof(CPUHexagonState, vstore_pending[i]),
             vstore_pending_names[i]);
     }
+#ifndef CONFIG_USER_ONLY
+    hex_cause_code = tcg_global_mem_new(tcg_env,
+        offsetof(CPUHexagonState, cause_code), "cause_code");
+#endif
 }
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index 87b7f10d7fd..d91bbcf1dc8 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -21,7 +21,7 @@
 import re
 import string
 import hex_common
-
+from textwrap import dedent
 
 ##
 ## Generate the TCG code to call the helper
@@ -49,6 +49,18 @@ def gen_tcg_func(f, tag, regs, imms):
 
     f.write("    Insn *insn G_GNUC_UNUSED = ctx->insn;\n")
 
+    if "A_PRIV" in hex_common.attribdict[tag]:
+        f.write(dedent("""\
+#ifdef CONFIG_USER_ONLY
+    hex_gen_exception_end_tb(ctx, HEX_CAUSE_PRIV_USER_NO_SINSN);
+#else
+"""))
+    if "A_GUEST" in hex_common.attribdict[tag]:
+        f.write(dedent("""\
+#ifdef CONFIG_USER_ONLY
+    hex_gen_exception_end_tb(ctx, HEX_CAUSE_PRIV_USER_NO_GINSN);
+#else
+"""))
     if hex_common.need_ea(tag):
         f.write("    TCGv EA G_GNUC_UNUSED = tcg_temp_new();\n")
 
@@ -100,6 +112,11 @@ def gen_tcg_func(f, tag, regs, imms):
         if reg.is_written():
             reg.gen_write(f, tag)
 
+    if (
+        "A_PRIV" in hex_common.attribdict[tag]
+        or "A_GUEST" in hex_common.attribdict[tag]
+    ):
+        f.write("#endif   /* CONFIG_USER_ONLY */\n")
     f.write("}\n\n")
 
 
@@ -124,18 +141,10 @@ def main():
             f.write('#include "idef-generated-emitter.h.inc"\n\n')
 
         for tag in hex_common.tags:
-            ## Skip the priv instructions
-            if "A_PRIV" in hex_common.attribdict[tag]:
-                continue
-            ## Skip the guest instructions
-            if "A_GUEST" in hex_common.attribdict[tag]:
-                continue
-            ## Skip the diag instructions
-            if tag == "Y6_diag":
-                continue
-            if tag == "Y6_diag0":
-                continue
-            if tag == "Y6_diag1":
+            if hex_common.tag_ignore(tag):
+                f.write(f"static void generate_{tag}"
+                        f"(DisasContext *ctx)\n")
+                f.write("{\n}\n\n")
                 continue
 
             gen_def_tcg_func(f, tag, tagregs, tagimms)
-- 
2.34.1


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

* [PATCH v5 10/35] target/hexagon: Add a placeholder fp exception
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (8 preceding siblings ...)
  2026-03-11  3:48 ` [PATCH v5 09/35] target/hexagon: Add privilege check, use tag_ignore() Brian Cain
@ 2026-03-11  3:48 ` Brian Cain
  2026-03-11  3:48 ` [PATCH v5 11/35] target/hexagon: Add guest, system reg number defs Brian Cain
                   ` (24 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/arch.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/target/hexagon/arch.c b/target/hexagon/arch.c
index e17e714a6ac..0a400bf7a77 100644
--- a/target/hexagon/arch.c
+++ b/target/hexagon/arch.c
@@ -208,6 +208,11 @@ void arch_fpop_start(CPUHexagonState *env)
  * model it in qemu user mode.
  */
 #define RAISE_FP_EXCEPTION   do {} while (0)
+#else
+ /*
+  * To be implemented.
+  */
+#define RAISE_FP_EXCEPTION   do { g_assert_not_reached(); } while (0)
 #endif
 
 #define SOFTFLOAT_TEST_FLAG(FLAG, MYF, MYE) \
-- 
2.34.1


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

* [PATCH v5 11/35] target/hexagon: Add guest, system reg number defs
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (9 preceding siblings ...)
  2026-03-11  3:48 ` [PATCH v5 10/35] target/hexagon: Add a placeholder fp exception Brian Cain
@ 2026-03-11  3:48 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 12/35] target/hexagon: Add guest, system reg number state Brian Cain
                   ` (23 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
---
 target/hexagon/cpu.h      |   7 +++
 target/hexagon/hex_regs.h | 117 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 124 insertions(+)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 937194e460e..3825de43ee7 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -20,6 +20,13 @@
 
 #include "fpu/softfloat-types.h"
 
+#ifndef CONFIG_USER_ONLY
+#define NUM_GREGS 32
+#define GREG_WRITES_MAX 2
+#define NUM_SREGS 64
+#define SREG_WRITES_MAX 2
+#endif
+
 #include "cpu-qom.h"
 #include "exec/cpu-common.h"
 #include "exec/cpu-defs.h"
diff --git a/target/hexagon/hex_regs.h b/target/hexagon/hex_regs.h
index bddfc28021c..214b7b8fde8 100644
--- a/target/hexagon/hex_regs.h
+++ b/target/hexagon/hex_regs.h
@@ -81,4 +81,121 @@ enum {
     HEX_REG_UTIMERHI          = 63,
 };
 
+#ifndef CONFIG_USER_ONLY
+
+#define HEX_GREG_VALUES \
+  DECL_HEX_GREG(G0,         0) \
+  DECL_HEX_GREG(GELR,       0) \
+  DECL_HEX_GREG(G1,         1) \
+  DECL_HEX_GREG(GSR,        1) \
+  DECL_HEX_GREG(G2,         2) \
+  DECL_HEX_GREG(GOSP,       2) \
+  DECL_HEX_GREG(G3,         3) \
+  DECL_HEX_GREG(GBADVA,     3) \
+  DECL_HEX_GREG(GCYCLE_1T,  10) \
+  DECL_HEX_GREG(GCYCLE_2T,  11) \
+  DECL_HEX_GREG(GCYCLE_3T,  12) \
+  DECL_HEX_GREG(GCYCLE_4T,  13) \
+  DECL_HEX_GREG(GCYCLE_5T,  14) \
+  DECL_HEX_GREG(GCYCLE_6T,  15) \
+  DECL_HEX_GREG(GPMUCNT4,   16) \
+  DECL_HEX_GREG(GPMUCNT5,   17) \
+  DECL_HEX_GREG(GPMUCNT6,   18) \
+  DECL_HEX_GREG(GPMUCNT7,   19) \
+  DECL_HEX_GREG(GPCYCLELO,  24) \
+  DECL_HEX_GREG(GPCYCLEHI,  25) \
+  DECL_HEX_GREG(GPMUCNT0,   26) \
+  DECL_HEX_GREG(GPMUCNT1,   27) \
+  DECL_HEX_GREG(GPMUCNT2,   28) \
+  DECL_HEX_GREG(GPMUCNT3,   29) \
+  DECL_HEX_GREG_DONE
+
+#define DECL_HEX_GREG_DONE
+#define DECL_HEX_GREG(name, val) HEX_GREG_ ##name = val,
+enum hex_greg {
+    HEX_GREG_VALUES
+};
+#undef DECL_HEX_GREG
+#undef DECL_HEX_GREG_DONE
+
+#define DECL_HEX_GREG_DONE 0
+#define DECL_HEX_GREG(_, val) (1 << val) |
+static inline bool greg_implemented(enum hex_greg greg)
+{
+#if NUM_GREGS > 32
+#error "NUM_GREGS too large for greg_implemented(): update `impl_bitmap`"
+#endif
+    static int32_t impl_bitmap = HEX_GREG_VALUES;
+    return impl_bitmap & (1 << greg);
+}
+#undef DECL_HEX_GREG
+#undef DECL_HEX_GREG_DONE
+
+#endif /* CONFIG_USER_ONLY */
+
+#ifndef CONFIG_USER_ONLY
+enum {
+    HEX_SREG_SGP0 = 0,
+    HEX_SREG_SGP1 = 1,
+    HEX_SREG_STID = 2,
+    HEX_SREG_ELR = 3,
+    HEX_SREG_BADVA0 = 4,
+    HEX_SREG_BADVA1 = 5,
+    HEX_SREG_SSR = 6,
+    HEX_SREG_CCR = 7,
+    HEX_SREG_HTID = 8,
+    HEX_SREG_BADVA = 9,
+    HEX_SREG_IMASK = 10,
+    HEX_SREG_GEVB  = 11,
+    HEX_SREG_GLB_START = 16,
+    HEX_SREG_EVB = 16,
+    HEX_SREG_MODECTL = 17,
+    HEX_SREG_SYSCFG = 18,
+    HEX_SREG_IPENDAD = 20,
+    HEX_SREG_VID = 21,
+    HEX_SREG_VID1 = 22,
+    HEX_SREG_BESTWAIT = 23,
+    HEX_SREG_IEL = 24,
+    HEX_SREG_SCHEDCFG = 25,
+    HEX_SREG_IAHL = 26,
+    HEX_SREG_CFGBASE = 27,
+    HEX_SREG_DIAG = 28,
+    HEX_SREG_REV = 29,
+    HEX_SREG_PCYCLELO = 30,
+    HEX_SREG_PCYCLEHI = 31,
+    HEX_SREG_ISDBST = 32,
+    HEX_SREG_ISDBCFG0 = 33,
+    HEX_SREG_ISDBCFG1 = 34,
+    HEX_SREG_LIVELOCK = 35,
+    HEX_SREG_BRKPTPC0 = 36,
+    HEX_SREG_BRKPTCFG0 = 37,
+    HEX_SREG_BRKPTPC1 = 38,
+    HEX_SREG_BRKPTCFG1 = 39,
+    HEX_SREG_ISDBMBXIN = 40,
+    HEX_SREG_ISDBMBXOUT = 41,
+    HEX_SREG_ISDBEN = 42,
+    HEX_SREG_ISDBGPR = 43,
+    HEX_SREG_PMUCNT4 = 44,
+    HEX_SREG_PMUCNT5 = 45,
+    HEX_SREG_PMUCNT6 = 46,
+    HEX_SREG_PMUCNT7 = 47,
+    HEX_SREG_PMUCNT0 = 48,
+    HEX_SREG_PMUCNT1 = 49,
+    HEX_SREG_PMUCNT2 = 50,
+    HEX_SREG_PMUCNT3 = 51,
+    HEX_SREG_PMUEVTCFG = 52,
+    HEX_SREG_PMUSTID0 = 53,
+    HEX_SREG_PMUEVTCFG1 = 54,
+    HEX_SREG_PMUSTID1 = 55,
+    HEX_SREG_TIMERLO = 56,
+    HEX_SREG_TIMERHI = 57,
+    HEX_SREG_PMUCFG = 58,
+    HEX_SREG_S59 = 59,
+    HEX_SREG_S60 = 60,
+    HEX_SREG_S61 = 61,
+    HEX_SREG_S62 = 62,
+    HEX_SREG_S63 = 63,
+};
+#endif /* !CONFIG_USER_ONLY */
+
 #endif
-- 
2.34.1


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

* [PATCH v5 12/35] target/hexagon: Add guest, system reg number state
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (10 preceding siblings ...)
  2026-03-11  3:48 ` [PATCH v5 11/35] target/hexagon: Add guest, system reg number defs Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 13/35] target/hexagon: Add TCG values for sreg, greg Brian Cain
                   ` (22 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu.h | 11 +++++++++++
 target/hexagon/cpu.c |  5 +++++
 2 files changed, 16 insertions(+)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 3825de43ee7..3562965c88a 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -99,6 +99,17 @@ typedef struct CPUArchState {
     target_ulong stack_start;
 
     uint8_t slot_cancelled;
+
+#ifndef CONFIG_USER_ONLY
+    /* Some system registers are per thread and some are global. */
+    uint32_t t_sreg[NUM_SREGS];
+
+    uint32_t greg[NUM_GREGS];
+    uint32_t wait_next_pc;
+
+    /* This alias of CPUState.cpu_index is used by imported sources: */
+    uint32_t threadId;
+#endif
     target_ulong new_value_usr;
 
     MemLog mem_log_stores[STORES_MAX];
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 1f172404608..6fabfaad6d2 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -306,6 +306,11 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
     set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
     /* Default NaN value: sign bit set, all frac bits set */
     set_float_default_nan_pattern(0b11111111, &env->fp_status);
+#ifndef CONFIG_USER_ONLY
+    memset(env->t_sreg, 0, sizeof(uint32_t) * NUM_SREGS);
+    memset(env->greg, 0, sizeof(uint32_t) * NUM_GREGS);
+    env->wait_next_pc = 0;
+#endif
     env->cause_code = HEX_EVENT_NONE;
 }
 
-- 
2.34.1


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

* [PATCH v5 13/35] target/hexagon: Add TCG values for sreg, greg
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (11 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 12/35] target/hexagon: Add guest, system reg number state Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 14/35] target/hexagon: Add guest/sys reg writes to DisasContext Brian Cain
                   ` (21 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/translate.h |  5 +++++
 target/hexagon/translate.c | 16 ++++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 2804e08ce57..40d365f4250 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -281,6 +281,11 @@ extern TCGv_i64 hex_llsc_val_i64;
 extern TCGv hex_vstore_addr[VSTORES_MAX];
 extern TCGv hex_vstore_size[VSTORES_MAX];
 extern TCGv hex_vstore_pending[VSTORES_MAX];
+#ifndef CONFIG_USER_ONLY
+extern TCGv_i32 hex_greg[NUM_GREGS];
+extern TCGv_i32 hex_t_sreg[NUM_SREGS];
+#endif
+
 
 void hex_gen_exception_end_tb(DisasContext *ctx, int excp);
 
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 571ba9cae41..cd6affa2f49 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -66,6 +66,8 @@ TCGv hex_vstore_size[VSTORES_MAX];
 TCGv hex_vstore_pending[VSTORES_MAX];
 
 #ifndef CONFIG_USER_ONLY
+TCGv_i32 hex_greg[NUM_GREGS];
+TCGv_i32 hex_t_sreg[NUM_SREGS];
 TCGv_i32 hex_cause_code;
 #endif
 
@@ -1099,6 +1101,20 @@ void hexagon_translate_init(void)
 
     opcode_init();
 
+#ifndef CONFIG_USER_ONLY
+    for (i = 0; i < NUM_GREGS; i++) {
+            hex_greg[i] = tcg_global_mem_new_i32(tcg_env,
+                offsetof(CPUHexagonState, greg[i]),
+                hexagon_gregnames[i]);
+    }
+    for (i = 0; i < NUM_SREGS; i++) {
+        if (i < HEX_SREG_GLB_START) {
+            hex_t_sreg[i] = tcg_global_mem_new_i32(tcg_env,
+                offsetof(CPUHexagonState, t_sreg[i]),
+                hexagon_sregnames[i]);
+        }
+    }
+#endif
     for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
         hex_gpr[i] = tcg_global_mem_new(tcg_env,
             offsetof(CPUHexagonState, gpr[i]),
-- 
2.34.1


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

* [PATCH v5 14/35] target/hexagon: Add guest/sys reg writes to DisasContext
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (12 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 13/35] target/hexagon: Add TCG values for sreg, greg Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 15/35] target/hexagon: Add imported macro, attr defs for sysemu Brian Cain
                   ` (20 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/translate.h | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 40d365f4250..7e528379db6 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -40,6 +40,14 @@ typedef struct DisasContext {
     DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
     DECLARE_BITMAP(predicated_regs, TOTAL_PER_THREAD_REGS);
     bool implicit_usr_write;
+#ifndef CONFIG_USER_ONLY
+    int greg_log[GREG_WRITES_MAX];
+    int greg_log_idx;
+    int sreg_log[SREG_WRITES_MAX];
+    int sreg_log_idx;
+    TCGv_i32 t_sreg_new_value[NUM_SREGS];
+    TCGv_i32 greg_new_value[NUM_GREGS];
+#endif
     int preg_log[PRED_WRITES_MAX];
     int preg_log_idx;
     DECLARE_BITMAP(pregs_written, NUM_PREGS);
@@ -80,6 +88,34 @@ typedef struct DisasContext {
 
 bool is_gather_store_insn(DisasContext *ctx);
 
+#ifndef CONFIG_USER_ONLY
+static inline void ctx_log_greg_write(DisasContext *ctx, int rnum)
+{
+    assert(rnum <= HEX_GREG_G3);
+    ctx->greg_log[ctx->greg_log_idx] = rnum;
+    ctx->greg_log_idx++;
+}
+
+static inline void ctx_log_greg_write_pair(DisasContext *ctx, int rnum)
+{
+    assert(!(rnum % 2));
+    ctx_log_greg_write(ctx, rnum);
+    ctx_log_greg_write(ctx, rnum + 1);
+}
+
+static inline void ctx_log_sreg_write(DisasContext *ctx, int rnum)
+{
+    ctx->sreg_log[ctx->sreg_log_idx] = rnum;
+    ctx->sreg_log_idx++;
+}
+
+static inline void ctx_log_sreg_write_pair(DisasContext *ctx, int rnum)
+{
+    ctx_log_sreg_write(ctx, rnum);
+    ctx_log_sreg_write(ctx, rnum + 1);
+}
+#endif
+
 static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
 {
     if (!test_bit(pnum, ctx->pregs_written)) {
-- 
2.34.1


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

* [PATCH v5 15/35] target/hexagon: Add imported macro, attr defs for sysemu
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (13 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 14/35] target/hexagon: Add guest/sys reg writes to DisasContext Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 16/35] target/hexagon: Add new macro definitions " Brian Cain
                   ` (19 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/attribs_def.h.inc   |  49 ++-
 target/hexagon/imported/macros.def | 482 ++++++++++++++++++++++++++++-
 2 files changed, 518 insertions(+), 13 deletions(-)
 mode change 100755 => 100644 target/hexagon/imported/macros.def

diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 9e3a05f8828..06ab826b49f 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -52,6 +52,9 @@ DEF_ATTRIB(REGWRSIZE_4B, "Memory width is 4 bytes", "", "")
 DEF_ATTRIB(REGWRSIZE_8B, "Memory width is 8 bytes", "", "")
 DEF_ATTRIB(MEMLIKE, "Memory-like instruction", "", "")
 DEF_ATTRIB(MEMLIKE_PACKET_RULES, "follows Memory-like packet rules", "", "")
+DEF_ATTRIB(CACHEOP, "Cache operation", "", "")
+DEF_ATTRIB(COPBYADDRESS, "Cache operation by address", "", "")
+DEF_ATTRIB(COPBYIDX, "Cache operation by index", "", "")
 DEF_ATTRIB(RELEASE, "Releases a lock", "", "")
 DEF_ATTRIB(ACQUIRE, "Acquires a lock", "", "")
 
@@ -101,23 +104,44 @@ DEF_ATTRIB(ROPS_3, "Compound instruction worth 3 RISC-ops", "", "")
 
 /* access to implicit registers */
 DEF_ATTRIB(IMPLICIT_WRITES_LR, "Writes the link register", "", "UREG.LR")
+DEF_ATTRIB(IMPLICIT_READS_LR, "Reads the link register", "UREG.LR", "")
+DEF_ATTRIB(IMPLICIT_READS_LC0, "Reads loop count for loop 0", "UREG.LC0", "")
+DEF_ATTRIB(IMPLICIT_READS_LC1, "Reads loop count for loop 1", "UREG.LC1", "")
+DEF_ATTRIB(IMPLICIT_READS_SA0, "Reads start address for loop 0", "UREG.SA0", "")
+DEF_ATTRIB(IMPLICIT_READS_SA1, "Reads start address for loop 1", "UREG.SA1", "")
+DEF_ATTRIB(IMPLICIT_WRITES_PC, "Writes the program counter", "", "UREG.PC")
+DEF_ATTRIB(IMPLICIT_READS_PC, "Reads the program counter", "UREG.PC", "")
 DEF_ATTRIB(IMPLICIT_WRITES_SP, "Writes the stack pointer", "", "UREG.SP")
+DEF_ATTRIB(IMPLICIT_READS_SP, "Reads the stack pointer", "UREG.SP", "")
 DEF_ATTRIB(IMPLICIT_WRITES_FP, "Writes the frame pointer", "", "UREG.FP")
+DEF_ATTRIB(IMPLICIT_READS_FP, "Reads the frame pointer", "UREG.FP", "")
+DEF_ATTRIB(IMPLICIT_WRITES_GP, "Writes the GP register", "", "UREG.GP")
+DEF_ATTRIB(IMPLICIT_READS_GP, "Reads the GP register", "UREG.GP", "")
 DEF_ATTRIB(IMPLICIT_WRITES_LC0, "Writes loop count for loop 0", "", "UREG.LC0")
 DEF_ATTRIB(IMPLICIT_WRITES_LC1, "Writes loop count for loop 1", "", "UREG.LC1")
 DEF_ATTRIB(IMPLICIT_WRITES_SA0, "Writes start addr for loop 0", "", "UREG.SA0")
 DEF_ATTRIB(IMPLICIT_WRITES_SA1, "Writes start addr for loop 1", "", "UREG.SA1")
+DEF_ATTRIB(IMPLICIT_WRITES_R00, "Writes Register 0", "", "UREG.R00")
 DEF_ATTRIB(IMPLICIT_WRITES_P0, "Writes Predicate 0", "", "UREG.P0")
 DEF_ATTRIB(IMPLICIT_WRITES_P1, "Writes Predicate 1", "", "UREG.P1")
 DEF_ATTRIB(IMPLICIT_WRITES_P2, "Writes Predicate 1", "", "UREG.P2")
 DEF_ATTRIB(IMPLICIT_WRITES_P3, "May write Predicate 3", "", "UREG.P3")
-DEF_ATTRIB(IMPLICIT_READS_PC, "Reads the PC register", "", "")
-DEF_ATTRIB(IMPLICIT_READS_P0, "Reads the P0 register", "", "")
-DEF_ATTRIB(IMPLICIT_READS_P1, "Reads the P1 register", "", "")
-DEF_ATTRIB(IMPLICIT_READS_P2, "Reads the P2 register", "", "")
-DEF_ATTRIB(IMPLICIT_READS_P3, "Reads the P3 register", "", "")
+DEF_ATTRIB(IMPLICIT_READS_R00, "Reads Register 0", "UREG.R00", "")
+DEF_ATTRIB(IMPLICIT_READS_P0, "Reads Predicate 0", "UREG.P0", "")
+DEF_ATTRIB(IMPLICIT_READS_P1, "Reads Predicate 1", "UREG.P1", "")
+DEF_ATTRIB(IMPLICIT_READS_P3, "Reads Predicate 3", "UREG.P3", "")
+DEF_ATTRIB(IMPLICIT_READS_Q3, "Reads Vector Predicate 3", "UREG.Q3", "")
+DEF_ATTRIB(IMPLICIT_READS_CS, "Reads the CS/M register", "UREG.CS", "")
 DEF_ATTRIB(IMPLICIT_WRITES_USR, "May write USR", "", "")
-DEF_ATTRIB(IMPLICIT_READS_SP, "Reads the SP register", "", "")
+DEF_ATTRIB(IMPLICIT_WRITES_CCR, "Writes CCR register", "", "UREG.CCR")
+DEF_ATTRIB(IMPLICIT_WRITES_GOSP, "Writes GOSP register", "", "UREG.GOSP")
+DEF_ATTRIB(IMPLICIT_WRITES_SSR, "Writes SSR register", "", "UREG.SSR")
+DEF_ATTRIB(IMPLICIT_WRITES_SGP0, "Writes SGP0 register", "", "UREG.SGP0")
+DEF_ATTRIB(IMPLICIT_WRITES_SGP1, "Writes SGP1 register", "", "UREG.SGP1")
+DEF_ATTRIB(IMPLICIT_WRITES_IMASK_ANYTHREAD,
+    "Writes IMASK for any thread", "", "")
+DEF_ATTRIB(IMPLICIT_WRITES_STID_PRIO_ANYTHREAD,
+    "Writes STID priority for any thread", "", "")
 DEF_ATTRIB(COMMUTES, "The operation is communitive", "", "")
 DEF_ATTRIB(DEALLOCRET, "dealloc_return", "", "")
 DEF_ATTRIB(DEALLOCFRAME, "deallocframe", "", "")
@@ -137,9 +161,15 @@ DEF_ATTRIB(RESTRICT_SLOT3ONLY, "Must execute on slot3", "", "")
 DEF_ATTRIB(RESTRICT_NOSLOT1, "No slot 1 instruction in parallel", "", "")
 DEF_ATTRIB(RESTRICT_PREFERSLOT0, "Try to encode into slot 0", "", "")
 DEF_ATTRIB(RESTRICT_PACKET_AXOK, "May exist with A-type or X-type", "", "")
+DEF_ATTRIB(RESTRICT_SINGLE_MEM_FIRST, "Single memory op must be first", "", "")
+DEF_ATTRIB(RESTRICT_SLOT1_AOK, "Slot 1 is allowed", "", "")
 
 DEF_ATTRIB(ICOP, "Instruction cache op", "", "")
 
+DEF_ATTRIB(EXCEPTION_SWI, "Software interrupt exception", "", "")
+DEF_ATTRIB(DMA, "DMA instruction", "", "")
+DEF_ATTRIB(NO_TIMING_LOG, "Does not get logged to the timing model", "", "")
+
 DEF_ATTRIB(HWLOOP0_END, "Ends HW loop0", "", "")
 DEF_ATTRIB(HWLOOP1_END, "Ends HW loop1", "", "")
 DEF_ATTRIB(RET_TYPE, "return type", "", "")
@@ -151,6 +181,10 @@ DEF_ATTRIB(DCFETCH, "dcfetch type", "", "")
 
 DEF_ATTRIB(L2FETCH, "Instruction is l2fetch type", "", "")
 
+DEF_ATTRIB(DCTAGOP, "Data cache tag operation", "", "")
+DEF_ATTRIB(ICTAGOP, "Instruction cache tag operation", "", "")
+DEF_ATTRIB(L2TAGOP, "L2 cache tag operation", "", "")
+
 DEF_ATTRIB(ICINVA, "icinva", "", "")
 DEF_ATTRIB(DCCLEANINVA, "dccleaninva", "", "")
 
@@ -166,6 +200,9 @@ DEF_ATTRIB(NOTE_LATEPRED, "The predicate can not be used as a .new", "", "")
 DEF_ATTRIB(NOTE_NVSLOT0, "Can execute only in slot 0 (ST)", "", "")
 DEF_ATTRIB(NOTE_NOVP, "Cannot be paired with a HVX permute instruction", "", "")
 DEF_ATTRIB(NOTE_VA_UNARY, "Combined with HVX ALU op (must be unary)", "", "")
+DEF_ATTRIB(NOTE_SLOT1_AOK, "Slot 1 is allowed", "", "")
+DEF_ATTRIB(NOTE_GUEST, "Guest mode instruction", "", "")
+DEF_ATTRIB(NOTE_BADTAG_UNDEF, "Bad tag results in undefined behavior", "", "")
 
 /* V6 MMVector Notes for Documentation */
 DEF_ATTRIB(NOTE_SHIFT_RESOURCE, "Uses the HVX shift resource.", "", "")
diff --git a/target/hexagon/imported/macros.def b/target/hexagon/imported/macros.def
old mode 100755
new mode 100644
index 4bbcfdd5e19..13eb13c71f7
--- a/target/hexagon/imported/macros.def
+++ b/target/hexagon/imported/macros.def
@@ -353,6 +353,12 @@ DEF_MACRO(
     ()
 )
 
+DEF_MACRO(
+    fREAD_SSR, /* read SSR register */
+    (READ_RREG(REG_SSR)),          /* behavior */
+    ()
+)
+
 DEF_MACRO(
     fWRITE_LR, /* write lr */
     WRITE_RREG(REG_LR,A),          /* behavior */
@@ -371,12 +377,36 @@ DEF_MACRO(
     (A_IMPLICIT_WRITES_SP)
 )
 
+DEF_MACRO(
+    fWRITE_GOSP, /* write gosp */
+    WRITE_RREG(REG_GOSP,A),          /* behavior */
+    (A_IMPLICIT_WRITES_GOSP)
+)
+
 DEF_MACRO(
     fREAD_SP, /* read stack pointer */
     (READ_RREG(REG_SP)),          /* behavior */
     ()
 )
 
+DEF_MACRO(
+    fREAD_GOSP, /* read guest other stack pointer */
+    (READ_RREG(REG_GOSP)),          /* behavior */
+    ()
+)
+
+DEF_MACRO(
+    fREAD_GELR, /* read guest other stack pointer */
+    (READ_RREG(REG_GELR)),          /* behavior */
+    ()
+)
+
+DEF_MACRO(
+    fREAD_GEVB, /* read guest other stack pointer */
+    (READ_RREG(REG_GEVB)),          /* behavior */
+    ()
+)
+
 DEF_MACRO(
     fREAD_CSREG, /* read  CS register */
     (READ_RREG(REG_CSA+N)),          /* behavior */
@@ -570,6 +600,11 @@ DEF_MACRO(
     WRITE_PREG(3,VAL),     /* behavior */
     (A_IMPLICIT_WRITES_P3)
 )
+DEF_MACRO(
+	fWRITE_P3_LATE, /* write Predicate 0 */
+	{WRITE_PREG(3,VAL); fHIDE(MARK_LATE_PRED_WRITE(3))} ,          /* behavior */
+	(A_IMPLICIT_WRITES_P3,A_RESTRICT_LATEPRED)
+)
 
 DEF_MACRO(
     fPART1, /* write Predicate 0 */
@@ -660,6 +695,7 @@ DEF_MACRO(
     ((size8s_t)((size2s_t)(A))),
     /* optional attributes */
 )
+
 DEF_MACRO(
     fCAST2_8u, /* macro name */
     ((size8u_t)((size2u_t)(A))),
@@ -1532,18 +1568,137 @@ DEF_MACRO(fECHO,
 /* OS interface and stop/wait               */
 /********************************************/
 
+DEF_MACRO(RUNNABLE_THREADS_MAX,
+    /* */,
+    ()
+)
+
+DEF_MACRO(THREAD_IS_ON,
+    ((PROC->arch_proc_options->thread_enable_mask>>TNUM) & 0x1),
+    ()
+)
+
+DEF_MACRO(THREAD_EN_MASK,
+    ((PROC->arch_proc_options->thread_enable_mask)),
+    ()
+)
+
+
+
+DEF_MACRO(READ_IMASK,
+    /* */,
+    ()
+)
+DEF_MACRO(WRITE_IMASK,
+    /* */,
+    (A_IMPLICIT_WRITES_IMASK_ANYTHREAD)
+)
+
+
+DEF_MACRO(WRITE_PRIO,
+    /* */,
+    (A_IMPLICIT_WRITES_STID_PRIO_ANYTHREAD)
+)
+
+
+DEF_MACRO(DO_IASSIGNW,
+    /* */,
+    (A_IMPLICIT_WRITES_IMASK_ANYTHREAD)
+)
+
+
+
+
+DEF_MACRO(fDO_NMI,
+    /* */,
+)
+
+DEF_MACRO(fDO_TRACE,
+    /* */,
+)
+
+DEF_MACRO(DO_IASSIGNR,
+    /* */,
+    ()
+)
+
+DEF_MACRO(DO_SWI,
+        /* */,
+        (A_EXCEPTION_SWI)
+)
+
+DEF_MACRO(DO_CSWI,
+        LOG_GLOBAL_REG_WRITE(REG_IPEND,GLOBAL_REG_READ(REG_IPEND) & ~((REG) & GLOBAL_REG_READ(REG_IEL)));,
+        ()
+)
+
+DEF_MACRO(DO_CIAD,
+        sys_ciad(thread,VAL); LOG_GLOBAL_REG_WRITE(REG_IAD,GLOBAL_REG_READ(REG_IAD) & ~(VAL));,
+        (A_EXCEPTION_SWI)
+)
+
+DEF_MACRO(DO_SIAD,
+        sys_siad(thread,VAL); LOG_GLOBAL_REG_WRITE(REG_IAD,GLOBAL_REG_READ(REG_IAD) | (VAL));,
+        (A_EXCEPTION_SWI)
+)
+
+DEF_MACRO(fBREAK,
+    /* */,
+    ()
+)
+
 DEF_MACRO(fPAUSE,
     {sys_pause(thread, insn->slot, IMM);},
     ()
 )
 
+
 DEF_MACRO(fTRAP,
-    warn("Trap NPC=%x ",fREAD_NPC());
-    warn("Trap exception, PCYCLE=%lld TYPE=%d NPC=%x IMM=0x%x",thread->processor_ptr->pstats[pcycles],TRAPTYPE,fREAD_NPC(),IMM);
-    register_trap_exception(thread,fREAD_NPC(),TRAPTYPE,IMM);,
+    /* */,
+    (A_EXCEPTION_SWI)
+)
+
+DEF_MACRO(fCLEAR_RTE_EX,
+      /* */,
+      ()
+)
+
+DEF_MACRO(fTLB_LOCK_AVAILABLE,
+    (fREAD_GLOBAL_REG_FIELD(SYSCONF,SYSCFG_TLBLOCK) == 0),
     ()
 )
 
+DEF_MACRO(fK0_LOCK_AVAILABLE,
+    (fREAD_GLOBAL_REG_FIELD(SYSCONF,SYSCFG_K0LOCK) == 0),
+    ()
+)
+
+DEF_MACRO(fSET_TLB_LOCK,
+      {
+      if (fTLB_LOCK_AVAILABLE()) {
+        fLOG_GLOBAL_REG_FIELD(SYSCONF,SYSCFG_TLBLOCK,1);
+      } else {
+        sys_waiting_for_tlb_lock(thread);
+      }
+      },
+      ()
+)
+
+DEF_MACRO(fSET_K0_LOCK,
+      /* */,
+      ()
+)
+
+DEF_MACRO(fCLEAR_TLB_LOCK,
+      /* */,
+      ()
+)
+
+DEF_MACRO(fCLEAR_K0_LOCK,
+      /* */,
+      ()
+)
+
 DEF_MACRO(fALIGN_REG_FIELD_VALUE,
     ((VAL)<<reg_field_info[FIELD].offset),
     /* */
@@ -1554,6 +1709,24 @@ DEF_MACRO(fGET_REG_FIELD_MASK,
     /* */
 )
 
+DEF_MACRO(fLOG_REG_FIELD,
+    LOG_MASKED_REG_WRITE(thread,REG_##REG,
+    fALIGN_REG_FIELD_VALUE(FIELD,VAL),
+    fGET_REG_FIELD_MASK(FIELD)),
+    ()
+)
+
+DEF_MACRO(fWRITE_GLOBAL_REG_FIELD,
+    /* */,
+)
+
+DEF_MACRO(fLOG_GLOBAL_REG_FIELD,
+    LOG_MASKED_GLOBAL_REG_WRITE(REG_##REG,
+        fALIGN_REG_FIELD_VALUE(FIELD,VAL),
+        fGET_REG_FIELD_MASK(FIELD)),
+    ()
+)
+
 DEF_MACRO(fREAD_REG_FIELD,
     fEXTRACTU_BITS(thread->Regs[REG_##REG],
         reg_field_info[FIELD].width,
@@ -1561,6 +1734,11 @@ DEF_MACRO(fREAD_REG_FIELD,
     /* ATTRIBS */
 )
 
+DEF_MACRO(fREAD_GLOBAL_REG_FIELD,
+    /* */,
+    /* ATTRIBS */
+)
+
 DEF_MACRO(fGET_FIELD,
     fEXTRACTU_BITS(VAL,
         reg_field_info[FIELD].width,
@@ -1576,6 +1754,174 @@ DEF_MACRO(fSET_FIELD,
     /* ATTRIBS */
 )
 
+DEF_MACRO(fSET_RUN_MODE_NOW,
+        /* */,
+)
+
+DEF_MACRO(fIN_DEBUG_MODE,
+    (thread->debug_mode || (fREAD_GLOBAL_REG_FIELD(ISDBST,ISDBST_DEBUGMODE) & 1<<TNUM)),
+    ()
+)
+DEF_MACRO(fIN_DEBUG_MODE_NO_ISDB,
+    (thread->debug_mode),
+    ()
+)
+
+
+DEF_MACRO(fIN_DEBUG_MODE_WARN,
+    {
+        if (fREAD_GLOBAL_REG_FIELD(ISDBST,ISDBST_DEBUGMODE) & 1<<TNUM)
+            warn("In ISDB debug mode, but TB told me to step normally");
+    },
+    ()
+)
+
+DEF_MACRO(fCLEAR_RUN_MODE,
+    {fLOG_GLOBAL_REG_FIELD(MODECTL,MODECTL_E,
+     fREAD_GLOBAL_REG_FIELD(MODECTL,MODECTL_E) & ~(1<<(TNUM)))},
+    /* NOTHING */
+)
+
+DEF_MACRO(fCLEAR_RUN_MODE_NOW,
+    /* */,
+    /* NOTHING */
+)
+
+DEF_MACRO(fGET_RUN_MODE,
+        /* */,
+)
+
+DEF_MACRO(fSET_WAIT_MODE,
+    {fLOG_GLOBAL_REG_FIELD(MODECTL,MODECTL_W,
+    fREAD_GLOBAL_REG_FIELD(MODECTL,MODECTL_W) | 1<<(TNUM))},
+    /* NOTHING */
+)
+
+DEF_MACRO(fCLEAR_WAIT_MODE,
+        /* */,
+)
+
+DEF_MACRO(fGET_WAIT_MODE,
+        /* */,
+)
+
+
+DEF_MACRO(fRESET_THREAD,
+        register_reset_interrupt(T,NUM),
+)
+
+DEF_MACRO(fREAD_CURRENT_EVB,
+    (GLOBAL_REG_READ(REG_EVB)),
+    /* nothing */
+)
+
+DEF_MACRO(fREAD_ELR,
+    READ_RREG(REG_ELR),
+    ()
+)
+
+DEF_MACRO(fPOW2_HELP_ROUNDUP,
+    ((VAL) | ((VAL) >> 1) | ((VAL) >> 2) | ((VAL) >> 4) | ((VAL) >> 8) | ((VAL) >> 16)),
+    ()
+)
+
+DEF_MACRO(fPOW2_ROUNDUP,
+    fPOW2_HELP_ROUNDUP((VAL)-1)+1,
+    ()
+)
+
+DEF_MACRO(fTLB_IDXMASK,
+    /* */,
+    ()
+)
+
+DEF_MACRO(fTLB_NONPOW2WRAP,
+    /* */,
+    /* ATTRIBS */
+)
+
+DEF_MACRO(fTLBW,
+    /* */,
+    /* ATTRIBS */
+)
+
+DEF_MACRO(fTLB_ENTRY_OVERLAP,
+    fHIDE( (sys_check_overlap(thread,VALUE)!=-2) ),
+    /* ATTRIBS */
+)
+
+DEF_MACRO(fTLB_ENTRY_OVERLAP_IDX,
+    fHIDE(sys_check_overlap(thread,VALUE)),
+    /* ATTRIBS */
+)
+
+
+DEF_MACRO(fTLBR,
+    TLB_REG_READ(fTLB_NONPOW2WRAP(fTLB_IDXMASK(INDEX))),
+    /* ATTRIBS */
+)
+
+DEF_MACRO(fTLBP,
+    tlb_lookup(thread,((TLBHI)>>12),((TLBHI)<<12),1),
+    /* attribs */
+)
+
+
+
+DEF_MACRO(READ_SGP0,
+    READ_RREG(REG_SGP),
+    ()
+)
+
+DEF_MACRO(READ_SGP1,
+    READ_RREG(REG_SGP+1),
+    ()
+)
+
+DEF_MACRO(READ_SGP10,
+    READ_RREG_PAIR(REG_SGP),
+    ()
+)
+
+DEF_MACRO(READ_UGP,
+    READ_RREG(REG_UGP),
+)
+
+DEF_MACRO(WRITE_SGP0,
+    WRITE_RREG(REG_SGP,VAL),
+    (A_IMPLICIT_WRITES_SGP0)
+)
+
+DEF_MACRO(WRITE_SGP1,
+    WRITE_RREG(REG_SGP+1,VAL),
+    (A_IMPLICIT_WRITES_SGP1)
+)
+
+DEF_MACRO(WRITE_SGP10,
+    WRITE_RREG_PAIR(REG_SGP,VAL),
+    (A_IMPLICIT_WRITES_SGP0,A_IMPLICIT_WRITES_SGP1)
+)
+
+DEF_MACRO(WRITE_UGP,
+        WRITE_RREG(REG_UGP,VAL),
+)
+
+DEF_MACRO(fSTART,
+    /* */,
+    ()
+)
+
+DEF_MACRO(fRESUME,
+    fLOG_GLOBAL_REG_FIELD(MODECTL,MODECTL_W,
+    fREAD_GLOBAL_REG_FIELD(MODECTL,MODECTL_W) & (~(REG))),
+    ()
+)
+
+DEF_MACRO(fGET_TNUM,
+    thread->threadId,
+    ()
+)
+
 /********************************************/
 /* Cache Management                         */
 /********************************************/
@@ -1602,19 +1948,49 @@ DEF_MACRO(fISYNC,
 )
 
 
+DEF_MACRO(fICFETCH,
+    ,
+    ()
+)
+
 DEF_MACRO(fDCFETCH,
     sys_dcfetch(thread, (REG), insn->slot),
     (A_MEMLIKE)
 )
 
 DEF_MACRO(fICINVA,
-    {
-        arch_internal_flush(thread->processor_ptr, 0, 0xffffffff);
-        sys_icinva(thread, (REG),insn->slot);
-    },
+    /* */,
     (A_ICINVA)
 )
 
+DEF_MACRO(fDCTAGR,
+    ({DST=sys_dctagr(thread, INDEX, insn->slot,DSTREGNO);})/* FIXME */,
+    ()
+)
+
+DEF_MACRO(fDCTAGW,
+    (sys_dctagw(thread, INDEX, PART2, insn->slot)),
+    ()
+)
+DEF_MACRO(fICTAGR,
+    ({DST=sys_ictagr(thread, INDEX, insn->slot,REGNO);}),
+    ()
+)
+
+DEF_MACRO(fICDATAR,
+    ({DST=sys_icdatar(thread, INDEX, insn->slot);}),
+    ()
+)
+
+DEF_MACRO(fICTAGW,
+    (sys_ictagw(thread, INDEX, PART2, insn->slot)),
+    ()
+)
+DEF_MACRO(fICDATAW,
+    ({ fHIDE(); }),
+    ()
+)
+
 DEF_MACRO(fL2FETCH,
     sys_l2fetch(thread, ADDR,HEIGHT,WIDTH,STRIDE,FLAGS, insn->slot),
     (A_MEMLIKE,A_L2FETCH)
@@ -1635,6 +2011,12 @@ DEF_MACRO(fDCZEROA,
     (A_MEMLIKE)
 )
 
+DEF_MACRO(fDCINVA,
+    sys_dcinva(thread, (REG)),
+    (A_MEMLIKE)
+)
+
+
 DEF_MACRO(fCHECKFORPRIV,
     {sys_check_privs(thread); if (EXCEPTION_DETECTED) return; },
     ()
@@ -1645,6 +2027,16 @@ DEF_MACRO(fCHECKFORGUEST,
     ()
 )
 
+DEF_MACRO(fTAKEN_INTERRUPT_EDGECLEAR,
+        { proc->global_regs[REG_IPEND] &= ~(INT_NUMTOMASK(intnum) & proc->global_regs[REG_IEL]); },
+        ()
+)
+
+DEF_MACRO(fSET_IAD,
+    /* */,
+    ()
+)
+
 DEF_MACRO(fBRANCH_SPECULATE_STALL,
     {
         sys_speculate_branch_stall(thread, insn->slot, JUMP_COND(JUMP_PRED_SET),
@@ -1664,3 +2056,79 @@ DEF_MACRO(IV1DEAD,
     ,
     ()
 )
+
+DEF_MACRO(fIN_MONITOR_MODE,
+    sys_in_monitor_mode(thread),
+    ()
+)
+
+DEF_MACRO(fIN_USER_MODE,
+    sys_in_user_mode(thread),
+    ()
+)
+
+DEF_MACRO(fIN_GUEST_MODE,
+    sys_in_guest_mode(thread),
+    ()
+)
+
+DEF_MACRO(fGRE_ENABLED,
+    fREAD_REG_FIELD(CCR,CCR_GRE),
+    ()
+)
+
+DEF_MACRO(fGTE_ENABLED,
+    fREAD_REG_FIELD(CCR,CCR_GRE),
+    ()
+)
+
+DEF_MACRO(fTRAP1_VIRTINSN,
+    ((fIN_GUEST_MODE())
+     && (fGRE_ENABLED())
+     && (   ((IMM) == 1)
+         || ((IMM) == 3)
+         || ((IMM) == 4)
+         || ((IMM) == 6))),
+    ()
+)
+
+DEF_MACRO(fVIRTINSN_RTE,
+    do {
+        thread->trap1_info = TRAP1_VIRTINSN_RTE;
+        fLOG_REG_FIELD(SSR,SSR_SS,fREAD_REG_FIELD(GSR,GSR_SS));
+        fLOG_REG_FIELD(CCR,CCR_GIE,fREAD_REG_FIELD(GSR,GSR_IE));
+        fLOG_REG_FIELD(SSR,SSR_GM,!fREAD_REG_FIELD(GSR,GSR_UM));
+        fBRANCH((fREAD_GELR() & -4),COF_TYPE_RTE);
+        fINTERNAL_CLEAR_SAMEPAGE();
+    } while (0),
+    (A_IMPLICIT_WRITES_CCR,A_IMPLICIT_WRITES_SSR)
+)
+
+DEF_MACRO(fVIRTINSN_SETIE,
+    do {
+        fLOG_REG_FIELD(CCR,CCR_GIE,(REG) & 1);
+        REG = fREAD_REG_FIELD(CCR,CCR_GIE);
+        thread->trap1_info = TRAP1_VIRTINSN_SETIE;
+    } while (0),
+    (A_IMPLICIT_WRITES_CCR)
+)
+
+DEF_MACRO(fVIRTINSN_GETIE,
+    {
+        thread->trap1_info = TRAP1_VIRTINSN_GETIE;
+        REG = fREAD_REG_FIELD(CCR,CCR_GIE);
+    },
+    ()
+)
+
+DEF_MACRO(fVIRTINSN_SPSWAP,
+    do {
+        if (fREAD_REG_FIELD(GSR,GSR_UM)) {
+            size4u_t TEMP = REG;
+            REG = fREAD_GOSP();
+            fWRITE_GOSP(TEMP);
+            thread->trap1_info = TRAP1_VIRTINSN_SPSWAP;
+        }
+    } while (0),
+    (A_IMPLICIT_WRITES_GOSP)
+)
-- 
2.34.1


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

* [PATCH v5 16/35] target/hexagon: Add new macro definitions for sysemu
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (14 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 15/35] target/hexagon: Add imported macro, attr defs for sysemu Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 17/35] target/hexagon: Add handlers for guest/sysreg r/w Brian Cain
                   ` (18 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Also: add nop TCG overrides for break, unpause, fetchbo; add TCG
override for dczeroa_nt (non-temporal variant of dczeroa).

break: this hardware breakpoint instruction is used with the in-silicon
debugger feature, this is not modeled.

unpause: this instruction is used to resume hardware threads that are
stalled by pause instructions.  pause is modeled as a nop, or in RR
mode as an EXCP_YIELD.  This instruction is safe to ignore.

Since prefetch functions are not modeled, fetchbo is safe to ignore.

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/gen_tcg.h    |   9 ++
 target/hexagon/macros.h     |  25 +++-
 target/hexagon/sys_macros.h | 237 ++++++++++++++++++++++++++++++++++++
 target/hexagon/op_helper.c  |   4 +
 4 files changed, 274 insertions(+), 1 deletion(-)
 create mode 100644 target/hexagon/sys_macros.h

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 7b96dab9185..bd04386d860 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -488,6 +488,7 @@
 
 /* dczeroa clears the 32 byte cache line at the address given */
 #define fGEN_TCG_Y2_dczeroa(SHORTCODE) SHORTCODE
+#define fGEN_TCG_Y2_dczeroa_nt(SHORTCODE) SHORTCODE
 
 /* In linux-user mode, these are not modelled, suppress compiler warning */
 #define fGEN_TCG_Y2_dcinva(SHORTCODE) \
@@ -1132,6 +1133,9 @@
                            RdV, tcg_constant_tl(0)); \
     } while (0)
 
+#define fGEN_TCG_Y2_break(SHORTCODE)
+#define fGEN_TCG_J2_unpause(SHORTCODE)
+
 #define fGEN_TCG_J2_pause(SHORTCODE) \
     do { \
         uiV = uiV; \
@@ -1341,6 +1345,11 @@
         RsV = RsV; \
         uiV = uiV; \
     } while (0)
+#define fGEN_TCG_Y2_dcfetchbo_nt(SHORTCODE) \
+    do { \
+        RsV = RsV; \
+        uiV = uiV; \
+    } while (0)
 
 #define fGEN_TCG_L2_loadw_aq(SHORTCODE)                 SHORTCODE
 #define fGEN_TCG_L4_loadd_aq(SHORTCODE)                 SHORTCODE
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 6c2862a2320..e4bfea4923f 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -631,8 +631,18 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
 #define fCONSTLL(A) A##LL
 #define fECHO(A) (A)
 
-#define fTRAP(TRAPTYPE, IMM) helper_raise_exception(env, HEX_EXCP_TRAP0)
+#ifdef CONFIG_USER_ONLY
+#define fTRAP(TRAPTYPE, IMM) \
+    do { \
+        hexagon_raise_exception_err(env, HEX_EVENT_TRAP0, PC); \
+    } while (0)
+#endif
+
+#define fDO_TRACE(SREG)
+#define fBREAK()
+#define fUNPAUSE()
 #define fPAUSE(IMM)
+#define fDCFETCH(REG)
 
 #define fALIGN_REG_FIELD_VALUE(FIELD, VAL) \
     ((VAL) << reg_field_info[FIELD].offset)
@@ -654,5 +664,18 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
 #define fBRANCH_SPECULATE_STALL(DOTNEWVAL, JUMP_COND, SPEC_DIR, HINTBITNUM, \
                                 STRBITNUM) /* Nothing */
 
+#ifdef CONFIG_USER_ONLY
+/*
+ * This macro can only be true in guest mode.
+ * In user mode, the 4 VIRTINSN's can't be reached
+ */
+#define fTRAP1_VIRTINSN(IMM)       (false)
+#define fVIRTINSN_SPSWAP(IMM, REG) g_assert_not_reached()
+#define fVIRTINSN_GETIE(IMM, REG)  g_assert_not_reached()
+#define fVIRTINSN_SETIE(IMM, REG)  g_assert_not_reached()
+#define fVIRTINSN_RTE(IMM, REG)    g_assert_not_reached()
+#endif
+
+#define fPREDUSE_TIMING()
 
 #endif
diff --git a/target/hexagon/sys_macros.h b/target/hexagon/sys_macros.h
new file mode 100644
index 00000000000..f497d55bb81
--- /dev/null
+++ b/target/hexagon/sys_macros.h
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HEXAGON_SYS_MACROS_H
+#define HEXAGON_SYS_MACROS_H
+
+/*
+ * Macro definitions for Hexagon system mode
+ */
+
+#ifndef CONFIG_USER_ONLY
+
+#ifdef QEMU_GENERATE
+#define GET_SSR_FIELD(RES, FIELD) \
+    GET_FIELD(RES, FIELD, hex_t_sreg[HEX_SREG_SSR])
+#else
+
+#define GET_SSR_FIELD(FIELD, REGIN) \
+    (uint32_t)GET_FIELD(FIELD, REGIN)
+#define GET_SYSCFG_FIELD(FIELD, REGIN) \
+    (uint32_t)GET_FIELD(FIELD, REGIN)
+#define SET_SYSTEM_FIELD(ENV, REG, FIELD, VAL) \
+    do { \
+        HexagonCPU *_sf_cpu = env_archcpu(ENV); \
+        uint32_t regval; \
+        if ((REG) < HEX_SREG_GLB_START) { \
+            regval = (ENV)->t_sreg[(REG)]; \
+        } else { \
+            regval = _sf_cpu->globalregs ? \
+                hexagon_globalreg_read(_sf_cpu->globalregs, (REG), \
+                                       (ENV)->threadId) : 0; \
+        } \
+        fINSERT_BITS(regval, reg_field_info[FIELD].width, \
+                     reg_field_info[FIELD].offset, (VAL)); \
+        if ((REG) < HEX_SREG_GLB_START) { \
+            (ENV)->t_sreg[(REG)] = regval; \
+        } else if (_sf_cpu->globalregs) { \
+            hexagon_globalreg_write(_sf_cpu->globalregs, (REG), regval, \
+                                    (ENV)->threadId); \
+        } \
+    } while (0)
+#define SET_SSR_FIELD(ENV, FIELD, VAL) \
+    SET_SYSTEM_FIELD(ENV, HEX_SREG_SSR, FIELD, VAL)
+#define SET_SYSCFG_FIELD(ENV, FIELD, VAL) \
+    SET_SYSTEM_FIELD(ENV, HEX_SREG_SYSCFG, FIELD, VAL)
+
+#define CCR_FIELD_SET(ENV, FIELD) \
+    (!!GET_FIELD(FIELD, (ENV)->t_sreg[HEX_SREG_CCR]))
+
+/*
+ * Direct-to-guest is not implemented yet, continuing would cause unexpected
+ * behavior, so we abort.
+ */
+#define ASSERT_DIRECT_TO_GUEST_UNSET(ENV, EXCP) \
+    do { \
+        switch (EXCP) { \
+        case HEX_EVENT_TRAP0: \
+            g_assert(!CCR_FIELD_SET(ENV, CCR_GTE)); \
+            break; \
+        case HEX_EVENT_IMPRECISE: \
+        case HEX_EVENT_PRECISE: \
+        case HEX_EVENT_FPTRAP: \
+            g_assert(!CCR_FIELD_SET(ENV, CCR_GEE)); \
+            break; \
+        default: \
+            if ((EXCP) >= HEX_EVENT_INT0) { \
+                g_assert(!CCR_FIELD_SET(ENV, CCR_GIE)); \
+            } \
+            break; \
+        } \
+    } while (0)
+#endif
+
+#define fREAD_ELR() (env->t_sreg[HEX_SREG_ELR])
+
+#define fLOAD_PHYS(NUM, SIZE, SIGN, SRC1, SRC2, DST) { \
+  const uintptr_t rs = ((unsigned long)(unsigned)(SRC1)) & 0x7ff; \
+  const uintptr_t rt = ((unsigned long)(unsigned)(SRC2)) << 11; \
+  const uintptr_t addr = rs + rt;         \
+  cpu_physical_memory_read(addr, &DST, sizeof(uint32_t)); \
+}
+
+#define fPOW2_HELP_ROUNDUP(VAL) \
+    ((VAL) | \
+     ((VAL) >> 1) | \
+     ((VAL) >> 2) | \
+     ((VAL) >> 4) | \
+     ((VAL) >> 8) | \
+     ((VAL) >> 16))
+#define fPOW2_ROUNDUP(VAL) (fPOW2_HELP_ROUNDUP((VAL) - 1) + 1)
+
+#define fTRAP(TRAPTYPE, IMM) \
+    register_trap_exception(env, TRAPTYPE, IMM, PC)
+
+#define fVIRTINSN_SPSWAP(IMM, REG)
+#define fVIRTINSN_GETIE(IMM, REG) { REG = 0xdeafbeef; }
+#define fVIRTINSN_SETIE(IMM, REG)
+#define fVIRTINSN_RTE(IMM, REG)
+#define fGRE_ENABLED() \
+    GET_FIELD(CCR_GRE, env->t_sreg[HEX_SREG_CCR])
+#define fTRAP1_VIRTINSN(IMM) \
+    (fGRE_ENABLED() && \
+        (((IMM) == 1) || ((IMM) == 3) || ((IMM) == 4) || ((IMM) == 6)))
+
+/* Not modeled in qemu */
+
+#define MARK_LATE_PRED_WRITE(RNUM)
+#define fICINVIDX(REG)
+#define fICKILL()
+#define fDCKILL()
+#define fL2KILL()
+#define fL2UNLOCK()
+#define fL2CLEAN()
+#define fL2CLEANINV()
+#define fL2CLEANPA(REG)
+#define fL2CLEANINVPA(REG)
+#define fL2CLEANINVIDX(REG)
+#define fL2CLEANIDX(REG)
+#define fL2INVIDX(REG)
+#define fL2TAGR(INDEX, DST, DSTREG)
+#define fL2UNLOCKA(VA) ((void) VA)
+#define fL2TAGW(INDEX, PART2)
+#define fDCCLEANIDX(REG)
+#define fDCCLEANINVIDX(REG)
+
+/* Always succeed: */
+#define fL2LOCKA(EA, PDV, PDN) ((void) EA, PDV = 0xFF)
+#define fCLEAR_RTE_EX() \
+    do { \
+        uint32_t tmp = env->t_sreg[HEX_SREG_SSR]; \
+        fINSERT_BITS(tmp, reg_field_info[SSR_EX].width, \
+                     reg_field_info[SSR_EX].offset, 0); \
+        log_sreg_write(env, HEX_SREG_SSR, tmp, slot); \
+    } while (0)
+
+#define fDCINVIDX(REG)
+#define fDCINVA(REG) do { REG = REG; } while (0) /* Nothing to do in qemu */
+
+#define fTLB_IDXMASK(INDEX) \
+    ((INDEX) & (fPOW2_ROUNDUP( \
+        fCAST4u(hexagon_tlb_get_num_entries(env_archcpu(env)->tlb))) - 1))
+
+#define fTLB_NONPOW2WRAP(INDEX) \
+    (((INDEX) >= hexagon_tlb_get_num_entries(env_archcpu(env)->tlb)) ? \
+         ((INDEX) - hexagon_tlb_get_num_entries(env_archcpu(env)->tlb)) : \
+         (INDEX))
+
+
+#define fTLBW(INDEX, VALUE) \
+    hex_tlbw(env, (INDEX), (VALUE))
+#define fTLBW_EXTENDED(INDEX, VALUE) \
+    hex_tlbw(env, (INDEX), (VALUE))
+#define fTLB_ENTRY_OVERLAP(VALUE) \
+    (hex_tlb_check_overlap(env, VALUE, -1) != -2)
+#define fTLB_ENTRY_OVERLAP_IDX(VALUE) \
+    hex_tlb_check_overlap(env, VALUE, -1)
+#define fTLBR(INDEX) \
+    hexagon_tlb_read(env_archcpu(env)->tlb, \
+                     fTLB_NONPOW2WRAP(fTLB_IDXMASK(INDEX)))
+#define fTLBR_EXTENDED(INDEX) \
+    hexagon_tlb_read(env_archcpu(env)->tlb, \
+                     fTLB_NONPOW2WRAP(fTLB_IDXMASK(INDEX)))
+#define fTLBP(TLBHI) \
+    hex_tlb_lookup(env, ((TLBHI) >> 12), ((TLBHI) << 12))
+#define iic_flush_cache(p)
+
+#define fIN_DEBUG_MODE(TNUM) ({ \
+    HexagonCPU *_cpu = env_archcpu(env); \
+    uint32_t _isdbst = _cpu->globalregs ? \
+        hexagon_globalreg_read(_cpu->globalregs, \
+                               HEX_SREG_ISDBST, env->threadId) : 0; \
+    (GET_FIELD(ISDBST_DEBUGMODE, _isdbst) \
+        & (0x1 << (TNUM))) != 0; })
+
+#define fIN_DEBUG_MODE_NO_ISDB(TNUM) false
+#define fIN_DEBUG_MODE_WARN(TNUM) false
+
+#ifdef QEMU_GENERATE
+
+/*
+ * Read tags back as zero for now:
+ *
+ * tag value in RD[31:10] for 32k, RD[31:9] for 16k
+ */
+#define fICTAGR(RS, RD, RD2) \
+    do { \
+        RD = ctx->zero; \
+    } while (0)
+#define fICTAGW(RS, RD)
+#define fICDATAR(RS, RD) \
+    do { \
+        RD = ctx->zero; \
+    } while (0)
+#define fICDATAW(RS, RD)
+
+#define fDCTAGW(RS, RT)
+/* tag: RD[23:0], state: RD[30:29] */
+#define fDCTAGR(INDEX, DST, DST_REG_NUM) \
+    do { \
+        DST = ctx->zero; \
+    } while (0)
+#else
+
+/*
+ * Read tags back as zero for now:
+ *
+ * tag value in RD[31:10] for 32k, RD[31:9] for 16k
+ */
+#define fICTAGR(RS, RD, RD2) \
+    do { \
+        RD = 0x00; \
+    } while (0)
+#define fICTAGW(RS, RD)
+#define fICDATAR(RS, RD) \
+    do { \
+        RD = 0x00; \
+    } while (0)
+#define fICDATAW(RS, RD)
+
+#define fDCTAGW(RS, RT)
+/* tag: RD[23:0], state: RD[30:29] */
+#define fDCTAGR(INDEX, DST, DST_REG_NUM) \
+    do { \
+        DST = 0; \
+    } while (0)
+#endif
+
+#else
+#define ASSERT_DIRECT_TO_GUEST_UNSET(ENV, EXCP) do { } while (0)
+#endif
+
+#define NUM_TLB_REGS(x) (hexagon_tlb_get_num_entries(env_archcpu(env)->tlb))
+
+#endif
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 368391bb846..53898db815b 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -24,6 +24,7 @@
 #include "cpu.h"
 #include "internal.h"
 #include "macros.h"
+#include "sys_macros.h"
 #include "arch.h"
 #include "hex_arch_types.h"
 #include "fma_emu.h"
@@ -31,6 +32,9 @@
 #include "mmvec/macros.h"
 #include "op_helper.h"
 #include "translate.h"
+#ifndef CONFIG_USER_ONLY
+#include "hexswi.h"
+#endif
 
 #define SF_BIAS        127
 #define SF_MANTBITS    23
-- 
2.34.1


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

* [PATCH v5 17/35] target/hexagon: Add handlers for guest/sysreg r/w
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (15 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 16/35] target/hexagon: Add new macro definitions " Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 18/35] target/hexagon: Add placeholder greg/sreg r/w helpers Brian Cain
                   ` (17 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

This commit provides handlers to generate TCG for guest and system
register reads and writes.  They will be leveraged by a future commit.

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/genptr.c | 147 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 147 insertions(+)

diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 9eb21da6f3e..2310b9aec3a 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -23,6 +23,7 @@
 #include "exec/helper-gen.h"
 #include "insn.h"
 #include "opcodes.h"
+#include "sys_macros.h"
 #include "translate.h"
 #define QEMU_GENERATE       /* Used internally by macros.h */
 #include "macros.h"
@@ -120,6 +121,152 @@ TCGv get_result_pred(DisasContext *ctx, int pnum)
     }
 }
 
+#ifndef CONFIG_USER_ONLY
+G_GNUC_UNUSED
+static bool greg_writable(int rnum, bool pair)
+{
+    if (pair) {
+        if (rnum < HEX_GREG_G3) {
+            return true;
+        }
+        qemu_log_mask(LOG_UNIMP,
+                "Warning: ignoring write to guest register pair G%d:%d\n",
+                rnum + 1, rnum);
+    } else {
+        if (rnum <= HEX_GREG_G3) {
+            return true;
+        }
+        qemu_log_mask(LOG_UNIMP,
+                "Warning: ignoring write to guest register G%d\n", rnum);
+    }
+    return false;
+}
+
+G_GNUC_UNUSED
+static void check_greg_impl(int rnum, bool pair)
+{
+    if (pair && (!greg_implemented(rnum) || !greg_implemented(rnum + 1))) {
+        qemu_log_mask(LOG_UNIMP,
+                "Warning: guest register pair G%d:%d is unimplemented or "
+                "reserved. Read will yield 0.\n",
+                rnum + 1, rnum);
+    } else if (!pair && !greg_implemented(rnum)) {
+        qemu_log_mask(LOG_UNIMP,
+                "Warning: guest register G%d is unimplemented or reserved."
+                " Read will yield 0.\n", rnum);
+    }
+}
+
+G_GNUC_UNUSED
+static inline void gen_log_greg_write(DisasContext *ctx, int rnum, TCGv_i32 val)
+{
+    tcg_gen_mov_i32(ctx->greg_new_value[rnum], val);
+}
+
+G_GNUC_UNUSED
+static void gen_log_greg_write_pair(DisasContext *ctx, int rnum, TCGv_i64 val)
+{
+    TCGv_i32 val32 = tcg_temp_new_i32();
+
+    /* Low word */
+    tcg_gen_extrl_i64_i32(val32, val);
+    gen_log_greg_write(ctx, rnum, val32);
+
+    /* High word */
+    tcg_gen_extrh_i64_i32(val32, val);
+    gen_log_greg_write(ctx, rnum + 1, val32);
+}
+
+static const uint32_t sreg_immut_masks[NUM_SREGS] = {
+    [HEX_SREG_STID] = 0xff00ff00,
+    [HEX_SREG_ELR] = 0x00000003,
+    [HEX_SREG_SSR] = 0x00008000,
+    [HEX_SREG_CCR] = 0x10e0ff24,
+    [HEX_SREG_HTID] = IMMUTABLE,
+    [HEX_SREG_IMASK] = 0xffff0000,
+    [HEX_SREG_GEVB] = 0x000000ff,
+};
+
+G_GNUC_UNUSED
+static void gen_log_sreg_write(DisasContext *ctx, int rnum, TCGv_i32 val)
+{
+    const uint32_t reg_mask = sreg_immut_masks[rnum];
+
+    if (reg_mask != IMMUTABLE) {
+        if (rnum < HEX_SREG_GLB_START) {
+            gen_masked_reg_write(val, hex_t_sreg[rnum], reg_mask);
+            tcg_gen_mov_i32(ctx->t_sreg_new_value[rnum], val);
+        } else {
+            gen_helper_sreg_write_masked(tcg_env, tcg_constant_i32(rnum), val);
+        }
+    }
+}
+
+G_GNUC_UNUSED
+static void gen_log_sreg_write_pair(DisasContext *ctx, int rnum, TCGv_i64 val)
+{
+    TCGv_i32 val32 = tcg_temp_new_i32();
+
+    /* Low word */
+    tcg_gen_extrl_i64_i32(val32, val);
+    gen_log_sreg_write(ctx, rnum, val32);
+
+    /* High word */
+    tcg_gen_extrh_i64_i32(val32, val);
+    gen_log_sreg_write(ctx, rnum + 1, val32);
+}
+
+G_GNUC_UNUSED
+static void gen_read_sreg(TCGv_i32 dst, int reg_num)
+{
+    if (reg_num >= HEX_SREG_GLB_START || reg_num == HEX_SREG_BADVA) {
+        gen_helper_sreg_read(dst, tcg_env, tcg_constant_i32(reg_num));
+    } else {
+        tcg_gen_mov_i32(dst, hex_t_sreg[reg_num]);
+    }
+}
+
+G_GNUC_UNUSED
+static void gen_read_sreg_pair(TCGv_i64 dst, int reg_num)
+{
+    if (reg_num < HEX_SREG_GLB_START) {
+        if (reg_num + 1 == HEX_SREG_BADVA) {
+            TCGv_i32 badva = tcg_temp_new_i32();
+            gen_helper_sreg_read(badva, tcg_env,
+                                 tcg_constant_i32(HEX_SREG_BADVA));
+            tcg_gen_concat_i32_i64(dst, hex_t_sreg[reg_num], badva);
+        } else {
+            tcg_gen_concat_i32_i64(dst, hex_t_sreg[reg_num],
+                                        hex_t_sreg[reg_num + 1]);
+        }
+    } else {
+        gen_helper_sreg_read_pair(dst, tcg_env, tcg_constant_i32(reg_num));
+    }
+}
+
+G_GNUC_UNUSED
+static void gen_read_greg(TCGv_i32 dst, int reg_num)
+{
+    if (reg_num <= HEX_GREG_G3) {
+        tcg_gen_mov_i32(dst, hex_greg[reg_num]);
+    } else {
+        gen_helper_greg_read(dst, tcg_env, tcg_constant_i32(reg_num));
+    }
+}
+
+G_GNUC_UNUSED
+static void gen_read_greg_pair(TCGv_i64 dst, int reg_num)
+{
+    if (reg_num == HEX_GREG_G0 || reg_num == HEX_GREG_G2) {
+        tcg_gen_concat_i32_i64(dst, hex_greg[reg_num],
+                                    hex_greg[reg_num + 1]);
+    } else {
+        gen_helper_greg_read_pair(dst, tcg_env, tcg_constant_i32(reg_num));
+    }
+}
+#endif
+
+
 void gen_pred_write(DisasContext *ctx, int pnum, TCGv val)
 {
     TCGv pred = get_result_pred(ctx, pnum);
-- 
2.34.1


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

* [PATCH v5 18/35] target/hexagon: Add placeholder greg/sreg r/w helpers
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (16 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 17/35] target/hexagon: Add handlers for guest/sysreg r/w Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 19/35] target/hexagon: Add vmstate representation Brian Cain
                   ` (16 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/helper.h    |  8 ++++++++
 target/hexagon/op_helper.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h
index 64456822bc1..28b9b59e0f2 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -107,3 +107,11 @@ DEF_HELPER_4(probe_noshuf_load, void, env, i32, int, int)
 DEF_HELPER_2(probe_pkt_scalar_store_s0, void, env, int)
 DEF_HELPER_2(probe_hvx_stores, void, env, int)
 DEF_HELPER_2(probe_pkt_scalar_hvx_stores, void, env, int)
+
+#if !defined(CONFIG_USER_ONLY)
+DEF_HELPER_2(sreg_read, i32, env, i32)
+DEF_HELPER_2(sreg_read_pair, i64, env, i32)
+DEF_HELPER_2(greg_read, i32, env, i32)
+DEF_HELPER_2(greg_read_pair, i64, env, i32)
+DEF_HELPER_3(sreg_write_masked, void, env, i32, i32)
+#endif
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 53898db815b..359bf12f1f2 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1373,6 +1373,34 @@ void HELPER(vwhist128qm)(CPUHexagonState *env, int32_t uiV)
     }
 }
 
+#ifndef CONFIG_USER_ONLY
+void HELPER(sreg_write_masked)(CPUHexagonState *env, uint32_t reg, uint32_t val)
+{
+    g_assert_not_reached();
+}
+
+uint32_t HELPER(sreg_read)(CPUHexagonState *env, uint32_t reg)
+{
+    g_assert_not_reached();
+}
+
+uint64_t HELPER(sreg_read_pair)(CPUHexagonState *env, uint32_t reg)
+{
+    g_assert_not_reached();
+}
+
+uint32_t HELPER(greg_read)(CPUHexagonState *env, uint32_t reg)
+{
+    g_assert_not_reached();
+}
+
+uint64_t HELPER(greg_read_pair)(CPUHexagonState *env, uint32_t reg)
+{
+    g_assert_not_reached();
+}
+#endif
+
+
 /* These macros can be referenced in the generated helper functions */
 #define warn(...) /* Nothing */
 #define fatal(...) g_assert_not_reached();
-- 
2.34.1


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

* [PATCH v5 19/35] target/hexagon: Add vmstate representation
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (17 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 18/35] target/hexagon: Add placeholder greg/sreg r/w helpers Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-25 19:21   ` Philippe Mathieu-Daudé
  2026-03-11  3:49 ` [PATCH v5 20/35] target/hexagon: Make A_PRIV, "J2_trap*" insts need_env() Brian Cain
                   ` (15 subsequent siblings)
  34 siblings, 1 reply; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/internal.h |  4 ++++
 target/hexagon/cpu.c      |  3 +++
 target/hexagon/machine.c  | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 39 insertions(+)
 create mode 100644 target/hexagon/machine.c

diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index 5fc837ae229..cd06ff41d4f 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -31,4 +31,8 @@ void hexagon_debug(CPUHexagonState *env);
 
 extern const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS];
 
+#ifndef CONFIG_USER_ONLY
+extern const VMStateDescription vmstate_hexagon_cpu;
+#endif
+
 #endif
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 6fabfaad6d2..38d605b06ba 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -387,6 +387,9 @@ static void hexagon_cpu_class_init(ObjectClass *c, const void *data)
     cc->gdb_stop_before_watchpoint = true;
     cc->gdb_core_xml_file = "hexagon-core.xml";
     cc->disas_set_info = hexagon_cpu_disas_set_info;
+#ifndef CONFIG_USER_ONLY
+    dc->vmsd = &vmstate_hexagon_cpu;
+#endif
     cc->tcg_ops = &hexagon_tcg_ops;
 }
 
diff --git a/target/hexagon/machine.c b/target/hexagon/machine.c
new file mode 100644
index 00000000000..d6dcd07dd4a
--- /dev/null
+++ b/target/hexagon/machine.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "migration/cpu.h"
+#include "cpu.h"
+
+const VMStateDescription vmstate_hexagon_cpu = {
+    .name = "cpu",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(env.gpr, HexagonCPU, TOTAL_PER_THREAD_REGS),
+        VMSTATE_UINT32_ARRAY(env.pred, HexagonCPU, NUM_PREGS),
+        VMSTATE_UINT32_ARRAY(env.t_sreg, HexagonCPU, NUM_SREGS),
+        VMSTATE_UINT32_ARRAY(env.greg, HexagonCPU, NUM_GREGS),
+        VMSTATE_UINT32(env.next_PC, HexagonCPU),
+        VMSTATE_UINT32(env.tlb_lock_state, HexagonCPU),
+        VMSTATE_UINT32(env.k0_lock_state, HexagonCPU),
+        VMSTATE_UINT32(env.tlb_lock_count, HexagonCPU),
+        VMSTATE_UINT32(env.k0_lock_count, HexagonCPU),
+        VMSTATE_UINT32(env.threadId, HexagonCPU),
+        VMSTATE_UINT32(env.cause_code, HexagonCPU),
+        VMSTATE_UINT32(env.wait_next_pc, HexagonCPU),
+        VMSTATE_UINT64(env.t_cycle_count, HexagonCPU),
+
+        VMSTATE_END_OF_LIST()
+    },
+};
-- 
2.34.1


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

* [PATCH v5 20/35] target/hexagon: Make A_PRIV, "J2_trap*" insts need_env()
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (18 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 19/35] target/hexagon: Add vmstate representation Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 21/35] target/hexagon: Define register fields for system regs Brian Cain
                   ` (14 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/hex_common.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 1daf7239fc4..f7ca4986ca8 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -250,7 +250,9 @@ def need_env(tag):
             "A_LOAD" in attribdict[tag] or
             "A_CVI_GATHER" in attribdict[tag] or
             "A_CVI_SCATTER" in attribdict[tag] or
-            "A_IMPLICIT_WRITES_USR" in attribdict[tag])
+            "A_IMPLICIT_WRITES_USR" in attribdict[tag] or
+            "A_PRIV" in attribdict[tag] or
+            "J2_trap" in tag)
 
 
 def need_slot(tag):
-- 
2.34.1


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

* [PATCH v5 21/35] target/hexagon: Define register fields for system regs
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (19 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 20/35] target/hexagon: Make A_PRIV, "J2_trap*" insts need_env() Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 22/35] target/hexagon: Implement do_raise_exception() Brian Cain
                   ` (13 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Define the register fields for ssr, schedcfg, stid, bestwait, ccr,
modectl, imask, ipendad.

Define the fields for TLB entries.


Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/reg_fields_def.h.inc | 96 +++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/target/hexagon/reg_fields_def.h.inc b/target/hexagon/reg_fields_def.h.inc
index f2a58d486c5..9b112ccec64 100644
--- a/target/hexagon/reg_fields_def.h.inc
+++ b/target/hexagon/reg_fields_def.h.inc
@@ -39,3 +39,99 @@ DEF_REG_FIELD(USR_FPDBZE,        26, 1)
 DEF_REG_FIELD(USR_FPOVFE,        27, 1)
 DEF_REG_FIELD(USR_FPUNFE,        28, 1)
 DEF_REG_FIELD(USR_FPINPE,        29, 1)
+
+DEF_REG_FIELD(IPENDAD_IAD, 16, 16)
+DEF_REG_FIELD(IPENDAD_IPEND, 0, 16)
+
+DEF_REG_FIELD(SCHEDCFG_EN, 8, 1)
+DEF_REG_FIELD(SCHEDCFG_INTNO, 0, 4)
+DEF_REG_FIELD(BESTWAIT_PRIO, 0, 9)
+
+
+/* PTE (aka TLB entry) fields */
+DEF_REG_FIELD(PTE_PPD, 0, 24)
+DEF_REG_FIELD(PTE_C, 24, 4)
+DEF_REG_FIELD(PTE_U, 28, 1)
+DEF_REG_FIELD(PTE_R, 29, 1)
+DEF_REG_FIELD(PTE_W, 30, 1)
+DEF_REG_FIELD(PTE_X, 31, 1)
+DEF_REG_FIELD(PTE_VPN, 32, 20)
+DEF_REG_FIELD(PTE_ASID, 52, 7)
+DEF_REG_FIELD(PTE_ATR0, 59, 1)
+DEF_REG_FIELD(PTE_ATR1, 60, 1)
+DEF_REG_FIELD(PTE_PA35, 61, 1)
+DEF_REG_FIELD(PTE_G, 62, 1)
+DEF_REG_FIELD(PTE_V, 63, 1)
+
+/* SYSCFG fields */
+DEF_REG_FIELD(SYSCFG_MMUEN, 0, 1)
+DEF_REG_FIELD(SYSCFG_ICEN, 1, 1)
+DEF_REG_FIELD(SYSCFG_DCEN, 2, 1)
+DEF_REG_FIELD(SYSCFG_ISDBTRUSTED, 3, 1)
+DEF_REG_FIELD(SYSCFG_GIE, 4, 1)
+DEF_REG_FIELD(SYSCFG_ISDBREADY, 5, 1)
+DEF_REG_FIELD(SYSCFG_PCYCLEEN, 6, 1)
+DEF_REG_FIELD(SYSCFG_V2X, 7, 1)
+DEF_REG_FIELD(SYSCFG_IGNOREDABORT, 8, 1)
+DEF_REG_FIELD(SYSCFG_PM, 9, 1)
+DEF_REG_FIELD(SYSCFG_TLBLOCK, 11, 1)
+DEF_REG_FIELD(SYSCFG_K0LOCK, 12, 1)
+DEF_REG_FIELD(SYSCFG_BQ, 13, 1)
+DEF_REG_FIELD(SYSCFG_PRIO, 14, 1)
+DEF_REG_FIELD(SYSCFG_DMT, 15, 1)
+DEF_REG_FIELD(SYSCFG_L2CFG, 16, 3)
+DEF_REG_FIELD(SYSCFG_ITCM, 19, 1)
+DEF_REG_FIELD(SYSCFG_L2NWA, 21, 1)
+DEF_REG_FIELD(SYSCFG_L2NRA, 22, 1)
+DEF_REG_FIELD(SYSCFG_L2WB, 23, 1)
+DEF_REG_FIELD(SYSCFG_L2P, 24, 1)
+DEF_REG_FIELD(SYSCFG_SLVCTL0, 25, 2)
+DEF_REG_FIELD(SYSCFG_SLVCTL1, 27, 2)
+DEF_REG_FIELD(SYSCFG_L2PARTSIZE, 29, 2)
+DEF_REG_FIELD(SYSCFG_L2GCA, 31, 1)
+
+/* SSR fields */
+DEF_REG_FIELD(SSR_CAUSE, 0, 8)
+DEF_REG_FIELD(SSR_ASID, 8, 7)
+DEF_REG_FIELD(SSR_UM, 16, 1)
+DEF_REG_FIELD(SSR_EX, 17, 1)
+DEF_REG_FIELD(SSR_IE, 18, 1)
+DEF_REG_FIELD(SSR_GM, 19, 1)
+DEF_REG_FIELD(SSR_V0, 20, 1)
+DEF_REG_FIELD(SSR_V1, 21, 1)
+DEF_REG_FIELD(SSR_BVS, 22, 1)
+DEF_REG_FIELD(SSR_CE, 23, 1)
+DEF_REG_FIELD(SSR_PE, 24, 1)
+DEF_REG_FIELD(SSR_BP, 25, 1)
+DEF_REG_FIELD(SSR_XE2, 26, 1)
+DEF_REG_FIELD(SSR_XA, 27, 3)
+DEF_REG_FIELD(SSR_SS, 30, 1)
+DEF_REG_FIELD(SSR_XE, 31, 1)
+
+/* misc registers */
+DEF_REG_FIELD(IMASK_MASK, 0, 16)
+
+DEF_REG_FIELD(STID_PRIO, 16, 8)
+DEF_REG_FIELD(STID_STID, 0, 8)
+
+/* MODECTL fields */
+DEF_REG_FIELD(MODECTL_E, 0, 8)
+DEF_REG_FIELD(MODECTL_W, 16, 8)
+
+DEF_REG_FIELD(CCR_L1ICP, 0, 2)
+DEF_REG_FIELD(CCR_L1DCP, 3, 2)
+DEF_REG_FIELD(CCR_L2CP, 6, 2)
+
+DEF_REG_FIELD(CCR_HFI, 16, 1)
+DEF_REG_FIELD(CCR_HFD, 17, 1)
+DEF_REG_FIELD(CCR_HFIL2, 18, 1)
+DEF_REG_FIELD(CCR_HFDL2, 19, 1)
+DEF_REG_FIELD(CCR_SFD, 20, 1)
+
+DEF_REG_FIELD(CCR_GIE, 24, 1)
+DEF_REG_FIELD(CCR_GTE, 25, 1)
+DEF_REG_FIELD(CCR_GEE, 26, 1)
+DEF_REG_FIELD(CCR_GRE, 27, 1)
+DEF_REG_FIELD(CCR_VV1, 29, 1)
+DEF_REG_FIELD(CCR_VV2, 30, 1)
+DEF_REG_FIELD(CCR_VV3, 31, 1)
-- 
2.34.1


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

* [PATCH v5 22/35] target/hexagon: Implement do_raise_exception()
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (20 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 21/35] target/hexagon: Define register fields for system regs Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 23/35] target/hexagon: Add system reg insns Brian Cain
                   ` (12 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/internal.h  |  5 +++++
 target/hexagon/op_helper.c | 14 ++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index cd06ff41d4f..33d73ed18d1 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -31,6 +31,11 @@ void hexagon_debug(CPUHexagonState *env);
 
 extern const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS];
 
+void G_NORETURN do_raise_exception(CPUHexagonState *env,
+        uint32_t exception,
+        uint32_t PC,
+        uintptr_t retaddr);
+
 #ifndef CONFIG_USER_ONLY
 extern const VMStateDescription vmstate_hexagon_cpu;
 #endif
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 359bf12f1f2..327c233c01b 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -40,6 +40,20 @@
 #define SF_MANTBITS    23
 
 /* Exceptions processing helpers */
+G_NORETURN
+void do_raise_exception(CPUHexagonState *env, uint32_t exception,
+                        uint32_t PC, uintptr_t retaddr)
+{
+    CPUState *cs = env_cpu(env);
+    qemu_log_mask(CPU_LOG_INT, "%s: 0x%08" PRIx32 ", @ %08" PRIx32 "\n",
+                  __func__, exception, PC);
+    ASSERT_DIRECT_TO_GUEST_UNSET(env, exception);
+
+    env->gpr[HEX_REG_PC] = PC;
+    cs->exception_index = exception;
+    cpu_loop_exit_restore(cs, retaddr);
+}
+
 G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
                                             uint32_t exception,
                                             uintptr_t pc)
-- 
2.34.1


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

* [PATCH v5 23/35] target/hexagon: Add system reg insns
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (21 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 22/35] target/hexagon: Implement do_raise_exception() Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 24/35] target/hexagon: Add sysemu TCG overrides Brian Cain
                   ` (11 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Acked-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/imported/encode_pp.def | 128 ++++++++++++--
 target/hexagon/imported/system.idef   | 244 ++++++++++++++++++++++++--
 2 files changed, 345 insertions(+), 27 deletions(-)

diff --git a/target/hexagon/imported/encode_pp.def b/target/hexagon/imported/encode_pp.def
index 0cd30a5e857..04e911f59c8 100644
--- a/target/hexagon/imported/encode_pp.def
+++ b/target/hexagon/imported/encode_pp.def
@@ -382,15 +382,18 @@ DEF_ENC32(L4_return_fnew_pt,  ICLASS_LD" 011 0 000 sssss PP1110vv ---ddddd")
 DEF_ENC32(L4_return_tnew_pnt, ICLASS_LD" 011 0 000 sssss PP0010vv ---ddddd")
 DEF_ENC32(L4_return_fnew_pnt, ICLASS_LD" 011 0 000 sssss PP1010vv ---ddddd")
 
-DEF_ENC32(L2_loadw_locked,ICLASS_LD" 001 0 000 sssss PP000--- 000ddddd")
-
+/** Load Acquire Store Release Encoding **/
 
+DEF_ENC32(L2_loadw_locked,    ICLASS_LD" 001 0 000 sssss PP000--- 000ddddd")
+DEF_ENC32(L4_loadd_locked,    ICLASS_LD" 001 0 000 sssss PP010--- 000ddddd")
 
 DEF_ENC32(L2_loadw_aq,        ICLASS_LD" 001 0 000 sssss PP001--- 000ddddd")
 DEF_ENC32(L4_loadd_aq,        ICLASS_LD" 001 0 000 sssss PP011--- 000ddddd")
 
-DEF_ENC32(R6_release_at_vi,    ICLASS_ST" 000 01 11sssss PP0ttttt --0011dd")
-DEF_ENC32(R6_release_st_vi,   ICLASS_ST" 000 01 11sssss PP0ttttt --1011dd")
+
+DEF_ENC32(S2_storew_locked,   ICLASS_ST" 000 01 01sssss PP-ttttt ----00dd")
+DEF_ENC32(S4_stored_locked,   ICLASS_ST" 000 01 11sssss PP0ttttt ----00dd")
+
 
 DEF_ENC32(S2_storew_rl_at_vi,  ICLASS_ST" 000 01 01sssss PP-ttttt --0010dd")
 DEF_ENC32(S2_storew_rl_st_vi, ICLASS_ST" 000 01 01sssss PP-ttttt --1010dd")
@@ -398,17 +401,15 @@ DEF_ENC32(S2_storew_rl_st_vi, ICLASS_ST" 000 01 01sssss PP-ttttt --1010dd")
 DEF_ENC32(S4_stored_rl_at_vi,  ICLASS_ST" 000 01 11sssss PP0ttttt --0010dd")
 DEF_ENC32(S4_stored_rl_st_vi, ICLASS_ST" 000 01 11sssss PP0ttttt --1010dd")
 
-DEF_ENC32(L4_loadd_locked,ICLASS_LD" 001 0 000 sssss PP010--- 000ddddd")
-DEF_EXT_SPACE(EXTRACTW,   ICLASS_LD" 001 0 000 iiiii PP0iiiii -01iiiii")
+DEF_ENC32(R6_release_at_vi,    ICLASS_ST" 000 01 11sssss PP0ttttt --0011dd")
+DEF_ENC32(R6_release_st_vi,   ICLASS_ST" 000 01 11sssss PP0ttttt --1011dd")
+
+DEF_EXT_SPACE(EXTRACTW,   ICLASS_LD" 001 0 000 iiiii PP0iiiii 001iiiii")
 DEF_ENC32(Y2_dcfetchbo,   ICLASS_LD" 010 0 000 sssss PP0--iii iiiiiiii")
 
 
 
 
-
-
-
-
 /*******************************/
 /*                             */
 /*                             */
@@ -488,13 +489,17 @@ STD_PST_ENC(rinew, "1 101","10ttt")
 /*                               x bus/cache     */
 /*                                    x store/cache     */
 DEF_ENC32(S2_allocframe,   ICLASS_ST" 000 01 00xxxxx PP000iii iiiiiiii")
-DEF_ENC32(S2_storew_locked,ICLASS_ST" 000 01 01sssss PP-ttttt ----00dd")
-DEF_ENC32(S4_stored_locked,ICLASS_ST" 000 01 11sssss PP0ttttt ----00dd")
+DEF_ENC32(Y5_l2locka,      ICLASS_ST" 000 01 11sssss PP1----- ------dd")
 DEF_ENC32(Y2_dczeroa,      ICLASS_ST" 000 01 10sssss PP0----- --------")
 
 
 DEF_ENC32(Y2_barrier,      ICLASS_ST" 100 00 00----- PP------ 000-----")
 DEF_ENC32(Y2_syncht,       ICLASS_ST" 100 00 10----- PP------ --------")
+DEF_ENC32(Y2_l2kill,       ICLASS_ST" 100 00 01----- PP-000-- --------")
+DEF_ENC32(Y5_l2gunlock,    ICLASS_ST" 100 00 01----- PP-010-- --------")
+DEF_ENC32(Y5_l2gclean,     ICLASS_ST" 100 00 01----- PP-100-- --------")
+DEF_ENC32(Y5_l2gcleaninv,  ICLASS_ST" 100 00 01----- PP-110-- --------")
+DEF_ENC32(Y2_l2cleaninvidx,ICLASS_ST" 100 00 11sssss PP------ --------")
 
 
 
@@ -502,9 +507,28 @@ DEF_ENC32(Y2_dccleana,     ICLASS_ST" 000 00 00sssss PP------ --------")
 DEF_ENC32(Y2_dcinva,       ICLASS_ST" 000 00 01sssss PP------ --------")
 DEF_ENC32(Y2_dccleaninva,  ICLASS_ST" 000 00 10sssss PP------ --------")
 
-DEF_ENC32(Y4_l2fetch,      ICLASS_ST" 011 00 00sssss PP-ttttt 000-----")
+/* Super */
+DEF_ENC32(Y2_dckill,       ICLASS_ST" 001 00 00----- PP------ --------")
+DEF_ENC32(Y2_dccleanidx,   ICLASS_ST" 001 00 01sssss PP------ --------")
+DEF_ENC32(Y2_dcinvidx,     ICLASS_ST" 001 00 10sssss PP------ --------")
+DEF_ENC32(Y2_dccleaninvidx,ICLASS_ST" 001 00 11sssss PP------ --------")
+
+DEF_ENC32(Y2_dctagw       ,ICLASS_ST" 010 00 00sssss PP-ttttt --------")
+DEF_ENC32(Y2_dctagr       ,ICLASS_ST" 010 00 01sssss PP------ ---ddddd")
+
+DEF_ENC32(Y4_l2tagw       ,ICLASS_ST" 010 00 10sssss PP0ttttt --------")
+DEF_ENC32(Y4_l2tagr       ,ICLASS_ST" 010 00 11sssss PP------ ---ddddd")
+
+DEF_ENC32(Y4_l2fetch,          ICLASS_ST" 011 00 00sssss PP-ttttt 000-----")
+DEF_ENC32(Y5_l2cleanidx,   ICLASS_ST" 011 00 01sssss PP------ --------")
+DEF_ENC32(Y5_l2invidx,     ICLASS_ST" 011 00 10sssss PP------ --------")
+DEF_ENC32(Y5_l2unlocka,    ICLASS_ST" 011 00 11sssss PP------ --------")
 DEF_ENC32(Y5_l2fetch,      ICLASS_ST" 011 01 00sssss PP-ttttt --------")
 
+DEF_ENC32(Y6_l2gcleanpa,   ICLASS_ST" 011 01 01----- PP-ttttt --------")
+DEF_ENC32(Y6_l2gcleaninvpa,ICLASS_ST" 011 01 10----- PP-ttttt --------")
+
+
 /*******************************/
 /*                             */
 /*                             */
@@ -547,13 +571,23 @@ DEF_ENC32(J2_jumprfnewpt, ICLASS_J" 0011  011sssss  PP-11-uu  --------")
 
 DEF_FIELDROW_DESC32(ICLASS_J" 0100 -------- PP------ --------","[#4] (#u8) ")
 DEF_ENC32(J2_trap0,     ICLASS_J" 0100  00------  PP-iiiii  ---iii--")
-DEF_ENC32(J2_pause,     ICLASS_J" 0100  01------  PP-iiiii  ---iii--")
+DEF_ENC32(J2_trap1,     ICLASS_J" 0100  10-xxxxx  PP-iiiii  ---iii--")
+DEF_ENC32(J2_pause,     ICLASS_J" 0100  01----ii  PP-iiiii  ---iii--")
+
+DEF_FIELDROW_DESC32(ICLASS_J" 0101 -------- PP------ --------","[#5] Rd=(Rs) ")
+DEF_ENC32(Y2_icdatar,   ICLASS_J" 0101  101sssss  PP------  ---ddddd")
+DEF_ENC32(Y2_ictagr,    ICLASS_J" 0101  111sssss  PP------  ---ddddd")
+DEF_ENC32(Y2_ictagw,    ICLASS_J" 0101  110sssss  PP0ttttt  --------")
+DEF_ENC32(Y2_icdataw,   ICLASS_J" 0101  110sssss  PP1ttttt  --------")
 
 DEF_FIELDROW_DESC32(ICLASS_J" 0110 -------- PP------ --------","[#6] icop(Rs) ")
 DEF_ENC32(Y2_icinva,    ICLASS_J" 0110  110sssss  PP000---  --------")
+DEF_ENC32(Y2_icinvidx,  ICLASS_J" 0110  110sssss  PP001---  --------")
+DEF_ENC32(Y2_ickill,    ICLASS_J" 0110  110-----  PP010---  --------")
 
 DEF_FIELDROW_DESC32(ICLASS_J" 0111 -------- PP------ --------","[#7] () ")
 DEF_ENC32(Y2_isync,     ICLASS_J" 0111  11000000  PP0---00  00000010")
+DEF_ENC32(J2_rte,       ICLASS_J" 0111  111-----  PP00----  000-----")
 
 /* JUMP */
 DEF_FIELDROW_DESC32(ICLASS_J" 100- -------- PP------ --------","[#8,9] PC=(#r22)")
@@ -738,12 +772,19 @@ DEF_ENC32(J2_jumprltezpt,ICLASS_CR" 0001  11isssss  PPi1iiii  iiiiiii-")
 
 DEF_FIELDROW_DESC32(    ICLASS_CR" 0010  --------  PP------  --------","[#2] Cd=Rs ")
 DEF_ENC32(A2_tfrrcr,    ICLASS_CR" 0010  001sssss  PP------  ---ddddd")
+DEF_ENC32(G4_tfrgrcr,   ICLASS_CR" 0010  000sssss  PP------  ---ddddd")
+DEF_ENC32(Y4_trace,     ICLASS_CR" 0010  010sssss  PP------  000-----")
+DEF_ENC32(Y6_diag,      ICLASS_CR" 0010  010sssss  PP------  001-----")
+DEF_ENC32(Y6_diag0,     ICLASS_CR" 0010  010sssss  PP-ttttt  010-----")
+DEF_ENC32(Y6_diag1,     ICLASS_CR" 0010  010sssss  PP-ttttt  011-----")
 
 DEF_FIELDROW_DESC32(    ICLASS_CR" 0011  --------  PP------  --------","[#3] Cdd=Rss ")
 DEF_ENC32(A4_tfrpcp,    ICLASS_CR" 0011  001sssss  PP------  ---ddddd")
+DEF_ENC32(G4_tfrgpcp,   ICLASS_CR" 0011  000sssss  PP------  ---ddddd")
 
 DEF_FIELDROW_DESC32(    ICLASS_CR" 1000  --------  PP------  --------","[#8] Rdd=Css ")
 DEF_ENC32(A4_tfrcpp,    ICLASS_CR" 1000  000sssss  PP------  ---ddddd")
+DEF_ENC32(G4_tfrgcpp,   ICLASS_CR" 1000  001sssss  PP------  ---ddddd")
 
 DEF_FIELDROW_DESC32(    ICLASS_CR" 1001  --------  PP------  --------","[#9] (#r8,#U10)")
 DEF_ENC32(J2_ploop1si,  ICLASS_CR" 1001  101IIIII  PP-iiiii  IIIii-II")
@@ -754,6 +795,7 @@ DEF_ENC32(J2_loop1i,    ICLASS_CR" 1001  001IIIII  PP-iiiii  IIIii-II")
 
 DEF_FIELDROW_DESC32(    ICLASS_CR" 1010  --------  PP------  --------","[#10] Rd=Cs ")
 DEF_ENC32(A2_tfrcrr,    ICLASS_CR" 1010  000sssss  PP------  ---ddddd")
+DEF_ENC32(G4_tfrgcrr,   ICLASS_CR" 1010  001sssss  PP------  ---ddddd")
 DEF_ENC32(C4_addipc,    ICLASS_CR" 1010  01001001  PP-iiiii  i--ddddd")
 
 
@@ -781,6 +823,64 @@ DEF_ENC32(C4_fastcorner9_not,   ICLASS_CR"1011 0001--ss  PP1---tt 1--1--dd")
 
 
 
+/* Supervisor CR ops */
+/* Interrupts */
+DEF_FIELDROW_DESC32(   ICLASS_CR" 0100 -------- PP------  --------","[#4] (Rs,Pt)")
+DEF_ENC32(Y2_swi,      ICLASS_CR" 0100 000sssss PP------ 000-----")
+DEF_ENC32(Y2_cswi,     ICLASS_CR" 0100 000sssss PP------ 001-----")
+DEF_ENC32(Y2_iassignw, ICLASS_CR" 0100 000sssss PP------ 010-----")
+DEF_ENC32(Y2_ciad,     ICLASS_CR" 0100 000sssss PP------ 011-----")
+DEF_ENC32(Y2_setimask, ICLASS_CR" 0100 100sssss PP----tt 000-----")
+DEF_ENC32(Y2_setprio,  ICLASS_CR" 0100 100sssss PP----tt 001-----")
+DEF_ENC32(Y4_siad,     ICLASS_CR" 0100 100sssss PP------ 011-----")
+
+DEF_ENC32(Y2_wait,     ICLASS_CR" 0100 010sssss PP------ 000-----")
+DEF_ENC32(Y2_resume,   ICLASS_CR" 0100 010sssss PP------ 001-----")
+DEF_ENC32(Y2_stop,     ICLASS_CR" 0100 011sssss PP------ 000-----")
+DEF_ENC32(Y2_start,    ICLASS_CR" 0100 011sssss PP------ 001-----")
+DEF_ENC32(Y4_nmi,      ICLASS_CR" 0100 011sssss PP------ 010-----")
+
+DEF_FIELDROW_DESC32(   ICLASS_CR" 0101 -------- PP------  --------","[#5] Rx ")
+DEF_ENC32(Y2_crswap0,  ICLASS_CR" 0101 000xxxxx PP------ --------")
+DEF_ENC32(Y4_crswap1,  ICLASS_CR" 0101 001xxxxx PP------ --------")
+
+DEF_FIELDROW_DESC32(   ICLASS_CR" 0110 -------- PP------  --------","[#6] Rd=(Rs)")
+DEF_ENC32(Y2_getimask, ICLASS_CR" 0110 000sssss PP------ ---ddddd")
+DEF_ENC32(Y2_iassignr, ICLASS_CR" 0110 011sssss PP------ ---ddddd")
+
+DEF_FIELDROW_DESC32(   ICLASS_CR" 0111 -------- PP------  --------","[#7] cr=Rs ")
+DEF_ENC32(Y2_tfrsrcr,  ICLASS_CR" 0111 00-sssss PP------ -ddddddd")
+
+DEF_FIELDROW_DESC32(   ICLASS_CR" 1100 -------- PP------  --------","[#12] ")
+DEF_ENC32(Y2_break,    ICLASS_CR" 1100 001----- PP------ 000-----")
+DEF_ENC32(Y2_tlblock,  ICLASS_CR" 1100 001----- PP------ 001-----")
+DEF_ENC32(Y2_tlbunlock,ICLASS_CR" 1100 001----- PP------ 010-----")
+DEF_ENC32(Y2_k0lock,   ICLASS_CR" 1100 001----- PP------ 011-----")
+DEF_ENC32(Y2_k0unlock, ICLASS_CR" 1100 001----- PP------ 100-----")
+DEF_ENC32(Y2_tlbp,     ICLASS_CR" 1100 100sssss PP------ ---ddddd")
+DEF_ENC32(Y5_tlboc,    ICLASS_CR" 1100 111sssss PP------ ---ddddd")
+DEF_ENC32(Y5_tlbasidi, ICLASS_CR" 1100 101sssss PP------ --------")
+DEF_ENC32(Y2_tlbr,     ICLASS_CR" 1100 010sssss PP------ ---ddddd")
+DEF_ENC32(Y2_tlbw,     ICLASS_CR" 1100 000sssss PP0ttttt --------")
+DEF_ENC32(Y5_ctlbw,    ICLASS_CR" 1100 110sssss PP0ttttt ---ddddd")
+
+DEF_FIELDROW_DESC32(   ICLASS_CR" 1101 -------- PP------  --------","[#13] Rxx ")
+DEF_ENC32(Y4_crswap10, ICLASS_CR" 1101 10-xxxxx PP------ ---00000")
+DEF_ENC32(Y4_tfrspcp,  ICLASS_CR" 1101 00-sssss PP------ -ddddddd")
+
+DEF_FIELDROW_DESC32(   ICLASS_CR" 1110 -------- PP------  --------","[#14] Rd=cr ")
+DEF_ENC32(Y2_tfrscrr,  ICLASS_CR" 1110 1sssssss PP------ ---ddddd")
+
+DEF_FIELDROW_DESC32(   ICLASS_CR" 1111 -------- PP------  --------","[#15] Rdd=Sss ")
+DEF_ENC32(Y4_tfrscpp,  ICLASS_CR" 1111 0sssssss PP------ ---ddddd")
+
+
+
+
+
+
+
+
 /*******************************/
 /*                             */
 /*                             */
diff --git a/target/hexagon/imported/system.idef b/target/hexagon/imported/system.idef
index 7c6568e75e4..df4527a5fa9 100644
--- a/target/hexagon/imported/system.idef
+++ b/target/hexagon/imported/system.idef
@@ -25,31 +25,230 @@
 /* User->OS interface                       */
 /********************************************/
 
-Q6INSN(J2_trap0,"trap0(#u8)",ATTRIBS(A_COF),
+Q6INSN(J2_trap0,"trap0(#u8)",ATTRIBS(A_COF,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),
 "Trap to Operating System",
     fTRAP(0,uiV);
 )
 
-Q6INSN(J2_pause,"pause(#u8)",ATTRIBS(A_COF),
+Q6INSN(J2_trap1,"trap1(Rx32,#u8)",ATTRIBS(A_COF,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),
+"Trap to Operating System",
+	/*
+	 * Note: if RxV is not written, we get the same as the input.
+	 * Since trap1 is SOLO, this means the register will effectively not be updated
+	 */
+	if (!fTRAP1_VIRTINSN(uiV)) {
+		fTRAP(1,uiV);
+	} else if (uiV == 1) {
+		fVIRTINSN_RTE(uiV,RxV);
+	} else if (uiV == 3) {
+		fVIRTINSN_SETIE(uiV,RxV);
+	} else if (uiV == 4) {
+		fVIRTINSN_GETIE(uiV,RxV);
+	} else if (uiV == 6) {
+		fVIRTINSN_SPSWAP(uiV,RxV);
+	})
+
+Q6INSN(J2_pause,"pause(#u8)",ATTRIBS(A_COF,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),
 "Enter low-power state for #u8 cycles",{fPAUSE(uiV);})
 
-Q6INSN(Y2_icinva,"icinva(Rs32)",ATTRIBS(A_ICOP,A_ICFLUSHOP),"Instruction Cache Invalidate Address",{fEA_REG(RsV); fICINVA(EA);})
+Q6INSN(J2_rte,  "rte", ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NO_TIMING_LOG),
+"Return from Exception",
+{
+fHIDE(if((thread->timing_on) && (thread->status & EXEC_STATUS_REPLAY)) { return; })
+fHIDE(CALLBACK(thread->processor_ptr->options->rte_callback,
+      thread->system_ptr,thread->processor_ptr,
+      thread->threadId,0);)
+fCLEAR_RTE_EX();
+fBRANCH(fREAD_ELR(),COF_TYPE_RTE);})
 
-Q6INSN(Y2_isync,"isync",ATTRIBS(),"Memory Synchronization",{fISYNC();})
-Q6INSN(Y2_barrier,"barrier",ATTRIBS(A_RESTRICT_SLOT0ONLY),"Memory Barrier",{fBARRIER();})
-Q6INSN(Y2_syncht,"syncht",ATTRIBS(A_RESTRICT_SLOT0ONLY),"Memory Synchronization",{fSYNCH();})
 
+/********************************************/
+/* Interrupt Management                     */
+/********************************************/
 
-Q6INSN(Y2_dcfetchbo,"dcfetch(Rs32+#u11:3)",ATTRIBS(A_RESTRICT_PREFERSLOT0,A_DCFETCH),"Data Cache Prefetch",{fEA_RI(RsV,uiV); fDCFETCH(EA);})
+Q6INSN(Y2_swi,"swi(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK),"Software Interrupt",{DO_SWI(RsV);})
+Q6INSN(Y2_cswi,"cswi(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK),"Cancel Software Interrupt",{DO_CSWI(RsV);})
+Q6INSN(Y2_ciad,"ciad(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK),"Re-enable interrupt in IAD",{DO_CIAD(RsV);})
+Q6INSN(Y4_siad,"siad(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK),"Disable interrupt in IAD",{DO_SIAD(RsV);})
+Q6INSN(Y2_iassignr,"Rd32=iassignr(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK),"Read interrupt to thread assignments",{DO_IASSIGNR(RsV,RdV);})
+Q6INSN(Y2_iassignw,"iassignw(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK),"Write interrupt to thread assignments",{DO_IASSIGNW(RsV);})
 
 
-Q6INSN(Y2_dczeroa,"dczeroa(Rs32)",ATTRIBS(A_STORE,A_RESTRICT_SLOT0ONLY,A_DCZEROA),"Zero an aligned 32-byte cacheline",{fEA_REG(RsV); fDCZEROA(EA);})
-Q6INSN(Y2_dccleana,"dccleana(Rs32)",ATTRIBS(A_RESTRICT_SLOT0ONLY,A_DCFLUSHOP),"Data Cache Clean Address",{fEA_REG(RsV); fDCCLEANA(EA);})
-Q6INSN(Y2_dccleaninva,"dccleaninva(Rs32)",ATTRIBS(A_RESTRICT_SLOT0ONLY,A_DCFLUSHOP),"Data Cache Clean and Invalidate Address",{fEA_REG(RsV); fDCCLEANINVA(EA);})
-Q6INSN(Y2_dcinva,"dcinva(Rs32)",ATTRIBS(A_RESTRICT_SLOT0ONLY,A_DCFLUSHOP),"Data Cache Invalidate Address",{fEA_REG(RsV); fDCCLEANINVA(EA);})
+Q6INSN(Y2_getimask,"Rd32=getimask(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK),"Read imask register of another thread",
+{RdV = READ_IMASK(RsV & thread->processor_ptr->thread_system_mask); })
 
+Q6INSN(Y2_setimask,"setimask(Pt4,Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK),"Change imask register of another thread",
+{fPREDUSE_TIMING();WRITE_IMASK(PtV & thread->processor_ptr->thread_system_mask,RsV); })
 
-Q6INSN(Y4_l2fetch,"l2fetch(Rs32,Rt32)",ATTRIBS(A_RESTRICT_SLOT0ONLY),"L2 Cache Prefetch",
+
+
+/********************************************/
+/* TLB management                           */
+/********************************************/
+
+Q6INSN(Y2_tlbw,"tlbw(Rss32,Rt32)", ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),
+"Write TLB entry", {fTLBW(RtV,RssV);})
+
+Q6INSN(Y5_ctlbw,"Rd32=ctlbw(Rss32,Rt32)", ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),
+"Conditional Write TLB entry",
+{
+  if (fTLB_ENTRY_OVERLAP( (1LL<<63) | RssV )) {
+        RdV=fTLB_ENTRY_OVERLAP_IDX( (1LL<<63) | RssV);
+     } else {
+        fTLBW(RtV,RssV);
+        RdV=0x80000000;
+     }
+})
+
+Q6INSN(Y5_tlboc,"Rd32=tlboc(Rss32)", ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),
+"TLB overlap check",
+{
+  if (fTLB_ENTRY_OVERLAP( (1LL<<63) | RssV )) {
+        RdV=fTLB_ENTRY_OVERLAP_IDX( (1LL<<63) | RssV);
+     } else {
+        RdV=0x80000000;
+     }
+})
+
+Q6INSN(Y2_tlbr,"Rdd32=tlbr(Rs32)", ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET), "Read TLB entry",
+{RddV = fTLBR(RsV);})
+
+Q6INSN(Y2_tlbp,"Rd32=tlbp(Rs32)", ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET), "Probe TLB", {RdV=fTLBP(RsV);})
+
+Q6INSN(Y5_tlbasidi,"tlbinvasid(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET), "Invalidate ASID",
+{
+	fHIDE(int i;)
+    fHIDE(unsigned int NUM_TLB_ENTRIES = NUM_TLB_REGS(thread->processor_ptr);)
+	for (i = 0; i < NUM_TLB_ENTRIES; i++) {
+		if ((fGET_FIELD(fTLBR(i),PTE_G) == 0) &&
+			(fGET_FIELD(fTLBR(i),PTE_ASID) == fEXTRACTU_RANGE(RsV,26,20))) {
+			fTLBW(i,fTLBR(i) & ~(1ULL << 63));
+		}
+	}
+})
+
+Q6INSN(Y2_tlblock,"tlblock", ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_NO_TIMING_LOG), "Lock TLB",
+{fSET_TLB_LOCK();})
+
+Q6INSN(Y2_tlbunlock,"tlbunlock", ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET), "Unlock TLB",
+{fCLEAR_TLB_LOCK();})
+
+Q6INSN(Y2_k0lock,"k0lock", ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_NO_TIMING_LOG), "Lock K0",
+{fSET_K0_LOCK();})
+
+Q6INSN(Y2_k0unlock,"k0unlock", ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET), "Unlock K0",
+{fCLEAR_K0_LOCK();})
+
+/********************************************/
+/* Supervisor Reg Management                */
+/********************************************/
+
+Q6INSN(Y2_crswap0,"crswap(Rx32,sgp0)",ATTRIBS(A_PRIV,A_NOTE_PRIV), "Swap system general pointer 0 with GPR",
+{fHIDE(size4s_t tmp;) tmp = RxV; RxV = READ_SGP0(); WRITE_SGP0(tmp);})
+Q6INSN(Y4_crswap1,"crswap(Rx32,sgp1)",ATTRIBS(A_PRIV,A_NOTE_PRIV), "Swap system general pointer 1 with GPR",
+{fHIDE(size4s_t tmp;) tmp = RxV; RxV = READ_SGP1(); WRITE_SGP1(tmp);})
+
+Q6INSN(Y4_crswap10,"crswap(Rxx32,sgp1:0)",ATTRIBS(A_PRIV,A_NOTE_PRIV), "Swap system general purpose 0/1 with GPR Pair",
+{fHIDE(size8s_t tmp;) tmp = RxxV; RxxV=READ_SGP10(); WRITE_SGP10(tmp);})
+
+Q6INSN(Y2_tfrscrr,"Rd32=Ss128",ATTRIBS(A_PRIV,A_NOTE_PRIV),"Transfer Supervisor Reg to GPR", {RdV=SsV;})
+Q6INSN(Y2_tfrsrcr,"Sd128=Rs32",ATTRIBS(A_PRIV,A_NOTE_PRIV),"Transfer GPR to Supervisor Reg", {SdV=RsV;})
+Q6INSN(Y4_tfrscpp,"Rdd32=Sss128",ATTRIBS(A_PRIV,A_NOTE_PRIV),"Transfer Supervisor Reg to GPR", {RddV=SssV;})
+Q6INSN(Y4_tfrspcp,"Sdd128=Rss32",ATTRIBS(A_PRIV,A_NOTE_PRIV),"Transfer GPR to Supervisor Reg", {SddV=RssV;})
+
+Q6INSN(G4_tfrgcrr,"Rd32=Gs32",ATTRIBS(A_GUEST,A_NOTE_GUEST),"Transfer Guest Reg to GPR", {RdV=GsV;})
+Q6INSN(G4_tfrgrcr,"Gd32=Rs32",ATTRIBS(A_GUEST,A_NOTE_GUEST),"Transfer GPR to Guest Reg", {GdV=RsV;})
+Q6INSN(G4_tfrgcpp,"Rdd32=Gss32",ATTRIBS(A_GUEST,A_NOTE_GUEST),"Transfer Guest Reg to GPR", {RddV=GssV;})
+Q6INSN(G4_tfrgpcp,"Gdd32=Rss32",ATTRIBS(A_GUEST,A_NOTE_GUEST),"Transfer GPR to Guest Reg", {GddV=RssV;})
+
+
+
+Q6INSN(Y2_setprio,"setprio(Pt4,Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV),"Change TID Prio of another thread",
+{fPREDUSE_TIMING();WRITE_PRIO(PtV & thread->processor_ptr->thread_system_mask,RsV); })
+
+
+
+
+/********************************************/
+/* Power Management / Thread on/off         */
+/********************************************/
+Q6INSN(Y6_diag,"diag(Rs32)",ATTRIBS(),"Send value to Diag trace module",{
+})
+Q6INSN(Y6_diag0,"diag0(Rss32,Rtt32)",ATTRIBS(),"Send values of two register to DIAG Trace. Set X=0",{
+})
+Q6INSN(Y6_diag1,"diag1(Rss32,Rtt32)",ATTRIBS(),"Send values of two register to DIAG Trace.  Set X=1",{
+})
+
+
+Q6INSN(Y4_trace,"trace(Rs32)",ATTRIBS(A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK),"Send value to ETM trace",{
+    fDO_TRACE(RsV);
+})
+
+Q6INSN(Y2_stop,"stop(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),"Stop thread(s)",{
+    fHIDE(RsV=RsV;)
+    if (!fIN_DEBUG_MODE_NO_ISDB(fGET_TNUM())) fCLEAR_RUN_MODE(fGET_TNUM());
+})
+
+Q6INSN(Y4_nmi,"nmi(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_NO_TIMING_LOG),"Raise NMI on thread(s)",{
+    fDO_NMI(RsV);
+})
+
+Q6INSN(Y2_start,"start(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),"Start thread(s)",fSTART(RsV);)
+
+Q6INSN(Y2_wait,"wait(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_NO_TIMING_LOG),"Make thread(s) wait",{
+    fHIDE(RsV=RsV;)
+    if (!fIN_DEBUG_MODE(fGET_TNUM())) fSET_WAIT_MODE(fGET_TNUM());
+	fIN_DEBUG_MODE_WARN(fGET_TNUM());
+})
+
+Q6INSN(Y2_resume,"resume(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),"Make thread(s) stop waiting",fRESUME(RsV);)
+
+Q6INSN(Y2_break,"brkpt",ATTRIBS(A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),"Breakpoint",{fBREAK();})
+
+
+/********************************************/
+/* Cache Management                         */
+/********************************************/
+
+Q6INSN(Y2_ictagr,"Rd32=ictagr(Rs32)",ATTRIBS(A_ICOP,A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_CACHEOP,A_COPBYIDX,A_ICTAGOP),"Instruction Cache Tag Read",{fICTAGR(RsV,RdV,RdN);})
+Q6INSN(Y2_ictagw,"ictagw(Rs32,Rt32)",ATTRIBS(A_ICOP,A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_CACHEOP,A_COPBYIDX,A_ICTAGOP),"Instruction Cache Tag Write",{fICTAGW(RsV,RtV);})
+Q6INSN(Y2_icdataw,"icdataw(Rs32,Rt32)",ATTRIBS(A_ICOP,A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_CACHEOP,A_COPBYIDX,A_ICTAGOP),"Instruction Cache Data Write",{fICDATAW(RsV,RtV);})
+Q6INSN(Y2_icdatar,"Rd32=icdatar(Rs32)",ATTRIBS(A_ICOP,A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_CACHEOP,A_COPBYIDX,A_ICTAGOP),"Instruction Cache Data Read",{fICDATAR(RsV, RdV);})
+Q6INSN(Y2_icinva,"icinva(Rs32)",ATTRIBS(A_ICOP,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_CACHEOP,A_COPBYADDRESS,A_ICFLUSHOP),"Instruction Cache Invalidate Address",{fEA_REG(RsV); fICINVA(EA);})
+Q6INSN(Y2_icinvidx,"icinvidx(Rs32)",ATTRIBS(A_ICOP,A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_CACHEOP,A_COPBYIDX,A_ICFLUSHOP),"Instruction Cache Invalidate Index",{fICINVIDX(RsV);})
+Q6INSN(Y2_ickill,"ickill",ATTRIBS(A_ICOP,A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_CACHEOP,A_ICFLUSHOP),"Instruction Cache Invalidate",{fICKILL();})
+
+Q6INSN(Y2_isync,"isync",ATTRIBS(A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),"Memory Synchronization",{fISYNC();})
+Q6INSN(Y2_barrier,"barrier",ATTRIBS(A_NOTE_NOPACKET,A_RESTRICT_SLOT0ONLY,A_RESTRICT_PACKET_AXOK),"Memory Barrier",{fBARRIER();})
+Q6INSN(Y2_syncht,"syncht",ATTRIBS(A_NOTE_NOPACKET,A_RESTRICT_SLOT0ONLY,A_RESTRICT_NOPACKET),"Memory Synchronization",{fSYNCH();})
+
+
+Q6INSN(Y2_dcfetchbo,"dcfetch(Rs32+#u11:3)",ATTRIBS(A_RESTRICT_PREFERSLOT0,A_DCFETCH,A_RESTRICT_NOSLOT1_STORE),"Data Cache Prefetch",{fEA_RI(RsV,uiV); fDCFETCH(EA);})
+Q6INSN(Y2_dckill,"dckill",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_SLOT0ONLY,A_RESTRICT_NOPACKET,A_CACHEOP,A_DCFLUSHOP),"Data Cache Invalidate",{fDCKILL();})
+
+
+Q6INSN(Y2_dczeroa,"dczeroa(Rs32)",ATTRIBS(A_STORE,A_RESTRICT_SLOT1_AOK,A_NOTE_SLOT1_AOK,A_RESTRICT_SLOT0ONLY,A_CACHEOP,A_COPBYADDRESS,A_DCZEROA),"Zero an aligned 32-byte cacheline",{fEA_REG(RsV); fDCZEROA(EA);})
+Q6INSN(Y2_dccleana,"dccleana(Rs32)",ATTRIBS(A_RESTRICT_SLOT1_AOK,A_NOTE_SLOT1_AOK,A_RESTRICT_SLOT0ONLY,A_CACHEOP,A_COPBYADDRESS,A_DCFLUSHOP),"Data Cache Clean Address",{fEA_REG(RsV); fDCCLEANA(EA);})
+Q6INSN(Y2_dccleanidx,"dccleanidx(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_RESTRICT_PACKET_AXOK,A_NOTE_AXOK,A_RESTRICT_SLOT0ONLY,A_CACHEOP,A_COPBYIDX,A_DCFLUSHOP),"Data Cache Clean Index",{fDCCLEANIDX(RsV);})
+Q6INSN(Y2_dccleaninva,"dccleaninva(Rs32)",ATTRIBS(A_RESTRICT_SLOT1_AOK,A_NOTE_SLOT1_AOK,A_RESTRICT_SLOT0ONLY,A_CACHEOP,A_COPBYADDRESS,A_DCFLUSHOP),"Data Cache Clean and Invalidate Address",{fEA_REG(RsV); fDCCLEANINVA(EA);})
+Q6INSN(Y2_dccleaninvidx,"dccleaninvidx(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_RESTRICT_PACKET_AXOK,A_NOTE_AXOK,A_RESTRICT_SLOT0ONLY,A_CACHEOP,A_COPBYIDX,A_DCFLUSHOP),"Data Cache Clean and Invalidate Index",{fDCCLEANINVIDX(RsV);})
+Q6INSN(Y2_dcinva,"dcinva(Rs32)",ATTRIBS(A_RESTRICT_SLOT1_AOK,A_NOTE_SLOT1_AOK,A_RESTRICT_SLOT0ONLY,A_CACHEOP,A_COPBYADDRESS,A_DCFLUSHOP),"Data Cache Invalidate Address",{fEA_REG(RsV); fDCCLEANINVA(EA);})
+Q6INSN(Y2_dcinvidx,"dcinvidx(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_RESTRICT_PACKET_AXOK,A_NOTE_AXOK,A_RESTRICT_SLOT0ONLY,A_CACHEOP,A_COPBYIDX,A_DCFLUSHOP),"Data Cache Invalidate Index",{fDCINVIDX(RsV);})
+Q6INSN(Y2_dctagr,"Rd32=dctagr(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_RESTRICT_PACKET_AXOK,A_NOTE_AXOK,A_RESTRICT_SLOT0ONLY,A_CACHEOP,A_COPBYIDX,A_DCTAGOP),"Data Cache Tag Read",{fDCTAGR(RsV,RdV,RdN);})
+Q6INSN(Y2_dctagw,"dctagw(Rs32,Rt32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_RESTRICT_SLOT0ONLY,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_CACHEOP,A_COPBYIDX,A_DCTAGOP),"Data Cache Tag Write",{fDCTAGW(RsV,RtV);})
+
+
+Q6INSN(Y2_l2kill,"l2kill",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_SLOT0ONLY,A_RESTRICT_NOPACKET,A_CACHEOP,A_L2FLUSHOP),"L2 Cache Invalidate",{fL2KILL();})
+Q6INSN(Y4_l2tagw,"l2tagw(Rs32,Rt32)",ATTRIBS(A_PRIV,A_NOTE_BADTAG_UNDEF,A_NOTE_PRIV,A_RESTRICT_SLOT0ONLY,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET,A_CACHEOP,A_COPBYIDX,A_L2TAGOP),"L2 Cache Tag Write",{fL2TAGW(RsV,RtV);})
+Q6INSN(Y4_l2tagr,"Rd32=l2tagr(Rs32)",ATTRIBS(A_PRIV,A_NOTE_BADTAG_UNDEF,A_NOTE_PRIV,A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK,A_RESTRICT_SLOT0ONLY,A_CACHEOP,A_COPBYIDX,A_L2TAGOP),"L2 Cache Tag Read",{fL2TAGR(RsV,RdV,RdN);})
+
+Q6INSN(Y2_l2cleaninvidx,"l2cleaninvidx(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK,A_RESTRICT_SLOT0ONLY,A_CACHEOP,A_COPBYIDX,A_L2FLUSHOP),"L2 Cache Clean and Invalidate Index",{fL2CLEANINVIDX(RsV); })
+Q6INSN(Y5_l2cleanidx,"l2cleanidx(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK,A_RESTRICT_SLOT0ONLY,A_CACHEOP,A_COPBYIDX,A_L2FLUSHOP),"L2 Cache Clean by Index",{fL2CLEANIDX(RsV); })
+Q6INSN(Y5_l2invidx,"l2invidx(Rs32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_AXOK,A_RESTRICT_PACKET_AXOK,A_RESTRICT_SLOT0ONLY,A_CACHEOP,A_COPBYIDX,A_L2FLUSHOP),"L2 Cache Invalidate by Index",{fL2INVIDX(RsV); })
+
+
+
+Q6INSN(Y4_l2fetch,"l2fetch(Rs32,Rt32)",ATTRIBS(A_RESTRICT_SLOT0ONLY,A_RESTRICT_PACKET_AXOK,A_NOTE_AXOK),"L2 Cache Prefetch",
 { fL2FETCH(RsV,
            (RtV&0xff), /*height*/
            ((RtV>>8)&0xff), /*width*/
@@ -59,10 +258,29 @@ Q6INSN(Y4_l2fetch,"l2fetch(Rs32,Rt32)",ATTRIBS(A_RESTRICT_SLOT0ONLY),"L2 Cache P
 
 
 
-Q6INSN(Y5_l2fetch,"l2fetch(Rs32,Rtt32)",ATTRIBS(A_RESTRICT_SLOT0ONLY),"L2 Cache Prefetch",
+Q6INSN(Y5_l2fetch,"l2fetch(Rs32,Rtt32)",ATTRIBS(A_RESTRICT_SLOT0ONLY,A_RESTRICT_PACKET_AXOK,A_NOTE_AXOK),"L2 Cache Prefetch",
 { fL2FETCH(RsV,
            fGETUHALF(0,RttV), /*height*/
            fGETUHALF(1,RttV), /*width*/
            fGETUHALF(2,RttV), /*stride*/
            fGETUHALF(3,RttV)); /*flags*/
 })
+
+Q6INSN(Y5_l2locka,"Pd4=l2locka(Rs32)", ATTRIBS(A_PRIV,A_NOTE_PRIV,A_CACHEOP,A_COPBYADDRESS,A_RESTRICT_SLOT0ONLY,A_RESTRICT_PACKET_AXOK,A_NOTE_AXOK,A_RESTRICT_LATEPRED,A_NOTE_LATEPRED),
+"Lock L2 cache line by address", { fEA_REG(RsV); fL2LOCKA(EA,PdV,PdN); fHIDE(MARK_LATE_PRED_WRITE(PdN)) })
+
+
+Q6INSN(Y5_l2unlocka,"l2unlocka(Rs32)", ATTRIBS(A_PRIV,A_NOTE_PRIV,A_CACHEOP,A_COPBYADDRESS,A_RESTRICT_SLOT0ONLY,A_RESTRICT_PACKET_AXOK,A_NOTE_AXOK), "UnLock L2 cache line by address", { fEA_REG(RsV); fL2UNLOCKA(EA); })
+
+
+
+Q6INSN(Y5_l2gunlock,"l2gunlock",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_SLOT0ONLY,A_RESTRICT_NOPACKET,A_CACHEOP,A_L2FLUSHOP),"L2 Global Unlock",{fL2UNLOCK();})
+
+Q6INSN(Y5_l2gclean,"l2gclean",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_SLOT0ONLY,A_RESTRICT_NOPACKET,A_CACHEOP,A_L2FLUSHOP),"L2 Global Clean",{fL2CLEAN();})
+
+Q6INSN(Y5_l2gcleaninv,"l2gcleaninv",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_SLOT0ONLY,A_RESTRICT_NOPACKET,A_CACHEOP,A_L2FLUSHOP),"L2 Global Clean and Invalidate",{fL2CLEANINV();})
+
+Q6INSN(Y6_l2gcleanpa,"l2gclean(Rtt32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_SLOT0ONLY,A_RESTRICT_NOPACKET,A_CACHEOP,A_L2FLUSHOP),"L2 Global Clean by PA Range",{fL2CLEANPA(RttV);})
+
+Q6INSN(Y6_l2gcleaninvpa,"l2gcleaninv(Rtt32)",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_SLOT0ONLY,A_RESTRICT_NOPACKET,A_CACHEOP,A_L2FLUSHOP),"L2 Global Clean and Invalidate by PA Range",{fL2CLEANINVPA(RttV);})
+
-- 
2.34.1


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

* [PATCH v5 24/35] target/hexagon: Add sysemu TCG overrides
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (22 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 23/35] target/hexagon: Add system reg insns Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-25 19:24   ` Philippe Mathieu-Daudé
  2026-03-11  3:49 ` [PATCH v5 25/35] target/hexagon: Add implicit attributes to sysemu macros Brian Cain
                   ` (10 subsequent siblings)
  34 siblings, 1 reply; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Define TCG overrides for setprio(), crswap(,sgp{0,1,1:0}).

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu_helper.h  | 18 ++++++++++++++++
 target/hexagon/gen_tcg_sys.h | 40 ++++++++++++++++++++++++++++++++++++
 target/hexagon/helper.h      |  1 +
 target/hexagon/genptr.c      |  4 ++++
 target/hexagon/op_helper.c   | 10 ++++++++-
 target/hexagon/hex_common.py |  2 ++
 target/hexagon/meson.build   | 13 ++++++------
 7 files changed, 81 insertions(+), 7 deletions(-)
 create mode 100644 target/hexagon/cpu_helper.h
 create mode 100644 target/hexagon/gen_tcg_sys.h

diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
new file mode 100644
index 00000000000..1486a03c64a
--- /dev/null
+++ b/target/hexagon/cpu_helper.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HEXAGON_CPU_HELPER_H
+#define HEXAGON_CPU_HELPER_H
+
+uint32_t hexagon_get_pmu_counter(CPUHexagonState *cur_env, int index);
+uint64_t hexagon_get_sys_pcycle_count(CPUHexagonState *env);
+uint32_t hexagon_get_sys_pcycle_count_low(CPUHexagonState *env);
+uint32_t hexagon_get_sys_pcycle_count_high(CPUHexagonState *env);
+void hexagon_set_sys_pcycle_count(CPUHexagonState *env, uint64_t);
+void hexagon_set_sys_pcycle_count_low(CPUHexagonState *env, uint32_t);
+void hexagon_set_sys_pcycle_count_high(CPUHexagonState *env, uint32_t);
+
+#endif
diff --git a/target/hexagon/gen_tcg_sys.h b/target/hexagon/gen_tcg_sys.h
new file mode 100644
index 00000000000..04549831ea5
--- /dev/null
+++ b/target/hexagon/gen_tcg_sys.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HEXAGON_GEN_TCG_SYS_H
+#define HEXAGON_GEN_TCG_SYS_H
+
+#define fGEN_TCG_Y2_setprio(SHORTCODE) \
+    gen_helper_setprio(tcg_env, PtV, RsV)
+
+#define fGEN_TCG_Y2_crswap0(SHORTCODE) \
+    do { \
+        TCGv_i32 tmp = tcg_temp_new_i32(); \
+        tcg_gen_mov_tl(tmp, RxV); \
+        tcg_gen_mov_tl(RxV, hex_t_sreg[HEX_SREG_SGP0]); \
+        tcg_gen_mov_tl(ctx->t_sreg_new_value[HEX_SREG_SGP0], tmp); \
+    } while (0)
+
+#define fGEN_TCG_Y4_crswap1(SHORTCODE) \
+    do { \
+        TCGv_i32 tmp = tcg_temp_new_i32(); \
+        tcg_gen_mov_tl(tmp, RxV); \
+        tcg_gen_mov_tl(RxV, hex_t_sreg[HEX_SREG_SGP1]); \
+        tcg_gen_mov_tl(ctx->t_sreg_new_value[HEX_SREG_SGP1], tmp); \
+    } while (0)
+
+#define fGEN_TCG_Y4_crswap10(SHORTCODE) \
+    do { \
+        TCGv_i64 tmp = tcg_temp_new_i64(); \
+        tcg_gen_mov_i64(tmp, RxxV); \
+        tcg_gen_concat_i32_i64(RxxV, \
+                               hex_t_sreg[HEX_SREG_SGP0], \
+                               hex_t_sreg[HEX_SREG_SGP1]); \
+        tcg_gen_extrl_i64_i32(ctx->t_sreg_new_value[HEX_SREG_SGP0], tmp); \
+        tcg_gen_extrh_i64_i32(ctx->t_sreg_new_value[HEX_SREG_SGP1], tmp); \
+    } while (0)
+
+#endif
diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h
index 28b9b59e0f2..5405342f798 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -114,4 +114,5 @@ DEF_HELPER_2(sreg_read_pair, i64, env, i32)
 DEF_HELPER_2(greg_read, i32, env, i32)
 DEF_HELPER_2(greg_read_pair, i64, env, i32)
 DEF_HELPER_3(sreg_write_masked, void, env, i32, i32)
+DEF_HELPER_3(setprio, void, env, i32, i32)
 #endif
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 2310b9aec3a..bac63a42def 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -31,6 +31,10 @@
 #undef QEMU_GENERATE
 #include "gen_tcg.h"
 #include "gen_tcg_hvx.h"
+#ifndef CONFIG_USER_ONLY
+#include "gen_tcg_sys.h"
+#endif
+
 #include "genptr.h"
 
 TCGv gen_read_reg(TCGv result, int num)
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 327c233c01b..d9d84f05553 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -19,9 +19,10 @@
 #include "qemu/log.h"
 #include "accel/tcg/cpu-ldst.h"
 #include "accel/tcg/probe.h"
+#include "qemu/main-loop.h"
+#include "cpu.h"
 #include "exec/helper-proto.h"
 #include "fpu/softfloat.h"
-#include "cpu.h"
 #include "internal.h"
 #include "macros.h"
 #include "sys_macros.h"
@@ -31,6 +32,7 @@
 #include "mmvec/mmvec.h"
 #include "mmvec/macros.h"
 #include "op_helper.h"
+#include "cpu_helper.h"
 #include "translate.h"
 #ifndef CONFIG_USER_ONLY
 #include "hexswi.h"
@@ -1412,6 +1414,12 @@ uint64_t HELPER(greg_read_pair)(CPUHexagonState *env, uint32_t reg)
 {
     g_assert_not_reached();
 }
+
+void HELPER(setprio)(CPUHexagonState *env, uint32_t thread, uint32_t prio)
+{
+    g_assert_not_reached();
+}
+
 #endif
 
 
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index f7ca4986ca8..3ba1a4523f1 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -1369,6 +1369,7 @@ def parse_common_args(desc):
     parser.add_argument("semantics", help="semantics file")
     parser.add_argument("overrides", help="overrides file")
     parser.add_argument("overrides_vec", help="vector overrides file")
+    parser.add_argument("overrides_sys", help="system overrides file")
     parser.add_argument("out", help="output file")
     parser.add_argument("--idef-parser",
                         help="file of instructions translated by idef-parser")
@@ -1376,6 +1377,7 @@ def parse_common_args(desc):
     read_semantics_file(args.semantics)
     read_overrides_file(args.overrides)
     read_overrides_file(args.overrides_vec)
+    read_overrides_file(args.overrides_sys)
     if args.idef_parser:
         read_idef_parser_enabled_file(args.idef_parser)
     calculate_attribs()
diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build
index d169cf71b2f..528beca3cd0 100644
--- a/target/hexagon/meson.build
+++ b/target/hexagon/meson.build
@@ -20,6 +20,7 @@ hexagon_ss = ss.source_set()
 hex_common_py = 'hex_common.py'
 gen_tcg_h = meson.current_source_dir() / 'gen_tcg.h'
 gen_tcg_hvx_h = meson.current_source_dir() / 'gen_tcg_hvx.h'
+gen_tcg_sys_h = meson.current_source_dir() / 'gen_tcg_sys.h'
 idef_parser_dir = meson.current_source_dir() / 'idef-parser'
 
 #
@@ -337,12 +338,12 @@ if idef_parser_enabled and 'hexagon-linux-user' in target_dirs
     # Setup input and dependencies for the next step, this depends on whether or
     # not idef-parser is enabled
     helper_dep = [semantics_generated, idef_generated_tcg_c, idef_generated_tcg]
-    helper_in = [semantics_generated, gen_tcg_h, gen_tcg_hvx_h, '--idef-parser', idef_generated_list]
+    helper_in = [semantics_generated, gen_tcg_h, gen_tcg_hvx_h, gen_tcg_sys_h, '--idef-parser', idef_generated_list]
 else
     # Setup input and dependencies for the next step, this depends on whether or
     # not idef-parser is enabled
     helper_dep = [semantics_generated]
-    helper_in = [semantics_generated, gen_tcg_h, gen_tcg_hvx_h]
+    helper_in = [semantics_generated, gen_tcg_h, gen_tcg_hvx_h, gen_tcg_sys_h]
 endif
 
 #
@@ -356,7 +357,7 @@ helper_protos_generated = custom_target(
     'helper_protos_generated.h.inc',
     output: 'helper_protos_generated.h.inc',
     depends: helper_dep,
-    depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h],
+    depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h, gen_tcg_sys_h],
     command: [python, files('gen_helper_protos.py'), helper_in, '@OUTPUT@'],
 )
 hexagon_ss.add(helper_protos_generated)
@@ -365,7 +366,7 @@ helper_funcs_generated = custom_target(
     'helper_funcs_generated.c.inc',
     output: 'helper_funcs_generated.c.inc',
     depends: helper_dep,
-    depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h],
+    depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h, gen_tcg_sys_h],
     command: [python, files('gen_helper_funcs.py'), helper_in, '@OUTPUT@'],
 )
 hexagon_ss.add(helper_funcs_generated)
@@ -374,7 +375,7 @@ tcg_funcs_generated = custom_target(
     'tcg_funcs_generated.c.inc',
     output: 'tcg_funcs_generated.c.inc',
     depends: helper_dep,
-    depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h],
+    depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h, gen_tcg_sys_h],
     command: [python, files('gen_tcg_funcs.py'), helper_in, '@OUTPUT@'],
 )
 hexagon_ss.add(tcg_funcs_generated)
@@ -383,7 +384,7 @@ analyze_funcs_generated = custom_target(
     'analyze_funcs_generated.c.inc',
     output: 'analyze_funcs_generated.c.inc',
     depends: helper_dep,
-    depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h],
+    depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h, gen_tcg_sys_h],
     command: [python, files('gen_analyze_funcs.py'), helper_in, '@OUTPUT@'],
 )
 hexagon_ss.add(analyze_funcs_generated)
-- 
2.34.1


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

* [PATCH v5 25/35] target/hexagon: Add implicit attributes to sysemu macros
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (23 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 24/35] target/hexagon: Add sysemu TCG overrides Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 26/35] target/hexagon: Add TCG overrides for int handler insts Brian Cain
                   ` (9 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/hex_common.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 3ba1a4523f1..9986f47114e 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -128,8 +128,11 @@ def calculate_attribs():
     add_qemu_macro_attrib("fTRAP", "A_IMPLICIT_READS_PC")
     add_qemu_macro_attrib("fSET_OVERFLOW", "A_IMPLICIT_WRITES_USR")
     add_qemu_macro_attrib("fSET_LPCFG", "A_IMPLICIT_WRITES_USR")
+    add_qemu_macro_attrib("fCLEAR_RTE_EX", "A_IMPLICIT_WRITES_SSR")
     add_qemu_macro_attrib("fLOAD", "A_SCALAR_LOAD")
     add_qemu_macro_attrib("fSTORE", "A_SCALAR_STORE")
+    add_qemu_macro_attrib("fSET_K0_LOCK", "A_IMPLICIT_READS_PC")
+    add_qemu_macro_attrib("fSET_TLB_LOCK", "A_IMPLICIT_READS_PC")
     add_qemu_macro_attrib('fLSBNEW0', 'A_IMPLICIT_READS_P0')
     add_qemu_macro_attrib('fLSBNEW0NOT', 'A_IMPLICIT_READS_P0')
     add_qemu_macro_attrib('fREAD_P0', 'A_IMPLICIT_READS_P0')
-- 
2.34.1


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

* [PATCH v5 26/35] target/hexagon: Add TCG overrides for int handler insts
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (24 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 25/35] target/hexagon: Add implicit attributes to sysemu macros Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 27/35] target/hexagon: Add TCG overrides for thread ctl Brian Cain
                   ` (8 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Define TCG overrides for {c,}swi {c,s}iad, iassign{r,w}, {s,g}etimask
instructions.

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/gen_tcg_sys.h | 25 ++++++++++++++++++++++
 target/hexagon/helper.h      |  8 ++++++++
 target/hexagon/op_helper.c   | 40 ++++++++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+)

diff --git a/target/hexagon/gen_tcg_sys.h b/target/hexagon/gen_tcg_sys.h
index 04549831ea5..cc72ca86db8 100644
--- a/target/hexagon/gen_tcg_sys.h
+++ b/target/hexagon/gen_tcg_sys.h
@@ -7,6 +7,31 @@
 #ifndef HEXAGON_GEN_TCG_SYS_H
 #define HEXAGON_GEN_TCG_SYS_H
 
+/* System mode instructions */
+#define fGEN_TCG_Y2_swi(SHORTCODE) \
+    gen_helper_swi(tcg_env, RsV)
+
+#define fGEN_TCG_Y2_cswi(SHORTCODE) \
+    gen_helper_cswi(tcg_env, RsV)
+
+#define fGEN_TCG_Y2_ciad(SHORTCODE) \
+    gen_helper_ciad(tcg_env, RsV)
+
+#define fGEN_TCG_Y4_siad(SHORTCODE) \
+    gen_helper_siad(tcg_env, RsV)
+
+#define fGEN_TCG_Y2_iassignw(SHORTCODE) \
+    gen_helper_iassignw(tcg_env, RsV)
+
+#define fGEN_TCG_Y2_iassignr(SHORTCODE) \
+    gen_helper_iassignr(RdV, tcg_env, RsV)
+
+#define fGEN_TCG_Y2_getimask(SHORTCODE) \
+    gen_helper_getimask(RdV, tcg_env, RsV)
+
+#define fGEN_TCG_Y2_setimask(SHORTCODE) \
+    gen_helper_setimask(tcg_env, PtV, RsV)
+
 #define fGEN_TCG_Y2_setprio(SHORTCODE) \
     gen_helper_setprio(tcg_env, PtV, RsV)
 
diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h
index 5405342f798..955287133e4 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -109,6 +109,14 @@ DEF_HELPER_2(probe_hvx_stores, void, env, int)
 DEF_HELPER_2(probe_pkt_scalar_hvx_stores, void, env, int)
 
 #if !defined(CONFIG_USER_ONLY)
+DEF_HELPER_2(swi, void, env, i32)
+DEF_HELPER_2(cswi, void, env, i32)
+DEF_HELPER_2(ciad, void, env, i32)
+DEF_HELPER_2(siad, void, env, i32)
+DEF_HELPER_2(iassignw, void, env, i32)
+DEF_HELPER_2(iassignr, i32, env, i32)
+DEF_HELPER_2(getimask, i32, env, i32)
+DEF_HELPER_3(setimask, void, env, i32, i32)
 DEF_HELPER_2(sreg_read, i32, env, i32)
 DEF_HELPER_2(sreg_read_pair, i64, env, i32)
 DEF_HELPER_2(greg_read, i32, env, i32)
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index d9d84f05553..e81e89b8bd9 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1390,6 +1390,46 @@ void HELPER(vwhist128qm)(CPUHexagonState *env, int32_t uiV)
 }
 
 #ifndef CONFIG_USER_ONLY
+void HELPER(ciad)(CPUHexagonState *env, uint32_t mask)
+{
+    g_assert_not_reached();
+}
+
+void HELPER(siad)(CPUHexagonState *env, uint32_t mask)
+{
+    g_assert_not_reached();
+}
+
+void HELPER(swi)(CPUHexagonState *env, uint32_t mask)
+{
+    g_assert_not_reached();
+}
+
+void HELPER(cswi)(CPUHexagonState *env, uint32_t mask)
+{
+    g_assert_not_reached();
+}
+
+void HELPER(iassignw)(CPUHexagonState *env, uint32_t src)
+{
+    g_assert_not_reached();
+}
+
+uint32_t HELPER(iassignr)(CPUHexagonState *env, uint32_t src)
+{
+    g_assert_not_reached();
+}
+
+uint32_t HELPER(getimask)(CPUHexagonState *env, uint32_t tid)
+{
+    g_assert_not_reached();
+}
+
+void HELPER(setimask)(CPUHexagonState *env, uint32_t tid, uint32_t imask)
+{
+    g_assert_not_reached();
+}
+
 void HELPER(sreg_write_masked)(CPUHexagonState *env, uint32_t reg, uint32_t val)
 {
     g_assert_not_reached();
-- 
2.34.1


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

* [PATCH v5 27/35] target/hexagon: Add TCG overrides for thread ctl
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (25 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 26/35] target/hexagon: Add TCG overrides for int handler insts Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 28/35] target/hexagon: Add TCG overrides for rte, nmi Brian Cain
                   ` (7 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Define TCG overrides for start, stop, wait, resume instructions.


Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/gen_tcg_sys.h | 18 ++++++++++++++++++
 target/hexagon/helper.h      |  4 ++++
 target/hexagon/op_helper.c   | 20 ++++++++++++++++++++
 3 files changed, 42 insertions(+)

diff --git a/target/hexagon/gen_tcg_sys.h b/target/hexagon/gen_tcg_sys.h
index cc72ca86db8..739e95ea60b 100644
--- a/target/hexagon/gen_tcg_sys.h
+++ b/target/hexagon/gen_tcg_sys.h
@@ -62,4 +62,22 @@
         tcg_gen_extrh_i64_i32(ctx->t_sreg_new_value[HEX_SREG_SGP1], tmp); \
     } while (0)
 
+#define fGEN_TCG_Y2_wait(SHORTCODE) \
+    do { \
+        RsV = RsV; \
+        gen_helper_wait(tcg_env, tcg_constant_tl(ctx->pkt->pc)); \
+    } while (0)
+
+#define fGEN_TCG_Y2_resume(SHORTCODE) \
+    gen_helper_resume(tcg_env, RsV)
+
+#define fGEN_TCG_Y2_start(SHORTCODE) \
+    gen_helper_start(tcg_env, RsV)
+
+#define fGEN_TCG_Y2_stop(SHORTCODE) \
+    do { \
+        RsV = RsV; \
+        gen_helper_stop(tcg_env); \
+    } while (0)
+
 #endif
diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h
index 955287133e4..682f0c6c26e 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -123,4 +123,8 @@ DEF_HELPER_2(greg_read, i32, env, i32)
 DEF_HELPER_2(greg_read_pair, i64, env, i32)
 DEF_HELPER_3(sreg_write_masked, void, env, i32, i32)
 DEF_HELPER_3(setprio, void, env, i32, i32)
+DEF_HELPER_2(start, void, env, i32)
+DEF_HELPER_1(stop, void, env)
+DEF_HELPER_2(wait, void, env, i32)
+DEF_HELPER_2(resume, void, env, i32)
 #endif
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index e81e89b8bd9..eac6a22fd64 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1420,6 +1420,26 @@ uint32_t HELPER(iassignr)(CPUHexagonState *env, uint32_t src)
     g_assert_not_reached();
 }
 
+void HELPER(start)(CPUHexagonState *env, uint32_t imask)
+{
+    g_assert_not_reached();
+}
+
+void HELPER(stop)(CPUHexagonState *env)
+{
+    g_assert_not_reached();
+}
+
+void HELPER(wait)(CPUHexagonState *env, target_ulong PC)
+{
+    g_assert_not_reached();
+}
+
+void HELPER(resume)(CPUHexagonState *env, uint32_t mask)
+{
+    g_assert_not_reached();
+}
+
 uint32_t HELPER(getimask)(CPUHexagonState *env, uint32_t tid)
 {
     g_assert_not_reached();
-- 
2.34.1


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

* [PATCH v5 28/35] target/hexagon: Add TCG overrides for rte, nmi
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (26 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 27/35] target/hexagon: Add TCG overrides for thread ctl Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 29/35] target/hexagon: Add sreg_{read,write} helpers Brian Cain
                   ` (6 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/gen_tcg_sys.h | 19 +++++++++++++++++++
 target/hexagon/helper.h      |  1 +
 target/hexagon/op_helper.c   |  4 ++++
 3 files changed, 24 insertions(+)

diff --git a/target/hexagon/gen_tcg_sys.h b/target/hexagon/gen_tcg_sys.h
index 739e95ea60b..04406db6a4b 100644
--- a/target/hexagon/gen_tcg_sys.h
+++ b/target/hexagon/gen_tcg_sys.h
@@ -80,4 +80,23 @@
         gen_helper_stop(tcg_env); \
     } while (0)
 
+/*
+ * rte (return from exception)
+ *     Clear the EX bit in SSR
+ *     Jump to ELR
+ */
+#define fGEN_TCG_J2_rte(SHORTCODE) \
+    do { \
+        TCGv_i32 new_ssr = tcg_temp_new_i32(); \
+        tcg_gen_deposit_tl(new_ssr, hex_t_sreg[HEX_SREG_SSR], \
+                           tcg_constant_tl(0), \
+                           reg_field_info[SSR_EX].offset, \
+                           reg_field_info[SSR_EX].width); \
+        gen_log_sreg_write(ctx, HEX_SREG_SSR, new_ssr); \
+        gen_jumpr(ctx, hex_t_sreg[HEX_SREG_ELR]); \
+    } while (0)
+
+#define fGEN_TCG_Y4_nmi(SHORTCODE) \
+    gen_helper_nmi(tcg_env, RsV)
+
 #endif
diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h
index 682f0c6c26e..9ca87acfe63 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -127,4 +127,5 @@ DEF_HELPER_2(start, void, env, i32)
 DEF_HELPER_1(stop, void, env)
 DEF_HELPER_2(wait, void, env, i32)
 DEF_HELPER_2(resume, void, env, i32)
+DEF_HELPER_2(nmi, void, env, i32)
 #endif
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index eac6a22fd64..af93be7a232 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1480,6 +1480,10 @@ void HELPER(setprio)(CPUHexagonState *env, uint32_t thread, uint32_t prio)
     g_assert_not_reached();
 }
 
+void HELPER(nmi)(CPUHexagonState *env, uint32_t thread_mask)
+{
+    g_assert_not_reached();
+}
 #endif
 
 
-- 
2.34.1


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

* [PATCH v5 29/35] target/hexagon: Add sreg_{read,write} helpers
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (27 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 28/35] target/hexagon: Add TCG overrides for rte, nmi Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-25 19:26   ` Philippe Mathieu-Daudé
  2026-03-11  3:49 ` [PATCH v5 30/35] target/hexagon: Add cpu modes, mmu indices, next_PC to state Brian Cain
                   ` (5 subsequent siblings)
  34 siblings, 1 reply; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain,
	Sid Manning

From: Brian Cain <bcain@quicinc.com>

Co-authored-by: Sid Manning <sidneym@quicinc.com>
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu.c        |  1 -
 target/hexagon/cpu_helper.c | 60 +++++++++++++++++++++++++++++++++++++
 target/hexagon/op_helper.c  | 30 +++++++++++++++++--
 3 files changed, 87 insertions(+), 4 deletions(-)
 create mode 100644 target/hexagon/cpu_helper.c

diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 38d605b06ba..dc3bd82bc05 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -339,7 +339,6 @@ static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
 
     qemu_init_vcpu(cs);
     cpu_reset(cs);
-
     mcc->parent_realize(dev, errp);
 }
 
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
new file mode 100644
index 00000000000..b8e0625e3f8
--- /dev/null
+++ b/target/hexagon/cpu_helper.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "cpu_helper.h"
+#include "system/cpus.h"
+#include "hw/core/boards.h"
+#include "hw/hexagon/hexagon.h"
+#include "exec/cpu-interrupt.h"
+#include "exec/target_page.h"
+#include "accel/tcg/cpu-ldst.h"
+#include "exec/cputlb.h"
+#include "qemu/log.h"
+#include "tcg/tcg-op.h"
+#include "internal.h"
+#include "macros.h"
+#include "sys_macros.h"
+#include "arch.h"
+
+
+uint32_t hexagon_get_pmu_counter(CPUHexagonState *cur_env, int index)
+{
+    g_assert_not_reached();
+}
+
+uint64_t hexagon_get_sys_pcycle_count(CPUHexagonState *env)
+{
+    g_assert_not_reached();
+}
+
+uint32_t hexagon_get_sys_pcycle_count_high(CPUHexagonState *env)
+{
+    g_assert_not_reached();
+}
+
+uint32_t hexagon_get_sys_pcycle_count_low(CPUHexagonState *env)
+{
+    g_assert_not_reached();
+}
+
+void hexagon_set_sys_pcycle_count_high(CPUHexagonState *env,
+        uint32_t cycles_hi)
+{
+    g_assert_not_reached();
+}
+
+void hexagon_set_sys_pcycle_count_low(CPUHexagonState *env,
+        uint32_t cycles_lo)
+{
+    g_assert_not_reached();
+}
+
+void hexagon_set_sys_pcycle_count(CPUHexagonState *env, uint64_t cycles)
+{
+    g_assert_not_reached();
+}
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index af93be7a232..3517f3768fd 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1452,17 +1452,41 @@ void HELPER(setimask)(CPUHexagonState *env, uint32_t tid, uint32_t imask)
 
 void HELPER(sreg_write_masked)(CPUHexagonState *env, uint32_t reg, uint32_t val)
 {
-    g_assert_not_reached();
+    BQL_LOCK_GUARD();
+    if (reg < HEX_SREG_GLB_START) {
+        env->t_sreg[reg] = val;
+    } else {
+        HexagonCPU *cpu = env_archcpu(env);
+        if (cpu->globalregs) {
+            hexagon_globalreg_write_masked(cpu->globalregs, reg, val);
+        }
+    }
+}
+
+static inline QEMU_ALWAYS_INLINE uint32_t sreg_read(CPUHexagonState *env,
+                                                    uint32_t reg)
+{
+    g_assert(bql_locked());
+    if (reg < HEX_SREG_GLB_START) {
+        return env->t_sreg[reg];
+    }
+    HexagonCPU *cpu = env_archcpu(env);
+    return cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, reg, env->threadId) : 0;
 }
 
 uint32_t HELPER(sreg_read)(CPUHexagonState *env, uint32_t reg)
 {
-    g_assert_not_reached();
+    BQL_LOCK_GUARD();
+    return sreg_read(env, reg);
 }
 
 uint64_t HELPER(sreg_read_pair)(CPUHexagonState *env, uint32_t reg)
 {
-    g_assert_not_reached();
+    BQL_LOCK_GUARD();
+
+    return deposit64((uint64_t) sreg_read(env, reg), 32, 32,
+        sreg_read(env, reg + 1));
 }
 
 uint32_t HELPER(greg_read)(CPUHexagonState *env, uint32_t reg)
-- 
2.34.1


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

* [PATCH v5 30/35] target/hexagon: Add cpu modes, mmu indices, next_PC to state
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (28 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 29/35] target/hexagon: Add sreg_{read,write} helpers Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 31/35] hw/hexagon: Introduce hexagon TLB device Brian Cain
                   ` (4 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu.h | 21 ++++++++++++++++++++-
 target/hexagon/cpu.c |  1 +
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 3562965c88a..9eb2d1bbabe 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -48,8 +48,26 @@
 #define VSTORES_MAX 2
 
 #define CPU_RESOLVING_TYPE TYPE_HEXAGON_CPU
+#ifndef CONFIG_USER_ONLY
+#define CPU_INTERRUPT_SWI      CPU_INTERRUPT_TGT_INT_0
+
+#define HEX_CPU_MODE_USER    1
+#define HEX_CPU_MODE_GUEST   2
+#define HEX_CPU_MODE_MONITOR 3
+
+#define HEX_EXE_MODE_OFF     1
+#define HEX_EXE_MODE_RUN     2
+#define HEX_EXE_MODE_WAIT    3
+#define HEX_EXE_MODE_DEBUG   4
+#endif
+
+#define MMU_USER_IDX         0
+#ifndef CONFIG_USER_ONLY
+#define MMU_GUEST_IDX        1
+#define MMU_KERNEL_IDX       2
+
+#endif
 
-#define MMU_USER_IDX 0
 
 #define HEXAGON_CPU_IRQ_0 0
 #define HEXAGON_CPU_IRQ_1 1
@@ -110,6 +128,7 @@ typedef struct CPUArchState {
     /* This alias of CPUState.cpu_index is used by imported sources: */
     uint32_t threadId;
 #endif
+    uint32_t next_PC;
     target_ulong new_value_usr;
 
     MemLog mem_log_stores[STORES_MAX];
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index dc3bd82bc05..b1317f83ef4 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -310,6 +310,7 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
     memset(env->t_sreg, 0, sizeof(uint32_t) * NUM_SREGS);
     memset(env->greg, 0, sizeof(uint32_t) * NUM_GREGS);
     env->wait_next_pc = 0;
+    env->next_PC = 0;
 #endif
     env->cause_code = HEX_EVENT_NONE;
 }
-- 
2.34.1


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

* [PATCH v5 31/35] hw/hexagon: Introduce hexagon TLB device
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (29 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 30/35] target/hexagon: Add cpu modes, mmu indices, next_PC to state Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-25 19:38   ` Philippe Mathieu-Daudé
  2026-03-11  3:49 ` [PATCH v5 32/35] target/hexagon: Add stubs for modify_ssr/get_exe_mode Brian Cain
                   ` (3 subsequent siblings)
  34 siblings, 1 reply; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo

Add the hexagon TLB QOM device model.

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
---
 include/hw/hexagon/hexagon_tlb.h |  45 +++
 target/hexagon/cpu.h             |   4 +
 hw/hexagon/hexagon_tlb.c         | 463 +++++++++++++++++++++++++++++++
 target/hexagon/cpu.c             |   5 +
 4 files changed, 517 insertions(+)
 create mode 100644 include/hw/hexagon/hexagon_tlb.h
 create mode 100644 hw/hexagon/hexagon_tlb.c

diff --git a/include/hw/hexagon/hexagon_tlb.h b/include/hw/hexagon/hexagon_tlb.h
new file mode 100644
index 00000000000..bcb387aa24d
--- /dev/null
+++ b/include/hw/hexagon/hexagon_tlb.h
@@ -0,0 +1,45 @@
+/*
+ * Hexagon TLB QOM Device
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_HEXAGON_TLB_H
+#define HW_HEXAGON_TLB_H
+
+#include "hw/core/sysbus.h"
+#include "qom/object.h"
+#include "exec/hwaddr.h"
+#include "exec/mmu-access-type.h"
+#define TYPE_HEXAGON_TLB "hexagon-tlb"
+OBJECT_DECLARE_SIMPLE_TYPE(HexagonTLBState, HEXAGON_TLB)
+
+struct HexagonTLBState {
+    SysBusDevice parent_obj;
+
+    uint32_t num_entries;
+    uint64_t *entries;
+};
+
+uint64_t hexagon_tlb_read(HexagonTLBState *tlb, uint32_t index);
+void hexagon_tlb_write(HexagonTLBState *tlb, uint32_t index, uint64_t value);
+
+bool hexagon_tlb_find_match(HexagonTLBState *tlb, uint32_t asid,
+                            uint32_t VA, MMUAccessType access_type,
+                            hwaddr *PA, int *prot, uint64_t *size,
+                            int32_t *excp, int *cause_code, int mmu_idx);
+
+uint32_t hexagon_tlb_lookup(HexagonTLBState *tlb, uint32_t asid,
+                            uint32_t VA, int *cause_code);
+
+int hexagon_tlb_check_overlap(HexagonTLBState *tlb, uint64_t entry,
+                              uint64_t index);
+
+void hexagon_tlb_dump(HexagonTLBState *tlb);
+
+bool hexagon_tlb_dump_entry(FILE *f, uint64_t entry);
+
+uint32_t hexagon_tlb_get_num_entries(HexagonTLBState *tlb);
+
+#endif /* HW_HEXAGON_TLB_H */
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 9eb2d1bbabe..e39e6e39fec 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -46,6 +46,7 @@
 #define REG_WRITES_MAX 32
 #define PRED_WRITES_MAX 5                   /* 4 insns + endloop */
 #define VSTORES_MAX 2
+#define MAX_TLB_ENTRIES 1024
 
 #define CPU_RESOLVING_TYPE TYPE_HEXAGON_CPU
 #ifndef CONFIG_USER_ONLY
@@ -174,6 +175,9 @@ struct ArchCPU {
     bool lldb_compat;
     target_ulong lldb_stack_adjust;
     bool short_circuit;
+#ifndef CONFIG_USER_ONLY
+    struct HexagonTLBState *tlb;
+#endif
 };
 
 #include "cpu_bits.h"
diff --git a/hw/hexagon/hexagon_tlb.c b/hw/hexagon/hexagon_tlb.c
new file mode 100644
index 00000000000..90f319f56d3
--- /dev/null
+++ b/hw/hexagon/hexagon_tlb.c
@@ -0,0 +1,463 @@
+/*
+ * Hexagon TLB QOM Device
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/hexagon/hexagon_tlb.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/core/resettable.h"
+#include "migration/vmstate.h"
+#include "qapi/error.h"
+#include "target/hexagon/cpu.h"
+#include "target/hexagon/cpu_bits.h"
+
+/* PTE (TLB entry) field extraction */
+#define GET_PTE_PPD(entry)   extract64((entry),  0, 24)
+#define GET_PTE_C(entry)     extract64((entry), 24,  4)
+#define GET_PTE_U(entry)     extract64((entry), 28,  1)
+#define GET_PTE_R(entry)     extract64((entry), 29,  1)
+#define GET_PTE_W(entry)     extract64((entry), 30,  1)
+#define GET_PTE_X(entry)     extract64((entry), 31,  1)
+#define GET_PTE_VPN(entry)   extract64((entry), 32, 20)
+#define GET_PTE_ASID(entry)  extract64((entry), 52,  7)
+#define GET_PTE_ATR0(entry)  extract64((entry), 59,  1)
+#define GET_PTE_ATR1(entry)  extract64((entry), 60,  1)
+#define GET_PTE_PA35(entry)  extract64((entry), 61,  1)
+#define GET_PTE_G(entry)     extract64((entry), 62,  1)
+#define GET_PTE_V(entry)     extract64((entry), 63,  1)
+
+/* PPD (physical page descriptor) */
+static inline uint64_t GET_PPD(uint64_t entry)
+{
+    return GET_PTE_PPD(entry) | (GET_PTE_PA35(entry) << 24);
+}
+
+#define NO_ASID      (1 << 8)
+
+typedef enum {
+    PGSIZE_4K,
+    PGSIZE_16K,
+    PGSIZE_64K,
+    PGSIZE_256K,
+    PGSIZE_1M,
+    PGSIZE_4M,
+    PGSIZE_16M,
+    PGSIZE_64M,
+    PGSIZE_256M,
+    PGSIZE_1G,
+    NUM_PGSIZE_TYPES
+} tlb_pgsize_t;
+
+static const char *pgsize_str[NUM_PGSIZE_TYPES] = {
+    "4K",
+    "16K",
+    "64K",
+    "256K",
+    "1M",
+    "4M",
+    "16M",
+    "64M",
+    "256M",
+    "1G",
+};
+
+#define INVALID_MASK 0xffffffffLL
+
+static const uint64_t encmask_2_mask[] = {
+    0x0fffLL,                           /* 4k,   0000 */
+    0x3fffLL,                           /* 16k,  0001 */
+    0xffffLL,                           /* 64k,  0010 */
+    0x3ffffLL,                          /* 256k, 0011 */
+    0xfffffLL,                          /* 1m,   0100 */
+    0x3fffffLL,                         /* 4m,   0101 */
+    0xffffffLL,                         /* 16m,  0110 */
+    0x3ffffffLL,                        /* 64m,  0111 */
+    0xfffffffLL,                        /* 256m, 1000 */
+    0x3fffffffLL,                       /* 1g,   1001 */
+    INVALID_MASK,                       /* RSVD, 0111 */
+};
+
+static inline tlb_pgsize_t hex_tlb_pgsize_type(uint64_t entry)
+{
+    if (entry == 0) {
+        qemu_log_mask(CPU_LOG_MMU, "%s: Supplied TLB entry was 0!\n",
+                      __func__);
+        return 0;
+    }
+    tlb_pgsize_t size = ctz64(entry);
+    g_assert(size < NUM_PGSIZE_TYPES);
+    return size;
+}
+
+static inline uint64_t hex_tlb_page_size_bytes(uint64_t entry)
+{
+    return 1ull << (TARGET_PAGE_BITS + 2 * hex_tlb_pgsize_type(entry));
+}
+
+static inline uint64_t hex_tlb_phys_page_num(uint64_t entry)
+{
+    uint32_t ppd = GET_PPD(entry);
+    return ppd >> 1;
+}
+
+static inline uint64_t hex_tlb_phys_addr(uint64_t entry)
+{
+    uint64_t pagemask = encmask_2_mask[hex_tlb_pgsize_type(entry)];
+    uint64_t pagenum = hex_tlb_phys_page_num(entry);
+    uint64_t PA = (pagenum << TARGET_PAGE_BITS) & (~pagemask);
+    return PA;
+}
+
+static inline uint64_t hex_tlb_virt_addr(uint64_t entry)
+{
+    return (uint64_t)GET_PTE_VPN(entry) << TARGET_PAGE_BITS;
+}
+
+bool hexagon_tlb_dump_entry(FILE *f, uint64_t entry)
+{
+    if (GET_PTE_V(entry)) {
+        fprintf(f, "0x%016" PRIx64 ": ", entry);
+        uint64_t PA = hex_tlb_phys_addr(entry);
+        uint64_t VA = hex_tlb_virt_addr(entry);
+        fprintf(f, "V:%" PRId64 " G:%" PRId64
+                " A1:%" PRId64 " A0:%" PRId64,
+                GET_PTE_V(entry),
+                GET_PTE_G(entry),
+                GET_PTE_ATR1(entry),
+                GET_PTE_ATR0(entry));
+        fprintf(f, " ASID:0x%02" PRIx64 " VA:0x%08" PRIx64,
+                GET_PTE_ASID(entry), VA);
+        fprintf(f,
+                " X:%" PRId64 " W:%" PRId64 " R:%" PRId64
+                " U:%" PRId64 " C:%" PRId64,
+                GET_PTE_X(entry),
+                GET_PTE_W(entry),
+                GET_PTE_R(entry),
+                GET_PTE_U(entry),
+                GET_PTE_C(entry));
+        fprintf(f, " PA:0x%09" PRIx64 " SZ:%s (0x%" PRIx64 ")", PA,
+                pgsize_str[hex_tlb_pgsize_type(entry)],
+                hex_tlb_page_size_bytes(entry));
+        fprintf(f, "\n");
+        return true;
+    }
+
+    /* Not valid */
+    return false;
+}
+
+static inline bool hex_tlb_entry_match_noperm(uint64_t entry, uint32_t asid,
+                                              uint64_t VA)
+{
+    if (GET_PTE_V(entry)) {
+        if (GET_PTE_G(entry)) {
+            /* Global entry - ignore ASID */
+        } else if (asid != NO_ASID) {
+            uint32_t tlb_asid = GET_PTE_ASID(entry);
+            if (tlb_asid != asid) {
+                return false;
+            }
+        }
+
+        uint64_t page_size = hex_tlb_page_size_bytes(entry);
+        uint64_t page_start =
+            ROUND_DOWN(hex_tlb_virt_addr(entry), page_size);
+        if (page_start <= VA && VA < page_start + page_size) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static inline void hex_tlb_entry_get_perm(uint64_t entry,
+                                          MMUAccessType access_type,
+                                          int mmu_idx, int *prot,
+                                          int32_t *excp, int *cause_code)
+{
+    bool perm_x = GET_PTE_X(entry);
+    bool perm_w = GET_PTE_W(entry);
+    bool perm_r = GET_PTE_R(entry);
+    bool perm_u = GET_PTE_U(entry);
+    bool user_idx = mmu_idx == MMU_USER_IDX;
+
+    if (mmu_idx == MMU_KERNEL_IDX) {
+        *prot = PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+        return;
+    }
+
+    *prot = PAGE_VALID;
+    switch (access_type) {
+    case MMU_INST_FETCH:
+        if (user_idx && !perm_u) {
+            *excp = HEX_EVENT_PRECISE;
+            *cause_code = HEX_CAUSE_FETCH_NO_UPAGE;
+        } else if (!perm_x) {
+            *excp = HEX_EVENT_PRECISE;
+            *cause_code = HEX_CAUSE_FETCH_NO_XPAGE;
+        }
+        break;
+    case MMU_DATA_LOAD:
+        if (user_idx && !perm_u) {
+            *excp = HEX_EVENT_PRECISE;
+            *cause_code = HEX_CAUSE_PRIV_NO_UREAD;
+        } else if (!perm_r) {
+            *excp = HEX_EVENT_PRECISE;
+            *cause_code = HEX_CAUSE_PRIV_NO_READ;
+        }
+        break;
+    case MMU_DATA_STORE:
+        if (user_idx && !perm_u) {
+            *excp = HEX_EVENT_PRECISE;
+            *cause_code = HEX_CAUSE_PRIV_NO_UWRITE;
+        } else if (!perm_w) {
+            *excp = HEX_EVENT_PRECISE;
+            *cause_code = HEX_CAUSE_PRIV_NO_WRITE;
+        }
+        break;
+    }
+
+    if (!user_idx || perm_u) {
+        if (perm_x) {
+            *prot |= PAGE_EXEC;
+        }
+        if (perm_r) {
+            *prot |= PAGE_READ;
+        }
+        if (perm_w) {
+            *prot |= PAGE_WRITE;
+        }
+    }
+}
+
+static inline bool hex_tlb_entry_match(uint64_t entry, uint8_t asid,
+                                       uint32_t VA,
+                                       MMUAccessType access_type, hwaddr *PA,
+                                       int *prot, uint64_t *size,
+                                       int32_t *excp, int *cause_code,
+                                       int mmu_idx)
+{
+    if (hex_tlb_entry_match_noperm(entry, asid, VA)) {
+        hex_tlb_entry_get_perm(entry, access_type, mmu_idx, prot, excp,
+                               cause_code);
+        *PA = hex_tlb_phys_addr(entry);
+        *size = hex_tlb_page_size_bytes(entry);
+        return true;
+    }
+    return false;
+}
+
+static bool hex_tlb_is_match(uint64_t entry1, uint64_t entry2,
+                             bool consider_gbit)
+{
+    bool valid1 = GET_PTE_V(entry1);
+    bool valid2 = GET_PTE_V(entry2);
+    uint64_t size1 = hex_tlb_page_size_bytes(entry1);
+    uint64_t vaddr1 = ROUND_DOWN(hex_tlb_virt_addr(entry1), size1);
+    uint64_t size2 = hex_tlb_page_size_bytes(entry2);
+    uint64_t vaddr2 = ROUND_DOWN(hex_tlb_virt_addr(entry2), size2);
+    int asid1 = GET_PTE_ASID(entry1);
+    int asid2 = GET_PTE_ASID(entry2);
+    bool gbit1 = GET_PTE_G(entry1);
+    bool gbit2 = GET_PTE_G(entry2);
+
+    if (!valid1 || !valid2) {
+        return false;
+    }
+
+    if (((vaddr1 <= vaddr2) && (vaddr2 < (vaddr1 + size1))) ||
+        ((vaddr2 <= vaddr1) && (vaddr1 < (vaddr2 + size2)))) {
+        if (asid1 == asid2) {
+            return true;
+        }
+        if ((consider_gbit && gbit1) || gbit2) {
+            return true;
+        }
+    }
+    return false;
+}
+
+/* Public API */
+
+uint64_t hexagon_tlb_read(HexagonTLBState *tlb, uint32_t index)
+{
+    g_assert(index < tlb->num_entries);
+    return tlb->entries[index];
+}
+
+void hexagon_tlb_write(HexagonTLBState *tlb, uint32_t index, uint64_t value)
+{
+    g_assert(index < tlb->num_entries);
+    tlb->entries[index] = value;
+}
+
+bool hexagon_tlb_find_match(HexagonTLBState *tlb, uint32_t asid,
+                            uint32_t VA, MMUAccessType access_type,
+                            hwaddr *PA, int *prot, uint64_t *size,
+                            int32_t *excp, int *cause_code, int mmu_idx)
+{
+    *PA = 0;
+    *prot = 0;
+    *size = 0;
+    *excp = 0;
+    *cause_code = 0;
+
+    for (uint32_t i = 0; i < tlb->num_entries; i++) {
+        if (hex_tlb_entry_match(tlb->entries[i], asid, VA, access_type,
+                                PA, prot, size, excp, cause_code, mmu_idx)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+uint32_t hexagon_tlb_lookup(HexagonTLBState *tlb, uint32_t asid,
+                            uint32_t VA, int *cause_code)
+{
+    uint32_t not_found = 0x80000000;
+    uint32_t idx = not_found;
+
+    for (uint32_t i = 0; i < tlb->num_entries; i++) {
+        uint64_t entry = tlb->entries[i];
+        if (hex_tlb_entry_match_noperm(entry, asid, VA)) {
+            if (idx != not_found) {
+                *cause_code = HEX_CAUSE_IMPRECISE_MULTI_TLB_MATCH;
+                break;
+            }
+            idx = i;
+        }
+    }
+
+    if (idx == not_found) {
+        qemu_log_mask(CPU_LOG_MMU,
+                      "%s: 0x%" PRIx32 ", 0x%08" PRIx32 " => NOT FOUND\n",
+                      __func__, asid, VA);
+    } else {
+        qemu_log_mask(CPU_LOG_MMU,
+                      "%s: 0x%" PRIx32 ", 0x%08" PRIx32 " => %d\n",
+                      __func__, asid, VA, idx);
+    }
+
+    return idx;
+}
+
+/*
+ * Return codes:
+ * 0 or positive             index of match
+ * -1                        multiple matches
+ * -2                        no match
+ */
+int hexagon_tlb_check_overlap(HexagonTLBState *tlb, uint64_t entry,
+                              uint64_t index)
+{
+    int matches = 0;
+    int last_match = 0;
+
+    for (uint32_t i = 0; i < tlb->num_entries; i++) {
+        if (hex_tlb_is_match(entry, tlb->entries[i], false)) {
+            matches++;
+            last_match = i;
+        }
+    }
+
+    if (matches == 1) {
+        return last_match;
+    }
+    if (matches == 0) {
+        return -2;
+    }
+    return -1;
+}
+
+void hexagon_tlb_dump(HexagonTLBState *tlb)
+{
+    for (uint32_t i = 0; i < tlb->num_entries; i++) {
+        hexagon_tlb_dump_entry(stdout, tlb->entries[i]);
+    }
+}
+
+uint32_t hexagon_tlb_get_num_entries(HexagonTLBState *tlb)
+{
+    return tlb->num_entries;
+}
+
+/* QOM lifecycle */
+
+static void hexagon_tlb_init(Object *obj)
+{
+}
+
+static void hexagon_tlb_realize(DeviceState *dev, Error **errp)
+{
+    HexagonTLBState *s = HEXAGON_TLB(dev);
+
+    if (s->num_entries == 0 || s->num_entries > MAX_TLB_ENTRIES) {
+        error_setg(errp, "Invalid TLB num-entries: %" PRIu32,
+                   s->num_entries);
+        return;
+    }
+    s->entries = g_new0(uint64_t, s->num_entries);
+}
+
+static void hexagon_tlb_finalize(Object *obj)
+{
+    HexagonTLBState *s = HEXAGON_TLB(obj);
+    g_free(s->entries);
+    s->entries = NULL;
+}
+
+static void hexagon_tlb_reset_hold(Object *obj, ResetType type)
+{
+    HexagonTLBState *s = HEXAGON_TLB(obj);
+    if (s->entries) {
+        memset(s->entries, 0, sizeof(uint64_t) * s->num_entries);
+    }
+}
+
+static const VMStateDescription vmstate_hexagon_tlb = {
+    .name = "hexagon-tlb",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT32(num_entries, HexagonTLBState),
+        VMSTATE_VARRAY_UINT32_ALLOC(entries, HexagonTLBState, num_entries,
+                                    0, vmstate_info_uint64, uint64_t),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static const Property hexagon_tlb_properties[] = {
+    DEFINE_PROP_UINT32("num-entries", HexagonTLBState, num_entries,
+                       MAX_TLB_ENTRIES),
+};
+
+static void hexagon_tlb_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    dc->realize = hexagon_tlb_realize;
+    rc->phases.hold = hexagon_tlb_reset_hold;
+    dc->vmsd = &vmstate_hexagon_tlb;
+    dc->user_creatable = false;
+    device_class_set_props(dc, hexagon_tlb_properties);
+}
+
+static const TypeInfo hexagon_tlb_info = {
+    .name = TYPE_HEXAGON_TLB,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(HexagonTLBState),
+    .instance_init = hexagon_tlb_init,
+    .instance_finalize = hexagon_tlb_finalize,
+    .class_init = hexagon_tlb_class_init,
+};
+
+static void hexagon_tlb_register_types(void)
+{
+    type_register_static(&hexagon_tlb_info);
+}
+
+type_init(hexagon_tlb_register_types)
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index b1317f83ef4..32d158684a0 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -23,6 +23,7 @@
 #include "qapi/error.h"
 #include "hw/core/qdev-properties.h"
 #include "fpu/softfloat-helpers.h"
+#include "hw/hexagon/hexagon_tlb.h"
 #include "tcg/tcg.h"
 #include "exec/gdbstub.h"
 #include "accel/tcg/cpu-ops.h"
@@ -50,6 +51,10 @@ static ObjectClass *hexagon_cpu_class_by_name(const char *cpu_model)
 }
 
 static const Property hexagon_cpu_properties[] = {
+#if !defined(CONFIG_USER_ONLY)
+    DEFINE_PROP_LINK("tlb", HexagonCPU, tlb, TYPE_HEXAGON_TLB,
+                     HexagonTLBState *),
+#endif
     DEFINE_PROP_BOOL("lldb-compat", HexagonCPU, lldb_compat, false),
     DEFINE_PROP_UNSIGNED("lldb-stack-adjust", HexagonCPU, lldb_stack_adjust, 0,
                          qdev_prop_uint32, target_ulong),
-- 
2.34.1


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

* [PATCH v5 32/35] target/hexagon: Add stubs for modify_ssr/get_exe_mode
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (30 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 31/35] hw/hexagon: Introduce hexagon TLB device Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 33/35] target/hexagon: Add clear_wait_mode() definition Brian Cain
                   ` (2 subsequent siblings)
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo

Add hex_mmu.[ch], cpu mode helpers, and additional includes/stubs
that integrate the TLB device with the CPU model.

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu-param.h  |   4 +
 target/hexagon/cpu.h        |  17 +++
 target/hexagon/cpu_helper.h |   2 +
 target/hexagon/hex_mmu.h    |  25 ++++
 target/hexagon/internal.h   |   9 ++
 target/hexagon/sys_macros.h |   3 +
 target/hexagon/cpu.c        |  25 ++++
 target/hexagon/cpu_helper.c |  10 ++
 target/hexagon/hex_mmu.c    | 277 ++++++++++++++++++++++++++++++++++++
 target/hexagon/translate.c  |   2 +-
 10 files changed, 373 insertions(+), 1 deletion(-)
 create mode 100644 target/hexagon/hex_mmu.h
 create mode 100644 target/hexagon/hex_mmu.c

diff --git a/target/hexagon/cpu-param.h b/target/hexagon/cpu-param.h
index 1f0f22a7968..9eae7d2361c 100644
--- a/target/hexagon/cpu-param.h
+++ b/target/hexagon/cpu-param.h
@@ -18,7 +18,11 @@
 #ifndef HEXAGON_CPU_PARAM_H
 #define HEXAGON_CPU_PARAM_H
 
+#ifdef CONFIG_USER_ONLY
 #define TARGET_PAGE_BITS 16     /* 64K pages */
+#else
+#define TARGET_PAGE_BITS 12     /* 4K pages */
+#endif
 
 #define TARGET_VIRT_ADDR_SPACE_BITS 32
 
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index e39e6e39fec..d8092cb6fe7 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -38,6 +38,9 @@
 #error "Hexagon does not support system emulation"
 #endif
 
+#ifndef CONFIG_USER_ONLY
+#endif
+
 #define NUM_PREGS 4
 #define TOTAL_PER_THREAD_REGS 64
 
@@ -51,6 +54,8 @@
 #define CPU_RESOLVING_TYPE TYPE_HEXAGON_CPU
 #ifndef CONFIG_USER_ONLY
 #define CPU_INTERRUPT_SWI      CPU_INTERRUPT_TGT_INT_0
+#define CPU_INTERRUPT_K0_UNLOCK CPU_INTERRUPT_TGT_INT_1
+#define CPU_INTERRUPT_TLB_UNLOCK CPU_INTERRUPT_TGT_INT_2
 
 #define HEX_CPU_MODE_USER    1
 #define HEX_CPU_MODE_GUEST   2
@@ -67,6 +72,12 @@
 #define MMU_GUEST_IDX        1
 #define MMU_KERNEL_IDX       2
 
+typedef enum {
+    HEX_LOCK_UNLOCKED       = 0,
+    HEX_LOCK_WAITING        = 1,
+    HEX_LOCK_OWNER          = 2,
+    HEX_LOCK_QUEUED        = 3
+} hex_lock_state_t;
 #endif
 
 
@@ -128,6 +139,10 @@ typedef struct CPUArchState {
 
     /* This alias of CPUState.cpu_index is used by imported sources: */
     uint32_t threadId;
+    hex_lock_state_t tlb_lock_state;
+    hex_lock_state_t k0_lock_state;
+    uint32_t tlb_lock_count;
+    uint32_t k0_lock_count;
 #endif
     uint32_t next_PC;
     target_ulong new_value_usr;
@@ -177,12 +192,14 @@ struct ArchCPU {
     bool short_circuit;
 #ifndef CONFIG_USER_ONLY
     struct HexagonTLBState *tlb;
+    uint32_t htid;
 #endif
 };
 
 #include "cpu_bits.h"
 
 FIELD(TB_FLAGS, IS_TIGHT_LOOP, 0, 1)
+FIELD(TB_FLAGS, MMU_INDEX, 1, 3)
 
 G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
                                             uint32_t exception,
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index 1486a03c64a..18300657f3d 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -14,5 +14,7 @@ uint32_t hexagon_get_sys_pcycle_count_high(CPUHexagonState *env);
 void hexagon_set_sys_pcycle_count(CPUHexagonState *env, uint64_t);
 void hexagon_set_sys_pcycle_count_low(CPUHexagonState *env, uint32_t);
 void hexagon_set_sys_pcycle_count_high(CPUHexagonState *env, uint32_t);
+void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old);
+int get_exe_mode(CPUHexagonState *env);
 
 #endif
diff --git a/target/hexagon/hex_mmu.h b/target/hexagon/hex_mmu.h
new file mode 100644
index 00000000000..99ddb3736a2
--- /dev/null
+++ b/target/hexagon/hex_mmu.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HEXAGON_MMU_H
+#define HEXAGON_MMU_H
+
+#include "cpu.h"
+
+extern void hex_tlbw(CPUHexagonState *env, uint32_t index, uint64_t value);
+extern uint32_t hex_tlb_lookup(CPUHexagonState *env, uint32_t ssr, uint32_t VA);
+extern void hex_mmu_on(CPUHexagonState *env);
+extern void hex_mmu_off(CPUHexagonState *env);
+extern void hex_mmu_mode_change(CPUHexagonState *env);
+extern bool hex_tlb_find_match(CPUHexagonState *env, uint32_t VA,
+                               MMUAccessType access_type, hwaddr *PA, int *prot,
+                               uint64_t *size, int32_t *excp, int mmu_idx);
+extern int hex_tlb_check_overlap(CPUHexagonState *env, uint64_t entry,
+                                 uint64_t index);
+extern void hex_tlb_lock(CPUHexagonState *env);
+extern void hex_tlb_unlock(CPUHexagonState *env);
+void dump_mmu(CPUHexagonState *env);
+#endif
diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index 33d73ed18d1..4338914efb5 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -36,6 +36,15 @@ void G_NORETURN do_raise_exception(CPUHexagonState *env,
         uint32_t PC,
         uintptr_t retaddr);
 
+#define hexagon_cpu_mmu_enabled(env) ({ \
+    HexagonCPU *cpu = env_archcpu(env); \
+    cpu->globalregs ? \
+        GET_SYSCFG_FIELD(SYSCFG_MMUEN, \
+            hexagon_globalreg_read(cpu->globalregs, \
+                                   HEX_SREG_SYSCFG, (env)->threadId)) : \
+        0; \
+})
+
 #ifndef CONFIG_USER_ONLY
 extern const VMStateDescription vmstate_hexagon_cpu;
 #endif
diff --git a/target/hexagon/sys_macros.h b/target/hexagon/sys_macros.h
index f497d55bb81..364fcde7383 100644
--- a/target/hexagon/sys_macros.h
+++ b/target/hexagon/sys_macros.h
@@ -139,6 +139,9 @@
 #define fDCINVIDX(REG)
 #define fDCINVA(REG) do { REG = REG; } while (0) /* Nothing to do in qemu */
 
+#define fSET_TLB_LOCK()       hex_tlb_lock(env);
+#define fCLEAR_TLB_LOCK()     hex_tlb_unlock(env);
+
 #define fTLB_IDXMASK(INDEX) \
     ((INDEX) & (fPOW2_ROUNDUP( \
         fCAST4u(hexagon_tlb_get_num_entries(env_archcpu(env)->tlb))) - 1))
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 32d158684a0..5c937fa1cd1 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -27,6 +27,13 @@
 #include "tcg/tcg.h"
 #include "exec/gdbstub.h"
 #include "accel/tcg/cpu-ops.h"
+#include "cpu_helper.h"
+#include "hex_mmu.h"
+
+#ifndef CONFIG_USER_ONLY
+#include "sys_macros.h"
+#include "accel/tcg/cpu-ldst.h"
+#endif
 
 static void hexagon_v66_cpu_init(Object *obj) { }
 static void hexagon_v67_cpu_init(Object *obj) { }
@@ -54,6 +61,7 @@ static const Property hexagon_cpu_properties[] = {
 #if !defined(CONFIG_USER_ONLY)
     DEFINE_PROP_LINK("tlb", HexagonCPU, tlb, TYPE_HEXAGON_TLB,
                      HexagonTLBState *),
+    DEFINE_PROP_UINT32("htid", HexagonCPU, htid, 0),
 #endif
     DEFINE_PROP_BOOL("lldb-compat", HexagonCPU, lldb_compat, false),
     DEFINE_PROP_UNSIGNED("lldb-stack-adjust", HexagonCPU, lldb_stack_adjust, 0,
@@ -280,6 +288,13 @@ static TCGTBCPUState hexagon_get_tb_cpu_state(CPUState *cs)
         hexagon_raise_exception_err(env, HEX_CAUSE_PC_NOT_ALIGNED, 0);
     }
 
+#ifndef CONFIG_USER_ONLY
+    hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, MMU_INDEX,
+                           cpu_mmu_index(env_cpu(env), false));
+#else
+    hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, MMU_INDEX, MMU_USER_IDX);
+#endif
+
     return (TCGTBCPUState){ .pc = pc, .flags = hex_flags };
 }
 
@@ -297,6 +312,7 @@ static void hexagon_restore_state_to_opc(CPUState *cs,
     cpu_env(cs)->gpr[HEX_REG_PC] = data[0];
 }
 
+
 static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
 {
     CPUState *cs = CPU(obj);
@@ -315,7 +331,15 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
     memset(env->t_sreg, 0, sizeof(uint32_t) * NUM_SREGS);
     memset(env->greg, 0, sizeof(uint32_t) * NUM_GREGS);
     env->wait_next_pc = 0;
+    env->tlb_lock_state = HEX_LOCK_UNLOCKED;
+    env->k0_lock_state = HEX_LOCK_UNLOCKED;
+    env->tlb_lock_count = 0;
+    env->k0_lock_count = 0;
     env->next_PC = 0;
+
+    HexagonCPU *cpu = HEXAGON_CPU(cs);
+    env->t_sreg[HEX_SREG_HTID] = cpu->htid;
+    env->threadId = cpu->htid;
 #endif
     env->cause_code = HEX_EVENT_NONE;
 }
@@ -344,6 +368,7 @@ static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
                              gdb_find_static_feature("hexagon-hvx.xml"), 0);
 
     qemu_init_vcpu(cs);
+
     cpu_reset(cs);
     mcc->parent_realize(dev, errp);
 }
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index b8e0625e3f8..b6a8bd35309 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -58,3 +58,13 @@ void hexagon_set_sys_pcycle_count(CPUHexagonState *env, uint64_t cycles)
 {
     g_assert_not_reached();
 }
+
+void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old)
+{
+    g_assert_not_reached();
+}
+
+int get_exe_mode(CPUHexagonState *env)
+{
+    g_assert_not_reached();
+}
diff --git a/target/hexagon/hex_mmu.c b/target/hexagon/hex_mmu.c
new file mode 100644
index 00000000000..1cdc92fdc31
--- /dev/null
+++ b/target/hexagon/hex_mmu.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/main-loop.h"
+#include "qemu/qemu-print.h"
+#include "cpu.h"
+#include "system/cpus.h"
+#include "internal.h"
+#include "exec/cpu-interrupt.h"
+#include "cpu_helper.h"
+#include "exec/cputlb.h"
+#include "hex_mmu.h"
+#include "macros.h"
+#include "sys_macros.h"
+#include "hw/hexagon/hexagon_tlb.h"
+#include "hw/hexagon/hexagon_globalreg.h"
+
+static inline void hex_log_tlbw(uint32_t index, uint64_t entry)
+{
+    if (qemu_loglevel_mask(CPU_LOG_MMU)) {
+        if (qemu_log_enabled()) {
+            FILE *logfile = qemu_log_trylock();
+            if (logfile) {
+                fprintf(logfile, "tlbw[%03d]: ", index);
+                if (!hexagon_tlb_dump_entry(logfile, entry)) {
+                    fprintf(logfile, "invalid\n");
+                }
+                qemu_log_unlock(logfile);
+            }
+        }
+    }
+}
+
+void hex_tlbw(CPUHexagonState *env, uint32_t index, uint64_t value)
+{
+    uint32_t myidx = fTLB_NONPOW2WRAP(fTLB_IDXMASK(index));
+    HexagonTLBState *tlb = env_archcpu(env)->tlb;
+    uint64_t old_entry = hexagon_tlb_read(tlb, myidx);
+
+    bool old_entry_valid = extract64(old_entry, 63, 1);
+    if (old_entry_valid && hexagon_cpu_mmu_enabled(env)) {
+        CPUState *cs = env_cpu(env);
+        tlb_flush(cs);
+    }
+    hexagon_tlb_write(tlb, myidx, value);
+    hex_log_tlbw(myidx, value);
+}
+
+void hex_mmu_on(CPUHexagonState *env)
+{
+    CPUState *cs = env_cpu(env);
+    qemu_log_mask(CPU_LOG_MMU, "Hexagon MMU turned on!\n");
+    tlb_flush(cs);
+}
+
+void hex_mmu_off(CPUHexagonState *env)
+{
+    CPUState *cs = env_cpu(env);
+    qemu_log_mask(CPU_LOG_MMU, "Hexagon MMU turned off!\n");
+    tlb_flush(cs);
+}
+
+void hex_mmu_mode_change(CPUHexagonState *env)
+{
+    qemu_log_mask(CPU_LOG_MMU, "Hexagon mode change!\n");
+    CPUState *cs = env_cpu(env);
+    tlb_flush(cs);
+}
+
+bool hex_tlb_find_match(CPUHexagonState *env, uint32_t VA,
+                        MMUAccessType access_type, hwaddr *PA, int *prot,
+                        uint64_t *size, int32_t *excp, int mmu_idx)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t ssr = env->t_sreg[HEX_SREG_SSR];
+    uint8_t asid = GET_SSR_FIELD(SSR_ASID, ssr);
+    int cause_code = 0;
+
+    bool found = hexagon_tlb_find_match(cpu->tlb, asid, VA, access_type,
+                                        PA, prot, size, excp, &cause_code,
+                                        mmu_idx);
+    if (cause_code) {
+        env->cause_code = cause_code;
+    }
+    return found;
+}
+
+/* Called from tlbp instruction */
+uint32_t hex_tlb_lookup(CPUHexagonState *env, uint32_t ssr, uint32_t VA)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    uint8_t asid = GET_SSR_FIELD(SSR_ASID, ssr);
+    int cause_code = 0;
+
+    uint32_t result = hexagon_tlb_lookup(cpu->tlb, asid, VA, &cause_code);
+    if (cause_code) {
+        env->cause_code = cause_code;
+    }
+    return result;
+}
+
+/*
+ * Return codes:
+ * 0 or positive             index of match
+ * -1                        multiple matches
+ * -2                        no match
+ */
+int hex_tlb_check_overlap(CPUHexagonState *env, uint64_t entry, uint64_t index)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    return hexagon_tlb_check_overlap(cpu->tlb, entry, index);
+}
+
+void dump_mmu(CPUHexagonState *env)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    hexagon_tlb_dump(cpu->tlb);
+}
+
+static inline void print_thread(const char *str, CPUState *cs)
+{
+    g_assert(bql_locked());
+    CPUHexagonState *thread = cpu_env(cs);
+    bool is_stopped = cpu_is_stopped(cs);
+    int exe_mode = get_exe_mode(thread);
+    hex_lock_state_t lock_state = thread->tlb_lock_state;
+    qemu_log_mask(CPU_LOG_MMU,
+           "%s: threadId = %d: %s, exe_mode = %s, tlb_lock_state = %s\n",
+           str,
+           thread->threadId,
+           is_stopped ? "stopped" : "running",
+           exe_mode == HEX_EXE_MODE_OFF ? "off" :
+           exe_mode == HEX_EXE_MODE_RUN ? "run" :
+           exe_mode == HEX_EXE_MODE_WAIT ? "wait" :
+           exe_mode == HEX_EXE_MODE_DEBUG ? "debug" :
+           "unknown",
+           lock_state == HEX_LOCK_UNLOCKED ? "unlocked" :
+           lock_state == HEX_LOCK_WAITING ? "waiting" :
+           lock_state == HEX_LOCK_OWNER ? "owner" :
+           "unknown");
+}
+
+static inline void print_thread_states(const char *str)
+{
+    CPUState *cs;
+    CPU_FOREACH(cs) {
+        print_thread(str, cs);
+    }
+}
+
+void hex_tlb_lock(CPUHexagonState *env)
+{
+    qemu_log_mask(CPU_LOG_MMU, "hex_tlb_lock: " TARGET_FMT_ld "\n",
+                  env->threadId);
+    BQL_LOCK_GUARD();
+    g_assert((env->tlb_lock_count == 0) || (env->tlb_lock_count == 1));
+
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t syscfg = cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SYSCFG,
+                               env->threadId) : 0;
+    uint8_t tlb_lock = GET_SYSCFG_FIELD(SYSCFG_TLBLOCK, syscfg);
+    if (tlb_lock) {
+        if (env->tlb_lock_state == HEX_LOCK_QUEUED) {
+            env->next_PC += 4;
+            env->tlb_lock_count++;
+            env->tlb_lock_state = HEX_LOCK_OWNER;
+            SET_SYSCFG_FIELD(env, SYSCFG_TLBLOCK, 1);
+            return;
+        }
+        if (env->tlb_lock_state == HEX_LOCK_OWNER) {
+            qemu_log_mask(CPU_LOG_MMU | LOG_GUEST_ERROR,
+                          "Double tlblock at PC: 0x%x, thread may hang\n",
+                          env->next_PC);
+            env->next_PC += 4;
+            CPUState *cs = env_cpu(env);
+            cpu_interrupt(cs, CPU_INTERRUPT_HALT);
+            return;
+        }
+        env->tlb_lock_state = HEX_LOCK_WAITING;
+        CPUState *cs = env_cpu(env);
+        cpu_interrupt(cs, CPU_INTERRUPT_HALT);
+    } else {
+        env->next_PC += 4;
+        env->tlb_lock_count++;
+        env->tlb_lock_state = HEX_LOCK_OWNER;
+        SET_SYSCFG_FIELD(env, SYSCFG_TLBLOCK, 1);
+    }
+
+    if (qemu_loglevel_mask(CPU_LOG_MMU)) {
+        qemu_log_mask(CPU_LOG_MMU, "Threads after hex_tlb_lock:\n");
+        print_thread_states("\tThread");
+    }
+}
+
+void hex_tlb_unlock(CPUHexagonState *env)
+{
+    BQL_LOCK_GUARD();
+    g_assert((env->tlb_lock_count == 0) || (env->tlb_lock_count == 1));
+
+    /* Nothing to do if the TLB isn't locked by this thread */
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t syscfg = cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SYSCFG,
+                               env->threadId) : 0;
+    uint8_t tlb_lock = GET_SYSCFG_FIELD(SYSCFG_TLBLOCK, syscfg);
+    if ((tlb_lock == 0) ||
+        (env->tlb_lock_state != HEX_LOCK_OWNER)) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "thread %d attempted to tlbunlock without having the "
+                      "lock, tlb_lock state = %d\n",
+                      env->threadId, env->tlb_lock_state);
+        g_assert(env->tlb_lock_state != HEX_LOCK_WAITING);
+        return;
+    }
+
+    env->tlb_lock_count--;
+    env->tlb_lock_state = HEX_LOCK_UNLOCKED;
+    SET_SYSCFG_FIELD(env, SYSCFG_TLBLOCK, 0);
+
+    /* Look for a thread to unlock */
+    unsigned int this_threadId = env->threadId;
+    CPUHexagonState *unlock_thread = NULL;
+    CPUState *cs;
+    CPU_FOREACH(cs) {
+        CPUHexagonState *thread = cpu_env(cs);
+
+        /*
+         * The hardware implements round-robin fairness, so we look for threads
+         * starting at env->threadId + 1 and incrementing modulo the number of
+         * threads.
+         *
+         * To implement this, we check if thread is a earlier in the modulo
+         * sequence than unlock_thread.
+         *     if unlock thread is higher than this thread
+         *         thread must be between this thread and unlock_thread
+         *     else
+         *         thread higher than this thread is ahead of unlock_thread
+         *         thread must be lower then unlock thread
+         */
+        if (thread->tlb_lock_state == HEX_LOCK_WAITING) {
+            if (!unlock_thread) {
+                unlock_thread = thread;
+            } else if (unlock_thread->threadId > this_threadId) {
+                if (this_threadId < thread->threadId &&
+                    thread->threadId < unlock_thread->threadId) {
+                    unlock_thread = thread;
+                }
+            } else {
+                if (thread->threadId > this_threadId) {
+                    unlock_thread = thread;
+                }
+                if (thread->threadId < unlock_thread->threadId) {
+                    unlock_thread = thread;
+                }
+            }
+        }
+    }
+    if (unlock_thread) {
+        cs = env_cpu(unlock_thread);
+        print_thread("\tWaiting thread found", cs);
+        unlock_thread->tlb_lock_state = HEX_LOCK_QUEUED;
+        SET_SYSCFG_FIELD(unlock_thread, SYSCFG_TLBLOCK, 1);
+        cpu_interrupt(cs, CPU_INTERRUPT_TLB_UNLOCK);
+    }
+
+    if (qemu_loglevel_mask(CPU_LOG_MMU)) {
+        qemu_log_mask(CPU_LOG_MMU, "Threads after hex_tlb_unlock:\n");
+        print_thread_states("\tThread");
+    }
+
+}
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index cd6affa2f49..4df4226cbcb 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -987,7 +987,7 @@ static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
     HexagonCPU *hex_cpu = env_archcpu(cpu_env(cs));
     uint32_t hex_flags = dcbase->tb->flags;
 
-    ctx->mem_idx = MMU_USER_IDX;
+    ctx->mem_idx = FIELD_EX32(hex_flags, TB_FLAGS, MMU_INDEX);
     ctx->num_packets = 0;
     ctx->num_insns = 0;
     ctx->num_hvx_insns = 0;
-- 
2.34.1


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

* [PATCH v5 33/35] target/hexagon: Add clear_wait_mode() definition
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (31 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 32/35] target/hexagon: Add stubs for modify_ssr/get_exe_mode Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 34/35] target/hexagon: Define f{S,G}ET_FIELD macros Brian Cain
  2026-03-11  3:49 ` [PATCH v5 35/35] target/hexagon: Add hex_interrupts support Brian Cain
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu_helper.h |  1 +
 target/hexagon/cpu_helper.c | 15 +++++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index 18300657f3d..d15385daf83 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -16,5 +16,6 @@ void hexagon_set_sys_pcycle_count_low(CPUHexagonState *env, uint32_t);
 void hexagon_set_sys_pcycle_count_high(CPUHexagonState *env, uint32_t);
 void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old);
 int get_exe_mode(CPUHexagonState *env);
+void clear_wait_mode(CPUHexagonState *env);
 
 #endif
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index b6a8bd35309..6fbf5fc8e2f 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -64,6 +64,21 @@ void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old)
     g_assert_not_reached();
 }
 
+void clear_wait_mode(CPUHexagonState *env)
+{
+    g_assert(bql_locked());
+
+    HexagonCPU *cpu = env_archcpu(env);
+    if (cpu->globalregs) {
+        const uint32_t modectl =
+            hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
+                                   env->threadId);
+        uint32_t thread_wait_mask = GET_FIELD(MODECTL_W, modectl);
+        thread_wait_mask &= ~(0x1 << env->threadId);
+        SET_SYSTEM_FIELD(env, HEX_SREG_MODECTL, MODECTL_W, thread_wait_mask);
+    }
+}
+
 int get_exe_mode(CPUHexagonState *env)
 {
     g_assert_not_reached();
-- 
2.34.1


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

* [PATCH v5 34/35] target/hexagon: Define f{S,G}ET_FIELD macros
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (32 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 33/35] target/hexagon: Add clear_wait_mode() definition Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  2026-03-11  3:49 ` [PATCH v5 35/35] target/hexagon: Add hex_interrupts support Brian Cain
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain

From: Brian Cain <bcain@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/macros.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index e4bfea4923f..26d3f7d8a4b 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -653,6 +653,16 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
                    reg_field_info[FIELD].width, \
                    reg_field_info[FIELD].offset)
 
+#define fGET_FIELD(VAL, FIELD) \
+    fEXTRACTU_BITS(VAL, \
+                   reg_field_info[FIELD].width, \
+                   reg_field_info[FIELD].offset)
+#define fSET_FIELD(VAL, FIELD, NEWVAL) \
+    fINSERT_BITS(VAL, \
+                 reg_field_info[FIELD].width, \
+                 reg_field_info[FIELD].offset, \
+                 (NEWVAL))
+
 #ifdef QEMU_GENERATE
 #define fDCZEROA(REG) \
     do { \
-- 
2.34.1


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

* [PATCH v5 35/35] target/hexagon: Add hex_interrupts support
  2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
                   ` (33 preceding siblings ...)
  2026-03-11  3:49 ` [PATCH v5 34/35] target/hexagon: Define f{S,G}ET_FIELD macros Brian Cain
@ 2026-03-11  3:49 ` Brian Cain
  34 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2026-03-11  3:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, philmd, ltaylorsimpson, matheus.bernardino,
	marco.liebel, quic_mburton, sid.manning, ale, anjo, Brian Cain,
	Sid Manning, Michael Lambert

From: Brian Cain <bcain@quicinc.com>

Co-authored-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Co-authored-by: Sid Manning <sidneym@quicinc.com>
Co-authored-by: Michael Lambert <mlambert@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 target/hexagon/cpu.h            |   2 +
 target/hexagon/hex_interrupts.h |  15 ++
 target/hexagon/cpu.c            |   4 +
 target/hexagon/hex_interrupts.c | 375 ++++++++++++++++++++++++++++++++
 4 files changed, 396 insertions(+)
 create mode 100644 target/hexagon/hex_interrupts.h
 create mode 100644 target/hexagon/hex_interrupts.c

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index d8092cb6fe7..0017be9dff7 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -192,6 +192,8 @@ struct ArchCPU {
     bool short_circuit;
 #ifndef CONFIG_USER_ONLY
     struct HexagonTLBState *tlb;
+    uint32_t boot_addr;
+    struct HexagonGlobalRegState *globalregs;
     uint32_t htid;
 #endif
 };
diff --git a/target/hexagon/hex_interrupts.h b/target/hexagon/hex_interrupts.h
new file mode 100644
index 00000000000..6b6f5403633
--- /dev/null
+++ b/target/hexagon/hex_interrupts.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HEX_INTERRUPTS_H
+#define HEX_INTERRUPTS_H
+
+bool hex_check_interrupts(CPUHexagonState *env);
+void hex_clear_interrupts(CPUHexagonState *env, uint32_t mask, uint32_t type);
+void hex_raise_interrupts(CPUHexagonState *env, uint32_t mask, uint32_t type);
+void hex_interrupt_update(CPUHexagonState *env);
+
+#endif
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 5c937fa1cd1..938492897fd 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -61,6 +61,9 @@ static const Property hexagon_cpu_properties[] = {
 #if !defined(CONFIG_USER_ONLY)
     DEFINE_PROP_LINK("tlb", HexagonCPU, tlb, TYPE_HEXAGON_TLB,
                      HexagonTLBState *),
+    DEFINE_PROP_UINT32("exec-start-addr", HexagonCPU, boot_addr, 0xffffffff),
+    DEFINE_PROP_LINK("global-regs", HexagonCPU, globalregs,
+        TYPE_HEXAGON_GLOBALREG, HexagonGlobalRegState *),
     DEFINE_PROP_UINT32("htid", HexagonCPU, htid, 0),
 #endif
     DEFINE_PROP_BOOL("lldb-compat", HexagonCPU, lldb_compat, false),
@@ -340,6 +343,7 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
     HexagonCPU *cpu = HEXAGON_CPU(cs);
     env->t_sreg[HEX_SREG_HTID] = cpu->htid;
     env->threadId = cpu->htid;
+    env->gpr[HEX_REG_PC] = cpu->boot_addr;
 #endif
     env->cause_code = HEX_EVENT_NONE;
 }
diff --git a/target/hexagon/hex_interrupts.c b/target/hexagon/hex_interrupts.c
new file mode 100644
index 00000000000..f1be67d5116
--- /dev/null
+++ b/target/hexagon/hex_interrupts.c
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/main-loop.h"
+#include "cpu.h"
+#include "cpu_helper.h"
+#include "exec/cpu-interrupt.h"
+#include "hex_interrupts.h"
+#include "macros.h"
+#include "sys_macros.h"
+#include "system/cpus.h"
+#include "hw/hexagon/hexagon_globalreg.h"
+
+static bool hex_is_qualified_for_int(CPUHexagonState *env, int int_num);
+
+static bool get_syscfg_gie(CPUHexagonState *env)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t syscfg = cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SYSCFG,
+                               env->threadId) : 0;
+    return GET_SYSCFG_FIELD(SYSCFG_GIE, syscfg);
+}
+
+static bool get_ssr_ex(CPUHexagonState *env)
+{
+    uint32_t ssr = env->t_sreg[HEX_SREG_SSR];
+    return GET_SSR_FIELD(SSR_EX, ssr);
+}
+
+static bool get_ssr_ie(CPUHexagonState *env)
+{
+    uint32_t ssr = env->t_sreg[HEX_SREG_SSR];
+    return GET_SSR_FIELD(SSR_IE, ssr);
+}
+
+/* Do these together so we only have to call hexagon_modify_ssr once */
+static void set_ssr_ex_cause(CPUHexagonState *env, int ex, uint32_t cause)
+{
+    uint32_t old = env->t_sreg[HEX_SREG_SSR];
+    SET_SYSTEM_FIELD(env, HEX_SREG_SSR, SSR_EX, ex);
+    SET_SYSTEM_FIELD(env, HEX_SREG_SSR, SSR_CAUSE, cause);
+    uint32_t new = env->t_sreg[HEX_SREG_SSR];
+    hexagon_modify_ssr(env, new, old);
+}
+
+static bool get_iad_bit(CPUHexagonState *env, int int_num)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t ipendad = cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, HEX_SREG_IPENDAD,
+                               env->threadId) : 0;
+    uint32_t iad = GET_FIELD(IPENDAD_IAD, ipendad);
+    return extract32(iad, int_num, 1);
+}
+
+static void set_iad_bit(CPUHexagonState *env, int int_num, int val)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t ipendad = cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, HEX_SREG_IPENDAD,
+                               env->threadId) : 0;
+    uint32_t iad = GET_FIELD(IPENDAD_IAD, ipendad);
+    iad = deposit32(iad, int_num, 1, val);
+    fSET_FIELD(ipendad, IPENDAD_IAD, iad);
+    if (cpu->globalregs) {
+        hexagon_globalreg_write(cpu->globalregs, HEX_SREG_IPENDAD,
+                                ipendad, env->threadId);
+    }
+}
+
+static uint32_t get_ipend(CPUHexagonState *env)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t ipendad = cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, HEX_SREG_IPENDAD,
+                               env->threadId) : 0;
+    return GET_FIELD(IPENDAD_IPEND, ipendad);
+}
+
+static inline bool get_ipend_bit(CPUHexagonState *env, int int_num)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t ipendad = cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, HEX_SREG_IPENDAD,
+                               env->threadId) : 0;
+    uint32_t ipend = GET_FIELD(IPENDAD_IPEND, ipendad);
+    return extract32(ipend, int_num, 1);
+}
+
+static void clear_ipend(CPUHexagonState *env, uint32_t mask)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t ipendad = cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, HEX_SREG_IPENDAD,
+                               env->threadId) : 0;
+    uint32_t ipend = GET_FIELD(IPENDAD_IPEND, ipendad);
+    ipend &= ~mask;
+    fSET_FIELD(ipendad, IPENDAD_IPEND, ipend);
+    if (cpu->globalregs) {
+        hexagon_globalreg_write(cpu->globalregs, HEX_SREG_IPENDAD,
+                                ipendad, env->threadId);
+    }
+}
+
+static void set_ipend(CPUHexagonState *env, uint32_t mask)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t ipendad = cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, HEX_SREG_IPENDAD,
+                               env->threadId) : 0;
+    uint32_t ipend = GET_FIELD(IPENDAD_IPEND, ipendad);
+    ipend |= mask;
+    fSET_FIELD(ipendad, IPENDAD_IPEND, ipend);
+    if (cpu->globalregs) {
+        hexagon_globalreg_write(cpu->globalregs, HEX_SREG_IPENDAD,
+                                ipendad, env->threadId);
+    }
+}
+
+static void set_ipend_bit(CPUHexagonState *env, int int_num, int val)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t ipendad = cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, HEX_SREG_IPENDAD,
+                               env->threadId) : 0;
+    uint32_t ipend = GET_FIELD(IPENDAD_IPEND, ipendad);
+    ipend = deposit32(ipend, int_num, 1, val);
+    fSET_FIELD(ipendad, IPENDAD_IPEND, ipend);
+    if (cpu->globalregs) {
+        hexagon_globalreg_write(cpu->globalregs, HEX_SREG_IPENDAD,
+                                ipendad, env->threadId);
+    }
+}
+
+static bool get_imask_bit(CPUHexagonState *env, int int_num)
+{
+    uint32_t imask = env->t_sreg[HEX_SREG_IMASK];
+    return extract32(imask, int_num, 1);
+}
+
+static uint32_t get_prio(CPUHexagonState *env)
+{
+    uint32_t stid = env->t_sreg[HEX_SREG_STID];
+    return extract32(stid, reg_field_info[STID_PRIO].offset,
+                     reg_field_info[STID_PRIO].width);
+}
+
+static void set_elr(CPUHexagonState *env, uint32_t val)
+{
+    env->t_sreg[HEX_SREG_ELR] = val;
+}
+
+static bool get_schedcfgen(CPUHexagonState *env)
+{
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t schedcfg = cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SCHEDCFG,
+                               env->threadId) : 0;
+    return extract32(schedcfg, reg_field_info[SCHEDCFG_EN].offset,
+                     reg_field_info[SCHEDCFG_EN].width);
+}
+
+static bool is_lowest_prio(CPUHexagonState *env, int int_num)
+{
+    uint32_t my_prio = get_prio(env);
+    CPUState *cs;
+
+    CPU_FOREACH(cs) {
+        CPUHexagonState *hex_env = cpu_env(cs);
+        if (!hex_is_qualified_for_int(hex_env, int_num)) {
+            continue;
+        }
+
+        /* Note that lower values indicate *higher* priority */
+        if (my_prio < get_prio(hex_env)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+static bool hex_is_qualified_for_int(CPUHexagonState *env, int int_num)
+{
+    bool syscfg_gie = get_syscfg_gie(env);
+    bool iad = get_iad_bit(env, int_num);
+    bool ssr_ie = get_ssr_ie(env);
+    bool ssr_ex = get_ssr_ex(env);
+    bool imask = get_imask_bit(env, int_num);
+
+    return syscfg_gie && !iad && ssr_ie && !ssr_ex && !imask;
+}
+
+static void clear_pending_locks(CPUHexagonState *env)
+{
+    g_assert(bql_locked());
+    if (env->k0_lock_state == HEX_LOCK_WAITING) {
+        env->k0_lock_state = HEX_LOCK_UNLOCKED;
+    }
+    if (env->tlb_lock_state == HEX_LOCK_WAITING) {
+        env->tlb_lock_state = HEX_LOCK_UNLOCKED;
+    }
+}
+
+static bool should_not_exec(CPUHexagonState *env)
+{
+    return (get_exe_mode(env) == HEX_EXE_MODE_WAIT);
+}
+
+static void restore_state(CPUHexagonState *env, bool int_accepted)
+{
+    CPUState *cs = env_cpu(env);
+    cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD | CPU_INTERRUPT_SWI);
+    if (!int_accepted && should_not_exec(env)) {
+        cpu_interrupt(cs, CPU_INTERRUPT_HALT);
+    }
+}
+
+static void hex_accept_int(CPUHexagonState *env, int int_num)
+{
+    CPUState *cs = env_cpu(env);
+    HexagonCPU *cpu = env_archcpu(env);
+    uint32_t evb = cpu->globalregs ?
+        hexagon_globalreg_read(cpu->globalregs, HEX_SREG_EVB,
+                               env->threadId) : 0;
+    const int exe_mode = get_exe_mode(env);
+    const bool in_wait_mode = exe_mode == HEX_EXE_MODE_WAIT;
+
+    set_ipend_bit(env, int_num, 0);
+    set_iad_bit(env, int_num, 1);
+    set_ssr_ex_cause(env, 1, HEX_CAUSE_INT0 | int_num);
+    cs->exception_index = HEX_EVENT_INT0 + int_num;
+    env->cause_code = HEX_EVENT_INT0 + int_num;
+    clear_pending_locks(env);
+    if (in_wait_mode) {
+        qemu_log_mask(CPU_LOG_INT,
+            "%s: thread " TARGET_FMT_ld " resuming, exiting WAIT mode\n",
+            __func__, env->threadId);
+        set_elr(env, env->wait_next_pc);
+        clear_wait_mode(env);
+        cs->halted = false;
+    } else if (env->k0_lock_state == HEX_LOCK_WAITING) {
+        g_assert_not_reached();
+    } else {
+        set_elr(env, env->gpr[HEX_REG_PC]);
+    }
+    env->gpr[HEX_REG_PC] = evb | (cs->exception_index << 2);
+    if (get_ipend(env) == 0) {
+        restore_state(env, true);
+    }
+}
+
+
+bool hex_check_interrupts(CPUHexagonState *env)
+{
+    CPUState *cs = env_cpu(env);
+    bool int_handled = false;
+    bool ssr_ex = get_ssr_ex(env);
+    int max_ints = 32;
+    bool schedcfgen;
+
+    /* Early exit if nothing pending */
+    if (get_ipend(env) == 0) {
+        restore_state(env, false);
+        return false;
+    }
+
+    BQL_LOCK_GUARD();
+    /* Only check priorities when schedcfgen is set */
+    schedcfgen = get_schedcfgen(env);
+    for (int i = 0; i < max_ints; i++) {
+        if (!get_iad_bit(env, i) && get_ipend_bit(env, i)) {
+            qemu_log_mask(CPU_LOG_INT,
+                          "%s: thread[" TARGET_FMT_ld "] "
+                          "pc = 0x" TARGET_FMT_lx
+                          " found int %d\n",
+                          __func__, env->threadId,
+                          env->gpr[HEX_REG_PC], i);
+            if (hex_is_qualified_for_int(env, i) &&
+                (!schedcfgen || is_lowest_prio(env, i))) {
+                qemu_log_mask(CPU_LOG_INT,
+                              "%s: thread[" TARGET_FMT_ld "] int %d handled_\n",
+                              __func__, env->threadId, i);
+                hex_accept_int(env, i);
+                int_handled = true;
+                break;
+            }
+            bool syscfg_gie = get_syscfg_gie(env);
+            bool iad = get_iad_bit(env, i);
+            bool ssr_ie = get_ssr_ie(env);
+            bool imask = get_imask_bit(env, i);
+
+            qemu_log_mask(CPU_LOG_INT,
+                          "%s: thread[" TARGET_FMT_ld "] "
+                          "int %d not handled, qualified: %d, "
+                          "schedcfg_en: %d, low prio %d\n",
+                          __func__, env->threadId, i,
+                          hex_is_qualified_for_int(env, i), schedcfgen,
+                          is_lowest_prio(env, i));
+
+            qemu_log_mask(CPU_LOG_INT,
+                          "%s: thread[" TARGET_FMT_ld "] "
+                          "int %d not handled, GIE %d, iad %d, "
+                          "SSR:IE %d, SSR:EX: %d, imask bit %d\n",
+                          __func__, env->threadId, i, syscfg_gie, iad, ssr_ie,
+                          ssr_ex, imask);
+        }
+    }
+
+    /*
+     * If we didn't handle the interrupt and it wasn't
+     * because we were in EX state, then we won't be able
+     * to execute the interrupt on this CPU unless something
+     * changes in the CPU state.  Clear the interrupt_request bits
+     * while preserving the IPEND bits, and we can re-assert the
+     * interrupt_request bit(s) when we execute one of those instructions.
+     */
+    if (!int_handled && !ssr_ex) {
+        restore_state(env, int_handled);
+    } else if (int_handled) {
+        assert(!cs->halted);
+    }
+
+    return int_handled;
+}
+
+void hex_clear_interrupts(CPUHexagonState *env, uint32_t mask, uint32_t type)
+{
+    if (mask == 0) {
+        return;
+    }
+
+    /*
+     * Notify all CPUs that the interrupt has happened
+     */
+    BQL_LOCK_GUARD();
+    clear_ipend(env, mask);
+    hex_interrupt_update(env);
+}
+
+void hex_raise_interrupts(CPUHexagonState *env, uint32_t mask, uint32_t type)
+{
+    g_assert(bql_locked());
+    if (mask == 0) {
+        return;
+    }
+
+    /*
+     * Notify all CPUs that the interrupt has happened
+     */
+    set_ipend(env, mask);
+    hex_interrupt_update(env);
+}
+
+void hex_interrupt_update(CPUHexagonState *env)
+{
+    CPUState *cs;
+
+    g_assert(bql_locked());
+    if (get_ipend(env) != 0) {
+        CPU_FOREACH(cs) {
+            CPUHexagonState *hex_env = cpu_env(cs);
+            const int exe_mode = get_exe_mode(hex_env);
+            if (exe_mode != HEX_EXE_MODE_OFF) {
+                cpu_interrupt(cs, CPU_INTERRUPT_SWI);
+                cpu_resume(cs);
+            }
+        }
+    }
+}
-- 
2.34.1


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

* Re: [PATCH v5 06/35] target/hexagon: Suppress unused-variable warnings for sysemu source regs
  2026-03-11  3:48 ` [PATCH v5 06/35] target/hexagon: Suppress unused-variable warnings for sysemu source regs Brian Cain
@ 2026-03-12 21:03   ` Taylor Simpson
  0 siblings, 0 replies; 41+ messages in thread
From: Taylor Simpson @ 2026-03-12 21:03 UTC (permalink / raw)
  To: Brian Cain
  Cc: qemu-devel, philmd, matheus.bernardino, marco.liebel,
	quic_mburton, sid.manning, ale, anjo

[-- Attachment #1: Type: text/plain, Size: 1030 bytes --]

On Tue, Mar 10, 2026 at 9:49 PM Brian Cain <brian.cain@oss.qualcomm.com>
wrote:

> The analyze_read() methods on GuestSource, GuestPairSource,
> SystemSource, and SystemPairSource were no-ops because these
> source registers do not need read-tracking in the analyze phase.
> However, gen_analyze_funcs.py unconditionally declares the
> register-number variable (e.g. GsN) via decl_reg_num() for all
> registers that are read or written.  When building with
> hexagon-softmmu, the generated analyze function bodies are
> compiled (outside the #ifndef CONFIG_USER_ONLY guard), and the
> declared-but-unreferenced register-number variable triggers
> -Werror=unused-variable under both gcc and clang.
>
> Emit a (void) cast on the register number from analyze_read() to
> suppress the warning.
>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
>  target/hexagon/hex_common.py | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>

[-- Attachment #2: Type: text/html, Size: 1546 bytes --]

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

* Re: [PATCH v5 19/35] target/hexagon: Add vmstate representation
  2026-03-11  3:49 ` [PATCH v5 19/35] target/hexagon: Add vmstate representation Brian Cain
@ 2026-03-25 19:21   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 41+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-03-25 19:21 UTC (permalink / raw)
  To: Brian Cain, qemu-devel
  Cc: ltaylorsimpson, matheus.bernardino, marco.liebel, quic_mburton,
	sid.manning, ale, anjo, Brian Cain

On 11/3/26 04:49, Brian Cain wrote:
> From: Brian Cain <bcain@quicinc.com>
> 
> Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
>   target/hexagon/internal.h |  4 ++++
>   target/hexagon/cpu.c      |  3 +++
>   target/hexagon/machine.c  | 32 ++++++++++++++++++++++++++++++++
>   3 files changed, 39 insertions(+)
>   create mode 100644 target/hexagon/machine.c
> 
> diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
> index 5fc837ae229..cd06ff41d4f 100644
> --- a/target/hexagon/internal.h
> +++ b/target/hexagon/internal.h
> @@ -31,4 +31,8 @@ void hexagon_debug(CPUHexagonState *env);
>   
>   extern const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS];
>   
> +#ifndef CONFIG_USER_ONLY
> +extern const VMStateDescription vmstate_hexagon_cpu;
> +#endif
> +
>   #endif
> diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
> index 6fabfaad6d2..38d605b06ba 100644
> --- a/target/hexagon/cpu.c
> +++ b/target/hexagon/cpu.c
> @@ -387,6 +387,9 @@ static void hexagon_cpu_class_init(ObjectClass *c, const void *data)
>       cc->gdb_stop_before_watchpoint = true;
>       cc->gdb_core_xml_file = "hexagon-core.xml";
>       cc->disas_set_info = hexagon_cpu_disas_set_info;
> +#ifndef CONFIG_USER_ONLY
> +    dc->vmsd = &vmstate_hexagon_cpu;
> +#endif
>       cc->tcg_ops = &hexagon_tcg_ops;
>   }
>   
> diff --git a/target/hexagon/machine.c b/target/hexagon/machine.c
> new file mode 100644
> index 00000000000..d6dcd07dd4a
> --- /dev/null
> +++ b/target/hexagon/machine.c
> @@ -0,0 +1,32 @@
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "migration/cpu.h"

We don't need to include the target-specific "migration/cpu.h" header,
the target-agnostic "migration/vmstate.h" should be sufficient. With
that change:

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

> +#include "cpu.h"
> +
> +const VMStateDescription vmstate_hexagon_cpu = {
> +    .name = "cpu",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT32_ARRAY(env.gpr, HexagonCPU, TOTAL_PER_THREAD_REGS),
> +        VMSTATE_UINT32_ARRAY(env.pred, HexagonCPU, NUM_PREGS),
> +        VMSTATE_UINT32_ARRAY(env.t_sreg, HexagonCPU, NUM_SREGS),
> +        VMSTATE_UINT32_ARRAY(env.greg, HexagonCPU, NUM_GREGS),
> +        VMSTATE_UINT32(env.next_PC, HexagonCPU),
> +        VMSTATE_UINT32(env.tlb_lock_state, HexagonCPU),
> +        VMSTATE_UINT32(env.k0_lock_state, HexagonCPU),
> +        VMSTATE_UINT32(env.tlb_lock_count, HexagonCPU),
> +        VMSTATE_UINT32(env.k0_lock_count, HexagonCPU),
> +        VMSTATE_UINT32(env.threadId, HexagonCPU),
> +        VMSTATE_UINT32(env.cause_code, HexagonCPU),
> +        VMSTATE_UINT32(env.wait_next_pc, HexagonCPU),
> +        VMSTATE_UINT64(env.t_cycle_count, HexagonCPU),
> +
> +        VMSTATE_END_OF_LIST()
> +    },
> +};



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

* Re: [PATCH v5 24/35] target/hexagon: Add sysemu TCG overrides
  2026-03-11  3:49 ` [PATCH v5 24/35] target/hexagon: Add sysemu TCG overrides Brian Cain
@ 2026-03-25 19:24   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 41+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-03-25 19:24 UTC (permalink / raw)
  To: Brian Cain, qemu-devel
  Cc: ltaylorsimpson, matheus.bernardino, marco.liebel, quic_mburton,
	sid.manning, ale, anjo, Brian Cain

On 11/3/26 04:49, Brian Cain wrote:
> From: Brian Cain <bcain@quicinc.com>
> 
> Define TCG overrides for setprio(), crswap(,sgp{0,1,1:0}).
> 
> Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
>   target/hexagon/cpu_helper.h  | 18 ++++++++++++++++
>   target/hexagon/gen_tcg_sys.h | 40 ++++++++++++++++++++++++++++++++++++
>   target/hexagon/helper.h      |  1 +
>   target/hexagon/genptr.c      |  4 ++++
>   target/hexagon/op_helper.c   | 10 ++++++++-
>   target/hexagon/hex_common.py |  2 ++
>   target/hexagon/meson.build   | 13 ++++++------
>   7 files changed, 81 insertions(+), 7 deletions(-)
>   create mode 100644 target/hexagon/cpu_helper.h
>   create mode 100644 target/hexagon/gen_tcg_sys.h


> diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
> index 327c233c01b..d9d84f05553 100644
> --- a/target/hexagon/op_helper.c
> +++ b/target/hexagon/op_helper.c
> @@ -19,9 +19,10 @@
>   #include "qemu/log.h"
>   #include "accel/tcg/cpu-ldst.h"
>   #include "accel/tcg/probe.h"
> +#include "qemu/main-loop.h"

"qemu/main-loop.h" doesn't seem used in this patch.

> +#include "cpu.h"
>   #include "exec/helper-proto.h"
>   #include "fpu/softfloat.h"
> -#include "cpu.h"
>   #include "internal.h"
>   #include "macros.h"
>   #include "sys_macros.h"
> @@ -31,6 +32,7 @@
>   #include "mmvec/mmvec.h"
>   #include "mmvec/macros.h"
>   #include "op_helper.h"
> +#include "cpu_helper.h"
>   #include "translate.h"
>   #ifndef CONFIG_USER_ONLY
>   #include "hexswi.h"
> @@ -1412,6 +1414,12 @@ uint64_t HELPER(greg_read_pair)(CPUHexagonState *env, uint32_t reg)
>   {
>       g_assert_not_reached();
>   }
> +
> +void HELPER(setprio)(CPUHexagonState *env, uint32_t thread, uint32_t prio)
> +{
> +    g_assert_not_reached();
> +}
> +
>   #endif



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

* Re: [PATCH v5 29/35] target/hexagon: Add sreg_{read,write} helpers
  2026-03-11  3:49 ` [PATCH v5 29/35] target/hexagon: Add sreg_{read,write} helpers Brian Cain
@ 2026-03-25 19:26   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 41+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-03-25 19:26 UTC (permalink / raw)
  To: Brian Cain, qemu-devel
  Cc: ltaylorsimpson, matheus.bernardino, marco.liebel, quic_mburton,
	sid.manning, ale, anjo, Brian Cain, Sid Manning

On 11/3/26 04:49, Brian Cain wrote:
> From: Brian Cain <bcain@quicinc.com>
> 
> Co-authored-by: Sid Manning <sidneym@quicinc.com>
> Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
>   target/hexagon/cpu.c        |  1 -
>   target/hexagon/cpu_helper.c | 60 +++++++++++++++++++++++++++++++++++++
>   target/hexagon/op_helper.c  | 30 +++++++++++++++++--
>   3 files changed, 87 insertions(+), 4 deletions(-)
>   create mode 100644 target/hexagon/cpu_helper.c


> diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
> index af93be7a232..3517f3768fd 100644
> --- a/target/hexagon/op_helper.c
> +++ b/target/hexagon/op_helper.c
> @@ -1452,17 +1452,41 @@ void HELPER(setimask)(CPUHexagonState *env, uint32_t tid, uint32_t imask)
>   
>   void HELPER(sreg_write_masked)(CPUHexagonState *env, uint32_t reg, uint32_t val)
>   {
> -    g_assert_not_reached();
> +    BQL_LOCK_GUARD();
> +    if (reg < HEX_SREG_GLB_START) {
> +        env->t_sreg[reg] = val;
> +    } else {
> +        HexagonCPU *cpu = env_archcpu(env);
> +        if (cpu->globalregs) {
> +            hexagon_globalreg_write_masked(cpu->globalregs, reg, val);
> +        }
> +    }
> +}
> +
> +static inline QEMU_ALWAYS_INLINE uint32_t sreg_read(CPUHexagonState *env,
> +                                                    uint32_t reg)
> +{
> +    g_assert(bql_locked());
> +    if (reg < HEX_SREG_GLB_START) {
> +        return env->t_sreg[reg];
> +    }
> +    HexagonCPU *cpu = env_archcpu(env);
> +    return cpu->globalregs ?
> +        hexagon_globalreg_read(cpu->globalregs, reg, env->threadId) : 0;
>   }
>   
>   uint32_t HELPER(sreg_read)(CPUHexagonState *env, uint32_t reg)
>   {
> -    g_assert_not_reached();
> +    BQL_LOCK_GUARD();

Ah I see, I suppose this is the patch that requires "qemu/main-loop.h".

> +    return sreg_read(env, reg);
>   }
>   
>   uint64_t HELPER(sreg_read_pair)(CPUHexagonState *env, uint32_t reg)
>   {
> -    g_assert_not_reached();
> +    BQL_LOCK_GUARD();
> +
> +    return deposit64((uint64_t) sreg_read(env, reg), 32, 32,
> +        sreg_read(env, reg + 1));
>   }
>   
>   uint32_t HELPER(greg_read)(CPUHexagonState *env, uint32_t reg)



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

* Re: [PATCH v5 31/35] hw/hexagon: Introduce hexagon TLB device
  2026-03-11  3:49 ` [PATCH v5 31/35] hw/hexagon: Introduce hexagon TLB device Brian Cain
@ 2026-03-25 19:38   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 41+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-03-25 19:38 UTC (permalink / raw)
  To: Brian Cain, qemu-devel
  Cc: ltaylorsimpson, matheus.bernardino, marco.liebel, quic_mburton,
	sid.manning, ale, anjo

Hi Brian,

On 11/3/26 04:49, Brian Cain wrote:
> Add the hexagon TLB QOM device model.
> 
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> 
> Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
> ---
>   include/hw/hexagon/hexagon_tlb.h |  45 +++
>   target/hexagon/cpu.h             |   4 +
>   hw/hexagon/hexagon_tlb.c         | 463 +++++++++++++++++++++++++++++++
>   target/hexagon/cpu.c             |   5 +
>   4 files changed, 517 insertions(+)
>   create mode 100644 include/hw/hexagon/hexagon_tlb.h
>   create mode 100644 hw/hexagon/hexagon_tlb.c
> 
> diff --git a/include/hw/hexagon/hexagon_tlb.h b/include/hw/hexagon/hexagon_tlb.h
> new file mode 100644
> index 00000000000..bcb387aa24d
> --- /dev/null
> +++ b/include/hw/hexagon/hexagon_tlb.h
> @@ -0,0 +1,45 @@
> +/*
> + * Hexagon TLB QOM Device
> + *
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef HW_HEXAGON_TLB_H
> +#define HW_HEXAGON_TLB_H
> +
> +#include "hw/core/sysbus.h"
> +#include "qom/object.h"
> +#include "exec/hwaddr.h"
> +#include "exec/mmu-access-type.h"
> +#define TYPE_HEXAGON_TLB "hexagon-tlb"
> +OBJECT_DECLARE_SIMPLE_TYPE(HexagonTLBState, HEXAGON_TLB)
> +
> +struct HexagonTLBState {
> +    SysBusDevice parent_obj;
> +
> +    uint32_t num_entries;
> +    uint64_t *entries;
> +};
> +
> +uint64_t hexagon_tlb_read(HexagonTLBState *tlb, uint32_t index);
> +void hexagon_tlb_write(HexagonTLBState *tlb, uint32_t index, uint64_t value);
> +
> +bool hexagon_tlb_find_match(HexagonTLBState *tlb, uint32_t asid,
> +                            uint32_t VA, MMUAccessType access_type,
> +                            hwaddr *PA, int *prot, uint64_t *size,
> +                            int32_t *excp, int *cause_code, int mmu_idx);
> +
> +uint32_t hexagon_tlb_lookup(HexagonTLBState *tlb, uint32_t asid,
> +                            uint32_t VA, int *cause_code);
> +
> +int hexagon_tlb_check_overlap(HexagonTLBState *tlb, uint64_t entry,
> +                              uint64_t index);
> +
> +void hexagon_tlb_dump(HexagonTLBState *tlb);
> +
> +bool hexagon_tlb_dump_entry(FILE *f, uint64_t entry);
> +
> +uint32_t hexagon_tlb_get_num_entries(HexagonTLBState *tlb);
> +
> +#endif /* HW_HEXAGON_TLB_H */
> diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
> index 9eb2d1bbabe..e39e6e39fec 100644
> --- a/target/hexagon/cpu.h
> +++ b/target/hexagon/cpu.h
> @@ -46,6 +46,7 @@
>   #define REG_WRITES_MAX 32
>   #define PRED_WRITES_MAX 5                   /* 4 insns + endloop */
>   #define VSTORES_MAX 2
> +#define MAX_TLB_ENTRIES 1024
>   
>   #define CPU_RESOLVING_TYPE TYPE_HEXAGON_CPU
>   #ifndef CONFIG_USER_ONLY
> @@ -174,6 +175,9 @@ struct ArchCPU {
>       bool lldb_compat;
>       target_ulong lldb_stack_adjust;
>       bool short_circuit;
> +#ifndef CONFIG_USER_ONLY
> +    struct HexagonTLBState *tlb;

Please use the typedef (dropping the 'struct').

> +#endif
>   };
>   
>   #include "cpu_bits.h"
> diff --git a/hw/hexagon/hexagon_tlb.c b/hw/hexagon/hexagon_tlb.c
> new file mode 100644
> index 00000000000..90f319f56d3
> --- /dev/null
> +++ b/hw/hexagon/hexagon_tlb.c
> @@ -0,0 +1,463 @@
> +/*
> + * Hexagon TLB QOM Device
> + *
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "hw/hexagon/hexagon_tlb.h"
> +#include "hw/core/qdev-properties.h"
> +#include "hw/core/resettable.h"
> +#include "migration/vmstate.h"
> +#include "qapi/error.h"
> +#include "target/hexagon/cpu.h"
> +#include "target/hexagon/cpu_bits.h"
> +
> +/* PTE (TLB entry) field extraction */
> +#define GET_PTE_PPD(entry)   extract64((entry),  0, 24)
> +#define GET_PTE_C(entry)     extract64((entry), 24,  4)
> +#define GET_PTE_U(entry)     extract64((entry), 28,  1)
> +#define GET_PTE_R(entry)     extract64((entry), 29,  1)
> +#define GET_PTE_W(entry)     extract64((entry), 30,  1)
> +#define GET_PTE_X(entry)     extract64((entry), 31,  1)
> +#define GET_PTE_VPN(entry)   extract64((entry), 32, 20)
> +#define GET_PTE_ASID(entry)  extract64((entry), 52,  7)
> +#define GET_PTE_ATR0(entry)  extract64((entry), 59,  1)
> +#define GET_PTE_ATR1(entry)  extract64((entry), 60,  1)
> +#define GET_PTE_PA35(entry)  extract64((entry), 61,  1)
> +#define GET_PTE_G(entry)     extract64((entry), 62,  1)
> +#define GET_PTE_V(entry)     extract64((entry), 63,  1)
> +
> +/* PPD (physical page descriptor) */
> +static inline uint64_t GET_PPD(uint64_t entry)
> +{
> +    return GET_PTE_PPD(entry) | (GET_PTE_PA35(entry) << 24);
> +}
> +
> +#define NO_ASID      (1 << 8)
> +
> +typedef enum {
> +    PGSIZE_4K,
> +    PGSIZE_16K,
> +    PGSIZE_64K,
> +    PGSIZE_256K,
> +    PGSIZE_1M,
> +    PGSIZE_4M,
> +    PGSIZE_16M,
> +    PGSIZE_64M,
> +    PGSIZE_256M,
> +    PGSIZE_1G,
> +    NUM_PGSIZE_TYPES

Matter of style, since the last entry isn't part of the enum
I'd use:

   #define NUM_PGSIZE_TYPES (PGSIZE_1G + 1)

> +} tlb_pgsize_t;
> +
> +static const char *pgsize_str[NUM_PGSIZE_TYPES] = {
> +    "4K",
> +    "16K",
> +    "64K",
> +    "256K",
> +    "1M",
> +    "4M",
> +    "16M",
> +    "64M",
> +    "256M",
> +    "1G",
> +};
> +
> +#define INVALID_MASK 0xffffffffLL
> +
> +static const uint64_t encmask_2_mask[] = {
> +    0x0fffLL,                           /* 4k,   0000 */
> +    0x3fffLL,                           /* 16k,  0001 */
> +    0xffffLL,                           /* 64k,  0010 */
> +    0x3ffffLL,                          /* 256k, 0011 */
> +    0xfffffLL,                          /* 1m,   0100 */
> +    0x3fffffLL,                         /* 4m,   0101 */
> +    0xffffffLL,                         /* 16m,  0110 */
> +    0x3ffffffLL,                        /* 64m,  0111 */
> +    0xfffffffLL,                        /* 256m, 1000 */
> +    0x3fffffffLL,                       /* 1g,   1001 */
> +    INVALID_MASK,                       /* RSVD, 0111 */

Typo '1111' I suppose, since 0111 is 64M.

> +};
> +
> +static inline tlb_pgsize_t hex_tlb_pgsize_type(uint64_t entry)
> +{
> +    if (entry == 0) {
> +        qemu_log_mask(CPU_LOG_MMU, "%s: Supplied TLB entry was 0!\n",
> +                      __func__);
> +        return 0;
> +    }
> +    tlb_pgsize_t size = ctz64(entry);
> +    g_assert(size < NUM_PGSIZE_TYPES);
> +    return size;
> +}
> +
> +static inline uint64_t hex_tlb_page_size_bytes(uint64_t entry)
> +{
> +    return 1ull << (TARGET_PAGE_BITS + 2 * hex_tlb_pgsize_type(entry));
> +}
> +
> +static inline uint64_t hex_tlb_phys_page_num(uint64_t entry)
> +{
> +    uint32_t ppd = GET_PPD(entry);
> +    return ppd >> 1;
> +}
> +
> +static inline uint64_t hex_tlb_phys_addr(uint64_t entry)
> +{
> +    uint64_t pagemask = encmask_2_mask[hex_tlb_pgsize_type(entry)];
> +    uint64_t pagenum = hex_tlb_phys_page_num(entry);
> +    uint64_t PA = (pagenum << TARGET_PAGE_BITS) & (~pagemask);

We are replacing all TARGET_PAGE_BITS uses by qemu_target_page_bits().

> +    return PA;
> +}
> +
> +static inline uint64_t hex_tlb_virt_addr(uint64_t entry)
> +{
> +    return (uint64_t)GET_PTE_VPN(entry) << TARGET_PAGE_BITS;
> +}
> +
> +bool hexagon_tlb_dump_entry(FILE *f, uint64_t entry)
> +{

Prefer Monitor* instead of FILE*.

> +    if (GET_PTE_V(entry)) {
> +        fprintf(f, "0x%016" PRIx64 ": ", entry);
> +        uint64_t PA = hex_tlb_phys_addr(entry);
> +        uint64_t VA = hex_tlb_virt_addr(entry);
> +        fprintf(f, "V:%" PRId64 " G:%" PRId64
> +                " A1:%" PRId64 " A0:%" PRId64,
> +                GET_PTE_V(entry),
> +                GET_PTE_G(entry),
> +                GET_PTE_ATR1(entry),
> +                GET_PTE_ATR0(entry));
> +        fprintf(f, " ASID:0x%02" PRIx64 " VA:0x%08" PRIx64,
> +                GET_PTE_ASID(entry), VA);
> +        fprintf(f,
> +                " X:%" PRId64 " W:%" PRId64 " R:%" PRId64
> +                " U:%" PRId64 " C:%" PRId64,
> +                GET_PTE_X(entry),
> +                GET_PTE_W(entry),
> +                GET_PTE_R(entry),
> +                GET_PTE_U(entry),
> +                GET_PTE_C(entry));
> +        fprintf(f, " PA:0x%09" PRIx64 " SZ:%s (0x%" PRIx64 ")", PA,
> +                pgsize_str[hex_tlb_pgsize_type(entry)],
> +                hex_tlb_page_size_bytes(entry));
> +        fprintf(f, "\n");
> +        return true;
> +    }
> +
> +    /* Not valid */
> +    return false;
> +}
> +
> +static inline bool hex_tlb_entry_match_noperm(uint64_t entry, uint32_t asid,
> +                                              uint64_t VA)
> +{
> +    if (GET_PTE_V(entry)) {
> +        if (GET_PTE_G(entry)) {
> +            /* Global entry - ignore ASID */
> +        } else if (asid != NO_ASID) {
> +            uint32_t tlb_asid = GET_PTE_ASID(entry);
> +            if (tlb_asid != asid) {
> +                return false;
> +            }
> +        }
> +
> +        uint64_t page_size = hex_tlb_page_size_bytes(entry);
> +        uint64_t page_start =
> +            ROUND_DOWN(hex_tlb_virt_addr(entry), page_size);
> +        if (page_start <= VA && VA < page_start + page_size) {
> +            return true;
> +        }
> +    }
> +    return false;
> +}
> +
> +static inline void hex_tlb_entry_get_perm(uint64_t entry,
> +                                          MMUAccessType access_type,
> +                                          int mmu_idx, int *prot,
> +                                          int32_t *excp, int *cause_code)
> +{
> +    bool perm_x = GET_PTE_X(entry);
> +    bool perm_w = GET_PTE_W(entry);
> +    bool perm_r = GET_PTE_R(entry);
> +    bool perm_u = GET_PTE_U(entry);
> +    bool user_idx = mmu_idx == MMU_USER_IDX;
> +
> +    if (mmu_idx == MMU_KERNEL_IDX) {
> +        *prot = PAGE_VALID | PAGE_READ | PAGE_WRITE | PAGE_EXEC;
> +        return;
> +    }
> +
> +    *prot = PAGE_VALID;
> +    switch (access_type) {
> +    case MMU_INST_FETCH:
> +        if (user_idx && !perm_u) {
> +            *excp = HEX_EVENT_PRECISE;
> +            *cause_code = HEX_CAUSE_FETCH_NO_UPAGE;
> +        } else if (!perm_x) {
> +            *excp = HEX_EVENT_PRECISE;
> +            *cause_code = HEX_CAUSE_FETCH_NO_XPAGE;
> +        }
> +        break;
> +    case MMU_DATA_LOAD:
> +        if (user_idx && !perm_u) {
> +            *excp = HEX_EVENT_PRECISE;
> +            *cause_code = HEX_CAUSE_PRIV_NO_UREAD;
> +        } else if (!perm_r) {
> +            *excp = HEX_EVENT_PRECISE;
> +            *cause_code = HEX_CAUSE_PRIV_NO_READ;
> +        }
> +        break;
> +    case MMU_DATA_STORE:
> +        if (user_idx && !perm_u) {
> +            *excp = HEX_EVENT_PRECISE;
> +            *cause_code = HEX_CAUSE_PRIV_NO_UWRITE;
> +        } else if (!perm_w) {
> +            *excp = HEX_EVENT_PRECISE;
> +            *cause_code = HEX_CAUSE_PRIV_NO_WRITE;
> +        }
> +        break;
> +    }
> +
> +    if (!user_idx || perm_u) {
> +        if (perm_x) {
> +            *prot |= PAGE_EXEC;
> +        }
> +        if (perm_r) {
> +            *prot |= PAGE_READ;
> +        }
> +        if (perm_w) {
> +            *prot |= PAGE_WRITE;
> +        }
> +    }
> +}
> +
> +static inline bool hex_tlb_entry_match(uint64_t entry, uint8_t asid,
> +                                       uint32_t VA,
> +                                       MMUAccessType access_type, hwaddr *PA,
> +                                       int *prot, uint64_t *size,
> +                                       int32_t *excp, int *cause_code,
> +                                       int mmu_idx)
> +{
> +    if (hex_tlb_entry_match_noperm(entry, asid, VA)) {
> +        hex_tlb_entry_get_perm(entry, access_type, mmu_idx, prot, excp,
> +                               cause_code);
> +        *PA = hex_tlb_phys_addr(entry);
> +        *size = hex_tlb_page_size_bytes(entry);
> +        return true;
> +    }
> +    return false;
> +}
> +
> +static bool hex_tlb_is_match(uint64_t entry1, uint64_t entry2,
> +                             bool consider_gbit)
> +{
> +    bool valid1 = GET_PTE_V(entry1);
> +    bool valid2 = GET_PTE_V(entry2);
> +    uint64_t size1 = hex_tlb_page_size_bytes(entry1);
> +    uint64_t vaddr1 = ROUND_DOWN(hex_tlb_virt_addr(entry1), size1);
> +    uint64_t size2 = hex_tlb_page_size_bytes(entry2);
> +    uint64_t vaddr2 = ROUND_DOWN(hex_tlb_virt_addr(entry2), size2);
> +    int asid1 = GET_PTE_ASID(entry1);
> +    int asid2 = GET_PTE_ASID(entry2);
> +    bool gbit1 = GET_PTE_G(entry1);
> +    bool gbit2 = GET_PTE_G(entry2);
> +
> +    if (!valid1 || !valid2) {
> +        return false;
> +    }
> +
> +    if (((vaddr1 <= vaddr2) && (vaddr2 < (vaddr1 + size1))) ||
> +        ((vaddr2 <= vaddr1) && (vaddr1 < (vaddr2 + size2)))) {
> +        if (asid1 == asid2) {
> +            return true;
> +        }
> +        if ((consider_gbit && gbit1) || gbit2) {
> +            return true;
> +        }
> +    }
> +    return false;
> +}
> +
> +/* Public API */
> +
> +uint64_t hexagon_tlb_read(HexagonTLBState *tlb, uint32_t index)
> +{
> +    g_assert(index < tlb->num_entries);
> +    return tlb->entries[index];
> +}
> +
> +void hexagon_tlb_write(HexagonTLBState *tlb, uint32_t index, uint64_t value)
> +{
> +    g_assert(index < tlb->num_entries);
> +    tlb->entries[index] = value;
> +}
> +
> +bool hexagon_tlb_find_match(HexagonTLBState *tlb, uint32_t asid,
> +                            uint32_t VA, MMUAccessType access_type,
> +                            hwaddr *PA, int *prot, uint64_t *size,
> +                            int32_t *excp, int *cause_code, int mmu_idx)
> +{
> +    *PA = 0;
> +    *prot = 0;
> +    *size = 0;
> +    *excp = 0;
> +    *cause_code = 0;
> +
> +    for (uint32_t i = 0; i < tlb->num_entries; i++) {
> +        if (hex_tlb_entry_match(tlb->entries[i], asid, VA, access_type,
> +                                PA, prot, size, excp, cause_code, mmu_idx)) {
> +            return true;
> +        }
> +    }
> +    return false;
> +}
> +
> +uint32_t hexagon_tlb_lookup(HexagonTLBState *tlb, uint32_t asid,
> +                            uint32_t VA, int *cause_code)
> +{
> +    uint32_t not_found = 0x80000000;
> +    uint32_t idx = not_found;
> +
> +    for (uint32_t i = 0; i < tlb->num_entries; i++) {
> +        uint64_t entry = tlb->entries[i];
> +        if (hex_tlb_entry_match_noperm(entry, asid, VA)) {
> +            if (idx != not_found) {
> +                *cause_code = HEX_CAUSE_IMPRECISE_MULTI_TLB_MATCH;
> +                break;
> +            }
> +            idx = i;
> +        }
> +    }
> +
> +    if (idx == not_found) {
> +        qemu_log_mask(CPU_LOG_MMU,
> +                      "%s: 0x%" PRIx32 ", 0x%08" PRIx32 " => NOT FOUND\n",
> +                      __func__, asid, VA);
> +    } else {
> +        qemu_log_mask(CPU_LOG_MMU,
> +                      "%s: 0x%" PRIx32 ", 0x%08" PRIx32 " => %d\n",
> +                      __func__, asid, VA, idx);
> +    }
> +
> +    return idx;
> +}
> +
> +/*
> + * Return codes:
> + * 0 or positive             index of match
> + * -1                        multiple matches
> + * -2                        no match
> + */
> +int hexagon_tlb_check_overlap(HexagonTLBState *tlb, uint64_t entry,
> +                              uint64_t index)
> +{
> +    int matches = 0;
> +    int last_match = 0;
> +
> +    for (uint32_t i = 0; i < tlb->num_entries; i++) {
> +        if (hex_tlb_is_match(entry, tlb->entries[i], false)) {
> +            matches++;
> +            last_match = i;
> +        }
> +    }
> +
> +    if (matches == 1) {
> +        return last_match;
> +    }
> +    if (matches == 0) {
> +        return -2;
> +    }
> +    return -1;
> +}
> +
> +void hexagon_tlb_dump(HexagonTLBState *tlb)
> +{
> +    for (uint32_t i = 0; i < tlb->num_entries; i++) {
> +        hexagon_tlb_dump_entry(stdout, tlb->entries[i]);
> +    }
> +}
> +
> +uint32_t hexagon_tlb_get_num_entries(HexagonTLBState *tlb)
> +{
> +    return tlb->num_entries;
> +}
> +
> +/* QOM lifecycle */
> +
> +static void hexagon_tlb_init(Object *obj)
> +{
> +}
> +
> +static void hexagon_tlb_realize(DeviceState *dev, Error **errp)
> +{
> +    HexagonTLBState *s = HEXAGON_TLB(dev);
> +
> +    if (s->num_entries == 0 || s->num_entries > MAX_TLB_ENTRIES) {
> +        error_setg(errp, "Invalid TLB num-entries: %" PRIu32,
> +                   s->num_entries);
> +        return;
> +    }
> +    s->entries = g_new0(uint64_t, s->num_entries);
> +}
> +
> +static void hexagon_tlb_finalize(Object *obj)
> +{
> +    HexagonTLBState *s = HEXAGON_TLB(obj);
> +    g_free(s->entries);

This should be done in the unrealize() handler.

> +    s->entries = NULL;
> +}
> +
> +static void hexagon_tlb_reset_hold(Object *obj, ResetType type)
> +{
> +    HexagonTLBState *s = HEXAGON_TLB(obj);
> +    if (s->entries) {
> +        memset(s->entries, 0, sizeof(uint64_t) * s->num_entries);
> +    }
> +}
> +
> +static const VMStateDescription vmstate_hexagon_tlb = {
> +    .name = "hexagon-tlb",
> +    .version_id = 0,
> +    .minimum_version_id = 0,
> +    .fields = (const VMStateField[]) {
> +        VMSTATE_UINT32(num_entries, HexagonTLBState),
> +        VMSTATE_VARRAY_UINT32_ALLOC(entries, HexagonTLBState, num_entries,
> +                                    0, vmstate_info_uint64, uint64_t),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};
> +
> +static const Property hexagon_tlb_properties[] = {
> +    DEFINE_PROP_UINT32("num-entries", HexagonTLBState, num_entries,
> +                       MAX_TLB_ENTRIES),
> +};
> +
> +static void hexagon_tlb_class_init(ObjectClass *klass, const void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    ResettableClass *rc = RESETTABLE_CLASS(klass);
> +
> +    dc->realize = hexagon_tlb_realize;
> +    rc->phases.hold = hexagon_tlb_reset_hold;
> +    dc->vmsd = &vmstate_hexagon_tlb;
> +    dc->user_creatable = false;
> +    device_class_set_props(dc, hexagon_tlb_properties);
> +}
> +
> +static const TypeInfo hexagon_tlb_info = {
> +    .name = TYPE_HEXAGON_TLB,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(HexagonTLBState),
> +    .instance_init = hexagon_tlb_init,
> +    .instance_finalize = hexagon_tlb_finalize,
> +    .class_init = hexagon_tlb_class_init,
> +};
> +
> +static void hexagon_tlb_register_types(void)
> +{
> +    type_register_static(&hexagon_tlb_info);
> +}
> +
> +type_init(hexagon_tlb_register_types)
> diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
> index b1317f83ef4..32d158684a0 100644
> --- a/target/hexagon/cpu.c
> +++ b/target/hexagon/cpu.c
> @@ -23,6 +23,7 @@
>   #include "qapi/error.h"
>   #include "hw/core/qdev-properties.h"
>   #include "fpu/softfloat-helpers.h"
> +#include "hw/hexagon/hexagon_tlb.h"
>   #include "tcg/tcg.h"
>   #include "exec/gdbstub.h"
>   #include "accel/tcg/cpu-ops.h"
> @@ -50,6 +51,10 @@ static ObjectClass *hexagon_cpu_class_by_name(const char *cpu_model)
>   }
>   
>   static const Property hexagon_cpu_properties[] = {
> +#if !defined(CONFIG_USER_ONLY)
> +    DEFINE_PROP_LINK("tlb", HexagonCPU, tlb, TYPE_HEXAGON_TLB,
> +                     HexagonTLBState *),

Not used at this point, maybe add later?

> +#endif
>       DEFINE_PROP_BOOL("lldb-compat", HexagonCPU, lldb_compat, false),
>       DEFINE_PROP_UNSIGNED("lldb-stack-adjust", HexagonCPU, lldb_stack_adjust, 0,
>                            qdev_prop_uint32, target_ulong),



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

end of thread, other threads:[~2026-03-25 19:38 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-11  3:48 [PATCH v5 00/35] Hexagon system emulation, Part 1/3 Brian Cain
2026-03-11  3:48 ` [PATCH v5 01/35] docs: Add hexagon sysemu docs Brian Cain
2026-03-11  3:48 ` [PATCH v5 02/35] docs/system: Add hexagon CPU emulation Brian Cain
2026-03-11  3:48 ` [PATCH v5 03/35] target/hexagon: Fix badva reference, delete CAUSE Brian Cain
2026-03-11  3:48 ` [PATCH v5 04/35] target/hexagon: Add missing A_CALL attr, hintjumpr to multi_cof Brian Cain
2026-03-11  3:48 ` [PATCH v5 05/35] target/hexagon: Handle system/guest registers in gen_analyze_funcs.py and hex_common.py Brian Cain
2026-03-11  3:48 ` [PATCH v5 06/35] target/hexagon: Suppress unused-variable warnings for sysemu source regs Brian Cain
2026-03-12 21:03   ` Taylor Simpson
2026-03-11  3:48 ` [PATCH v5 07/35] target/hexagon: Make gen_exception_end_tb non-static Brian Cain
2026-03-11  3:48 ` [PATCH v5 08/35] target/hexagon: Switch to tag_ignore(), generate via get_{user, sys}_tags() Brian Cain via qemu development
2026-03-11  3:48 ` [PATCH v5 09/35] target/hexagon: Add privilege check, use tag_ignore() Brian Cain
2026-03-11  3:48 ` [PATCH v5 10/35] target/hexagon: Add a placeholder fp exception Brian Cain
2026-03-11  3:48 ` [PATCH v5 11/35] target/hexagon: Add guest, system reg number defs Brian Cain
2026-03-11  3:49 ` [PATCH v5 12/35] target/hexagon: Add guest, system reg number state Brian Cain
2026-03-11  3:49 ` [PATCH v5 13/35] target/hexagon: Add TCG values for sreg, greg Brian Cain
2026-03-11  3:49 ` [PATCH v5 14/35] target/hexagon: Add guest/sys reg writes to DisasContext Brian Cain
2026-03-11  3:49 ` [PATCH v5 15/35] target/hexagon: Add imported macro, attr defs for sysemu Brian Cain
2026-03-11  3:49 ` [PATCH v5 16/35] target/hexagon: Add new macro definitions " Brian Cain
2026-03-11  3:49 ` [PATCH v5 17/35] target/hexagon: Add handlers for guest/sysreg r/w Brian Cain
2026-03-11  3:49 ` [PATCH v5 18/35] target/hexagon: Add placeholder greg/sreg r/w helpers Brian Cain
2026-03-11  3:49 ` [PATCH v5 19/35] target/hexagon: Add vmstate representation Brian Cain
2026-03-25 19:21   ` Philippe Mathieu-Daudé
2026-03-11  3:49 ` [PATCH v5 20/35] target/hexagon: Make A_PRIV, "J2_trap*" insts need_env() Brian Cain
2026-03-11  3:49 ` [PATCH v5 21/35] target/hexagon: Define register fields for system regs Brian Cain
2026-03-11  3:49 ` [PATCH v5 22/35] target/hexagon: Implement do_raise_exception() Brian Cain
2026-03-11  3:49 ` [PATCH v5 23/35] target/hexagon: Add system reg insns Brian Cain
2026-03-11  3:49 ` [PATCH v5 24/35] target/hexagon: Add sysemu TCG overrides Brian Cain
2026-03-25 19:24   ` Philippe Mathieu-Daudé
2026-03-11  3:49 ` [PATCH v5 25/35] target/hexagon: Add implicit attributes to sysemu macros Brian Cain
2026-03-11  3:49 ` [PATCH v5 26/35] target/hexagon: Add TCG overrides for int handler insts Brian Cain
2026-03-11  3:49 ` [PATCH v5 27/35] target/hexagon: Add TCG overrides for thread ctl Brian Cain
2026-03-11  3:49 ` [PATCH v5 28/35] target/hexagon: Add TCG overrides for rte, nmi Brian Cain
2026-03-11  3:49 ` [PATCH v5 29/35] target/hexagon: Add sreg_{read,write} helpers Brian Cain
2026-03-25 19:26   ` Philippe Mathieu-Daudé
2026-03-11  3:49 ` [PATCH v5 30/35] target/hexagon: Add cpu modes, mmu indices, next_PC to state Brian Cain
2026-03-11  3:49 ` [PATCH v5 31/35] hw/hexagon: Introduce hexagon TLB device Brian Cain
2026-03-25 19:38   ` Philippe Mathieu-Daudé
2026-03-11  3:49 ` [PATCH v5 32/35] target/hexagon: Add stubs for modify_ssr/get_exe_mode Brian Cain
2026-03-11  3:49 ` [PATCH v5 33/35] target/hexagon: Add clear_wait_mode() definition Brian Cain
2026-03-11  3:49 ` [PATCH v5 34/35] target/hexagon: Define f{S,G}ET_FIELD macros Brian Cain
2026-03-11  3:49 ` [PATCH v5 35/35] target/hexagon: Add hex_interrupts support Brian Cain

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox