<!-- SPDX-License-Identifier: BSD-2-Clause OR CC-BY-4.0 -->

<!--
This file is dual-licensed. You may choose to use this file under the terms of
either of the above licenses.

Note: This dual licensing does not apply to other files that may be part of the
same project unless stated otherwise.
-->

<registers name="Core Debug Registers" prefix="CSR_" label="core">
    These registers are only accessible from Debug Mode.

    <register name="Debug Control and Status" short="dcsr" address="0x7b0">
        Upon entry into Debug Mode, {dcsr-v} and {dcsr-prv} are updated
        with the privilege level the hart was previously in, and {dcsr-cause}
        is updated with the reason for Debug Mode entry.  Other than these
        fields and {dcsr-nmip}, the other fields of {csr-dcsr} are only
        writable by the external debugger.

        &lt;&lt;tab:dcsrcausepriority&gt;&gt; shows the priorities of
        reasons for entering Debug Mode.  Implementations should implement
        priorities as shown in the table. For compatibility with old versions of this spec, resethaltreq and haltreq are
        allowed to be at different positions than shown as long as:

        . resethaltreq is higher priority than haltreq
        . the relative order of the other four causes is maintained

        [[tab:dcsrcausepriority]]
        .Priority of reasons for entering Debug Mode from highest to lowest.
        [%autowidth,align="center",float="center",cols="^,^",options="header"]
        |===
        | {dcsr-cause} encoding | Cause
        | 5 | resethaltreq
        | 6 | halt group
        | 3 | haltreq
        | 2 | trigger (See &lt;&lt;tab:priority&gt;&gt; for detailed priority)
        | 1 | ebreak
        | 4 | step
        |===

        [NOTE]
        ====
        Note that mcontrol/mcontrol6 triggers which fire after the
        instruction which hit the trigger are considered
        to be high priority causes on the subsequent instruction.  Therefore,
        an execute trigger with timing=after on an ebreak instruction is lower
        priority than the ebreak itself because the trigger will fire after the
        ebreak instruction.  For the same reason, if a single instruction is
        stepped with both icount and {dcsr-step} then the {dcsr-step} has
        priority.  See &lt;&lt;tab:priority&gt;&gt; for the relative priorities of
        triggers with respect to the ebreak instruction.

        Most multi-hart implementations will probably hardwire {dcsr-stoptime}
        to 0, as the implementation can get complicated and the benefit is
        small.
        ====

        <field name="debugver" bits="31:28" access="R" reset="Preset">
            <value v="0" name="none">
            There is no debug support.
            </value>

            <value v="4" name="1.0">
            Debug support exists as it is described in this document.
            </value>

            <value v="15" name="custom">
            There is debug support, but it does not conform to any
            available version of this spec.
            </value>
        </field>
        <field name="0" bits="27:18" access="R" reset="0" />
        <field name="ebreakvs" bits="17" access="WARL" reset="0">
            <value v="0" name="exception">
            `ebreak` instructions in VS-mode behave as described in the
            Privileged Spec.
            </value>

            <value v="1" name="debug mode">
            `ebreak` instructions in VS-mode enter Debug Mode.
            </value>

            This bit is hardwired to 0 if the hart does not support virtualization mode.
        </field>
        <field name="ebreakvu" bits="16" access="WARL" reset="0">
            <value v="0" name="exception">
            `ebreak` instructions in VU-mode behave as described in the
            Privileged Spec.
            </value>

            <value v="1" name="debug mode">
            `ebreak` instructions in VU-mode enter Debug Mode.
            </value>

            This bit is hardwired to 0 if the hart does not support virtualization mode.
        </field>
        <field name="ebreakm" bits="15" access="R/W" reset="0">
            <value v="0" name="exception">
            `ebreak` instructions in M-mode behave as described in the
            Privileged Spec.
            </value>

            <value v="1" name="debug mode">
            `ebreak` instructions in M-mode enter Debug Mode.
            </value>
        </field>
        <field name="0" bits="14" access="R" reset="0" />
        <field name="ebreaks" bits="13" access="WARL" reset="0">
            <value v="0" name="exception">
            `ebreak` instructions in S-mode behave as described in the
            Privileged Spec.
            </value>

            <value v="1" name="debug mode">
            `ebreak` instructions in S-mode enter Debug Mode.
            </value>

            This bit is hardwired to 0 if the hart does not support S-mode.
        </field>
        <field name="ebreaku" bits="12" access="WARL" reset="0">
            <value v="0" name="exception">
            `ebreak` instructions in U-mode behave as described in the
            Privileged Spec.
            </value>

            <value v="1" name="debug mode">
            `ebreak` instructions in U-mode enter Debug Mode.
            </value>

            This bit is hardwired to 0 if the hart does not support U-mode.
        </field>
        <field name="stepie" bits="11" access="WARL" reset="0">
            <value v="0" name="interrupts disabled">
            Interrupts (including NMI) are disabled during single stepping
            with {dcsr-step} set.
            This value should be supported.
            </value>

            <value v="1" name="interrupts enabled">
            Interrupts (including NMI) are enabled during single stepping
            with {dcsr-step} set.
            </value>

            Implementations may hard wire this bit to 0.
            In that case interrupt behavior can be emulated by the debugger.

            The debugger must not change the value of this bit while the hart
            is running.
        </field>
        <field name="stopcount" bits="10" access="WARL" reset="Preset">
            <value v="0" name="normal">
            Increment counters as usual.
            </value>

            <value v="1" name="freeze">
            Don't increment any hart-local counters while in Debug Mode or
            on `ebreak` instructions that cause entry into Debug Mode.
            These counters include the `instret` CSR. On single-hart cores
            `cycle` should be stopped, but on multi-hart cores it must keep
            incrementing.
            </value>

            An implementation may hardwire this bit to 0 or 1.
        </field>
        <field name="stoptime" bits="9" access="WARL" reset="Preset">
            <value v="0" name="normal">
            `time` continues to reflect `mtime`.
            </value>

            <value v="1" name="freeze">
            `time` is frozen at the time that Debug Mode was entered. When
            leaving Debug Mode, `time` will reflect the latest
            value of `mtime` again.

            While all harts have {dcsr-stoptime}=1 and are in Debug Mode,
            `mtime` is allowed to stop incrementing.
            </value>

            An implementation may hardwire this bit to 0 or 1.
        </field>
        <field name="cause" bits="8:6" access="R" reset="0">
            Explains why Debug Mode was entered.

            When there are multiple reasons to enter Debug Mode in a single
            cycle, hardware should set {dcsr-cause} to the cause with the highest
            priority.  See &lt;&lt;tab:dcsrcausepriority&gt;&gt; for priorities.

            <value v="1" name="ebreak">
            An `ebreak` instruction was executed.
            </value>

            <value v="2" name="trigger">
            A Trigger Module trigger fired with action=1.
            </value>

            <value v="3" name="haltreq">
            The debugger requested entry to Debug Mode using {dmcontrol-haltreq}.
            </value>

            <value v="4" name="step">
            The hart single stepped because {dcsr-step} was set.
            </value>

            <value v="5" name="resethaltreq">
            The hart halted directly out of reset due to {resethaltreq} It
            is also acceptable to report 3 when this happens.
            </value>

            <value v="6" name="group">
            The hart halted because it's part of a halt group.
            Harts may report 3 for this cause instead.
            </value>

            Other values are reserved for future use.
        </field>
        <field name="v" bits="5" access="WARL" reset="0">
          Extends the prv field with the virtualization mode the hart was operating
          in when Debug Mode was entered. The encoding is described in &lt;&lt;tab:privmode&gt;&gt;.
          A debugger can change this value to change the hart's virtualization mode
          when exiting Debug Mode.
          This bit is hardwired to 0 on harts that do not support virtualization mode.
        </field>
        <field name="mprven" bits="4" access="WARL" reset="Preset">
            <value v="0" name="disabled">
            `mprv` in `mstatus` is ignored in Debug Mode.
            </value>

            <value v="1" name="enabled">
            `mprv` in `mstatus` takes effect in Debug Mode.
            </value>

            Implementing this bit is optional. It may be tied to either 0 or 1.
	</field>
        <field name="nmip" bits="3" access="R" reset="0">
            When set, there is a Non-Maskable-Interrupt (NMI) pending for the hart.

            Since an NMI can indicate a hardware error condition,
            reliable debugging may no longer be possible once this bit becomes set.
            This is implementation-dependent.
        </field>
        <field name="step" bits="2" access="R/W" reset="0">
            When set and not in Debug Mode, the hart will only execute a single
            instruction and then enter Debug Mode. See xref:stepbit[]
            for details.

            The debugger must not change the value of this bit while the hart
            is running.
        </field>
        <field name="prv" bits="1:0" access="WARL" reset="3">
            Contains the privilege mode the hart was operating in when Debug
            Mode was entered. The encoding is described in &lt;&lt;tab:privmode&gt;&gt;.  A debugger can change this value to change
            the hart's privilege mode when exiting Debug Mode.

            Not all privilege modes are supported on all harts. If the
            encoding written is not supported or the debugger is not allowed to
            change to it, the hart may change to any supported privilege mode.
        </field>
    </register>

    <register name="Debug PC" short="dpc" address="0x7b1">
        Upon entry to debug mode, {csr-dpc} is updated with the virtual address of
        the next instruction to be executed. The behavior is described in more
        detail in &lt;&lt;tab:dpc&gt;&gt;.

        [[tab:dpc]]
        .Virtual address in DPC.
        [%autowidth,align="center",float="center",cols="&gt;,^",options="header"]
        |===
        | Cause  | Virtual Address in DPC
        | `ebreak` | Address of the `ebreak` instruction
        | single step | Address of the instruction that would be executed next if no debugging was going on. Ie. `pc` + 4 for
        32-bit instructions that don't change program flow, the destination PC on taken jumps/branches, etc.
        | trigger module | The address of the next instruction to be executed at the time that debug mode was entered. If the trigger is {csr-mcontrol} and {mcontrol-timing} is 0 or if the trigger is
        {csr-mcontrol6} and `hit1` is 0, this corresponds to the address of the instruction which caused the trigger to fire.
        | halt request | Address of the next instruction to be executed at the time that debug mode was entered.
        |===

        Executing the Program Buffer may cause the value of {csr-dpc} to become
        UNSPECIFIED. If that is the case, it must be possible to read/write
        {csr-dpc} using an abstract command with {accessregister-postexec} not
        set.  The debugger must attempt to save {csr-dpc} between halting and
        executing a Program Buffer, and then restore {csr-dpc} before leaving
        Debug Mode.

        [NOTE]
        ====
            Allowing {csr-dpc} to become UNSPECIFIED upon Program Buffer
            execution allows for direct implementations that don't have a
            separate PC register, and do need to use the PC when executing the
            Program Buffer.
        ====

        If the Access Register abstract command supports reading {csr-dpc} while
        the hart is running, then the value read should be the address of a
        recently executed instruction.

        If the Access Register abstract command supports writing {csr-dpc} while
        the hart is running, then the executing program should jump to the
        written address shortly after the write occurs.

        The writability of {csr-dpc} follows the same rules as `mepc` as defined
        in the Privileged Spec.  In particular, {csr-dpc} must be able to hold
        all valid virtual addresses and the writability of the low bits depends
        on IALIGN.

        When resuming, the hart's PC is updated to the virtual address stored in
        {csr-dpc}. A debugger may write {csr-dpc} to change where the hart resumes.
        <field name="dpc" bits="DXLEN-1:0" access="R/W" reset="0" />
    </register>

    <register name="Debug Scratch Register 0" short="dscratch0" address="0x7b2">
        Optional scratch register that can be used by implementations that need
        it. A debugger must not write to this register unless {dm-hartinfo}
        explicitly mentions it (the Debug Module may use this register internally).
        <field name="dscratch0" bits="DXLEN-1:0" access="R/W" reset="0" />
    </register>

    <register name="Debug Scratch Register 1" short="dscratch1" address="0x7b3">
        Optional scratch register that can be used by implementations that need
        it. A debugger must not write to this register unless {dm-hartinfo}
        explicitly mentions it (the Debug Module may use this register internally).
        <field name="dscratch1" bits="DXLEN-1:0" access="R/W" reset="0" />
    </register>
</registers>
