* [PATCH v2 01/40] docs: Add hexagon sysemu docs
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 02/40] docs/system: Add hexagon CPU emulation Brian Cain
` (38 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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>
---
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 8f074e4371..bf7695658a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -237,6 +237,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/cdsp.rst
+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 0000000000..92ebc32dce
--- /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 7a0678cbdd..0471db8064 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 0000000000..237529273c
--- /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 0000000000..5f7084a6a0
--- /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 38e2418801..515e249326 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 v2 02/40] docs/system: Add hexagon CPU emulation
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
2025-09-02 3:46 ` [PATCH v2 01/40] docs: Add hexagon sysemu docs Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 03/40] target/hexagon: Fix badva reference, delete CAUSE Brian Cain
` (37 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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>
---
docs/system/hexagon/emulation.rst | 18 ++++++++++++++++++
docs/system/target-hexagon.rst | 1 +
2 files changed, 19 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 0000000000..75f46719b9
--- /dev/null
+++ b/docs/system/hexagon/emulation.rst
@@ -0,0 +1,18 @@
+.. 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>`_.
+
+.. code-block:: bash
+
diff --git a/docs/system/target-hexagon.rst b/docs/system/target-hexagon.rst
index 5f7084a6a0..416b8f7be7 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 v2 03/40] target/hexagon: Fix badva reference, delete CAUSE
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
2025-09-02 3:46 ` [PATCH v2 01/40] docs: Add hexagon sysemu docs Brian Cain
2025-09-02 3:46 ` [PATCH v2 02/40] docs/system: Add hexagon CPU emulation Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 04/40] target/hexagon: Add missing A_CALL attr, hintjumpr to multi_cof Brian Cain
` (36 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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>
---
target/hexagon/cpu.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index a5a04173ab..a193acdbfc 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -216,8 +216,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_reg(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 v2 04/40] target/hexagon: Add missing A_CALL attr, hintjumpr to multi_cof
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (2 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 03/40] target/hexagon: Fix badva reference, delete CAUSE Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 05/40] target/hexagon: Handle system/guest registers in gen_analyze_funcs.py and hex_common.py Brian Cain
` (35 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/hex_common.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 758e5fd12d..e60e8efabc 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -247,7 +247,11 @@ def need_next_PC(tag):
def need_pkt_has_multi_cof(tag):
- return "A_COF" in attribdict[tag]
+ if "A_JUMP" in attribdict[tag] or "A_CALL" in attribdict[tag]:
+ if tag == "J4_hintjumpr":
+ return False
+ return True
+ return False
def need_pkt_need_commit(tag):
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 05/40] target/hexagon: Handle system/guest registers in gen_analyze_funcs.py and hex_common.py
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (3 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 04/40] target/hexagon: Add missing A_CALL attr, hintjumpr to multi_cof Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 06/40] target/hexagon: Make gen_exception_end_tb non-static Brian Cain
` (34 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/gen_analyze_funcs.py | 21 +++-
target/hexagon/hex_common.py | 161 ++++++++++++++++++++++++++++
2 files changed, 179 insertions(+), 3 deletions(-)
diff --git a/target/hexagon/gen_analyze_funcs.py b/target/hexagon/gen_analyze_funcs.py
index 3ac7cc2cfe..dfdf5f3b87 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -22,6 +22,8 @@
import string
import hex_common
+def has_analyze_func(reg, mode):
+ return callable(getattr(reg, f"analyze_{mode}", None))
##
## Generate the code to analyze the instruction
@@ -42,6 +44,14 @@ 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 ("A_PRIV" in hex_common.attribdict[tag] or
+ "A_GUEST" in hex_common.attribdict[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,22 +68,27 @@ 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 has_analyze_func(reg, "read") or has_analyze_func(reg, "write"):
+ reg.decl_reg_num(f, regno)
## Analyze the register reads
for regno, register in enumerate(regs):
reg_type, reg_id = register
reg = hex_common.get_register(tag, reg_type, reg_id)
- if reg.is_read():
+ if reg.is_read() and has_analyze_func(reg, "read"):
reg.analyze_read(f, regno)
## Analyze the register writes
for regno, register in enumerate(regs):
reg_type, reg_id = register
reg = hex_common.get_register(tag, reg_type, reg_id)
- if reg.is_written():
+ if reg.is_written() and has_analyze_func(reg, "write"):
reg.analyze_write(f, tag, regno)
+ 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")
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index e60e8efabc..fa122b6d76 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -33,6 +33,42 @@
overrides = {} # tags with helper overrides
idef_parser_enabled = {} # tags enabled for idef-parser
+
+def is_sysemu_tag(tag):
+ return "A_PRIV" in attribdict[tag] or "A_GUEST" in attribdict[tag]
+
+
+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 \
+ any(attr in attribdict[tag] for attr in 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):
@@ -370,12 +406,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):
@@ -1013,6 +1053,117 @@ def analyze_write(self, f, tag, regno):
ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper);
"""))
+class GuestRegister(Register):
+ def gen_check_impl(self, f, regno):
+ if self.is_written():
+ f.write(code_fmt(f"""\
+ if (!greg_writable(insn->regno[{regno}],
+ {str(self.is_pair()).lower()})) {{
+ return;
+ }}
+ """))
+ else:
+ f.write(code_fmt(f"""\
+ check_greg_impl(insn->regno[{regno}],
+ {str(self.is_pair()).lower()});
+ """))
+
+class GuestDest(GuestRegister, Single, Dest):
+ def decl_tcg(self, f, tag, regno):
+ self.decl_reg_num(f, regno)
+ self.gen_check_impl(f, regno)
+ f.write(code_fmt(f"""\
+ TCGv {self.reg_tcg()} = tcg_temp_new();
+ """))
+ def log_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);
+ self.gen_check_impl(f, regno)
+ f.write(code_fmt(f"""\
+ TCGv {self.reg_tcg()} = tcg_temp_new();
+ gen_read_greg({self.reg_tcg()}, {self.reg_num});
+ """))
+
+class GuestPairDest(GuestRegister, Pair, Dest):
+ def decl_tcg(self, f, tag, regno):
+ self.decl_reg_num(f, regno)
+ self.gen_check_impl(f, regno)
+ f.write(code_fmt(f"""\
+ TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
+ """))
+ def log_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)
+ self.gen_check_impl(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});
+ """))
+
+class SystemDest(Register, Single, Dest):
+ def decl_tcg(self, f, tag, regno):
+ self.decl_reg_num(f, regno)
+ f.write(code_fmt(f"""\
+ TCGv {self.reg_tcg()} = tcg_temp_new();
+ """))
+ def log_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 {self.reg_tcg()} = tcg_temp_new();
+ gen_read_sreg({self.reg_tcg()}, {self.reg_num});
+ """))
+
+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 log_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 init_registers():
regs = {
GprDest("R", "d"),
@@ -1059,6 +1210,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 v2 06/40] target/hexagon: Make gen_exception_end_tb non-static
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (4 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 05/40] target/hexagon: Handle system/guest registers in gen_analyze_funcs.py and hex_common.py Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 07/40] target/hexagon: Switch to tag_ignore(), generate via get_{user, sys}_tags() Brian Cain via
` (33 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 | 9 ++++-----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index d251e2233f..2bd125297a 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -281,6 +281,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 02fd40c160..15f5adc400 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -185,13 +185,12 @@ 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);
gen_exception_raw(excp);
ctx->base.is_jmp = DISAS_NORETURN;
-
}
static int read_packet_words(CPUHexagonState *env, DisasContext *ctx,
@@ -558,7 +557,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);
}
}
@@ -912,7 +911,7 @@ static void decode_and_translate_packet(CPUHexagonState *env, DisasContext *ctx)
nwords = read_packet_words(env, ctx, words);
if (!nwords) {
- gen_exception_end_tb(ctx, HEX_CAUSE_INVALID_PACKET);
+ hex_gen_exception_end_tb(ctx, HEX_CAUSE_INVALID_PACKET);
return;
}
@@ -927,7 +926,7 @@ static void decode_and_translate_packet(CPUHexagonState *env, DisasContext *ctx)
gen_commit_packet(ctx);
ctx->base.pc_next += pkt.encod_pkt_size_in_bytes;
} else {
- gen_exception_end_tb(ctx, HEX_CAUSE_INVALID_PACKET);
+ hex_gen_exception_end_tb(ctx, HEX_CAUSE_INVALID_PACKET);
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 07/40] target/hexagon: Switch to tag_ignore(), generate via get_{user, sys}_tags()
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (5 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 06/40] target/hexagon: Make gen_exception_end_tb non-static Brian Cain
@ 2025-09-02 3:46 ` Brian Cain via
2025-09-02 3:46 ` [PATCH v2 08/40] target/hexagon: Add system event, cause codes Brian Cain
` (32 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain via @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 | 23 ++++++++++-------------
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_func_table.py | 14 ++------------
6 files changed, 31 insertions(+), 38 deletions(-)
diff --git a/target/hexagon/gen_helper_funcs.py b/target/hexagon/gen_helper_funcs.py
index c1f806ac4b..dd8ab60598 100755
--- a/target/hexagon/gen_helper_funcs.py
+++ b/target/hexagon/gen_helper_funcs.py
@@ -109,26 +109,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 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 77f8e0a6a3..59c8bdd05c 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 2f6e826f76..32bce9b002 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 bbbb02df3a..94dd1f876b 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 94a19ff412..17ba3f9db9 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")
diff --git a/target/hexagon/gen_tcg_func_table.py b/target/hexagon/gen_tcg_func_table.py
index 299a39b1aa..70c8db5c44 100755
--- a/target/hexagon/gen_tcg_func_table.py
+++ b/target/hexagon/gen_tcg_func_table.py
@@ -41,19 +41,9 @@ def main():
f.write("#define HEXAGON_FUNC_TABLE_H\n\n")
f.write("const SemanticInsn opcode_genptr[XX_LAST_OPCODE] = {\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):
continue
f.write(f" [{tag}] = generate_{tag},\n")
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 08/40] target/hexagon: Add system event, cause codes
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (6 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 07/40] target/hexagon: Switch to tag_ignore(), generate via get_{user, sys}_tags() Brian Cain via
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 09/40] target/hexagon: Add privilege check, use tag_ignore() Brian Cain
` (31 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 | 9 +++++
target/hexagon/cpu_bits.h | 80 ++++++++++++++++++++++++++++++++++-----
2 files changed, 80 insertions(+), 9 deletions(-)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 43a854f517..1fc4093176 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;
uint8_t width;
diff --git a/target/hexagon/cpu_bits.h b/target/hexagon/cpu_bits.h
index ff596e2a94..b118761e05 100644
--- a/target/hexagon/cpu_bits.h
+++ b/target/hexagon/cpu_bits.h
@@ -24,19 +24,81 @@
#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_PC_NOT_ALIGNED = 0x01e,
- HEX_CAUSE_PRIV_NO_UREAD = 0x024,
- HEX_CAUSE_PRIV_NO_UWRITE = 0x025,
+ HEX_CAUSE_RESET = 0x000,
+ HEX_CAUSE_BIU_PRECISE = 0x001,
+ HEX_CAUSE_UNSUPORTED_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,
+ 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_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,
+ HEX_CAUSE_VIC0 = 0x0c2,
+ HEX_CAUSE_VIC1 = 0x0c3,
+ HEX_CAUSE_VIC2 = 0x0c4,
+ HEX_CAUSE_VIC3 = 0x0c5,
};
#define PACKET_WORDS_MAX 4
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 09/40] target/hexagon: Add privilege check, use tag_ignore()
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (7 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 08/40] target/hexagon: Add system event, cause codes Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 10/40] target/hexagon: Add memory order definition Brian Cain
` (30 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 | 1 +
linux-user/hexagon/cpu_loop.c | 16 ++++++++++++++++
target/hexagon/cpu.c | 1 +
target/hexagon/translate.c | 8 ++++++++
target/hexagon/gen_tcg_funcs.py | 32 +++++++++++++++++++-------------
5 files changed, 45 insertions(+), 13 deletions(-)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 1fc4093176..df1f2b569c 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -85,6 +85,7 @@ typedef struct {
typedef struct CPUArchState {
target_ulong gpr[TOTAL_PER_THREAD_REGS];
target_ulong pred[NUM_PREGS];
+ target_ulong cause_code;
/* For comparing with LLDB on target - see adjust_stack_ptrs function */
target_ulong last_pc_dumped;
diff --git a/linux-user/hexagon/cpu_loop.c b/linux-user/hexagon/cpu_loop.c
index 25c97edcae..28ad8073f6 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 a193acdbfc..c9dfdd7864 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -298,6 +298,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(CPUState *s, disassemble_info *info)
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 15f5adc400..c87f07ab69 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -61,6 +61,10 @@ TCGv hex_vstore_addr[VSTORES_MAX];
TCGv hex_vstore_size[VSTORES_MAX];
TCGv hex_vstore_pending[VSTORES_MAX];
+#ifndef CONFIG_USER_ONLY
+TCGv hex_cause_code;
+#endif
+
static const char * const hexagon_prednames[] = {
"p0", "p1", "p2", "p3"
};
@@ -1107,4 +1111,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 c2ba91ddc0..65bfa046b8 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
@@ -50,6 +50,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")
@@ -97,6 +109,11 @@ def gen_tcg_func(f, tag, regs, imms):
if reg.is_written():
reg.log_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")
@@ -121,18 +138,7 @@ 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):
continue
gen_def_tcg_func(f, tag, tagregs, tagimms)
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 10/40] target/hexagon: Add memory order definition
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (8 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 09/40] target/hexagon: Add privilege check, use tag_ignore() Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 11/40] target/hexagon: Add a placeholder fp exception Brian Cain
` (29 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/cpu-param.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/target/hexagon/cpu-param.h b/target/hexagon/cpu-param.h
index 635d509e74..22bffa7881 100644
--- a/target/hexagon/cpu-param.h
+++ b/target/hexagon/cpu-param.h
@@ -25,4 +25,9 @@
#define TARGET_INSN_START_EXTRA_WORDS 0
+/*
+ * Hexagon processors have a strong memory model.
+ */
+#define TCG_GUEST_DEFAULT_MO (TCG_MO_ALL)
+
#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 11/40] target/hexagon: Add a placeholder fp exception
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (9 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 10/40] target/hexagon: Add memory order definition Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 12/40] target/hexagon: Add guest, system reg number defs Brian Cain
` (28 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 d053d68487..87c2f6a53f 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 v2 12/40] target/hexagon: Add guest, system reg number defs
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (10 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 11/40] target/hexagon: Add a placeholder fp exception Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 13/40] target/hexagon: Add guest, system reg number state Brian Cain
` (27 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/cpu.h | 5 ++
target/hexagon/hex_regs.h | 115 ++++++++++++++++++++++++++++++++++++++
2 files changed, 120 insertions(+)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index df1f2b569c..46e0dc9d0b 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -20,6 +20,11 @@
#include "fpu/softfloat-types.h"
+#define NUM_GREGS 32
+#define GREG_WRITES_MAX 2
+#define NUM_SREGS 64
+#define SREG_WRITES_MAX 2
+
#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 bddfc28021..ea8c62eba9 100644
--- a/target/hexagon/hex_regs.h
+++ b/target/hexagon/hex_regs.h
@@ -81,4 +81,119 @@ 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 */
+
+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
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 13/40] target/hexagon: Add guest, system reg number state
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (11 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 12/40] target/hexagon: Add guest, system reg number defs Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 14/40] target/hexagon: Add TCG values for sreg, greg Brian Cain
` (26 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 | 7 +++++++
target/hexagon/cpu.c | 4 ++++
2 files changed, 11 insertions(+)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 46e0dc9d0b..42b877a04c 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -97,6 +97,13 @@ 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. */
+ target_ulong t_sreg[NUM_SREGS];
+
+ target_ulong greg[NUM_GREGS];
+#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 c9dfdd7864..fa52ad7453 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -298,6 +298,10 @@ 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(target_ulong) * NUM_SREGS);
+ memset(env->greg, 0, sizeof(target_ulong) * NUM_GREGS);
+#endif
env->cause_code = HEX_EVENT_NONE;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 14/40] target/hexagon: Add TCG values for sreg, greg
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (12 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 13/40] target/hexagon: Add guest, system reg number state Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 15/40] target/hexagon: Add guest/sys reg writes to DisasContext Brian Cain
` (25 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/translate.h | 5 +++++
target/hexagon/translate.c | 2 ++
2 files changed, 7 insertions(+)
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 2bd125297a..4c1868369a 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -280,6 +280,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 hex_greg[NUM_GREGS];
+extern TCGv 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 c87f07ab69..d788aa227c 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -62,6 +62,8 @@ TCGv hex_vstore_size[VSTORES_MAX];
TCGv hex_vstore_pending[VSTORES_MAX];
#ifndef CONFIG_USER_ONLY
+TCGv hex_greg[NUM_GREGS];
+TCGv hex_t_sreg[NUM_SREGS];
TCGv hex_cause_code;
#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 15/40] target/hexagon: Add guest/sys reg writes to DisasContext
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (13 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 14/40] target/hexagon: Add TCG values for sreg, greg Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 16/40] target/hexagon: Add imported macro, attr defs for sysemu Brian Cain
` (24 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 4c1868369a..c3806fe068 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -39,6 +39,14 @@ typedef struct DisasContext {
int reg_log_idx;
DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
DECLARE_BITMAP(predicated_regs, TOTAL_PER_THREAD_REGS);
+#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 t_sreg_new_value[NUM_SREGS];
+ TCGv greg_new_value[NUM_GREGS];
+#endif
int preg_log[PRED_WRITES_MAX];
int preg_log_idx;
DECLARE_BITMAP(pregs_written, NUM_PREGS);
@@ -79,6 +87,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)
+{
+ if (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)
+{
+ 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 v2 16/40] target/hexagon: Add imported macro, attr defs for sysemu
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (14 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 15/40] target/hexagon: Add guest/sys reg writes to DisasContext Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 17/40] target/hexagon: Define DCache states Brian Cain
` (23 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/attribs_def.h.inc | 413 +++++++++++++++++++--
target/hexagon/imported/macros.def | 558 +++++++++++++++++++++++++++++
2 files changed, 941 insertions(+), 30 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 9e3a05f882..e86284732a 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -19,20 +19,41 @@
DEF_ATTRIB(AA_DUMMY, "Dummy Zeroth Attribute", "", "")
/* Misc */
+DEF_ATTRIB(FAKEINSN, "Not a real instruction", "", "")
+DEF_ATTRIB(MAPPING, "Not real -- asm mapped", "", "")
+DEF_ATTRIB(CONDMAPPING, "Not real -- mapped based on values", "", "")
DEF_ATTRIB(EXTENSION, "Extension instruction", "", "")
+DEF_ATTRIB(SHARED_EXTENSION, "Shared extension instruction", "", "")
+DEF_ATTRIB(CABAC,
+ "Cabac Instruction. Used in conjuction with QDSP6_CABAC_PRESENT", "",
+ "")
+DEF_ATTRIB(EXPERIMENTAL, "This may not work correctly not supported by RTL.",
+ "", "")
DEF_ATTRIB(PRIV, "Not available in user or guest mode", "", "")
DEF_ATTRIB(GUEST, "Not available in user mode", "", "")
DEF_ATTRIB(FPOP, "Floating Point Operation", "", "")
+DEF_ATTRIB(FPDOUBLE, "Double-precision Floating Point Operation", "", "")
+DEF_ATTRIB(FPSINGLE, "Single-precision Floating Point Operation", "", "")
+DEF_ATTRIB(SFMAKE, "Single Float Make", "", "")
+DEF_ATTRIB(DFMAKE, "Single Float Make", "", "")
+
+DEF_ATTRIB(NO_TIMING_LOG, "Does not get logged to the timing model", "", "")
DEF_ATTRIB(EXTENDABLE, "Immediate may be extended", "", "")
+DEF_ATTRIB(EXT_UPPER_IMMED, "Extend upper case immediate", "", "")
+DEF_ATTRIB(EXT_LOWER_IMMED, "Extend lower case immediate", "", "")
+DEF_ATTRIB(MUST_EXTEND, "Immediate must be extended", "", "")
+DEF_ATTRIB(NA_NT, "Non-Allocating Non-Temporal instruction", "", "")
+DEF_ATTRIB(INVPRED, "The predicate is inverted for true/false sense", "", "")
DEF_ATTRIB(ARCHV2, "V2 architecture", "", "")
DEF_ATTRIB(ARCHV3, "V3 architecture", "", "")
DEF_ATTRIB(ARCHV4, "V4 architecture", "", "")
DEF_ATTRIB(ARCHV5, "V5 architecture", "", "")
+DEF_ATTRIB(PACKED, "Packable instruction", "", "")
DEF_ATTRIB(SUBINSN, "sub-instruction", "", "")
/* Load and Store attributes */
@@ -46,21 +67,47 @@ DEF_ATTRIB(MEMSIZE_4B, "Memory width is 4 bytes", "", "")
DEF_ATTRIB(MEMSIZE_8B, "Memory width is 8 bytes", "", "")
DEF_ATTRIB(SCALAR_LOAD, "Load is scalar", "", "")
DEF_ATTRIB(SCALAR_STORE, "Store is scalar", "", "")
-DEF_ATTRIB(REGWRSIZE_1B, "Memory width is 1 byte", "", "")
-DEF_ATTRIB(REGWRSIZE_2B, "Memory width is 2 bytes", "", "")
-DEF_ATTRIB(REGWRSIZE_4B, "Memory width is 4 bytes", "", "")
-DEF_ATTRIB(REGWRSIZE_8B, "Memory width is 8 bytes", "", "")
+DEF_ATTRIB(REGWRSIZE_1B, "ETM Memory width is 1 byte", "", "")
+DEF_ATTRIB(REGWRSIZE_2B, "ETM Memory width is 2 bytes", "", "")
+DEF_ATTRIB(REGWRSIZE_4B, "ETM Memory width is 4 bytes", "", "")
+DEF_ATTRIB(REGWRSIZE_8B, "ETM 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", "", "")
DEF_ATTRIB(RLS_INNER, "Store release inner visibility", "", "")
+DEF_ATTRIB(RLS_OUTER, "Store release outer visibility", "", "")
DEF_ATTRIB(RLS_ALL_THREAD, "Store release among all threads", "", "")
DEF_ATTRIB(RLS_SAME_THREAD, "Store release with the same thread", "", "")
+/* Load and Store Addressing Mode Attributes */
+DEF_ATTRIB(EA_REG_ONLY, "EA = input register only", "", "")
+DEF_ATTRIB(EA_IMM_ONLY, "EA = immediate only", "", "")
+DEF_ATTRIB(EA_REG_PLUS_IMM, "EA = register plus immediate", "", "")
+DEF_ATTRIB(EA_REG_PLUS_REGSCALED, "EA = register plus scaled register", "", "")
+DEF_ATTRIB(EA_IMM_PLUS_REGSCALED, "EA = immediate plus scaled register", "", "")
+DEF_ATTRIB(EA_BREV_REG, "EA = bit-reversed input register", "", "")
+DEF_ATTRIB(EA_GP_IMM, "EA = GP plus immediate (unless extended)", "", "")
+DEF_ATTRIB(EA_PAGECROSS, "EA calculation can have a Page Cross Stall", "", "")
+
+DEF_ATTRIB(PM_ANY, "Post Modify", "", "")
+DEF_ATTRIB(PM_I, "Post Modify by Immediate", "", "")
+DEF_ATTRIB(PM_M, "Post Modify by M register", "", "")
+DEF_ATTRIB(PM_CIRI, "Post Modify with Circular Addressing by immediate", "", "")
+DEF_ATTRIB(PM_CIRR, "Post Modify with Circular Addressing by I field", "", "")
+
+DEF_ATTRIB(VMEM, "VMEM-type", "", "")
+DEF_ATTRIB(VBUF, "Touches the VBUF", "", "")
+DEF_ATTRIB(VDBG, "Vector debugging instruction", "", "")
+
/* V6 Vector attributes */
DEF_ATTRIB(CVI, "Executes on the HVX extension", "", "")
+DEF_ATTRIB(NT_VMEM, "Non-temporal memory access", "", "")
+DEF_ATTRIB(VMEMU, "Unaligned memory access", "", "")
DEF_ATTRIB(CVI_NEW, "New value memory instruction executes on HVX", "", "")
DEF_ATTRIB(CVI_VM, "Memory instruction executes on HVX", "", "")
@@ -69,109 +116,415 @@ DEF_ATTRIB(CVI_VP_VS, "Double vector permute/shft insn executes on HVX", "", "")
DEF_ATTRIB(CVI_VX, "Multiply instruction executes on HVX", "", "")
DEF_ATTRIB(CVI_VX_DV, "Double vector multiply insn executes on HVX", "", "")
DEF_ATTRIB(CVI_VS, "Shift instruction executes on HVX", "", "")
-DEF_ATTRIB(CVI_VS_3SRC, "This shift needs to borrow a source register", "", "")
+DEF_ATTRIB(
+ CVI_VS_3SRC,
+ "This shift instruction needs to borrow a source register from the VP slot",
+ "", "")
DEF_ATTRIB(CVI_VS_VX, "Permute/shift and multiply insn executes on HVX", "", "")
DEF_ATTRIB(CVI_VA, "ALU instruction executes on HVX", "", "")
+DEF_ATTRIB(CVI_VA_2SRC,
+ "This alu instruction executes on multimedia vector engine and "
+ "requires two vectro sources",
+ "", "")
DEF_ATTRIB(CVI_VA_DV, "Double vector alu instruction executes on HVX", "", "")
DEF_ATTRIB(CVI_4SLOT, "Consumes all the vector execution resources", "", "")
DEF_ATTRIB(CVI_TMP, "Transient Memory Load not written to register", "", "")
DEF_ATTRIB(CVI_REMAP, "Register Renaming not written to register file", "", "")
+DEF_ATTRIB(CVI_TMP_SRC, "Transient reassign", "", "")
+DEF_ATTRIB(CVI_EXTRACT, "HVX Extract Instruction that goes through L2", "", "")
+DEF_ATTRIB(CVI_EARLY, "HVX instructions that require early sources", "", "")
+DEF_ATTRIB(CVI_LATE, "HVX insn that always require late sources", "", "")
+DEF_ATTRIB(CVI_VV_LATE, "HVX insn that always require late Vv source", "", "")
+DEF_ATTRIB(CVI_REQUIRES_TMPLOAD, ".tmp load must be included in packet", "", "")
+DEF_ATTRIB(CVI_PUMP_2X, "Goes through the pipeline twice", "", "")
+DEF_ATTRIB(CVI_PUMP_4X, "Goes through the pipeline four times", "", "")
DEF_ATTRIB(CVI_GATHER, "CVI Gather operation", "", "")
DEF_ATTRIB(CVI_SCATTER, "CVI Scatter operation", "", "")
DEF_ATTRIB(CVI_SCATTER_RELEASE, "CVI Store Release for scatter", "", "")
+DEF_ATTRIB(CVI_GATHER_RELEASE, "CVI Store Release for gather", "", "")
DEF_ATTRIB(CVI_TMP_DST, "CVI instruction that doesn't write a register", "", "")
+DEF_ATTRIB(CVI_SCATTER_WORD_ACC, "CVI Scatter Word Accum (second pass)", "", "")
+DEF_ATTRIB(CVI_SCATTER_ACC, "CVI Scatter Accumulate", "", "")
+DEF_ATTRIB(CVI_VX_VSRC0_IS_DST,
+ "For the assembler to handle the special case of non-linear "
+ "instructions with Vxx specified both as src and dst in syntax ",
+ "", "")
+
+DEF_ATTRIB(CVI_VX_ACC_FWD, "VX Accumulator Forwarding", "", "")
+
+DEF_ATTRIB(CVI_VX_NO_TMP_LD,
+ "VX Accumulator renaming not allowed from tmp load instruction", "",
+ "")
+
+DEF_ATTRIB(RESTRICT_CVI_NOVP,
+ "Instructions with this attribute are assigned to the original "
+ "shift unit and can not be assigned to the shift/permute unit",
+ "", "")
+
+DEF_ATTRIB(CVI_GATHER_ADDR_2B, "CVI Scatter/Gather address is halfword", "", "")
+DEF_ATTRIB(CVI_GATHER_ADDR_4B, "CVI Scatter/Gather address is word", "", "")
+
+DEF_ATTRIB(VFETCH, "memory fetch op to L2 for a single vector", "", "")
+
DEF_ATTRIB(CVI_SLOT23, "Can execute in slot 2 or slot 3 (HVX)", "", "")
-DEF_ATTRIB(VTCM_ALLBANK_ACCESS, "Allocates in all VTCM schedulers.", "", "")
+DEF_ATTRIB(HVX_FLT, "This a floating point HVX instruction.", "", "")
+
+DEF_ATTRIB(
+ VTCM_ALLBANK_ACCESS,
+ "This instruction allocates in all VTCM schedulers due to a region access.",
+ "", "")
+DEF_ATTRIB(XUMINOR, "XU minor SMTable instruction", "", "")
+
+DEF_ATTRIB(SYNC_MARKER, "This instruction needs a sync marker.", "", "")
+
/* Change-of-flow attributes */
DEF_ATTRIB(JUMP, "Jump-type instruction", "", "")
+DEF_ATTRIB(DIRECT, "Uses an PC-relative immediate field", "", "")
DEF_ATTRIB(INDIRECT, "Absolute register jump", "", "")
+DEF_ATTRIB(CJUMP, "Conditional jump", "", "")
DEF_ATTRIB(CALL, "Function call instruction", "", "")
+DEF_ATTRIB(RET, "Function return instruction", "", "")
+DEF_ATTRIB(PERM, "Permute instruction", "", "")
DEF_ATTRIB(COF, "Change-of-flow instruction", "", "")
DEF_ATTRIB(HINTED_COF, "This instruction is a hinted change-of-flow", "", "")
DEF_ATTRIB(CONDEXEC, "May be cancelled by a predicate", "", "")
+DEF_ATTRIB(DOTOLD, "Uses a predicate generated in a previous packet", "", "")
+DEF_ATTRIB(DOTNEW, "Uses a predicate generated in the same packet", "", "")
DEF_ATTRIB(DOTNEWVALUE, "Uses a register value generated in this pkt", "", "")
DEF_ATTRIB(NEWCMPJUMP, "Compound compare and jump", "", "")
DEF_ATTRIB(NVSTORE, "New-value store", "", "")
DEF_ATTRIB(MEMOP, "memop", "", "")
-DEF_ATTRIB(ROPS_2, "Compound instruction worth 2 RISC-ops", "", "")
-DEF_ATTRIB(ROPS_3, "Compound instruction worth 3 RISC-ops", "", "")
+DEF_ATTRIB(ROPS_2, "Compound instruction worth 2 wimpy RISC-ops", "", "")
+DEF_ATTRIB(ROPS_3, "Compound instruction worth 3 wimpy 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_READS_FRAMEKEY, "Reads FRAMEKEY", "UREG.FRAMEKEY", "")
+DEF_ATTRIB(IMPLICIT_READS_FRAMELIMIT, "Reads FRAMELIMIT", "UREG.FRAMELIMIT", "")
+DEF_ATTRIB(IMPLICIT_READS_ELR, "Reads the ELR register", "MREG.ELR", "")
+DEF_ATTRIB(IMPLICIT_READS_SGP0, "Reads the SGP0 register", "MREG.SGP0", "")
+DEF_ATTRIB(IMPLICIT_READS_SGP1, "Reads the SGP1 register", "MREG.SGP1", "")
+DEF_ATTRIB(IMPLICIT_WRITES_SGP0, "Reads the SGP0 register", "", "MREG.SGP0")
+DEF_ATTRIB(IMPLICIT_WRITES_SGP1, "Reads the SGP1 register", "", "MREG.SGP1")
+DEF_ATTRIB(IMPLICIT_WRITES_STID_PRIO_ANYTHREAD, "Reads", "", "MREG.STID.PRIO")
+DEF_ATTRIB(IMPLICIT_WRITES_SRBIT, "Writes the OVF bit", "", "UREG.SR.OVF")
+DEF_ATTRIB(IMPLICIT_WRITES_FPFLAGS, "May write FP flags", "", "UREG.SR.FPFLAGS")
+DEF_ATTRIB(IMPLICIT_WRITES_LPCFG, "Writes the loop config", "", "UREG.SR.LPCFG")
+DEF_ATTRIB(IMPLICIT_WRITES_CVBITS, "Writes the CV flags", "", "UREG.SR.CV")
+DEF_ATTRIB(IMPLICIT_READS_FPRND, "May read FP rnd mode", "UREG.SR.FPRND", "")
+DEF_ATTRIB(IMPLICIT_READS_SSR, "May read SSR values", "MREG.SSR", "")
+DEF_ATTRIB(IMPLICIT_READS_CCR, "May read CCR values", "MREG.CCR", "")
+DEF_ATTRIB(IMPLICIT_WRITES_CCR, "May write CCR values", "", "MREG.CCR")
+DEF_ATTRIB(IMPLICIT_WRITES_SSR, "May write SSR values", "", "MREG.SSR")
+DEF_ATTRIB(IMPLICIT_READS_GELR, "May read GELR values", "GREG.GELR", "")
+DEF_ATTRIB(IMPLICIT_READS_GEVB, "May read GEVB values", "MREG.GEVB", "")
+DEF_ATTRIB(IMPLICIT_READS_GSR, "May read GSR values", "GREG.GSR", "")
+DEF_ATTRIB(IMPLICIT_READS_GOSP, "May read GOSP values", "GREG.GOSP", "")
+DEF_ATTRIB(IMPLICIT_WRITES_GELR, "May write GELR values", "", "GREG.GELR")
+DEF_ATTRIB(IMPLICIT_WRITES_GSR, "May write GSR values", "", "GREG.GSR")
+DEF_ATTRIB(IMPLICIT_WRITES_GOSP, "May write GOSP values", "", "GREG.GOSP")
+DEF_ATTRIB(IMPLICIT_READS_IPENDAD_IPEND, "May read", "MREG.IPENDAD.IPEND", "")
+DEF_ATTRIB(IMPLICIT_WRITES_IPENDAD_IPEND, "May write", "", "MREG.IPENDAD.IPEND")
+DEF_ATTRIB(IMPLICIT_READS_IPENDAD_IAD, "May read", "MREG.IPENDAD.IAD", "")
+DEF_ATTRIB(IMPLICIT_WRITES_IPENDAD_IAD, "May write", "", "MREG.IPENDAD.IAD")
+DEF_ATTRIB(IMPLICIT_WRITES_IMASK_ANYTHREAD, "May write", "", "MREG.IMASK")
+DEF_ATTRIB(IMPLICIT_READS_IMASK_ANYTHREAD, "May read", "MREG.IMASK", "")
+DEF_ATTRIB(IMPLICIT_READS_SYSCFG_K0LOCK, "May read", "MREG.SYSCFG.K0LOCK", "")
+DEF_ATTRIB(IMPLICIT_WRITES_SYSCFG_K0LOCK, "May write", "", "MREG.SYSCFG.K0LOCK")
+DEF_ATTRIB(IMPLICIT_READS_SYSCFG_TLBLOCK, "May read", "MREG.SYSCFG.TLBLOCK", "")
+DEF_ATTRIB(IMPLICIT_WRITES_SYSCFG_TLBLOCK, "May wr", "", "MREG.SYSCFG.TLBLOCK")
+DEF_ATTRIB(IMPLICIT_WRITES_SYSCFG_GCA, "May write", "", "MREG.SYSCFG.GCA")
+DEF_ATTRIB(IMPLICIT_READS_SYSCFG_GCA, "May read", "MREG.SYSCFG.GCA", "")
DEF_ATTRIB(IMPLICIT_WRITES_USR, "May write USR", "", "")
-DEF_ATTRIB(IMPLICIT_READS_SP, "Reads the SP register", "", "")
+
+/* Other things the instruction does */
+DEF_ATTRIB(ACC, "Has a multiply", "", "")
+DEF_ATTRIB(MPY, "Has a multiply", "", "")
+DEF_ATTRIB(SATURATE, "Does signed saturation", "", "")
+DEF_ATTRIB(USATURATE, "Does unsigned saturation", "", "")
+DEF_ATTRIB(CIRCADDR, "Uses circular addressing mode", "", "")
+DEF_ATTRIB(BREVADDR, "Uses bit reverse addressing mode", "", "")
+DEF_ATTRIB(BIDIRSHIFTL, "Uses a bidirectional shift left", "", "")
+DEF_ATTRIB(BIDIRSHIFTR, "Uses a bidirectional shift right", "", "")
+DEF_ATTRIB(BRANCHADDER, "Contains a PC-plus-immediate operation.", "", "")
+DEF_ATTRIB(CRSLOT23, "Can execute in slot 2 or slot 3 (CR)", "", "")
DEF_ATTRIB(COMMUTES, "The operation is communitive", "", "")
DEF_ATTRIB(DEALLOCRET, "dealloc_return", "", "")
DEF_ATTRIB(DEALLOCFRAME, "deallocframe", "", "")
-DEF_ATTRIB(CRSLOT23, "Can execute in slot 2 or slot 3 (CR)", "", "")
+/* Instruction Types */
+
+DEF_ATTRIB(IT_ALU, "ALU type", "", "")
+DEF_ATTRIB(IT_ALU_ADDSUB, "ALU add or subtract type", "", "")
+DEF_ATTRIB(IT_ALU_MINMAX, "ALU MIN or MAX type", "", "")
+DEF_ATTRIB(IT_ALU_MOVE, "ALU data movement type", "", "")
+DEF_ATTRIB(IT_ALU_LOGICAL, "ALU logical operation type", "", "")
+DEF_ATTRIB(IT_ALU_SHIFT, "ALU shift operation type", "", "")
+DEF_ATTRIB(IT_ALU_SHIFT_AND_OP, "ALU shift and additional op type", "", "")
+DEF_ATTRIB(IT_ALU_CMP, "ALU compare operation type", "", "")
+
+DEF_ATTRIB(IT_LOAD, "Loads from memory", "", "")
+DEF_ATTRIB(IT_STORE, "Stores to memory", "", "")
+
+DEF_ATTRIB(IT_MPY, "Multiply type", "", "")
+DEF_ATTRIB(IT_MPY_32, "32-bit Multiply type", "", "")
+
+DEF_ATTRIB(IT_COF, "Change-of-flow type", "", "")
+DEF_ATTRIB(IT_HWLOOP, "Sets up hardware loop registers", "", "")
+
+DEF_ATTRIB(IT_MISC, "misc instruction type", "", "")
+
DEF_ATTRIB(IT_NOP, "nop instruction", "", "")
DEF_ATTRIB(IT_EXTENDER, "constant extender instruction", "", "")
+/* Exceptions the instruction can generate */
+
+DEF_ATTRIB(EXCEPTION_TLB, "Can generate a TLB Miss Exception", "", "")
+DEF_ATTRIB(EXCEPTION_ACCESS, "Can generate Access Violation Exception", "", "")
+DEF_ATTRIB(EXCEPTION_SWI, "Software Interrupt (trap) exception", "", "")
+
+
+/* Documentation Notes */
+DEF_ATTRIB(NOTE_ARCHV2, "Only available in the V2 architecture", "", "")
+
+DEF_ATTRIB(NOTE_PACKET_PC, "The PC is the addr of the start of the pkt", "", "")
+
+DEF_ATTRIB(NOTE_PACKET_NPC, "Next PC is the address following pkt", "", "")
+
+DEF_ATTRIB(NOTE_CONDITIONAL, "can be conditionally executed", "", "")
+
+DEF_ATTRIB(NOTE_NEWVAL_SLOT0, "New-value oprnd must execute on slot 0", "", "")
+
+DEF_ATTRIB(NOTE_RELATIVE_ADDRESS, "A PC-relative address is formed", "", "")
+
+DEF_ATTRIB(NOTE_LA_RESTRICT, "Cannot be in the last pkt of a HW loop", "", "")
+
+DEF_ATTRIB(NOTE_OOBVSHIFT, "Possible shift overflow", "", "")
+DEF_ATTRIB(NOTE_BIDIRSHIFT, "Bidirectional shift", "", "")
+
+DEF_ATTRIB(NOTE_CVFLAGS, "Sets the Carry and Overflow flags in USR.", "", "")
+DEF_ATTRIB(NOTE_SR_OVF_WHEN_SATURATING, "Might set OVF bit", "", "")
+DEF_ATTRIB(NOTE_STNT,
+ "Non Temporal Data. The :nt appendix is a hint to the "
+ "microarchitecture indicating that the life of the cache line is "
+ "short. This information is used throughout the cache hierarchy to "
+ "make replacement and allocation decisions.",
+ "", "")
+DEF_ATTRIB(NOTE_PRIV, "Monitor-level feature", "", "")
+DEF_ATTRIB(NOTE_GUEST, "Guest-level feature", "", "")
+DEF_ATTRIB(NOTE_NOPACKET, "solo instruction", "", "")
+DEF_ATTRIB(NOTE_AXOK, "May only be grouped with ALU32 or non-FP XTYPE.", "", "")
+DEF_ATTRIB(NOTE_NOSLOT1, "Packet with this insn must have slot 1 empty", "", "")
+DEF_ATTRIB(NOTE_SLOT1_AOK, "Packet must have slot 1 empty or ALU32", "", "")
+DEF_ATTRIB(NOTE_NOSLOT01, "Packet must have both slot 1 and 2 empty", "", "")
+DEF_ATTRIB(NOTE_NEEDS_MEMLD, "Must be grouped with a memory load", "", "")
+DEF_ATTRIB(NOTE_LATEPRED, "The predicate can not be used as a .new", "", "")
+DEF_ATTRIB(NOTE_COMPAT_ACCURACY, "In the future accuracy may increase", "", "")
+DEF_ATTRIB(NOTE_NVSLOT0, "Can execute only in slot 0 (ST)", "", "")
+DEF_ATTRIB(NOTE_DEPRECATED, "Will be deprecated in a future version.", "", "")
+DEF_ATTRIB(NOTE_NONAPALIV1, "may not work correctly in Napali V1.", "", "")
+DEF_ATTRIB(NOTE_NOLAHAINAV1, "This may not work correctly in Lahaina V1.", "",
+ "")
+DEF_ATTRIB(NOTE_BADTAG_UNDEF, "Undefined if a tag is non-present", "", "")
+DEF_ATTRIB(NOTE_NOSLOT2_MPY, "Packet cannot have a slot 2 multiply", "", "")
+DEF_ATTRIB(NOTE_HVX_ONLY, "Only available on a core with HVX.", "", "")
+
+DEF_ATTRIB(NOTE_NOCOF_RESTRICT, "Cannot be grouped with any COF", "", "")
+DEF_ATTRIB(NOTE_BRANCHADDER_MAX1, "One PC-plus-offset calculation", "", "")
+
+DEF_ATTRIB(NOTE_CRSLOT23, "Execute on either slot2 or slot3 (CR)", "", "")
+DEF_ATTRIB(NOTE_EXTENSION_AUDIO, "Hexagon audio extensions", "", "")
+DEF_ATTRIB(NOTE_FETCHNT,
+ "Non Temporal Data Cache Prefetch. The :nt appendix is a hint to "
+ "the microarchitecture indicating that the life of the cache line "
+ "fetched is short. This information is used throughout the cache "
+ "hierarchy to make replacement and allocation decisions.",
+ "", "")
+DEF_ATTRIB(NOTE_VECX_V67, "This instruction is only available on V67", "", "")
+
+DEF_ATTRIB(NOTE_NOVP,
+ "This instruction cannot be paired with a HVX permute instruction",
+ "", "")
+DEF_ATTRIB(NOTE_VA_UNARY,
+ "If a packet contains this instruction and a HVX ALU op then the "
+ "ALU OP must be unary.",
+ "", "")
+
+
+/* V6 MMVector Notes for Documentation */
+DEF_ATTRIB(NOTE_ANY_RESOURCE, "Can use any HVX resource.", "", "")
+DEF_ATTRIB(NOTE_ANY2_RESOURCE, "Uses any pair of the HVX resources", "", "")
+DEF_ATTRIB(NOTE_PERMUTE_RESOURCE, "Uses the HVX permute resource.", "", "")
+DEF_ATTRIB(NOTE_SHIFT_RESOURCE, "Uses the HVX shift resource.", "", "")
+DEF_ATTRIB(NOTE_MPY_RESOURCE, "Uses a HVX multiply resource.", "", "")
+DEF_ATTRIB(NOTE_MPYDV_RESOURCE, "Uses both HVX multiply resources.", "", "")
+DEF_ATTRIB(NOTE_NT_VMEM, "Non-temporal hint to the micro-architecture", "", "")
+DEF_ATTRIB(NOTE_ALL_RESOURCE, "Uses all HVX resources.", "", "")
+DEF_ATTRIB(NOTE_VMEM, "Immediates are in multiples of vector length.", "", "")
+DEF_ATTRIB(NOTE_ANY_VS_VX_RESOURCE, "Consumes two resources", "", "")
+
+DEF_ATTRIB(NOTE_RT8, "Input scalar register Rt is limited to R0-R7", "", "")
+
+DEF_ATTRIB(NOTE_MX, "This is in-memory matrix multiply instruction.", "", "")
+DEF_ATTRIB(NOTE_VX_ACC_FWD,
+ "The accumulator (Vxx) source of this instruction must be generate "
+ "in the previous packet to avoid a stall. The accumulator cannot "
+ "come from a .tmp operation.",
+ "", "")
+DEF_ATTRIB(NOTE_TMP_NO_VX,
+ "The tmp load instruction destination register cannot be an "
+ "accumulator register.",
+ "", "")
+
+DEF_ATTRIB(
+ NOTE_NO_ECC,
+ "ECC is not supported for scatter and gather instructions. Enabling ECC "
+ "with unprotected access instructions result in undetermined behavior.",
+ "", "")
+
+/* FP8 instructions */
+DEF_ATTRIB(HVX_FP8, "HVX FP8 extension instruction", "", "")
+DEF_ATTRIB(HVX_IEEE_FP_OUT_8, "HVX IEEE FP extension instruction: 8-bit output",
+ "", "")
+
/* Restrictions to make note of */
+DEF_ATTRIB(RESTRICT_LOOP_LA, "Cannot be in the last packet of a loop", "", "")
+DEF_ATTRIB(RESTRICT_NEEDS_MEMLD, "Must be grouped with a load", "", "")
DEF_ATTRIB(RESTRICT_COF_MAX1, "One change-of-flow per packet", "", "")
DEF_ATTRIB(RESTRICT_NOPACKET, "Not allowed in a packet", "", "")
+DEF_ATTRIB(RESTRICT_NOSRMOVE, "Do not write SR in the same packet", "", "")
DEF_ATTRIB(RESTRICT_SLOT0ONLY, "Must execute on slot0", "", "")
DEF_ATTRIB(RESTRICT_SLOT1ONLY, "Must execute on slot1", "", "")
DEF_ATTRIB(RESTRICT_SLOT2ONLY, "Must execute on slot2", "", "")
DEF_ATTRIB(RESTRICT_SLOT3ONLY, "Must execute on slot3", "", "")
+DEF_ATTRIB(RESTRICT_NOSLOT2_MPY, "A packet cannot have a slot 2 mpy", "", "")
DEF_ATTRIB(RESTRICT_NOSLOT1, "No slot 1 instruction in parallel", "", "")
+DEF_ATTRIB(RESTRICT_SLOT1_AOK, "Slot 1 insn must be empty or A-type", "", "")
+DEF_ATTRIB(RESTRICT_NOSLOT01, "No slot 0 or 1 instructions in parallel", "", "")
+DEF_ATTRIB(RESTRICT_NOSLOT1_STORE, "Packet must not have slot 1 store", "", "")
+DEF_ATTRIB(RESTRICT_NOSLOT0_LOAD, "Packet must not have a slot 1 load", "", "")
+DEF_ATTRIB(RESTRICT_NOCOF, "Cannot be grouped with any COF", "", "")
+DEF_ATTRIB(RESTRICT_BRANCHADDER_MAX1, "One PC-plus-offset calculation", "", "")
DEF_ATTRIB(RESTRICT_PREFERSLOT0, "Try to encode into slot 0", "", "")
+DEF_ATTRIB(RESTRICT_SINGLE_MEM_FIRST, "Single memory op must be last", "", "")
DEF_ATTRIB(RESTRICT_PACKET_AXOK, "May exist with A-type or X-type", "", "")
+DEF_ATTRIB(RESTRICT_PACKET_SOMEREGS_OK, "Relaxed grouping rules", "", "")
+DEF_ATTRIB(RESTRICT_LATEPRED, "Predicate can not be used as a .new.", "", "")
+
+DEF_ATTRIB(PAIR_1OF2, "For assembler", "", "")
+DEF_ATTRIB(PAIR_2OF2, "For assembler", "", "")
+DEF_ATTRIB(NOTE_MX_PAIR,
+ "Weights and Activations need to be paired in a packet.", "", "")
+DEF_ATTRIB(NOTE_RESTRICT_CVI_NOVP,
+ "This instruction cannot use the permute/shift resource", "", "")
+
+/* Performance based preferences */
+DEF_ATTRIB(PREFER_SLOT3, "Complex XU prefering slot3", "", "")
+
+DEF_ATTRIB(RELAX_COF_1ST, "COF can be fisrt in assembly order", "", "")
+DEF_ATTRIB(RELAX_COF_2ND, "COF can be second in assembly order", "", "")
DEF_ATTRIB(ICOP, "Instruction cache op", "", "")
+DEF_ATTRIB(INTRINSIC_RETURNS_UNSIGNED, "Intrinsic returns an unsigned", "", "")
+
+DEF_ATTRIB(PRED_BIT_1, "The branch uses bit 1 as the prediction bit", "", "")
+DEF_ATTRIB(PRED_BIT_4, "The branch uses bit 4 as the prediction bit", "", "")
+DEF_ATTRIB(PRED_BIT_8, "The branch uses bit 8 as the prediction bit", "", "")
+DEF_ATTRIB(PRED_BIT_12, "The branch uses bit 12 as the prediction bit", "", "")
+DEF_ATTRIB(PRED_BIT_13, "The branch uses bit 13 as the prediction bit", "", "")
+DEF_ATTRIB(PRED_BIT_7, "The branch uses bit 7 as the prediction bit", "", "")
+DEF_ATTRIB(HWLOOP0_SETUP, "Sets up HW loop0", "", "")
+DEF_ATTRIB(HWLOOP1_SETUP, "Sets up HW loop1", "", "")
DEF_ATTRIB(HWLOOP0_END, "Ends HW loop0", "", "")
DEF_ATTRIB(HWLOOP1_END, "Ends HW loop1", "", "")
DEF_ATTRIB(RET_TYPE, "return type", "", "")
+DEF_ATTRIB(HINTJR, "hintjr type", "", "")
DEF_ATTRIB(DCZEROA, "dczeroa type", "", "")
+DEF_ATTRIB(ICTAGOP, "ictag op type", "", "")
DEF_ATTRIB(ICFLUSHOP, "icflush op type", "", "")
DEF_ATTRIB(DCFLUSHOP, "dcflush op type", "", "")
+DEF_ATTRIB(DCTAGOP, "dctag op type", "", "")
DEF_ATTRIB(L2FLUSHOP, "l2flush op type", "", "")
+DEF_ATTRIB(L2TAGOP, "l2tag op type", "", "")
DEF_ATTRIB(DCFETCH, "dcfetch type", "", "")
+DEF_ATTRIB(BIMODAL_BRANCH, "Updates the bimodal branch predictor", "", "")
+DEF_ATTRIB(VECINSN, "Long Vector Instruction", "", "")
+DEF_ATTRIB(MEMSIZE_32B, "Memory width is 32 bytes", "", "")
+DEF_ATTRIB(FOUR_PHASE, "Four Phase Instruction", "", "")
DEF_ATTRIB(L2FETCH, "Instruction is l2fetch type", "", "")
+DEF_ATTRIB(PREDUSE_BSB, "Instructions need back-skip-back scheduling", "", "")
DEF_ATTRIB(ICINVA, "icinva", "", "")
DEF_ATTRIB(DCCLEANINVA, "dccleaninva", "", "")
+DEF_ATTRIB(EXTENSION_AUDIO, "audio extension", "", "")
+
+DEF_ATTRIB(MEMCPY, "memcpy or dma-type instruction", "", "")
DEF_ATTRIB(NO_INTRINSIC, "Don't generate an intrisic", "", "")
-/* Documentation Notes */
-DEF_ATTRIB(NOTE_CONDITIONAL, "can be conditionally executed", "", "")
-DEF_ATTRIB(NOTE_NEWVAL_SLOT0, "New-value oprnd must execute on slot 0", "", "")
-DEF_ATTRIB(NOTE_PRIV, "Monitor-level feature", "", "")
-DEF_ATTRIB(NOTE_NOPACKET, "solo instruction", "", "")
-DEF_ATTRIB(NOTE_AXOK, "May only be grouped with ALU32 or non-FP XTYPE.", "", "")
-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(NO_XML, "Don't generate a XML docs for this instruction", "", "")
-/* V6 MMVector Notes for Documentation */
-DEF_ATTRIB(NOTE_SHIFT_RESOURCE, "Uses the HVX shift resource.", "", "")
-/* Restrictions to make note of */
-DEF_ATTRIB(RESTRICT_NOSLOT1_STORE, "Packet must not have slot 1 store", "", "")
-DEF_ATTRIB(RESTRICT_LATEPRED, "Predicate can not be used as a .new.", "", "")
+DEF_ATTRIB(DMA, "User-DMA instruction", "", "")
+DEF_ATTRIB(VERIF_DMASTEP,
+ "Hiphop needs to step dma prior to executing this packet", "", "")
+DEF_ATTRIB(VERIF_DMATICK,
+ "DMA gets a tick in verif mode for this instruction after a commit",
+ "", "")
+
+DEF_ATTRIB(HVX_IEEE_FP, "HVX IEEE FP extension instruction", "", "")
+DEF_ATTRIB(NOTE_HVX_IEEE_FP,
+ "Only supported on the HVX cores with the IEEE FP extension", "", "")
+
+DEF_ATTRIB(HVX_IEEE_FP_DV_ONE,
+ "HVX IEEE FP extension instruction - dual pipes: P2 and P3 - output "
+ "only on P2",
+ "", "")
+DEF_ATTRIB(HVX_IEEE_FP_ACC, "HVX IEEE FP accumulate instruction", "", "")
+DEF_ATTRIB(HVX_IEEE_BF,
+ "HVX IEEE BF extension instruction: 16-bit bfloat input", "", "")
+DEF_ATTRIB(HVX_IEEE_FP_OUT_BF,
+ "HVX IEEE FP extension instruction: 16-bit bfloat output", "", "")
+DEF_ATTRIB(HVX_IEEE_FP_OUT_16,
+ "HVX IEEE FP extension instruction: 16-bit output", "", "")
+DEF_ATTRIB(HVX_IEEE_FP_OUT_32,
+ "HVX IEEE FP extension instruction: 32-bit output", "", "")
+DEF_ATTRIB(HVX_IEEE_FP_BINARY_LATE,
+ "HVX IEEE FP extension instruction: Both inputs can arrive late", "",
+ "")
/* Keep this as the last attribute: */
DEF_ATTRIB(ZZ_LASTATTRIB, "Last attribute in the file", "", "")
diff --git a/target/hexagon/imported/macros.def b/target/hexagon/imported/macros.def
old mode 100755
new mode 100644
index 4bbcfdd5e1..f24f89f361
--- 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,209 @@ DEF_MACRO(fECHO,
/* OS interface and stop/wait */
/********************************************/
+DEF_MACRO(RUNNABLE_THREADS_MAX,
+ (thread->processor_ptr->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,
+ (((TH) >= (thread->processor_ptr->runnable_threads_max)) ? 0 : (thread->processor_ptr->thread[TH]->Regs[REG_IMASK])),
+ ()
+)
+DEF_MACRO(WRITE_IMASK,
+ if ((TH) < (thread->processor_ptr->runnable_threads_max)) { thread->processor_ptr->thread[TH]->Regs[REG_IMASK]=(VAL & reg_mutability[REG_IMASK] ); },
+ (A_IMPLICIT_WRITES_IMASK_ANYTHREAD)
+)
+
+
+DEF_MACRO(WRITE_PRIO,
+ {
+ if ((TH) < (thread->processor_ptr->runnable_threads_max)) {
+ size4u_t tid_reg = thread->processor_ptr->thread[TH]->Regs[REG_TID];
+ fINSERT_BITS(tid_reg, reg_field_info[STID_PRIO].width, reg_field_info[STID_PRIO].offset, VAL);
+ LOG_OTHER_THREAD_REG_WRITE(thread,REG_TID,tid_reg,TH);
+ }
+ },
+ (A_IMPLICIT_WRITES_STID_PRIO_ANYTHREAD)
+)
+
+
+DEF_MACRO(DO_IASSIGNW,
+ {
+ int i;
+ int intbitpos = ((REG>>16)&0xF);
+ for (i=0;i<RUNNABLE_THREADS_MAX;i++) {
+ if(( (thread->processor_ptr->arch_proc_options->thread_enable_mask>>i) & 0x1)) {
+ fINSERT_BITS(thread->processor_ptr->thread[i]->Regs[REG_IMASK],1, intbitpos, (REG>>i) & 1);
+ }
+ }
+ },
+ (A_IMPLICIT_WRITES_IMASK_ANYTHREAD)
+)
+
+
+
+
+DEF_MACRO(fDO_NMI,
+ {
+ int i;
+ for (i=0;i<RUNNABLE_THREADS_MAX;i++) {
+ if( ( (thread->processor_ptr->arch_proc_options->thread_enable_mask>>i) & 0x1) ) {
+ if (SREG & (1<<i)) {
+ register_nmi_interrupt(thread->processor_ptr->thread[i]);
+ }
+ }
+ }
+ },
+)
+
+DEF_MACRO(fDO_TRACE,
+ {
+ fHIDE(HEX_CALLBACK(thread->processor_ptr->options->trace_callback,
+ thread->system_ptr,thread->processor_ptr,
+ thread->threadId,SREG);)
+ },
+)
+
+DEF_MACRO(DO_IASSIGNR,
+ {
+ int i;
+ int result=0;
+ int intbitpos = ((SREG>>16)&0xF);
+ for (i=0;i<RUNNABLE_THREADS_MAX;i++) {
+ if(( (thread->processor_ptr->arch_proc_options->thread_enable_mask>>i) & 0x1)) {
+ result |= (((thread->processor_ptr->thread[i]->Regs[REG_IMASK]>>intbitpos)&1)<<i);
+ }
+ }
+ DREG=result;
+ },
+ ()
+)
+
+DEF_MACRO(DO_SWI,
+ {fHIDE(HEX_CALLBACK(thread->processor_ptr->options->swi_callback,
+ thread->system_ptr,thread->processor_ptr,
+ thread->threadId,REG));
+ LOG_GLOBAL_REG_WRITE(REG_IPEND,(GLOBAL_REG_READ(REG_IPEND) | (REG & GLOBAL_REG_READ(REG_IEL))));
+ },
+ (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,
+ {isdb_brkpt_insn(thread->processor_ptr,thread->threadId);},
+ ()
+)
+
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(fINTERNAL_CLEAR_SAMEPAGE,
+ /* force re-xlate at next fetch, refresh of in_user_mode, etc */
+ /* Permissions change too... */
+ sys_utlb_invalidate(thread->processor_ptr,thread),
+ /* NOTHING */
+)
+
+DEF_MACRO(fCLEAR_RTE_EX,
+ {
+ fLOG_REG_FIELD(SSR,SSR_EX,0);
+ fINTERNAL_CLEAR_SAMEPAGE();
+ },
+ ()
+)
+
+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,
+ {
+ if (fK0_LOCK_AVAILABLE() && sys_k0lock_queue_ready(thread)) {
+ warn("k0lock: T%d: PC=0x%x: PCycle=%lld",thread->threadId,thread->Regs[REG_PC],thread->processor_ptr->pstats[pcycles]);
+ fLOG_GLOBAL_REG_FIELD(SYSCONF,SYSCFG_K0LOCK,1);
+ } else {
+ warn("k0lock_waiting: T%d: PC=0x%x: PCycle=%lld",thread->threadId,thread->Regs[REG_PC],thread->processor_ptr->pstats[pcycles]);
+ sys_waiting_for_k0_lock(thread);
+ }
+ },
+ ()
+)
+
+DEF_MACRO(fCLEAR_TLB_LOCK,
+ {
+ int i;
+ fLOG_GLOBAL_REG_FIELD(SYSCONF,SYSCFG_TLBLOCK,0);
+ for (i = 0; i < RUNNABLE_THREADS_MAX; i++) {
+ if(( (thread->processor_ptr->arch_proc_options->thread_enable_mask>>i) & 0x1)) {
+ thread->processor_ptr->thread[i]->cu_tlb_lock_waiting = 0;
+ }
+ }
+ },
+ ()
+)
+
+DEF_MACRO(fCLEAR_K0_LOCK,
+ do {
+ warn("k0unlock: T%d: PC=0x%x: Pcycle=%lld",thread->threadId,thread->Regs[REG_PC], thread->processor_ptr->pstats[pcycles]);
+ sys_initiate_clear_k0_lock(thread);
+ } while (0),
+ ()
+)
+
DEF_MACRO(fALIGN_REG_FIELD_VALUE,
((VAL)<<reg_field_info[FIELD].offset),
/* */
@@ -1554,6 +1781,26 @@ 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,
+ fINSERT_BITS(thread->processor_ptr->global_regs[REG_##REG],
+ reg_field_info[FIELD].width,
+ reg_field_info[FIELD].offset,VAL),
+)
+
+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 +1808,13 @@ DEF_MACRO(fREAD_REG_FIELD,
/* ATTRIBS */
)
+DEF_MACRO(fREAD_GLOBAL_REG_FIELD,
+ fEXTRACTU_BITS(thread->processor_ptr->global_regs[REG_##REG],
+ reg_field_info[FIELD].width,
+ reg_field_info[FIELD].offset),
+ /* ATTRIBS */
+)
+
DEF_MACRO(fGET_FIELD,
fEXTRACTU_BITS(VAL,
reg_field_info[FIELD].width,
@@ -1576,6 +1830,185 @@ DEF_MACRO(fSET_FIELD,
/* ATTRIBS */
)
+DEF_MACRO(fSET_RUN_MODE_NOW,
+ {thread->processor_ptr->global_regs[REG_MODECTL] |= (1<<TNUM);
+ thread->last_commit_cycle = thread->processor_ptr->pcycle_counter;
+ sys_recalc_num_running_threads(thread->processor_ptr);},
+)
+
+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,
+ do {
+ fWRITE_GLOBAL_REG_FIELD(MODECTL,MODECTL_E,
+ fREAD_GLOBAL_REG_FIELD(MODECTL,MODECTL_E) & ~(1<<(TNUM)));
+ sys_recalc_num_running_threads(thread->processor_ptr);
+ } while (0),
+ /* NOTHING */
+)
+
+DEF_MACRO(fGET_RUN_MODE,
+ ((thread->processor_ptr->global_regs[REG_MODECTL]>>TNUM)&0x1),
+)
+
+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,
+ {thread->processor_ptr->global_regs[REG_MODECTL] &= ~(1<<(TNUM+16));
+ thread->last_commit_cycle = thread->processor_ptr->pcycle_counter;
+ sys_recalc_num_running_threads(thread->processor_ptr);},
+)
+
+DEF_MACRO(fGET_WAIT_MODE,
+ ((thread->processor_ptr->global_regs[REG_MODECTL]>>(TNUM+16))&0x1),
+)
+
+
+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,
+ ((INDEX) & (fPOW2_ROUNDUP(fCAST4u(thread->processor_ptr->arch_proc_options->jtlb_size)) - 1)),
+ ()
+)
+
+DEF_MACRO(fTLB_NONPOW2WRAP,
+ (((INDEX) >= thread->processor_ptr->arch_proc_options->jtlb_size) ? ((INDEX) - thread->processor_ptr->arch_proc_options->jtlb_size) : (INDEX)),
+ /* ATTRIBS */
+)
+
+DEF_MACRO(fTLBW,
+ do {size4u_t __myidx = fTLB_NONPOW2WRAP(fTLB_IDXMASK(INDEX));
+ TLB_REG_WRITE(__myidx,VALUE);
+ fHIDE(HEX_CALLBACK(thread->processor_ptr->options->tlbw_callback,thread->system_ptr,thread->processor_ptr,thread->threadId,__myidx);)
+ fHIDE(sys_tlb_write(thread,__myidx,VALUE);)} while (0),
+ /* 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,
+ fLOG_GLOBAL_REG_FIELD(MODECTL,MODECTL_E, fREAD_GLOBAL_REG_FIELD(MODECTL,MODECTL_E) | (((REG & ((1<<RUNNABLE_THREADS_MAX)-1))) & THREAD_EN_MASK(thread->processor_ptr))),
+ ()
+)
+
+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,6 +2035,11 @@ DEF_MACRO(fISYNC,
)
+DEF_MACRO(fICFETCH,
+ ,
+ ()
+)
+
DEF_MACRO(fDCFETCH,
sys_dcfetch(thread, (REG), insn->slot),
(A_MEMLIKE)
@@ -1615,6 +2053,34 @@ DEF_MACRO(fICINVA,
(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 +2101,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 +2117,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,
+ { sys_siad(thread,INT_NUMTOMASK(intnum)); thread->processor_ptr->global_regs[REG_IAD] |= INT_NUMTOMASK(intnum); },
+ ()
+)
+
DEF_MACRO(fBRANCH_SPECULATE_STALL,
{
sys_speculate_branch_stall(thread, insn->slot, JUMP_COND(JUMP_PRED_SET),
@@ -1664,3 +2146,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 v2 17/40] target/hexagon: Define DCache states
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (15 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 16/40] target/hexagon: Add imported macro, attr defs for sysemu Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 18/40] target/hexagon: Add new macro definitions for sysemu Brian Cain
` (22 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/cpu_bits.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/target/hexagon/cpu_bits.h b/target/hexagon/cpu_bits.h
index b118761e05..c7cc426ec8 100644
--- a/target/hexagon/cpu_bits.h
+++ b/target/hexagon/cpu_bits.h
@@ -101,6 +101,13 @@ enum hex_cause {
HEX_CAUSE_VIC3 = 0x0c5,
};
+enum data_cache_state {
+ HEX_DC_STATE_INVALID = 0x0,
+ HEX_DC_STATE_VALID = 0x1,
+ HEX_DC_STATE_RESERVED = 0x2,
+ HEX_DC_STATE_UNUSED_WT = 0x3,
+};
+
#define PACKET_WORDS_MAX 4
static inline uint32_t parse_bits(uint32_t encoding)
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 18/40] target/hexagon: Add new macro definitions for sysemu
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (16 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 17/40] target/hexagon: Define DCache states Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 19/40] target/hexagon: Add handlers for guest/sysreg r/w Brian Cain
` (21 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Also: add nop TCG overrides for break,unpause,fetchbo,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 cache/prefetch functions are not modeled, dczero and fetchbo are
safe to ignore.
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/gen_tcg.h | 9 ++
target/hexagon/macros.h | 30 ++++-
target/hexagon/sys_macros.h | 238 ++++++++++++++++++++++++++++++++++++
target/hexagon/op_helper.c | 1 +
4 files changed, 274 insertions(+), 4 deletions(-)
create mode 100644 target/hexagon/sys_macros.h
diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 8a3b801287..71f8a0e2d0 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) \
@@ -1133,6 +1134,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; \
@@ -1342,6 +1346,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 9ba9be408d..4823c97fde 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -538,9 +538,6 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
#ifdef CONFIG_USER_ONLY
#define fFRAMECHECK(ADDR, EA) do { } while (0) /* Not modelled in linux-user */
-#else
-/* System mode not implemented yet */
-#define fFRAMECHECK(ADDR, EA) g_assert_not_reached();
#endif
#ifdef QEMU_GENERATE
@@ -631,8 +628,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)
@@ -649,10 +656,25 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
ctx->dczero_addr = tcg_temp_new(); \
tcg_gen_mov_tl(ctx->dczero_addr, (REG)); \
} while (0)
+#else
+#define fDCZEROA(REG) ((void) REG)
#endif
#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
#endif
+
+#define fPREDUSE_TIMING()
diff --git a/target/hexagon/sys_macros.h b/target/hexagon/sys_macros.h
new file mode 100644
index 0000000000..3c4c3c7aa5
--- /dev/null
+++ b/target/hexagon/sys_macros.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright(c) 2019-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ * 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
+
+#define READ_SREG(NUM) arch_get_system_reg(env, NUM)
+#define READ_SGP0() arch_get_system_reg(env, HEX_SREG_SGP0)
+#define READ_SGP1() arch_get_system_reg(env, HEX_SREG_SGP1)
+#define READ_SGP10() ((uint64_t)arch_get_system_reg(env, HEX_SREG_SGP0) | \
+ ((uint64_t)arch_get_system_reg(env, HEX_SREG_SGP1) << 32))
+
+#define WRITE_SREG(NUM, VAL) log_sreg_write(env, NUM, VAL, slot)
+#define WRITE_SGP0(VAL) log_sreg_write(env, HEX_SREG_SGP0, VAL, slot)
+#define WRITE_SGP1(VAL) log_sreg_write(env, HEX_SREG_SGP1, VAL, slot)
+#define WRITE_SGP10(VAL) \
+ do { \
+ log_sreg_write(env, HEX_SREG_SGP0, (VAL) & 0xFFFFFFFF, slot); \
+ log_sreg_write(env, HEX_SREG_SGP1, (VAL) >> 32, slot); \
+ } while (0)
+
+#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 { \
+ uint32_t regval = arch_get_system_reg(ENV, REG); \
+ fINSERT_BITS(regval, reg_field_info[FIELD].width, \
+ reg_field_info[FIELD].offset, (VAL)); \
+ arch_set_system_reg(ENV, REG, regval); \
+ } 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, arch_get_system_reg(ENV, 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() (READ_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 fFRAMECHECK(ADDR, EA) g_assert_not_reached();
+
+#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, READ_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 = 0; \
+ tmp = arch_get_system_reg(env, 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 fSET_TLB_LOCK() g_assert_not_reached()
+#define fCLEAR_TLB_LOCK() g_assert_not_reached()
+
+#define fSET_K0_LOCK() g_assert_not_reached()
+#define fCLEAR_K0_LOCK() g_assert_not_reached()
+
+#define fTLB_IDXMASK(INDEX) \
+ ((INDEX) & (fPOW2_ROUNDUP(fCAST4u(env_archcpu(env)->num_tlbs)) - 1))
+
+#define fTLB_NONPOW2WRAP(INDEX) \
+ (((INDEX) >= env_archcpu(env)->num_tlbs) ? \
+ ((INDEX) - env_archcpu(env)->num_tlbs) : \
+ (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) \
+ (env->hex_tlb->entries[fTLB_NONPOW2WRAP(fTLB_IDXMASK(INDEX))])
+#define fTLBR_EXTENDED(INDEX) \
+ (env->hex_tlb->entries[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) \
+ ((GET_FIELD(ISDBST_DEBUGMODE, arch_get_system_reg(env, HEX_SREG_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 = HEX_DC_STATE_INVALID | 0x00; \
+ } while (0)
+#endif
+
+#endif
+
+#define NUM_TLB_REGS(x) (env_archcpu(env)->num_tlbs)
+
+#endif
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 444799d3ad..c3140b97bd 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"
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 19/40] target/hexagon: Add handlers for guest/sysreg r/w
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (17 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 18/40] target/hexagon: Add new macro definitions for sysemu Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 20/40] target/hexagon: Add placeholder greg/sreg r/w helpers Brian Cain
` (20 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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.
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/genptr.c | 138 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 138 insertions(+)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 08fc5413de..a474787816 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"
@@ -128,6 +129,143 @@ 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 val)
+{
+ tcg_gen_mov_tl(ctx->greg_new_value[rnum], val);
+}
+
+G_GNUC_UNUSED
+static void gen_log_greg_write_pair(DisasContext *ctx, int rnum, TCGv_i64 val)
+{
+ TCGv val32 = tcg_temp_new();
+
+ /* 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 target_ulong 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 val)
+{
+ const target_ulong 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_tl(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 val32 = tcg_temp_new();
+
+ /* 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 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_tl(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 badva = tcg_temp_new();
+ gen_helper_sreg_read(badva, tcg_env,
+ tcg_constant_tl(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_tl(reg_num));
+ }
+}
+
+G_GNUC_UNUSED
+static void gen_read_greg(TCGv dst, int reg_num)
+{
+ gen_helper_greg_read(dst, tcg_env, tcg_constant_tl(reg_num));
+}
+
+G_GNUC_UNUSED
+static void gen_read_greg_pair(TCGv_i64 dst, int reg_num)
+{
+ gen_helper_greg_read_pair(dst, tcg_env, tcg_constant_tl(reg_num));
+}
+#endif
+
+
void gen_log_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 v2 20/40] target/hexagon: Add placeholder greg/sreg r/w helpers
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (18 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 19/40] target/hexagon: Add handlers for guest/sysreg r/w Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 21/40] target/hexagon: Add vmstate representation Brian Cain
` (19 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 | 9 +++++++++
target/hexagon/op_helper.c | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h
index f8baa599c8..fddbd99a19 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -107,3 +107,12 @@ 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, void, env, i32, i32)
+DEF_HELPER_3(sreg_write_pair, void, env, i32, i64)
+#endif
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index c3140b97bd..72bb75a878 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1315,6 +1315,40 @@ void HELPER(vwhist128qm)(CPUHexagonState *env, int32_t uiV)
}
}
+#ifndef CONFIG_USER_ONLY
+void HELPER(sreg_write)(CPUHexagonState *env, uint32_t reg, uint32_t val)
+{
+ g_assert_not_reached();
+}
+
+void HELPER(sreg_write_pair)(CPUHexagonState *env, uint32_t reg, uint64_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 v2 21/40] target/hexagon: Add vmstate representation
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (19 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 20/40] target/hexagon: Add placeholder greg/sreg r/w helpers Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 22/40] target/hexagon: Make A_PRIV, "J2_trap*" insts need_env() Brian Cain
` (18 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 | 25 +++++++++++++++++++++++++
3 files changed, 32 insertions(+)
create mode 100644 target/hexagon/machine.c
diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index 32e96f00d9..9658141316 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 fa52ad7453..39b45e6452 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -377,6 +377,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 0000000000..988ede06e9
--- /dev/null
+++ b/target/hexagon/machine.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright(c) 2023-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ * 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 = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT(parent_obj, HexagonCPU, 0, vmstate_cpu_common, CPUState),
+ VMSTATE_UINTTL_ARRAY(env.gpr, HexagonCPU, TOTAL_PER_THREAD_REGS),
+ VMSTATE_UINTTL_ARRAY(env.pred, HexagonCPU, NUM_PREGS),
+ VMSTATE_UINTTL_ARRAY(env.t_sreg, HexagonCPU, NUM_SREGS),
+ VMSTATE_UINTTL_ARRAY(env.greg, HexagonCPU, NUM_GREGS),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 22/40] target/hexagon: Make A_PRIV, "J2_trap*" insts need_env()
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (20 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 21/40] target/hexagon: Add vmstate representation Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 23/40] target/hexagon: Define register fields for system regs Brian Cain
` (17 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 fa122b6d76..fe5263e13f 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -251,7 +251,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 v2 23/40] target/hexagon: Define register fields for system regs
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (21 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 22/40] target/hexagon: Make A_PRIV, "J2_trap*" insts need_env() Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:46 ` [PATCH v2 24/40] target/hexagon: Implement do_raise_exception() Brian Cain
` (16 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 f2a58d486c..9b112ccec6 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 v2 24/40] target/hexagon: Implement do_raise_exception()
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (22 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 23/40] target/hexagon: Define register fields for system regs Brian Cain
@ 2025-09-02 3:46 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 25/40] target/hexagon: Add system reg insns Brian Cain
` (15 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:46 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/internal.h | 5 +++++
target/hexagon/op_helper.c | 20 ++++++++++++++++++++
2 files changed, 25 insertions(+)
diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index 9658141316..7cf7bcaa6c 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,
+ target_ulong 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 72bb75a878..cbbf3048a0 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -37,6 +37,26 @@
#define SF_MANTBITS 23
/* Exceptions processing helpers */
+G_NORETURN
+void do_raise_exception(CPUHexagonState *env, uint32_t exception,
+ target_ulong PC, uintptr_t retaddr)
+{
+ CPUState *cs = env_cpu(env);
+#ifdef CONFIG_USER_ONLY
+ qemu_log_mask(CPU_LOG_INT, "%s: 0x%08x\n", __func__, exception);
+#else
+ qemu_log_mask(CPU_LOG_INT, "%s: 0x%08x, @ %08" PRIx32 "\n",
+ __func__, exception, PC);
+
+ ASSERT_DIRECT_TO_GUEST_UNSET(env, exception);
+#endif
+
+ env->gpr[HEX_REG_PC] = PC;
+ cs->exception_index = exception;
+ cpu_loop_exit_restore(cs, retaddr);
+ cs->halted = false;
+}
+
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 v2 25/40] target/hexagon: Add system reg insns
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (23 preceding siblings ...)
2025-09-02 3:46 ` [PATCH v2 24/40] target/hexagon: Implement do_raise_exception() Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 26/40] target/hexagon: Add sysemu TCG overrides Brian Cain
` (14 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/hex_common.py | 15 +-
target/hexagon/imported/encode_pp.def | 213 +++++++++++++++------
target/hexagon/imported/system.idef | 262 +++++++++++++++++++++++---
3 files changed, 408 insertions(+), 82 deletions(-)
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index fe5263e13f..24139cbe67 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -1237,11 +1237,18 @@ def init_registers():
for reg in new_regs:
new_registers[f"{reg.regtype}{reg.regid}"] = reg
+def is_new_reg(tag, regid):
+ if regid[0] in "NO":
+ return True
+ return regid[0] == "P" and \
+ f"{regid}N" in semdict[tag] and \
+ f"{regid}V" not in semdict[tag]
+
def get_register(tag, regtype, regid):
- if f"{regtype}{regid}V" in semdict[tag]:
- return registers[f"{regtype}{regid}"]
- else:
- return new_registers[f"{regtype}{regid}"]
+ regid = f"{regtype}{regid}"
+ is_new = is_new_reg(tag, regid)
+ reg = new_registers[regid] if is_new else registers[regid]
+ return reg
def helper_ret_type(tag, regs):
## If there is a scalar result, it is the return type
diff --git a/target/hexagon/imported/encode_pp.def b/target/hexagon/imported/encode_pp.def
index 0cd30a5e85..37faf62b1b 100644
--- a/target/hexagon/imported/encode_pp.def
+++ b/target/hexagon/imported/encode_pp.def
@@ -1,5 +1,5 @@
/*
- * Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ * Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,6 +16,7 @@
*/
/*
+ * encode32.def
* Encodings for 32 bit instructions
*
*/
@@ -341,6 +342,8 @@ DEF_ENC32(L4_pload##TAG##tnew_abs,ICLASS_LD" 1 11 "OPC" iiiii PP110tti 1--ddd
DEF_ENC32(L4_pload##TAG##fnew_abs,ICLASS_LD" 1 11 "OPC" iiiii PP111tti 1--ddddd")
+
+
/* 0 000 misc: dealloc,loadw_locked,dcfetch */
STD_LD_ENC(bzw4,"0 101")
STD_LD_ENC(bzw2,"0 011")
@@ -375,6 +378,7 @@ DEF_ANTICLASS32(ICLASS_LD" 1110 000----- PP------ --------",LD_ADDR_POST_REG)
DEF_ENC32(L2_deallocframe, ICLASS_LD" 000 0 000 sssss PP0----- ---ddddd")
DEF_ENC32(L4_return, ICLASS_LD" 011 0 000 sssss PP0000-- ---ddddd")
+
DEF_ENC32(L4_return_t, ICLASS_LD" 011 0 000 sssss PP0100vv ---ddddd")
DEF_ENC32(L4_return_f, ICLASS_LD" 011 0 000 sssss PP1100vv ---ddddd")
DEF_ENC32(L4_return_tnew_pt, ICLASS_LD" 011 0 000 sssss PP0110vv ---ddddd")
@@ -382,15 +386,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 +405,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 +493,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_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 +511,34 @@ 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 +581,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)")
@@ -591,7 +635,6 @@ DEF_ENC32(J2_callf, ICLASS_J" 1101 ii1iiiii PPi-0-uu iiiiiii-")
/*******************************/
-/* EJP: this has to match what we have in htmldocs.py... so I will call it CJ, we can change it */
DEF_CLASS32(ICLASS_CJ" 0--- -------- PP------ --------",CJ)
DEF_FIELDROW_DESC32(ICLASS_CJ" 00-- -------- -------- --------","[#0-3] pd=cmp.xx(R,#u5) ; if ([!]p0.new) jump:[h] #s9:2 ")
@@ -738,12 +781,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 +804,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")
@@ -776,8 +827,66 @@ DEF_ENC32(C4_and_orn, ICLASS_CR" 1011 1011--ss PP0---tt uu----dd")
DEF_ENC32(C4_or_andn, ICLASS_CR" 1011 1101--ss PP0---tt uu----dd")
DEF_ENC32(C4_or_orn, ICLASS_CR" 1011 1111--ss PP0---tt uu----dd")
-DEF_ENC32(C4_fastcorner9, ICLASS_CR"1011 0000--ss PP1---tt 1--1--dd")
-DEF_ENC32(C4_fastcorner9_not, ICLASS_CR"1011 0001--ss PP1---tt 1--1--dd")
+DEF_ENC32(C4_fastcorner9, ICLASS_CR"1011 0000--ss PP1---tt 1--1--dd")
+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")
+
+
+
+
+
@@ -956,9 +1065,9 @@ MPY_ENC(F2_dfmin, "1000","ddddd","0","0","1","1","11")
MPY_ENC(F2_dfmax, "1000","ddddd","0","1","0","0","11")
MPY_ENC(F2_dfmpyll, "1000","ddddd","0","1","0","1","11")
-MPY_ENC(M7_dcmpyrw, "1000","ddddd","0","0","0","1","10")
+MPY_ENC(M7_dcmpyrw, "1000","ddddd","0","0","0","1","10")
MPY_ENC(M7_dcmpyrwc, "1000","ddddd","0","0","1","1","10")
-MPY_ENC(M7_dcmpyiw, "1000","ddddd","0","1","1","0","10")
+MPY_ENC(M7_dcmpyiw, "1000","ddddd","0","1","1","0","10")
MPY_ENC(M7_dcmpyiwc, "1000","ddddd","0","1","1","1","10")
@@ -967,14 +1076,14 @@ DEF_FIELDROW_DESC32(ICLASS_M" 1001 -------- PP------ --------","[#9] Rd=(Rss,Rtt
MPY_ENC(M2_vdmpyrs_s0, "1001","ddddd","0","0","0","0","00")
MPY_ENC(M2_vdmpyrs_s1, "1001","ddddd","0","0","0","1","00")
-MPY_ENC(M7_wcmpyrw, "1001","ddddd","0","0","1","0","00")
+MPY_ENC(M7_wcmpyrw, "1001","ddddd","0","0","1","0","00")
MPY_ENC(M7_wcmpyrw_rnd, "1001","ddddd","0","0","1","1","00")
-MPY_ENC(M7_wcmpyiw, "1001","ddddd","0","1","0","0","00")
+MPY_ENC(M7_wcmpyiw, "1001","ddddd","0","1","0","0","00")
MPY_ENC(M7_wcmpyiw_rnd, "1001","ddddd","0","1","0","1","00")
-MPY_ENC(M7_wcmpyrwc, "1001","ddddd","0","1","1","0","00")
+MPY_ENC(M7_wcmpyrwc, "1001","ddddd","0","1","1","0","00")
MPY_ENC(M7_wcmpyrwc_rnd, "1001","ddddd","0","1","1","1","00")
-MPY_ENC(M7_wcmpyiwc, "1001","ddddd","1","0","0","0","00")
+MPY_ENC(M7_wcmpyiwc, "1001","ddddd","1","0","0","0","00")
MPY_ENC(M7_wcmpyiwc_rnd, "1001","ddddd","1","0","0","1","00")
@@ -1030,10 +1139,10 @@ MPY_ENC(F2_dfmpylh, "1010","xxxxx","0","0","0","0","11")
MPY_ENC(F2_dfmpyhh, "1010","xxxxx","0","0","0","1","11")
-MPY_ENC(M7_dcmpyrw_acc, "1010","xxxxx","0","0","0","1","10")
-MPY_ENC(M7_dcmpyrwc_acc, "1010","xxxxx","0","0","1","1","10")
-MPY_ENC(M7_dcmpyiw_acc, "1010","xxxxx","0","1","1","0","10")
-MPY_ENC(M7_dcmpyiwc_acc, "1010","xxxxx","1","0","1","0","10")
+MPY_ENC(M7_dcmpyrw_acc, "1010","xxxxx","0","0","0","1","10")
+MPY_ENC(M7_dcmpyrwc_acc, "1010","xxxxx","0","0","1","1","10")
+MPY_ENC(M7_dcmpyiw_acc, "1010","xxxxx","0","1","1","0","10")
+MPY_ENC(M7_dcmpyiwc_acc, "1010","xxxxx","1","0","1","0","10")
@@ -1063,7 +1172,6 @@ SP_MPY(M2_mpy_sat_rnd, "1100","ddddd","1","1","0")
SP_MPY(M2_mpyu, "1100","ddddd","0","0","1")
DEF_FIELDROW_DESC32(ICLASS_M" 1101 -------- PP------ --------","[#13] Rd=(Rs,Rt)")
-/* EJP: same as mpyi MPY_ENC(M2_mpyui, "1101","ddddd","0","0","1","0","00") */
MPY_ENC(M2_mpyi, "1101","ddddd","0","0","0","0","00")
MPY_ENC(M2_mpy_up, "1101","ddddd","0","0","0","0","01")
MPY_ENC(M2_mpyu_up, "1101","ddddd","0","0","1","0","01")
@@ -1266,7 +1374,6 @@ DEF_ENC32(C2_cmovenewif,ICLASS_ALU2op" 1110 1uu0iiii PP1iiiii iiiddddd")
DEF_ENC32(C2_cmoveit, ICLASS_ALU2op" 1110 0uu0iiii PP0iiiii iiiddddd")
DEF_ENC32(C2_cmoveif, ICLASS_ALU2op" 1110 1uu0iiii PP0iiiii iiiddddd")
-
DEF_FIELDROW_DESC32( ICLASS_ALU2op" 1111 -------- PP------ --------","[#15] nop")
DEF_ENC32(A2_nop, ICLASS_ALU2op" 1111 -------- PP------ --------")
@@ -1408,9 +1515,6 @@ DEF_FIELDROW_DESC32(ICLASS_ALU3op" 1110 -------- PP------ --------","[#14] Rese
-
-
-
/*******************************/
/* */
/* */
@@ -1508,7 +1612,6 @@ SH_RRI6_ENC(S6_rol_i_##TAGEND,MAJ4,MIN3,SMOD1 "11",DSTCHARS)
DEF_FIELDROW_DESC32(ICLASS_S2op" 0000 -------- PP------ --------","[#0] Rdd=(Rss,#u6)")
-/* EJP: there is actually quite a bit of space here, look at the reserved bits */
I6SHIFTTYPES(p, "0000","000","0","ddddd")
I5SHIFTTYPES_NOROL(vw, "0000","010","0","ddddd")
I4SHIFTTYPES(vh, "0000","100","0","ddddd")
@@ -1620,8 +1723,8 @@ SH2_RR_ENC(A2_roundsat, "1000","110","-","001","ddddd")
SH_RRI5_ENC(S2_asr_i_svw_trun, "1000","110", "010","ddddd")
SH_RRI5_ENC(A4_bitspliti, "1000","110", "100","ddddd")
-SH_RRI5_ENC(A7_clip, "1000","110", "101","ddddd")
-SH_RRI5_ENC(A7_vclip, "1000","110", "110","ddddd")
+SH_RRI5_ENC(A7_clip, "1000","110", "101","ddddd")
+SH_RRI5_ENC(A7_vclip, "1000","110", "110","ddddd")
SH2_RR_ENC(S4_clbpnorm, "1000","011","-","000","ddddd")
@@ -1743,10 +1846,11 @@ SH_RRR_ENC(S2_shuffob, "0001","00-","-","10-","ddddd")
SH_RRR_ENC(S2_shuffeh, "0001","00-","-","11-","ddddd")
SH_RRR_ENC(S2_shuffoh, "0001","10-","-","000","ddddd")
+// 001
SH_RRR_ENC(S2_vtrunewh, "0001","10-","-","010","ddddd")
-SH_RRR_ENC(S6_vtrunehb_ppp, "0001","10-","-","011","ddddd")
+SH_RRR_ENC(S6_vtrunehb_ppp, "0001","10-","-","011","ddddd")
SH_RRR_ENC(S2_vtrunowh, "0001","10-","-","100","ddddd")
-SH_RRR_ENC(S6_vtrunohb_ppp, "0001","10-","-","101","ddddd")
+SH_RRR_ENC(S6_vtrunohb_ppp, "0001","10-","-","101","ddddd")
SH_RRR_ENC(S2_lfsp, "0001","10-","-","110","ddddd")
SH_RRR_ENC(S4_vxaddsubw, "0001","01-","-","000","ddddd")
@@ -1780,8 +1884,6 @@ SH_RRR_ENC(S4_vrcrotate, "0011","11-","i","11i","ddddd")
DEF_FIELDROW_DESC32(ICLASS_S3op" 0100 -------- PP------ --------","[#4] Rd=(Rs,Rt,#u3)")
DEF_ENC32(S2_addasl_rrri, ICLASS_S3op" 0100 000 sssss PP0ttttt iiiddddd")
-
-
DEF_FIELDROW_DESC32(ICLASS_S3op" 0101 -------- PP------ --------","[#5] Rd=(Rss,Rt)")
SH_RRR_ENC(S2_asr_r_svw_trun, "0101","---","-","010","ddddd")
SH_RRR_ENC(M4_cmpyi_wh, "0101","---","-","100","ddddd")
@@ -1841,6 +1943,7 @@ DEF_FIELDROW_DESC32(ICLASS_S3op" 1010 -------- PP------ --------","[#10] Rxx=(Rs
SH_RRR_ENC(S2_insertp_rp, "1010","0--","0","---","xxxxx")
SH_RRR_ENC(M4_xor_xacc, "1010","10-","0","000","xxxxx")
+
DEF_FIELDROW_DESC32(ICLASS_S3op" 1011 -------- PP------ --------","[#11] Rxx=(Rss,Rt)")
RSHIFTTYPES(p_or, "1011","000","-","-","xxxxx")
RSHIFTTYPES(p_and, "1011","010","-","-","xxxxx")
@@ -1848,19 +1951,19 @@ RSHIFTTYPES(p_nac, "1011","100","-","-","xxxxx")
RSHIFTTYPES(p_acc, "1011","110","-","-","xxxxx")
RSHIFTTYPES(p_xor, "1011","011","-","-","xxxxx")
-SH_RRR_ENCX(A4_vrmaxh, "1011","001","0","001","uuuuu")
-SH_RRR_ENCX(A4_vrmaxuh, "1011","001","1","001","uuuuu")
-SH_RRR_ENCX(A4_vrmaxw, "1011","001","0","010","uuuuu")
-SH_RRR_ENCX(A4_vrmaxuw, "1011","001","1","010","uuuuu")
+SH_RRR_ENCX(A4_vrmaxh, "1011","001","0","001","uuuuu")
+SH_RRR_ENCX(A4_vrmaxuh, "1011","001","1","001","uuuuu")
+SH_RRR_ENCX(A4_vrmaxw, "1011","001","0","010","uuuuu")
+SH_RRR_ENCX(A4_vrmaxuw, "1011","001","1","010","uuuuu")
-SH_RRR_ENCX(A4_vrminh, "1011","001","0","101","uuuuu")
-SH_RRR_ENCX(A4_vrminuh, "1011","001","1","101","uuuuu")
-SH_RRR_ENCX(A4_vrminw, "1011","001","0","110","uuuuu")
-SH_RRR_ENCX(A4_vrminuw, "1011","001","1","110","uuuuu")
+SH_RRR_ENCX(A4_vrminh, "1011","001","0","101","uuuuu")
+SH_RRR_ENCX(A4_vrminuh, "1011","001","1","101","uuuuu")
+SH_RRR_ENCX(A4_vrminw, "1011","001","0","110","uuuuu")
+SH_RRR_ENCX(A4_vrminuw, "1011","001","1","110","uuuuu")
-SH_RRR_ENC(S2_vrcnegh, "1011","001","1","111","xxxxx")
+SH_RRR_ENC(S2_vrcnegh, "1011","001","1","111","xxxxx")
-SH_RRR_ENC(S4_vrcrotate_acc, "1011","101","i","--i","xxxxx")
+SH_RRR_ENC(S4_vrcrotate_acc, "1011","101","i","--i","xxxxx")
DEF_FIELDROW_DESC32(ICLASS_S3op" 1100 -------- PP------ --------","[#12] Rx=(Rs,Rt)")
@@ -1874,11 +1977,6 @@ DEF_FIELDROW_DESC32(ICLASS_S3op" 1101 -------- PP------ --------","[#13] Reserve
DEF_FIELDROW_DESC32(ICLASS_S3op" 1110 -------- PP------ --------","[#14] Reserved")
-DEF_FIELDROW_DESC32(ICLASS_S3op" 1111 -------- PP------ --------","[#14] User Instruction")
-
-
-
-
@@ -2129,3 +2227,6 @@ OP_OPI_RI(lsr,"1")
DEF_FIELDROW_DESC32(ICLASS_ALU64" 1111 -------- PP------ --------","[#15] Rd=(Rs,Ru,#u6:2)")
DEF_ENC32(M4_mpyri_addr_u2, ICLASS_ALU64" 1111 0ii sssss PPiddddd iiiuuuuu")
DEF_ENC32(M4_mpyri_addr, ICLASS_ALU64" 1111 1ii sssss PPiddddd iiiuuuuu")
+
+
+
diff --git a/target/hexagon/imported/system.idef b/target/hexagon/imported/system.idef
index 7c6568e75e..fd7ef18b3e 100644
--- a/target/hexagon/imported/system.idef
+++ b/target/hexagon/imported/system.idef
@@ -25,44 +25,262 @@
/* 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);
+ 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*/
- ((RtV>>16)&0xffff), /*stride*/
- 0); /*extra attrib flags*/
+ (RtV&0xff), /*height*/
+ ((RtV>>8)&0xff), /*width*/
+ ((RtV>>16)&0xffff), /*stride*/
+ 0); /*extra attrib flags*/
})
-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*/
+ 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 v2 26/40] target/hexagon: Add sysemu TCG overrides
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (24 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 25/40] target/hexagon: Add system reg insns Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 27/40] target/hexagon: Add implicit attributes to sysemu macros Brian Cain
` (13 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Define TCG overrides for setprio(), crswap(,sgp{0,1,1:0}).
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/cpu_helper.h | 32 ++++++++++++++++++++++++++++
target/hexagon/gen_tcg_sys.h | 41 ++++++++++++++++++++++++++++++++++++
target/hexagon/helper.h | 1 +
target/hexagon/cpu_helper.c | 38 +++++++++++++++++++++++++++++++++
target/hexagon/genptr.c | 4 ++++
target/hexagon/op_helper.c | 7 ++++++
target/hexagon/hex_common.py | 2 ++
target/hexagon/meson.build | 14 ++++++------
8 files changed, 133 insertions(+), 6 deletions(-)
create mode 100644 target/hexagon/cpu_helper.h
create mode 100644 target/hexagon/gen_tcg_sys.h
create mode 100644 target/hexagon/cpu_helper.c
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
new file mode 100644
index 0000000000..194bcbf451
--- /dev/null
+++ b/target/hexagon/cpu_helper.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright(c) 2019-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HEXAGON_CPU_HELPER_H
+#define HEXAGON_CPU_HELPER_H
+
+static inline void arch_set_thread_reg(CPUHexagonState *env, uint32_t reg,
+ uint32_t val)
+{
+ g_assert(reg < TOTAL_PER_THREAD_REGS);
+ g_assert_not_reached();
+}
+
+static inline uint32_t arch_get_thread_reg(CPUHexagonState *env, uint32_t reg)
+{
+ g_assert(reg < TOTAL_PER_THREAD_REGS);
+ g_assert_not_reached();
+}
+
+static inline void arch_set_system_reg(CPUHexagonState *env, uint32_t reg,
+ uint32_t val)
+{
+ g_assert_not_reached();
+}
+
+uint32_t arch_get_system_reg(CPUHexagonState *env, uint32_t reg);
+
+#endif
+
diff --git a/target/hexagon/gen_tcg_sys.h b/target/hexagon/gen_tcg_sys.h
new file mode 100644
index 0000000000..362703ab45
--- /dev/null
+++ b/target/hexagon/gen_tcg_sys.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright(c) 2022-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ * 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 tmp = tcg_temp_new(); \
+ 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 tmp = tcg_temp_new(); \
+ 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 { \
+ g_assert_not_reached(); \
+ 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 fddbd99a19..146f4f02e4 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -115,4 +115,5 @@ DEF_HELPER_2(greg_read, i32, env, i32)
DEF_HELPER_2(greg_read_pair, i64, env, i32)
DEF_HELPER_3(sreg_write, void, env, i32, i32)
DEF_HELPER_3(sreg_write_pair, void, env, i32, i64)
+DEF_HELPER_3(setprio, void, env, i32, i32)
#endif
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
new file mode 100644
index 0000000000..01fdd6b28d
--- /dev/null
+++ b/target/hexagon/cpu_helper.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright(c) 2019-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "cpu_helper.h"
+#include "system/cpus.h"
+#ifdef CONFIG_USER_ONLY
+#include "qemu.h"
+#include "exec/helper-proto.h"
+#else
+#include "hw/boards.h"
+#include "hw/hexagon/hexagon.h"
+#endif
+#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"
+
+
+#ifndef CONFIG_USER_ONLY
+
+uint32_t arch_get_system_reg(CPUHexagonState *env, uint32_t reg)
+{
+ g_assert_not_reached();
+}
+
+
+#endif
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index a474787816..0648daefb6 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 cbbf3048a0..cfd34d8712 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -31,6 +31,7 @@
#include "mmvec/mmvec.h"
#include "mmvec/macros.h"
#include "op_helper.h"
+#include "cpu_helper.h"
#include "translate.h"
#define SF_BIAS 127
@@ -1366,6 +1367,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 24139cbe67..009b71f8e6 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -1361,6 +1361,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")
@@ -1368,6 +1369,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 bb4ebaae81..3ec53010fa 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'
#
@@ -249,6 +250,7 @@ hexagon_ss.add(files(
'cpu.c',
'translate.c',
'op_helper.c',
+ 'cpu_helper.c',
'gdbstub.c',
'genptr.c',
'reg_fields.c',
@@ -346,12 +348,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
#
@@ -365,7 +367,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)
@@ -374,7 +376,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)
@@ -383,7 +385,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)
@@ -392,7 +394,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 v2 27/40] target/hexagon: Add implicit attributes to sysemu macros
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (25 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 26/40] target/hexagon: Add sysemu TCG overrides Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 28/40] target/hexagon: Add TCG overrides for int handler insts Brian Cain
` (12 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 009b71f8e6..39451e6d88 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -129,8 +129,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 v2 28/40] target/hexagon: Add TCG overrides for int handler insts
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (26 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 27/40] target/hexagon: Add implicit attributes to sysemu macros Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 29/40] target/hexagon: Add TCG overrides for thread ctl Brian Cain
` (11 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 362703ab45..642ca3d3ff 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 146f4f02e4..2fe4440ddc 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 cfd34d8712..01e2677a62 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1337,6 +1337,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 pred, uint32_t imask)
+{
+ g_assert_not_reached();
+}
+
void HELPER(sreg_write)(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 v2 29/40] target/hexagon: Add TCG overrides for thread ctl
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (27 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 28/40] target/hexagon: Add TCG overrides for int handler insts Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 30/40] target/hexagon: Add TCG overrides for rte, nmi Brian Cain
` (10 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 642ca3d3ff..942d07b401 100644
--- a/target/hexagon/gen_tcg_sys.h
+++ b/target/hexagon/gen_tcg_sys.h
@@ -63,4 +63,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 2fe4440ddc..ada520bd52 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -124,4 +124,8 @@ DEF_HELPER_2(greg_read_pair, i64, env, i32)
DEF_HELPER_3(sreg_write, void, env, i32, i32)
DEF_HELPER_3(sreg_write_pair, void, env, i32, i64)
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 01e2677a62..57d8e8305b 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1367,6 +1367,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 v2 30/40] target/hexagon: Add TCG overrides for rte, nmi
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (28 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 29/40] target/hexagon: Add TCG overrides for thread ctl Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 31/40] target/hexagon: Add sreg_{read,write} helpers Brian Cain
` (9 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 942d07b401..6d73a18db4 100644
--- a/target/hexagon/gen_tcg_sys.h
+++ b/target/hexagon/gen_tcg_sys.h
@@ -81,4 +81,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 new_ssr = tcg_temp_new(); \
+ 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 ada520bd52..730eaf8b9a 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -128,4 +128,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 57d8e8305b..0aa9b91f85 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1433,6 +1433,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 v2 31/40] target/hexagon: Add sreg_{read,write} helpers
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (29 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 30/40] target/hexagon: Add TCG overrides for rte, nmi Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 32/40] target/hexagon: Add locks, id, next_PC to state Brian Cain
` (8 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain, Sid Manning
From: Brian Cain <bcain@quicinc.com>
Co-authored-by: Sid Manning <sidneym@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/cpu_helper.h | 8 ++
target/hexagon/cpu.c | 1 -
target/hexagon/cpu_helper.c | 37 +++++++++
target/hexagon/op_helper.c | 152 +++++++++++++++++++++++++++++++++++-
4 files changed, 193 insertions(+), 5 deletions(-)
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index 194bcbf451..5f5f15149a 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -7,6 +7,14 @@
#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);
+
static inline void arch_set_thread_reg(CPUHexagonState *env, uint32_t reg,
uint32_t val)
{
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 39b45e6452..bdc9d18395 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -329,7 +329,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
index 01fdd6b28d..4b8697de65 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -29,10 +29,47 @@
#ifndef CONFIG_USER_ONLY
+uint32_t hexagon_get_pmu_counter(CPUHexagonState *cur_env, int index)
+{
+ g_assert_not_reached();
+}
+
uint32_t arch_get_system_reg(CPUHexagonState *env, uint32_t reg)
{
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();
+}
+
#endif
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 0aa9b91f85..7851f43475 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -19,6 +19,7 @@
#include "qemu/log.h"
#include "accel/tcg/cpu-ldst.h"
#include "accel/tcg/probe.h"
+#include "qemu/main-loop.h"
#include "exec/helper-proto.h"
#include "fpu/softfloat.h"
#include "cpu.h"
@@ -1397,25 +1398,168 @@ void HELPER(setimask)(CPUHexagonState *env, uint32_t pred, uint32_t imask)
g_assert_not_reached();
}
+static bool handle_pmu_sreg_write(CPUHexagonState *env, uint32_t reg,
+ uint32_t val)
+{
+ if (reg == HEX_SREG_PMUSTID0 || reg == HEX_SREG_PMUSTID1
+ || reg == HEX_SREG_PMUCFG || reg == HEX_SREG_PMUEVTCFG
+ || reg == HEX_SREG_PMUEVTCFG1
+ || (reg >= HEX_SREG_PMUCNT4 && reg <= HEX_SREG_PMUCNT3)) {
+ qemu_log_mask(LOG_UNIMP, "PMU registers not yet implemented");
+ return true;
+ }
+ return false;
+}
+
+static void modify_syscfg(CPUHexagonState *env, uint32_t val)
+{
+ g_assert_not_reached();
+}
+
+static void hexagon_set_vid(CPUHexagonState *env, uint32_t offset, int val)
+{
+ g_assert_not_reached();
+}
+
+static uint32_t hexagon_find_last_irq(CPUHexagonState *env, uint32_t vid)
+{
+ g_assert_not_reached();
+}
+
+static void hexagon_read_timer(CPUHexagonState *env, uint32_t *low,
+ uint32_t *high)
+{
+ qemu_log_mask(LOG_UNIMP, "reading timer_hi/lo not yet supported\n");
+}
+
+static inline QEMU_ALWAYS_INLINE void sreg_write(CPUHexagonState *env,
+ uint32_t reg, uint32_t val)
+
+{
+ g_assert(bql_locked());
+ if ((reg == HEX_SREG_VID) || (reg == HEX_SREG_VID1)) {
+ if (val != L2VIC_NO_PENDING) {
+ hexagon_set_vid(env,
+ (reg == HEX_SREG_VID) ? L2VIC_VID_0 : L2VIC_VID_1,
+ val);
+ arch_set_system_reg(env, reg, val);
+ }
+ } else if (reg == HEX_SREG_SYSCFG) {
+ modify_syscfg(env, val);
+ } else if (reg == HEX_SREG_IMASK) {
+ val = GET_FIELD(IMASK_MASK, val);
+ arch_set_system_reg(env, reg, val);
+ } else if (reg == HEX_SREG_PCYCLELO) {
+ hexagon_set_sys_pcycle_count_low(env, val);
+ } else if (reg == HEX_SREG_PCYCLEHI) {
+ hexagon_set_sys_pcycle_count_high(env, val);
+ } else if (!handle_pmu_sreg_write(env, reg, val)) {
+ if (reg >= HEX_SREG_GLB_START) {
+ arch_set_system_reg(env, reg, val);
+ } else {
+ arch_set_system_reg(env, reg, val);
+ }
+ }
+}
+
+static inline QEMU_ALWAYS_INLINE void
+sreg_write_masked(CPUHexagonState *env, uint32_t reg, uint32_t val)
+
+{
+ g_assert(bql_locked());
+ if ((reg == HEX_SREG_VID) || (reg == HEX_SREG_VID1)) {
+ HexagonCPU *cpu = env_archcpu(env);
+ val = hexagon_globalreg_masked_value(cpu, reg, val);
+ hexagon_set_vid(env,
+ (reg == HEX_SREG_VID) ? L2VIC_VID_0 : L2VIC_VID_1,
+ val);
+ arch_set_system_reg(env, reg, val);
+ } else if (reg == HEX_SREG_SYSCFG) {
+ modify_syscfg(env, val);
+ } else if (reg == HEX_SREG_IMASK) {
+ val = GET_FIELD(IMASK_MASK, val);
+ arch_set_system_reg_masked(env, reg, val);
+ } else if (reg == HEX_SREG_PCYCLELO) {
+ hexagon_set_sys_pcycle_count_low(env, val);
+ } else if (reg == HEX_SREG_PCYCLEHI) {
+ hexagon_set_sys_pcycle_count_high(env, val);
+ } else if (!handle_pmu_sreg_write(env, reg, val)) {
+ arch_set_system_reg_masked(env, reg, val);
+ }
+}
+
void HELPER(sreg_write)(CPUHexagonState *env, uint32_t reg, uint32_t val)
{
- g_assert_not_reached();
+ BQL_LOCK_GUARD();
+ sreg_write(env, reg, val);
}
void HELPER(sreg_write_pair)(CPUHexagonState *env, uint32_t reg, uint64_t val)
+{
+ BQL_LOCK_GUARD();
+ sreg_write(env, reg, val & 0xFFFFFFFF);
+ sreg_write(env, reg + 1, val >> 32);
+}
+
+void HELPER(sreg_write_pair_masked)(CPUHexagonState *env, uint32_t reg,
+ uint64_t val)
+
+{
+ BQL_LOCK_GUARD();
+ sreg_write_masked(env, reg, val & 0xFFFFFFFF);
+ sreg_write_masked(env, reg + 1, val >> 32);
+}
+static inline QEMU_ALWAYS_INLINE uint32_t sreg_read(CPUHexagonState *env,
+ uint32_t reg)
{
- g_assert_not_reached();
+ g_assert(bql_locked());
+ if (reg == HEX_SREG_PMUSTID0 || reg == HEX_SREG_PMUSTID1
+ || reg == HEX_SREG_PMUCFG || reg == HEX_SREG_PMUEVTCFG
+ || reg == HEX_SREG_PMUEVTCFG1
+ || (reg >= HEX_SREG_PMUCNT4 && reg <= HEX_SREG_PMUCNT3)) {
+ qemu_log_mask(LOG_UNIMP, "PMU registers not yet implemented");
+ return 0;
+ }
+ if ((reg == HEX_SREG_VID) || (reg == HEX_SREG_VID1)) {
+ const uint32_t vid = hexagon_find_last_irq(env, reg);
+ arch_set_system_reg(env, reg, vid);
+ } else if ((reg == HEX_SREG_TIMERLO) || (reg == HEX_SREG_TIMERHI)) {
+ uint32_t low = 0;
+ uint32_t high = 0;
+ hexagon_read_timer(env, &low, &high);
+ arch_set_system_reg(env, HEX_SREG_TIMERLO, low);
+ arch_set_system_reg(env, HEX_SREG_TIMERHI, high);
+ } else if (reg == HEX_SREG_BADVA) {
+ target_ulong ssr = arch_get_system_reg(env, HEX_SREG_SSR);
+ if (GET_SSR_FIELD(SSR_BVS, ssr)) {
+ return arch_get_system_reg(env, HEX_SREG_BADVA1);
+ }
+ return arch_get_system_reg(env, HEX_SREG_BADVA0);
+ }
+ return arch_get_system_reg(env, reg);
}
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();
+ if (reg == HEX_SREG_TIMERLO) {
+ uint32_t low = 0;
+ uint32_t high = 0;
+ hexagon_read_timer(env, &low, &high);
+ arch_set_system_reg(env, HEX_SREG_TIMERLO, low);
+ arch_set_system_reg(env, HEX_SREG_TIMERHI, high);
+ } else if (reg == HEX_SREG_PCYCLELO) {
+ return hexagon_get_sys_pcycle_count(env);
+ }
+ return (uint64_t)sreg_read(env, reg) |
+ (((uint64_t)sreg_read(env, reg + 1)) << 32);
}
uint32_t HELPER(greg_read)(CPUHexagonState *env, uint32_t reg)
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 32/40] target/hexagon: Add locks, id, next_PC to state
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (30 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 31/40] target/hexagon: Add sreg_{read,write} helpers Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 33/40] target/hexagon: Add a TLB count property Brian Cain
` (7 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 | 34 +++++++++++++++++++++++++++++++++-
target/hexagon/cpu.c | 4 ++++
target/hexagon/machine.c | 4 ++++
3 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 42b877a04c..fc6552e64c 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -46,8 +46,34 @@
#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 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
+#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
+
+typedef enum {
+ HEX_LOCK_UNLOCKED = 0,
+ HEX_LOCK_WAITING = 1,
+ HEX_LOCK_OWNER = 2,
+ HEX_LOCK_QUEUED = 3
+} hex_lock_state_t;
+#endif
-#define MMU_USER_IDX 0
#define HEXAGON_CPU_IRQ_0 0
#define HEXAGON_CPU_IRQ_1 1
@@ -103,7 +129,13 @@ typedef struct CPUArchState {
target_ulong t_sreg[NUM_SREGS];
target_ulong greg[NUM_GREGS];
+
+ /* This alias of CPUState.cpu_index is used by imported sources: */
+ target_ulong threadId;
+ hex_lock_state_t tlb_lock_state;
+ hex_lock_state_t k0_lock_state;
#endif
+ target_ulong 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 bdc9d18395..a508f27fe4 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -301,6 +301,10 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
#ifndef CONFIG_USER_ONLY
memset(env->t_sreg, 0, sizeof(target_ulong) * NUM_SREGS);
memset(env->greg, 0, sizeof(target_ulong) * NUM_GREGS);
+ env->threadId = cs->cpu_index;
+ env->tlb_lock_state = HEX_LOCK_UNLOCKED;
+ env->k0_lock_state = HEX_LOCK_UNLOCKED;
+ env->next_PC = 0;
#endif
env->cause_code = HEX_EVENT_NONE;
}
diff --git a/target/hexagon/machine.c b/target/hexagon/machine.c
index 988ede06e9..18c3f87188 100644
--- a/target/hexagon/machine.c
+++ b/target/hexagon/machine.c
@@ -19,6 +19,10 @@ const VMStateDescription vmstate_hexagon_cpu = {
VMSTATE_UINTTL_ARRAY(env.pred, HexagonCPU, NUM_PREGS),
VMSTATE_UINTTL_ARRAY(env.t_sreg, HexagonCPU, NUM_SREGS),
VMSTATE_UINTTL_ARRAY(env.greg, HexagonCPU, NUM_GREGS),
+ VMSTATE_UINTTL(env.next_PC, HexagonCPU),
+ VMSTATE_UINTTL(env.tlb_lock_state, HexagonCPU),
+ VMSTATE_UINTTL(env.k0_lock_state, HexagonCPU),
+ VMSTATE_UINTTL(env.threadId, HexagonCPU),
VMSTATE_END_OF_LIST()
},
};
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 33/40] target/hexagon: Add a TLB count property
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (31 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 32/40] target/hexagon: Add locks, id, next_PC to state Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 34/40] target/hexagon: Add {TLB, k0}lock, cause code, wait_next_pc Brian Cain via
` (6 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/cpu.h | 2 ++
target/hexagon/cpu.c | 3 +++
2 files changed, 5 insertions(+)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index fc6552e64c..8b1ff23c01 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -44,6 +44,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
@@ -181,6 +182,7 @@ struct ArchCPU {
bool lldb_compat;
target_ulong lldb_stack_adjust;
bool short_circuit;
+ uint32_t num_tlbs;
};
#include "cpu_bits.h"
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index a508f27fe4..56098b4c55 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -50,6 +50,9 @@ static ObjectClass *hexagon_cpu_class_by_name(const char *cpu_model)
}
static const Property hexagon_cpu_properties[] = {
+#if !defined(CONFIG_USER_ONLY)
+ DEFINE_PROP_UINT32("jtlb-entries", HexagonCPU, num_tlbs, MAX_TLB_ENTRIES),
+#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 v2 34/40] target/hexagon: Add {TLB, k0}lock, cause code, wait_next_pc
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (32 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 33/40] target/hexagon: Add a TLB count property Brian Cain
@ 2025-09-02 3:47 ` Brian Cain via
2025-09-02 3:47 ` [PATCH v2 35/40] target/hexagon: Add stubs for modify_ssr/get_exe_mode Brian Cain
` (5 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain via @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
{TLB,k0}lock counts are used to represent the TLB, k0 locks among
hardware threads.
wait_next_pc represents the program counter to set when resuming from
a wait-for-interrupts state.
cause_code contains the precise exception cause.This will be used by
subsequent commits.
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/cpu.h | 3 +++
target/hexagon/cpu.c | 4 ++++
target/hexagon/machine.c | 4 ++++
3 files changed, 11 insertions(+)
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 8b1ff23c01..6b49912c08 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -130,11 +130,14 @@ typedef struct CPUArchState {
target_ulong t_sreg[NUM_SREGS];
target_ulong greg[NUM_GREGS];
+ target_ulong wait_next_pc;
/* This alias of CPUState.cpu_index is used by imported sources: */
target_ulong threadId;
hex_lock_state_t tlb_lock_state;
hex_lock_state_t k0_lock_state;
+ target_ulong tlb_lock_count;
+ target_ulong k0_lock_count;
#endif
target_ulong next_PC;
target_ulong new_value_usr;
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 56098b4c55..43fd13cd0d 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -307,7 +307,11 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
env->threadId = cs->cpu_index;
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;
+ env->wait_next_pc = 0;
+ env->cause_code = HEX_EVENT_NONE;
#endif
env->cause_code = HEX_EVENT_NONE;
}
diff --git a/target/hexagon/machine.c b/target/hexagon/machine.c
index 18c3f87188..10e0fe9688 100644
--- a/target/hexagon/machine.c
+++ b/target/hexagon/machine.c
@@ -22,7 +22,11 @@ const VMStateDescription vmstate_hexagon_cpu = {
VMSTATE_UINTTL(env.next_PC, HexagonCPU),
VMSTATE_UINTTL(env.tlb_lock_state, HexagonCPU),
VMSTATE_UINTTL(env.k0_lock_state, HexagonCPU),
+ VMSTATE_UINTTL(env.tlb_lock_count, HexagonCPU),
+ VMSTATE_UINTTL(env.k0_lock_count, HexagonCPU),
VMSTATE_UINTTL(env.threadId, HexagonCPU),
+ VMSTATE_UINTTL(env.cause_code, HexagonCPU),
+ VMSTATE_UINTTL(env.wait_next_pc, HexagonCPU),
VMSTATE_END_OF_LIST()
},
};
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 35/40] target/hexagon: Add stubs for modify_ssr/get_exe_mode
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (33 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 34/40] target/hexagon: Add {TLB, k0}lock, cause code, wait_next_pc Brian Cain via
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 36/40] target/hexagon: Add gdb support for sys regs Brian Cain
` (4 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain
From: Brian Cain <bcain@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/cpu_helper.h | 2 ++
target/hexagon/cpu_helper.c | 8 ++++++++
2 files changed, 10 insertions(+)
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index 5f5f15149a..e0c0c037a6 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -14,6 +14,8 @@ 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);
static inline void arch_set_thread_reg(CPUHexagonState *env, uint32_t reg,
uint32_t val)
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index 4b8697de65..bc51714406 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -71,5 +71,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();
+}
#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 36/40] target/hexagon: Add gdb support for sys regs
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (34 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 35/40] target/hexagon: Add stubs for modify_ssr/get_exe_mode Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 37/40] target/hexagon: Add initial MMU model Brian Cain
` (3 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain, Matheus Tavares Bernardino
From: Brian Cain <bcain@quicinc.com>
Co-authored-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/cpu.h | 6 ++
target/hexagon/internal.h | 4 ++
target/hexagon/cpu.c | 17 ++++++
target/hexagon/gdbstub.c | 45 ++++++++++++++
target/hexagon/op_helper.c | 22 +++++++
gdb-xml/hexagon-sys.xml | 116 +++++++++++++++++++++++++++++++++++++
6 files changed, 210 insertions(+)
create mode 100644 gdb-xml/hexagon-sys.xml
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 6b49912c08..627748392f 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -196,6 +196,12 @@ G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
uint32_t exception,
uintptr_t pc);
+#ifndef CONFIG_USER_ONLY
+uint32_t hexagon_greg_read(CPUHexagonState *env, uint32_t reg);
+uint32_t hexagon_sreg_read(CPUHexagonState *env, uint32_t reg);
+void hexagon_gdb_sreg_write(CPUHexagonState *env, uint32_t reg, uint32_t val);
+#endif
+
typedef HexagonCPU ArchCPU;
void hexagon_translate_init(void);
diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index 7cf7bcaa6c..c24c360921 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -22,6 +22,10 @@
int hexagon_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int hexagon_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+#ifndef CONFIG_USER_ONLY
+int hexagon_sys_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n);
+int hexagon_sys_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n);
+#endif
int hexagon_hvx_gdb_read_register(CPUState *env, GByteArray *mem_buf, int n);
int hexagon_hvx_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n);
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 43fd13cd0d..2ee379121e 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -27,6 +27,10 @@
#include "exec/gdbstub.h"
#include "accel/tcg/cpu-ops.h"
+#ifndef CONFIG_USER_ONLY
+#include "sys_macros.h"
+#endif
+
static void hexagon_v66_cpu_init(Object *obj) { }
static void hexagon_v67_cpu_init(Object *obj) { }
static void hexagon_v68_cpu_init(Object *obj) { }
@@ -338,6 +342,12 @@ static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
hexagon_hvx_gdb_write_register,
gdb_find_static_feature("hexagon-hvx.xml"), 0);
+#ifndef CONFIG_USER_ONLY
+ gdb_register_coprocessor(cs, hexagon_sys_gdb_read_register,
+ hexagon_sys_gdb_write_register,
+ gdb_find_static_feature("hexagon-sys.xml"), 0);
+#endif
+
qemu_init_vcpu(cs);
cpu_reset(cs);
mcc->parent_realize(dev, errp);
@@ -393,6 +403,13 @@ static void hexagon_cpu_class_init(ObjectClass *c, const void *data)
cc->tcg_ops = &hexagon_tcg_ops;
}
+#ifndef CONFIG_USER_ONLY
+uint32_t hexagon_greg_read(CPUHexagonState *env, uint32_t reg)
+{
+ g_assert_not_reached();
+}
+#endif
+
#define DEFINE_CPU(type_name, initfn) \
{ \
.name = type_name, \
diff --git a/target/hexagon/gdbstub.c b/target/hexagon/gdbstub.c
index 12d6b3bbcb..8476199b75 100644
--- a/target/hexagon/gdbstub.c
+++ b/target/hexagon/gdbstub.c
@@ -76,6 +76,51 @@ int hexagon_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
g_assert_not_reached();
}
+#ifndef CONFIG_USER_ONLY
+int hexagon_sys_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+{
+ CPUHexagonState *env = cpu_env(cs);
+
+ if (n < NUM_SREGS) {
+ return gdb_get_regl(mem_buf, hexagon_sreg_read(env, n));
+ }
+ n -= NUM_SREGS;
+
+ if (n < NUM_GREGS) {
+ return gdb_get_regl(mem_buf, hexagon_greg_read(env, n));
+ }
+ n -= NUM_GREGS;
+
+ n -= TOTAL_PER_THREAD_REGS;
+
+ if (n < NUM_PREGS) {
+ env->pred[n] = ldtul_p(mem_buf) & 0xff;
+ return sizeof(uint8_t);
+ }
+
+ n -= NUM_PREGS;
+
+ g_assert_not_reached();
+}
+
+int hexagon_sys_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ CPUHexagonState *env = cpu_env(cs);
+
+ if (n < NUM_SREGS) {
+ hexagon_gdb_sreg_write(env, n, ldtul_p(mem_buf));
+ return sizeof(target_ulong);
+ }
+ n -= NUM_SREGS;
+
+ if (n < NUM_GREGS) {
+ return env->greg[n] = ldtul_p(mem_buf);
+ }
+ n -= NUM_GREGS;
+
+ g_assert_not_reached();
+}
+#endif
static int gdb_get_vreg(CPUHexagonState *env, GByteArray *mem_buf, int n)
{
int total = 0;
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 7851f43475..a03fd078be 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -1494,6 +1494,23 @@ void HELPER(sreg_write)(CPUHexagonState *env, uint32_t reg, uint32_t val)
sreg_write(env, reg, val);
}
+void HELPER(sreg_write_masked)(CPUHexagonState *env, uint32_t reg, uint32_t val)
+{
+ BQL_LOCK_GUARD();
+ sreg_write_masked(env, reg, val);
+}
+
+void hexagon_gdb_sreg_write(CPUHexagonState *env, uint32_t reg, uint32_t val)
+{
+ BQL_LOCK_GUARD();
+ sreg_write(env, reg, val);
+ /*
+ * The above is needed to run special logic for regs like syscfg, but it
+ * won't set read-only bits. This will:
+ */
+ arch_set_system_reg(env, reg, val);
+}
+
void HELPER(sreg_write_pair)(CPUHexagonState *env, uint32_t reg, uint64_t val)
{
BQL_LOCK_GUARD();
@@ -1546,6 +1563,11 @@ uint32_t HELPER(sreg_read)(CPUHexagonState *env, uint32_t reg)
return sreg_read(env, reg);
}
+uint32_t hexagon_sreg_read(CPUHexagonState *env, uint32_t reg)
+{
+ return sreg_read(env, reg);
+}
+
uint64_t HELPER(sreg_read_pair)(CPUHexagonState *env, uint32_t reg)
{
BQL_LOCK_GUARD();
diff --git a/gdb-xml/hexagon-sys.xml b/gdb-xml/hexagon-sys.xml
new file mode 100644
index 0000000000..8a84be28ab
--- /dev/null
+++ b/gdb-xml/hexagon-sys.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0"?>
+<!--
+ Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+
+ Note: this file is intended to be use with LLDB, so it contains fields
+ that may be unknown to GDB. For more information on such fields, please
+ see:
+ https://github.com/llvm/llvm-project/blob/287aa6c4536408413b860e61fca0318a27214cf3/lldb/docs/lldb-gdb-remote.txt#L738-L860
+ https://github.com/llvm/llvm-project/blob/287aa6c4536408413b860e61fca0318a27214cf3/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp#L4275-L4335
+-->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.hexagon.sys">
+
+ <reg name="sgp0" altname="s0" bitsize="32" offset="4416" encoding="uint" format="hex" group="System Registers" dwarf_regnum="135" />
+ <reg name="sgp1" altname="s1" bitsize="32" offset="4420" encoding="uint" format="hex" group="System Registers" dwarf_regnum="136" />
+ <reg name="stid" altname="s2" bitsize="32" offset="4424" encoding="uint" format="hex" group="System Registers" dwarf_regnum="137" />
+ <reg name="elr" altname="s3" bitsize="32" offset="4428" encoding="uint" format="hex" group="System Registers" dwarf_regnum="138" />
+ <reg name="badva0" altname="s4" bitsize="32" offset="4432" encoding="uint" format="hex" group="System Registers" dwarf_regnum="139" />
+ <reg name="badva1" altname="s5" bitsize="32" offset="4436" encoding="uint" format="hex" group="System Registers" dwarf_regnum="140" />
+ <reg name="ssr" altname="s6" bitsize="32" offset="4440" encoding="uint" format="hex" group="System Registers" dwarf_regnum="141" />
+ <reg name="ccr" altname="s7" bitsize="32" offset="4444" encoding="uint" format="hex" group="System Registers" dwarf_regnum="142" />
+ <reg name="htid" altname="s8" bitsize="32" offset="4448" encoding="uint" format="hex" group="System Registers" dwarf_regnum="143" />
+ <reg name="badva" altname="s9" bitsize="32" offset="4452" encoding="uint" format="hex" group="System Registers" dwarf_regnum="144" />
+ <reg name="imask" altname="s10" bitsize="32" offset="4456" encoding="uint" format="hex" group="System Registers" dwarf_regnum="145" />
+ <reg name="gevb" altname="s11" bitsize="32" offset="4460" encoding="uint" format="hex" group="System Registers" dwarf_regnum="146" />
+ <reg name="vwctrl" altname="s12" bitsize="32" offset="4464" encoding="uint" format="hex" group="System Registers" dwarf_regnum="147" />
+ <reg name="s13" bitsize="32" offset="4468" encoding="uint" format="hex" group="System Registers" dwarf_regnum="148" />
+ <reg name="s14" bitsize="32" offset="4472" encoding="uint" format="hex" group="System Registers" dwarf_regnum="149" />
+ <reg name="s15" bitsize="32" offset="4476" encoding="uint" format="hex" group="System Registers" dwarf_regnum="150" />
+ <reg name="evb" altname="s16" bitsize="32" offset="4480" encoding="uint" format="hex" group="System Registers" dwarf_regnum="151" />
+ <reg name="modectl" altname="s17" bitsize="32" offset="4484" encoding="uint" format="hex" group="System Registers" dwarf_regnum="152" />
+ <reg name="syscfg" altname="s18" bitsize="32" offset="4488" encoding="uint" format="hex" group="System Registers" dwarf_regnum="153" />
+ <reg name="segment" altname="s19" bitsize="32" offset="4492" encoding="uint" format="hex" group="System Registers" dwarf_regnum="154" />
+ <reg name="ipendad" altname="s20" bitsize="32" offset="4496" encoding="uint" format="hex" group="System Registers" dwarf_regnum="155" />
+ <reg name="vid" altname="s21" bitsize="32" offset="4500" encoding="uint" format="hex" group="System Registers" dwarf_regnum="156" />
+ <reg name="vid1" altname="s22" bitsize="32" offset="4504" encoding="uint" format="hex" group="System Registers" dwarf_regnum="157" />
+ <reg name="bestwait" altname="s23" bitsize="32" offset="4508" encoding="uint" format="hex" group="System Registers" dwarf_regnum="158" />
+ <reg name="s24" bitsize="32" offset="4512" encoding="uint" format="hex" group="System Registers" dwarf_regnum="159" />
+ <reg name="schedcfg" altname="s25" bitsize="32" offset="4516" encoding="uint" format="hex" group="System Registers" dwarf_regnum="160" />
+ <reg name="s26" bitsize="32" offset="4520" encoding="uint" format="hex" group="System Registers" dwarf_regnum="161" />
+ <reg name="cfgbase" altname="s27" bitsize="32" offset="4524" encoding="uint" format="hex" group="System Registers" dwarf_regnum="162" />
+ <reg name="diag" altname="s28" bitsize="32" offset="4528" encoding="uint" format="hex" group="System Registers" dwarf_regnum="163" />
+ <reg name="rev" altname="s29" bitsize="32" offset="4532" encoding="uint" format="hex" group="System Registers" dwarf_regnum="164" />
+ <reg name="pcyclelo" altname="s30" bitsize="32" offset="4536" encoding="uint" format="hex" group="System Registers" dwarf_regnum="165" />
+ <reg name="pcyclehi" altname="s31" bitsize="32" offset="4540" encoding="uint" format="hex" group="System Registers" dwarf_regnum="166" />
+ <reg name="isdbst" altname="s32" bitsize="32" offset="4544" encoding="uint" format="hex" group="System Registers" dwarf_regnum="167" />
+ <reg name="isdbcfg0" altname="s33" bitsize="32" offset="4548" encoding="uint" format="hex" group="System Registers" dwarf_regnum="168" />
+ <reg name="isdbcfg1" altname="s34" bitsize="32" offset="4552" encoding="uint" format="hex" group="System Registers" dwarf_regnum="169" />
+ <reg name="livelock" altname="s35" bitsize="32" offset="4556" encoding="uint" format="hex" group="System Registers" dwarf_regnum="170" />
+ <reg name="brkptpc0" altname="s36" bitsize="32" offset="4560" encoding="uint" format="hex" group="System Registers" dwarf_regnum="171" />
+ <reg name="brkptcfg0" altname="s37" bitsize="32" offset="4564" encoding="uint" format="hex" group="System Registers" dwarf_regnum="172" />
+ <reg name="brkptpc1" altname="s38" bitsize="32" offset="4568" encoding="uint" format="hex" group="System Registers" dwarf_regnum="173" />
+ <reg name="brkptcfg1" altname="s39" bitsize="32" offset="4572" encoding="uint" format="hex" group="System Registers" dwarf_regnum="174" />
+ <reg name="isdbmbxin" altname="s40" bitsize="32" offset="4576" encoding="uint" format="hex" group="System Registers" dwarf_regnum="175" />
+ <reg name="isdbmbxout" altname="s41" bitsize="32" offset="4580" encoding="uint" format="hex" group="System Registers" dwarf_regnum="176" />
+ <reg name="isdben" altname="s42" bitsize="32" offset="4584" encoding="uint" format="hex" group="System Registers" dwarf_regnum="177" />
+ <reg name="isdbgpr" altname="s43" bitsize="32" offset="4588" encoding="uint" format="hex" group="System Registers" dwarf_regnum="178" />
+ <reg name="pmucnt4" altname="s44" bitsize="32" offset="4592" encoding="uint" format="hex" group="System Registers" dwarf_regnum="179" />
+ <reg name="pmucnt5" altname="s45" bitsize="32" offset="4596" encoding="uint" format="hex" group="System Registers" dwarf_regnum="180" />
+ <reg name="pmucnt6" altname="s46" bitsize="32" offset="4600" encoding="uint" format="hex" group="System Registers" dwarf_regnum="181" />
+ <reg name="pmucnt7" altname="s47" bitsize="32" offset="4604" encoding="uint" format="hex" group="System Registers" dwarf_regnum="182" />
+ <reg name="pmucnt0" altname="s48" bitsize="32" offset="4608" encoding="uint" format="hex" group="System Registers" dwarf_regnum="183" />
+ <reg name="pmucnt1" altname="s49" bitsize="32" offset="4612" encoding="uint" format="hex" group="System Registers" dwarf_regnum="184" />
+ <reg name="pmucnt2" altname="s50" bitsize="32" offset="4616" encoding="uint" format="hex" group="System Registers" dwarf_regnum="185" />
+ <reg name="pmucnt3" altname="s51" bitsize="32" offset="4620" encoding="uint" format="hex" group="System Registers" dwarf_regnum="186" />
+ <reg name="pmuevtcfg" altname="s52" bitsize="32" offset="4624" encoding="uint" format="hex" group="System Registers" dwarf_regnum="187" />
+ <reg name="pmustid0" altname="s53" bitsize="32" offset="4628" encoding="uint" format="hex" group="System Registers" dwarf_regnum="188" />
+ <reg name="pmuevtcfg1" altname="s54" bitsize="32" offset="4632" encoding="uint" format="hex" group="System Registers" dwarf_regnum="189" />
+ <reg name="pmustid1" altname="s55" bitsize="32" offset="4636" encoding="uint" format="hex" group="System Registers" dwarf_regnum="190" />
+ <reg name="timerlo" altname="s56" bitsize="32" offset="4640" encoding="uint" format="hex" group="System Registers" dwarf_regnum="191" />
+ <reg name="timerhi" altname="s57" bitsize="32" offset="4644" encoding="uint" format="hex" group="System Registers" dwarf_regnum="192" />
+ <reg name="pmucfg" altname="s58" bitsize="32" offset="4648" encoding="uint" format="hex" group="System Registers" dwarf_regnum="193" />
+ <reg name="rgdr2" altname="s59" bitsize="32" offset="4652" encoding="uint" format="hex" group="System Registers" dwarf_regnum="194" />
+ <reg name="rgdr" altname="s60" bitsize="32" offset="4656" encoding="uint" format="hex" group="System Registers" dwarf_regnum="195" />
+ <reg name="turkey" altname="s61" bitsize="32" offset="4660" encoding="uint" format="hex" group="System Registers" dwarf_regnum="196" />
+ <reg name="duck" altname="s62" bitsize="32" offset="4664" encoding="uint" format="hex" group="System Registers" dwarf_regnum="197" />
+ <reg name="chicken" altname="s63" bitsize="32" offset="4668" encoding="uint" format="hex" group="System Registers" dwarf_regnum="198" />
+ <reg name="commit1t" altname="s64" bitsize="32" offset="4672" encoding="uint" format="hex" group="System Registers" dwarf_regnum="231" />
+
+ <reg name="gelr" altname="g0" bitsize="32" offset="4756" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="199" />
+ <reg name="gsr" altname="g1" bitsize="32" offset="4760" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="200" />
+ <reg name="gosp" altname="g2" bitsize="32" offset="4764" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="201" />
+ <reg name="gbadva" altname="g3" bitsize="32" offset="4768" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="202" />
+ <reg name="gcommit1t" altname="g4" bitsize="32" offset="4772" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="203" />
+ <reg name="gcommit2t" altname="g5" bitsize="32" offset="4776" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="204" />
+ <reg name="gcommit3t" altname="g6" bitsize="32" offset="4780" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="205" />
+ <reg name="gcommit4t" altname="g7" bitsize="32" offset="4784" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="206" />
+ <reg name="gcommit5t" altname="g8" bitsize="32" offset="4788" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="207" />
+ <reg name="gcommit6t" altname="g9" bitsize="32" offset="4792" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="208" />
+ <reg name="gpcycle1t" altname="g10" bitsize="32" offset="4796" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="209" />
+ <reg name="gpcycle2t" altname="g11" bitsize="32" offset="4800" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="210" />
+ <reg name="gpcycle3t" altname="g12" bitsize="32" offset="4804" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="211" />
+ <reg name="gpcycle4t" altname="g13" bitsize="32" offset="4808" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="212" />
+ <reg name="gpcycle5t" altname="g14" bitsize="32" offset="4812" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="213" />
+ <reg name="gpcycle6t" altname="g15" bitsize="32" offset="4816" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="214" />
+ <reg name="gpmucnt4" altname="g16" bitsize="32" offset="4820" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="215" />
+ <reg name="gpmucnt5" altname="g17" bitsize="32" offset="4824" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="216" />
+ <reg name="gpmucnt6" altname="g18" bitsize="32" offset="4828" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="217" />
+ <reg name="gpmucnt7" altname="g19" bitsize="32" offset="4832" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="218" />
+ <reg name="gcommit7t" altname="g20" bitsize="32" offset="4836" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="219" />
+ <reg name="gcommit8t" altname="g21" bitsize="32" offset="4840" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="220" />
+ <reg name="gpcycle7t" altname="g22" bitsize="32" offset="4844" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="221" />
+ <reg name="gpcycle8t" altname="g23" bitsize="32" offset="4848" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="222" />
+ <reg name="gpcyclelo" altname="g24" bitsize="32" offset="4852" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="223" />
+ <reg name="gpcyclehi" altname="g25" bitsize="32" offset="4856" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="224" />
+ <reg name="gpmucnt0" altname="g26" bitsize="32" offset="4860" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="225" />
+ <reg name="gpmucnt1" altname="g27" bitsize="32" offset="4864" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="226" />
+ <reg name="gpmucnt2" altname="g28" bitsize="32" offset="4868" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="227" />
+ <reg name="gpmucnt3" altname="g29" bitsize="32" offset="4872" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="228" />
+ <reg name="g30" bitsize="32" offset="4876" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="229" />
+ <reg name="g31" bitsize="32" offset="4880" encoding="uint" format="hex" group="Guest Registers" dwarf_regnum="230" />
+
+</feature>
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread* [PATCH v2 37/40] target/hexagon: Add initial MMU model
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (35 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 36/40] target/hexagon: Add gdb support for sys regs Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 38/40] target/hexagon: Add clear_wait_mode() definition Brian Cain
` (2 subsequent siblings)
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, Brian Cain, Michael Lambert, Sid Manning,
Matheus Tavares Bernardino
From: Brian Cain <bcain@quicinc.com>
Co-authored-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Co-authored-by: Michael Lambert <mlambert@quicinc.com>
Co-authored-by: Sid Manning <sidneym@quicinc.com>
Co-authored-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/cpu-param.h | 4 +
target/hexagon/cpu.h | 8 +
target/hexagon/hex_mmu.h | 30 +++
target/hexagon/internal.h | 8 +
target/hexagon/cpu.c | 42 +++
target/hexagon/hex_mmu.c | 525 +++++++++++++++++++++++++++++++++++++
target/hexagon/machine.c | 30 +++
target/hexagon/translate.c | 2 +-
8 files changed, 648 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 22bffa7881..38b463a780 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_PHYS_ADDR_SPACE_BITS 36
#define TARGET_VIRT_ADDR_SPACE_BITS 32
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 627748392f..f25b483188 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -36,6 +36,10 @@
#error "Hexagon does not support system emulation"
#endif
+#ifndef CONFIG_USER_ONLY
+typedef struct CPUHexagonTLBContext CPUHexagonTLBContext;
+#endif
+
#define NUM_PREGS 4
#define TOTAL_PER_THREAD_REGS 64
@@ -138,6 +142,7 @@ typedef struct CPUArchState {
hex_lock_state_t k0_lock_state;
target_ulong tlb_lock_count;
target_ulong k0_lock_count;
+ CPUHexagonTLBContext *hex_tlb;
#endif
target_ulong next_PC;
target_ulong new_value_usr;
@@ -185,12 +190,15 @@ struct ArchCPU {
bool lldb_compat;
target_ulong lldb_stack_adjust;
bool short_circuit;
+#ifndef CONFIG_USER_ONLY
uint32_t num_tlbs;
+#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/hex_mmu.h b/target/hexagon/hex_mmu.h
new file mode 100644
index 0000000000..61a8056f08
--- /dev/null
+++ b/target/hexagon/hex_mmu.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright(c) 2019-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HEXAGON_MMU_H
+#define HEXAGON_MMU_H
+
+#include "cpu.h"
+
+struct CPUHexagonTLBContext {
+ uint64_t entries[MAX_TLB_ENTRIES];
+};
+
+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_realize(CPUHexagonState *env);
+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, target_ulong VA,
+ MMUAccessType access_type, hwaddr *PA, int *prot,
+ int *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 c24c360921..94e5e502a9 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -40,6 +40,14 @@ void G_NORETURN do_raise_exception(CPUHexagonState *env,
target_ulong PC,
uintptr_t retaddr);
+#define hexagon_cpu_mmu_enabled(env) ({ \
+ HexagonCPU *cpu = env_archcpu(env); \
+ cpu->globalregs ? \
+ GET_SYSCFG_FIELD(SYSCFG_MMUEN, \
+ arch_get_system_reg(env, HEX_SREG_SYSCFG)) : \
+ 0; \
+})
+
#ifndef CONFIG_USER_ONLY
extern const VMStateDescription vmstate_hexagon_cpu;
#endif
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 2ee379121e..eb3adebb60 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -26,9 +26,12 @@
#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) { }
@@ -274,6 +277,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 };
}
@@ -291,6 +301,18 @@ static void hexagon_restore_state_to_opc(CPUState *cs,
cpu_env(cs)->gpr[HEX_REG_PC] = data[0];
}
+
+#ifndef CONFIG_USER_ONLY
+static void mmu_reset(CPUHexagonState *env)
+{
+ CPUState *cs = env_cpu(env);
+ if (cs->cpu_index == 0) {
+ memset(env->hex_tlb, 0, sizeof(*env->hex_tlb));
+ }
+}
+#endif
+
+
static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
@@ -306,6 +328,13 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
/* Default NaN value: sign bit set, all frac bits set */
set_float_default_nan_pattern(0b11111111, &env->fp_status);
#ifndef CONFIG_USER_ONLY
+ HexagonCPU *cpu = HEXAGON_CPU(cs);
+
+ memset(env->t_sreg, 0, sizeof(target_ulong) * NUM_SREGS);
+ memset(env->greg, 0, sizeof(target_ulong) * NUM_GREGS);
+
+ mmu_reset(env);
+ arch_set_system_reg(env, HEX_SREG_HTID, cs->cpu_index);
memset(env->t_sreg, 0, sizeof(target_ulong) * NUM_SREGS);
memset(env->greg, 0, sizeof(target_ulong) * NUM_GREGS);
env->threadId = cs->cpu_index;
@@ -338,6 +367,14 @@ static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
return;
}
+#ifndef CONFIG_USER_ONLY
+ HexagonCPU *cpu = HEXAGON_CPU(cs);
+ if (cpu->num_tlbs > MAX_TLB_ENTRIES) {
+ error_setg(errp, "Number of TLBs selected is invalid");
+ return;
+ }
+#endif
+
gdb_register_coprocessor(cs, hexagon_hvx_gdb_read_register,
hexagon_hvx_gdb_write_register,
gdb_find_static_feature("hexagon-hvx.xml"), 0);
@@ -349,6 +386,11 @@ static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
#endif
qemu_init_vcpu(cs);
+
+#ifndef CONFIG_USER_ONLY
+ CPUHexagonState *env = cpu_env(cs);
+ hex_mmu_realize(env);
+#endif
cpu_reset(cs);
mcc->parent_realize(dev, errp);
}
diff --git a/target/hexagon/hex_mmu.c b/target/hexagon/hex_mmu.c
new file mode 100644
index 0000000000..332e7f4029
--- /dev/null
+++ b/target/hexagon/hex_mmu.c
@@ -0,0 +1,525 @@
+/*
+ * Copyright(c) 2019-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.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 "reg_fields.h"
+
+#define GET_TLB_FIELD(ENTRY, FIELD) \
+ ((uint64_t)fEXTRACTU_BITS(ENTRY, reg_field_info[FIELD].width, \
+ reg_field_info[FIELD].offset))
+
+/* PPD (physical page descriptor) */
+static inline uint64_t GET_PPD(uint64_t entry)
+{
+ return GET_TLB_FIELD(entry, PTE_PPD) |
+ (GET_TLB_FIELD(entry, PTE_PA35) << reg_field_info[PTE_PPD].width);
+}
+
+#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 */
+};
+
+/*
+ * @return the page size type from @a entry.
+ */
+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;
+}
+
+/*
+ * @return the page size of @a entry, in bytes.
+ */
+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_TLB_FIELD(entry, PTE_VPN) << TARGET_PAGE_BITS;
+}
+
+static bool hex_dump_mmu_entry(FILE *f, uint64_t entry)
+{
+ if (GET_TLB_FIELD(entry, PTE_V)) {
+ 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_TLB_FIELD(entry, PTE_V), GET_TLB_FIELD(entry, PTE_G),
+ GET_TLB_FIELD(entry, PTE_ATR1), GET_TLB_FIELD(entry, PTE_ATR0));
+ fprintf(f, " ASID:0x%02" PRIx64 " VA:0x%08" PRIx64,
+ GET_TLB_FIELD(entry, PTE_ASID), VA);
+ fprintf(f,
+ " X:%" PRId64 " W:%" PRId64 " R:%" PRId64 " U:%" PRId64
+ " C:%" PRId64,
+ GET_TLB_FIELD(entry, PTE_X), GET_TLB_FIELD(entry, PTE_W),
+ GET_TLB_FIELD(entry, PTE_R), GET_TLB_FIELD(entry, PTE_U),
+ GET_TLB_FIELD(entry, PTE_C));
+ 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;
+}
+
+void dump_mmu(CPUHexagonState *env)
+{
+ int i;
+
+ HexagonCPU *cpu = env_archcpu(env);
+ for (i = 0; i < cpu->num_tlbs; i++) {
+ uint64_t entry = env->hex_tlb->entries[i];
+ if (GET_TLB_FIELD(entry, PTE_V)) {
+ qemu_printf("0x%016" PRIx64 ": ", entry);
+ uint64_t PA = hex_tlb_phys_addr(entry);
+ uint64_t VA = hex_tlb_virt_addr(entry);
+ qemu_printf(
+ "V:%" PRId64 " G:%" PRId64 " A1:%" PRId64 " A0:%" PRId64,
+ GET_TLB_FIELD(entry, PTE_V), GET_TLB_FIELD(entry, PTE_G),
+ GET_TLB_FIELD(entry, PTE_ATR1), GET_TLB_FIELD(entry, PTE_ATR0));
+ qemu_printf(" ASID:0x%02" PRIx64 " VA:0x%08" PRIx64,
+ GET_TLB_FIELD(entry, PTE_ASID), VA);
+ qemu_printf(
+ " X:%" PRId64 " W:%" PRId64 " R:%" PRId64 " U:%" PRId64
+ " C:%" PRId64,
+ GET_TLB_FIELD(entry, PTE_X), GET_TLB_FIELD(entry, PTE_W),
+ GET_TLB_FIELD(entry, PTE_R), GET_TLB_FIELD(entry, PTE_U),
+ GET_TLB_FIELD(entry, PTE_C));
+ qemu_printf(" PA:0x%09" PRIx64 " SZ:%s (0x%" PRIx64 ")", PA,
+ pgsize_str[hex_tlb_pgsize_type(entry)],
+ hex_tlb_page_size_bytes(entry));
+ qemu_printf("\n");
+ }
+ }
+}
+
+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 (!hex_dump_mmu_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));
+ bool old_entry_valid = GET_TLB_FIELD(env->hex_tlb->entries[myidx], PTE_V);
+ if (old_entry_valid && hexagon_cpu_mmu_enabled(env)) {
+ CPUState *cs = env_cpu(env);
+
+ tlb_flush(cs);
+ }
+ env->hex_tlb->entries[myidx] = (value);
+ hex_log_tlbw(myidx, value);
+}
+
+void hex_mmu_realize(CPUHexagonState *env)
+{
+ CPUState *cs = env_cpu(env);
+ if (cs->cpu_index == 0) {
+ env->hex_tlb = g_malloc0(sizeof(CPUHexagonTLBContext));
+ } else {
+ CPUState *cpu0 = qemu_get_cpu(0);
+ CPUHexagonState *env0 = cpu_env(cpu0);
+ env->hex_tlb = env0->hex_tlb;
+ }
+}
+
+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);
+}
+
+static inline bool hex_tlb_entry_match_noperm(uint64_t entry, uint32_t asid,
+ uint64_t VA)
+{
+ if (GET_TLB_FIELD(entry, PTE_V)) {
+ if (GET_TLB_FIELD(entry, PTE_G)) {
+ /* Global entry - ingnore ASID */
+ } else if (asid != NO_ASID) {
+ uint32_t tlb_asid = GET_TLB_FIELD(entry, PTE_ASID);
+ 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(CPUHexagonState *env, uint64_t entry,
+ MMUAccessType access_type,
+ int mmu_idx, int *prot,
+ int32_t *excp)
+{
+ g_assert_not_reached();
+}
+
+static inline bool hex_tlb_entry_match(CPUHexagonState *env, uint64_t entry,
+ uint8_t asid, target_ulong VA,
+ MMUAccessType access_type, hwaddr *PA,
+ int *prot, int *size, int32_t *excp,
+ int mmu_idx)
+{
+ if (hex_tlb_entry_match_noperm(entry, asid, VA)) {
+ hex_tlb_entry_get_perm(env, entry, access_type, mmu_idx, prot, excp);
+ *PA = hex_tlb_phys_addr(entry);
+ *size = hex_tlb_page_size_bytes(entry);
+ return true;
+ }
+ return false;
+}
+
+bool hex_tlb_find_match(CPUHexagonState *env, target_ulong VA,
+ MMUAccessType access_type, hwaddr *PA, int *prot,
+ int *size, int32_t *excp, int mmu_idx)
+{
+ *PA = 0;
+ *prot = 0;
+ *size = 0;
+ *excp = 0;
+ uint32_t ssr = arch_get_system_reg(env, HEX_SREG_SSR);
+ uint8_t asid = GET_SSR_FIELD(SSR_ASID, ssr);
+ int i;
+ HexagonCPU *cpu = env_archcpu(env);
+ for (i = 0; i < cpu->num_tlbs; i++) {
+ uint64_t entry = env->hex_tlb->entries[i];
+ if (hex_tlb_entry_match(env, entry, asid, VA, access_type, PA, prot,
+ size, excp, mmu_idx)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static uint32_t hex_tlb_lookup_by_asid(CPUHexagonState *env, uint32_t asid,
+ uint32_t VA)
+{
+ g_assert_not_reached();
+}
+
+/* Called from tlbp instruction */
+uint32_t hex_tlb_lookup(CPUHexagonState *env, uint32_t ssr, uint32_t VA)
+{
+ return hex_tlb_lookup_by_asid(env, GET_SSR_FIELD(SSR_ASID, ssr), VA);
+}
+
+static bool hex_tlb_is_match(CPUHexagonState *env,
+ uint64_t entry1, uint64_t entry2,
+ bool consider_gbit)
+{
+ bool valid1 = GET_TLB_FIELD(entry1, PTE_V);
+ bool valid2 = GET_TLB_FIELD(entry2, PTE_V);
+ 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_TLB_FIELD(entry1, PTE_ASID);
+ int asid2 = GET_TLB_FIELD(entry2, PTE_ASID);
+ bool gbit1 = GET_TLB_FIELD(entry1, PTE_G);
+ bool gbit2 = GET_TLB_FIELD(entry2, PTE_G);
+
+ 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;
+}
+
+/*
+ * 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)
+{
+ int matches = 0;
+ int last_match = 0;
+ int i;
+
+ HexagonCPU *cpu = env_archcpu(env);
+ for (i = 0; i < cpu->num_tlbs; i++) {
+ if (hex_tlb_is_match(env, entry, env->hex_tlb->entries[i], false)) {
+ matches++;
+ last_match = i;
+ }
+ }
+
+ if (matches == 1) {
+ return last_match;
+ }
+ if (matches == 0) {
+ return -2;
+ }
+ return -1;
+}
+
+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: %d\n", env->threadId);
+ BQL_LOCK_GUARD();
+ g_assert((env->tlb_lock_count == 0) || (env->tlb_lock_count == 1));
+
+ uint32_t syscfg = arch_get_system_reg(env, HEX_SREG_SYSCFG);
+ 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 */
+ uint32_t syscfg = arch_get_system_reg(env, HEX_SREG_SYSCFG);
+ 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/machine.c b/target/hexagon/machine.c
index 10e0fe9688..f3d2bdf41d 100644
--- a/target/hexagon/machine.c
+++ b/target/hexagon/machine.c
@@ -7,6 +7,33 @@
#include "qemu/osdep.h"
#include "migration/cpu.h"
#include "cpu.h"
+#include "hex_mmu.h"
+
+static int get_hex_tlb_ptr(QEMUFile *f, void *pv, size_t size,
+ const VMStateField *field)
+{
+ CPUHexagonTLBContext *tlb = pv;
+ for (int i = 0; i < ARRAY_SIZE(tlb->entries); i++) {
+ tlb->entries[i] = qemu_get_be64(f);
+ }
+ return 0;
+}
+
+static int put_hex_tlb_ptr(QEMUFile *f, void *pv, size_t size,
+ const VMStateField *field, JSONWriter *vmdesc)
+{
+ CPUHexagonTLBContext *tlb = pv;
+ for (int i = 0; i < ARRAY_SIZE(tlb->entries); i++) {
+ qemu_put_be64(f, tlb->entries[i]);
+ }
+ return 0;
+}
+
+const VMStateInfo vmstate_info_hex_tlb_ptr = {
+ .name = "hex_tlb_pointer",
+ .get = get_hex_tlb_ptr,
+ .put = put_hex_tlb_ptr,
+};
const VMStateDescription vmstate_hexagon_cpu = {
@@ -27,6 +54,9 @@ const VMStateDescription vmstate_hexagon_cpu = {
VMSTATE_UINTTL(env.threadId, HexagonCPU),
VMSTATE_UINTTL(env.cause_code, HexagonCPU),
VMSTATE_UINTTL(env.wait_next_pc, HexagonCPU),
+ VMSTATE_POINTER(env.hex_tlb, HexagonCPU, 0,
+ vmstate_info_hex_tlb_ptr, CPUHexagonTLBContext *),
+
VMSTATE_END_OF_LIST()
},
};
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index d788aa227c..b74ddc2acb 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -943,7 +943,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 v2 38/40] target/hexagon: Add clear_wait_mode() definition
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (36 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 37/40] target/hexagon: Add initial MMU model Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 39/40] target/hexagon: Define f{S,G}ET_FIELD macros Brian Cain
2025-09-02 3:47 ` [PATCH v2 40/40] target/hexagon: Add hex_interrupts support Brian Cain
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 | 13 +++++++++++++
2 files changed, 14 insertions(+)
diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
index e0c0c037a6..6f0c6697ad 100644
--- a/target/hexagon/cpu_helper.h
+++ b/target/hexagon/cpu_helper.h
@@ -16,6 +16,7 @@ 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);
static inline void arch_set_thread_reg(CPUHexagonState *env, uint32_t reg,
uint32_t val)
diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c
index bc51714406..00f47e5a07 100644
--- a/target/hexagon/cpu_helper.c
+++ b/target/hexagon/cpu_helper.c
@@ -76,6 +76,19 @@ 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 = arch_get_system_reg(env, HEX_SREG_MODECTL);
+ 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 v2 39/40] target/hexagon: Define f{S,G}ET_FIELD macros
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (37 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 38/40] target/hexagon: Add clear_wait_mode() definition Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
2025-09-02 3:47 ` [PATCH v2 40/40] target/hexagon: Add hex_interrupts support Brian Cain
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 4823c97fde..5c3a4a533c 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -650,6 +650,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 v2 40/40] target/hexagon: Add hex_interrupts support
2025-09-02 3:46 [PATCH v2 00/40] hexagon system emulation v2, part 1/3 Brian Cain
` (38 preceding siblings ...)
2025-09-02 3:47 ` [PATCH v2 39/40] target/hexagon: Define f{S,G}ET_FIELD macros Brian Cain
@ 2025-09-02 3:47 ` Brian Cain
39 siblings, 0 replies; 41+ messages in thread
From: Brian Cain @ 2025-09-02 3:47 UTC (permalink / raw)
To: qemu-devel
Cc: brian.cain, richard.henderson, philmd, matheus.bernardino, ale,
anjo, marco.liebel, ltaylorsimpson, alex.bennee, quic_mburton,
sid.manning, 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 | 1 +
target/hexagon/hex_interrupts.h | 15 ++
target/hexagon/cpu.c | 2 +
target/hexagon/hex_interrupts.c | 327 ++++++++++++++++++++++++++++++++
4 files changed, 345 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 f25b483188..d369e104ae 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -192,6 +192,7 @@ struct ArchCPU {
bool short_circuit;
#ifndef CONFIG_USER_ONLY
uint32_t num_tlbs;
+ uint32_t l2vic_base_addr;
#endif
};
diff --git a/target/hexagon/hex_interrupts.h b/target/hexagon/hex_interrupts.h
new file mode 100644
index 0000000000..17a243946c
--- /dev/null
+++ b/target/hexagon/hex_interrupts.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright(c) 2022-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ * 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 eb3adebb60..c128f47ad3 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -59,6 +59,8 @@ static ObjectClass *hexagon_cpu_class_by_name(const char *cpu_model)
static const Property hexagon_cpu_properties[] = {
#if !defined(CONFIG_USER_ONLY)
DEFINE_PROP_UINT32("jtlb-entries", HexagonCPU, num_tlbs, MAX_TLB_ENTRIES),
+ DEFINE_PROP_UINT32("l2vic-base-addr", HexagonCPU, l2vic_base_addr,
+ 0xffffffffULL),
#endif
DEFINE_PROP_BOOL("lldb-compat", HexagonCPU, lldb_compat, false),
DEFINE_PROP_UNSIGNED("lldb-stack-adjust", HexagonCPU, lldb_stack_adjust, 0,
diff --git a/target/hexagon/hex_interrupts.c b/target/hexagon/hex_interrupts.c
new file mode 100644
index 0000000000..b555565e55
--- /dev/null
+++ b/target/hexagon/hex_interrupts.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright(c) 2022-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ * 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"
+
+static bool hex_is_qualified_for_int(CPUHexagonState *env, int int_num);
+
+static bool get_syscfg_gie(CPUHexagonState *env)
+{
+ target_ulong syscfg = arch_get_system_reg(env, HEX_SREG_SYSCFG);
+ return GET_SYSCFG_FIELD(SYSCFG_GIE, syscfg);
+}
+
+static bool get_ssr_ex(CPUHexagonState *env)
+{
+ target_ulong ssr = arch_get_system_reg(env, HEX_SREG_SSR);
+ return GET_SSR_FIELD(SSR_EX, ssr);
+}
+
+static bool get_ssr_ie(CPUHexagonState *env)
+{
+ target_ulong ssr = arch_get_system_reg(env, 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)
+{
+ target_ulong old = arch_get_system_reg(env, HEX_SREG_SSR);
+ SET_SYSTEM_FIELD(env, HEX_SREG_SSR, SSR_EX, ex);
+ SET_SYSTEM_FIELD(env, HEX_SREG_SSR, SSR_CAUSE, cause);
+ target_ulong new = arch_get_system_reg(env, HEX_SREG_SSR);
+ hexagon_modify_ssr(env, new, old);
+}
+
+static bool get_iad_bit(CPUHexagonState *env, int int_num)
+{
+ target_ulong ipendad = arch_get_system_reg(env, HEX_SREG_IPENDAD);
+ target_ulong iad = GET_FIELD(IPENDAD_IAD, ipendad);
+ return extract32(iad, int_num, 1);
+}
+
+static void set_iad_bit(CPUHexagonState *env, int int_num, int val)
+{
+ target_ulong ipendad = arch_get_system_reg(env, HEX_SREG_IPENDAD);
+ target_ulong iad = GET_FIELD(IPENDAD_IAD, ipendad);
+ iad = deposit32(iad, int_num, 1, val);
+ fSET_FIELD(ipendad, IPENDAD_IAD, iad);
+ arch_set_system_reg(env, HEX_SREG_IPENDAD, ipendad);
+}
+
+static uint32_t get_ipend(CPUHexagonState *env)
+{
+ target_ulong ipendad = arch_get_system_reg(env, HEX_SREG_IPENDAD);
+ return GET_FIELD(IPENDAD_IPEND, ipendad);
+}
+
+static inline bool get_ipend_bit(CPUHexagonState *env, int int_num)
+{
+ target_ulong ipendad = arch_get_system_reg(env, HEX_SREG_IPENDAD);
+ target_ulong ipend = GET_FIELD(IPENDAD_IPEND, ipendad);
+ return extract32(ipend, int_num, 1);
+}
+
+static void clear_ipend(CPUHexagonState *env, uint32_t mask)
+{
+ target_ulong ipendad = arch_get_system_reg(env, HEX_SREG_IPENDAD);
+ target_ulong ipend = GET_FIELD(IPENDAD_IPEND, ipendad);
+ ipend &= ~mask;
+ fSET_FIELD(ipendad, IPENDAD_IPEND, ipend);
+ arch_set_system_reg(env, HEX_SREG_IPENDAD, ipendad);
+}
+
+static void set_ipend(CPUHexagonState *env, uint32_t mask)
+{
+ target_ulong ipendad = arch_get_system_reg(env, HEX_SREG_IPENDAD);
+ target_ulong ipend = GET_FIELD(IPENDAD_IPEND, ipendad);
+ ipend |= mask;
+ fSET_FIELD(ipendad, IPENDAD_IPEND, ipend);
+ arch_set_system_reg(env, HEX_SREG_IPENDAD, ipendad);
+}
+
+static void set_ipend_bit(CPUHexagonState *env, int int_num, int val)
+{
+ target_ulong ipendad = arch_get_system_reg(env, HEX_SREG_IPENDAD);
+ target_ulong ipend = GET_FIELD(IPENDAD_IPEND, ipendad);
+ ipend = deposit32(ipend, int_num, 1, val);
+ fSET_FIELD(ipendad, IPENDAD_IPEND, ipend);
+ arch_set_system_reg(env, HEX_SREG_IPENDAD, ipendad);
+}
+
+static bool get_imask_bit(CPUHexagonState *env, int int_num)
+{
+ target_ulong imask = arch_get_system_reg(env, HEX_SREG_IMASK);
+ return extract32(imask, int_num, 1);
+}
+
+static uint32_t get_prio(CPUHexagonState *env)
+{
+ target_ulong stid = arch_get_system_reg(env, HEX_SREG_STID);
+ return extract32(stid, reg_field_info[STID_PRIO].offset,
+ reg_field_info[STID_PRIO].width);
+}
+
+static void set_elr(CPUHexagonState *env, target_ulong val)
+{
+ arch_set_system_reg(env, HEX_SREG_ELR, val);
+}
+
+static bool get_schedcfgen(CPUHexagonState *env)
+{
+ target_ulong schedcfg = arch_get_system_reg(env, HEX_SREG_SCHEDCFG);
+ 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);
+ target_ulong evb = arch_get_system_reg(env, HEX_SREG_EVB);
+ 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) {
+ cs->interrupt_request |= CPU_INTERRUPT_SWI;
+ cpu_resume(cs);
+ }
+ }
+ }
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 41+ messages in thread