# Registers Hexagon has general registers and control registers. Control registers support special-purpose processor features such as hardware loops and predicates. ## General registers The Hexagon processor has thirty-two 32-bit general-purpose registers (named R0 through R31). These registers store operands in the instructions: - Memory addresses for load/store instructions - Data operands for arithmetic/logic instructions - Vector operands for 32-bit and 64-bit vector instructions For example: R1 = memh(R0) // Load from address R0 R4 = add(R2,R3) // Add R28 = vaddh(R11,R10) // Vector add halfword Copy to clipboard Page-1 Sheet.2 . . Sheet.3 Sheet.4 Rectangle R0 R0 Rectangle.3 R1 R1 Rectangle.4 R2 R2 Rectangle.5 R3 R3 Rectangle.6 R28 R28 Rectangle.7 R29 R29 Rectangle.8 R30 R30 Rectangle.9 R31 R31 Rectangle.1 R1:0 R1:0 Sheet.14 Rectangle.198 R3:2 R3:2 Sheet.16 Rectangle.200 R29:28 R29:28 Sheet.18 Rectangle.202 R31:30 R31:30 Sheet.20 . . Sheet.21 . . **General registers** ### Aliased registers Three of the general registers - R29 through R31 - support subroutines ([calls](https://docs.qualcomm.com/doc/80-N2040-60/topic/program-flow.html#v79-prm-calls)) and the [Software stack](https://docs.qualcomm.com/doc/80-N2040-60/topic/software-stack.html). The subroutine and stack instructions implicitly modify the registers. R29-R31 are aliased to SP, FP, and LR respectively. For example: SP = add(SP, #-8) // SP is an alias of R29 allocframe // Modifies SP (R29) and FP (R30) call init // Modifies LR (R31) Copy to clipboard General register aliases | **Register** | **Alias** | **Name** | **Description** | | --- | --- | --- | --- | | R29 | SP | Stack pointer | Points to the topmost element of the stack in memory. | | R30 | FP | Frame pointer | Points to the current stack frame. | | R31 | LR | Link register | Stores the return address of a subroutine call. | ### Register pairs The general registers can be specified as register pairs that represent a single 64-bit register. For example: R1:0 = memd(R3) // Load doubleword R7:6 = valignb(R9:8,R7:6, #2) // Vector align Copy to clipboard The first register in a register pair is always odd-numbered and the second is the next lower register. | **Register** | **Register pair** | | --- | --- | | R0 | R1:0 | | R1 | R1:0 | | R2 | R3:2 | | R3 | R3:2 | | R4 | R5:4 | | R5 | R5:4 | | R6 | R7:6 | | R7 | R7:6 | | **…** | **…** | | R24 | R25:24 | | R25 | R25:24 | | R26 | R27:26 | | R27 | R27:26 | | R28 | R29:28 | | R29 (SP) | R29:28 | | R30 (FP) | R31:30 (LR:FP) | | R31 (LR) | R31:30 (LR:FP) | | | | ## Control registers The Hexagon processor includes a set of 32-bit control registers that provide access to processor features such as the program counter, hardware loops, and vector predicates. Unlike general registers, control registers are used as instruction operands only in the following cases: - Instructions that require a specific control register as an operand - Register transfer instructions For example: R2 = memw(R0++M1) // Auto-increment addressing mode (M1) R9 = PC // Get program counter (PC) LC1 = R3 // Set hardware loop count (LC1) Copy to clipboard When a control register is used in a register transfer, the other operand must be a general register. Page-1 Sheet.1 Sheet.2 Loop registers Loop registers Rectangle.15 LC0 LC0 Rectangle.4 SA0 SA0 Rectangle.18 LC1 LC1 Rectangle.19 SA1 SA1 Rectangle.41 PC PC Rectangle.40 USR USR Sheet.9 User status register User status register Sheet.10 Sheet.11 Program counter Program counter Rectangle.210 M0 M0 Rectangle.212 M1 M1 Sheet.14 Modifier registers Modifier registers Sheet.15 Rectangle.28 P3:0 P3:0 Rectangle.31 UGP UGP Sheet.18 Predicate registers Predicate registers Sheet.19 User general pointer User general pointer Rectangle.70 GP GP Sheet.21 Global pointer Global pointer Rectangle.22 CS0 CS0 Rectangle.23 CS1 CS1 Sheet.24 Circular start registers Circular start registers Sheet.25 Rectangle.26 UPCYCLELO UPCYCLELO Rectangle.27 UPCYCLEHI UPCYCLEHI Sheet.28 Cycle count registers Cycle count registers Sheet.29 Rectangle.30 FRAMELIMIT FRAMELIMIT Rectangle.31 FRAMEKEY FRAMEKEY Sheet.32 Stack bounds register Stack bounds register Sheet.33 Stack smash register Stack smash register Rectangle.34 PKTCOUNTLO PKTCOUNTLO Rectangle.35 PKTCOUNTHI PKTCOUNTHI Sheet.36 Packet count registers Packet count registers Sheet.37 Rectangle.38 UTIMERLO UTIMERLO Rectangle.39 UTIMERHI UTIMERHI Sheet.40 Qtimer registers Qtimer registers Sheet.41 **Control registers** ### Aliased registers The control registers have numeric aliases (C0 through C31). The control register numbers (0 through 31) specify the control registers in [Instruction encoding](https://docs.qualcomm.com/doc/80-N2040-60/topic/instruction-encoding.html). Aliased control registers | **Register** | **Alias** | **Name** | | --- | --- | --- | | SA0 | C0 | Loop start address register 0 | | LC0 | C1 | Loop count register 0 | | SA1 | C2 | Loop start address register 1 | | LC1 | C3 | Loop count register 1 | | P3:0 | C4 | Predicate registers 3:0 | | reserved | C5 | | | M0 | C6 | Modifier register 0 | | M1 | C7 | Modifier register 1 | | USR | C8 | User status register | | PC | C9 | Program counter | | UGP | C10 | User general pointer | | GP | C11 | Global pointer | | CS0 | C12 | Circular start register 0 | | CS1 | C13 | Circular start register 1 | | UPCYCLELO | C14 | Cycle count register (low) | | UPCYCLEHI | C15 | Cycle count register (high) | | UPCYCLE | C15:14 | Cycle count register | | FRAMELIMIT | C16 | Frame limit register | | FRAMEKEY | C17 | Frame key register | | PKTCOUNTLO | C18 | Packet count register (low) | | PKTCOUNTHI | C19 | Packet count register (high) | | PKTCOUNT | C19:18 | Packet count register | | reserved | C20-29 | | | UTIMERLO | C30 | QTimer register (low) | | UTIMERHI | C31 | QTimer register (high) | | UTIMER | C31:30 | QTimer register | ### Control register pairs The control registers can be specified as register pairs that represent a single 64-bit register. Control registers specified as pairs must use their numeric aliases. For example: C1:0 = R5:4 / C1:0 specifies the LC0/SA0 register pair Copy to clipboard The first register in a control register pair must always be odd-numbered, and the second must be the next lower register. | **Register** | **Register pair** | | --- | --- | | C0 | C1:0 | | C1 | C1:0 | | C2 | C3:2 | | C3 | C3:2 | | C4 | C5:4 | | C5 | C5:4 | | C6 | C7:6 | | C7 | C7:6 | | **…** | **…** | | C30 | C31:30 | | C31 | C31:30 | | | | ### Program counter The program counter (PC) register points to the instruction packet to execute ([instruction packets](https://docs.qualcomm.com/doc/80-N2040-60/topic/instructions.html#v79-prm-instruction-packets)). The PC is read-only and updates when the current packet completes. Instruction execution modifies the PC. For example: R7 = PC // Get program counter Copy to clipboard ### Loop registers The Hexagon processor includes two sets of loop registers to support nested [Hardware loops](https://docs.qualcomm.com/doc/80-N2040-60/topic/registers.html#hardware-loops). Each hardware loop is implemented with a pair of registers containing the loop count and loop start address. The loop instruction implicitly modifies the loop registers, but the loop instructions can also be accessed directly. For example: loop0(start, R4) // Modifies LC0 and SA0 (LC0 = R4, SA0 = start) LC1 = R22 // Set loop1 count R9 = SA1 // Get loop1 start address Copy to clipboard Loop registers | **Register** | **Name** | **Description** | | --- | --- | --- | | LC0, LC1 | Loop count | Number of loop iterations to execute. | | SA0, SA1 | Loop start address | Address of first instruction in loop. | ### User status register The user status register (USR) stores processor status and control bits that user programs can access. The status bits contain the status results of certain instructions, while the control bits contain user-settable processor modes for hardware prefetching. For example: R9:8 = vaddw(R9:8, R3:2):sat // Vector add words R6 = USR // Get saturation status Copy to clipboard USR stores the following status and control values: - [Cache prefetch types supported by the Hexagon processor](https://docs.qualcomm.com/doc/80-N2040-60/topic/registers.html#cache-prefetch-types-supported-by-the-hexagon-processor) enable - Cache prefetch status - [Floating point](https://docs.qualcomm.com/doc/80-N2040-60/topic/registers.html#floating-point) modes - Floating point status - Floating point exception enable - Hardware loop configuration ([hardware loops](https://docs.qualcomm.com/doc/80-N2040-60/topic/program-flow.html#v79-prm-hardware-loops)) - Sticky [Saturation](https://docs.qualcomm.com/doc/80-N2040-60/topic/registers.html#saturation) overflow A user control register transfer to USR cannot be grouped in an instruction packet with a [Floating point](https://docs.qualcomm.com/doc/80-N2040-60/topic/registers.html#floating-point) instruction. When a transfer to USR changes the enable trap bits [29:25], an isync instruction ([memory ordering](https://docs.qualcomm.com/doc/80-N2040-60/topic/memory.html#v79-prm-memory-ordering)) must execute before the new exception programming can take effect. User status register | **Name** | **RW** | **Bits** | **Field** | **Description** | | --- | --- | --- | --- | --- | | USR | | 32 | | User status register | | | R | 31 | PFA | L2 prefetch active.


Set when the nonblocking l2fetch instruction prefetches
therequested data.


Remains set until thel2fetch prefetch operation completes
(or is inactive). | | | R | 30 | reserved | Reserved. | | | RW | 29 | FPINEE | Enable exception on IEEE inexact. | | | RW | 28 | FPUNFE | Enable exception on IEEE underflow. | | | RW | 27 | FPOVFE | Enable exception on IEEE overflow. | | | RW | 26 | FPDBZE | Enable exception on IEEE divide-by-zero. | | | RW | 25 | FPINVE | Enable exception on IEEE invalid. | | | R | 24 | reserved | Reserved | | | RW | 23:22 | FPRND | Rounding mode for floating point instructions.
| | | R | 21:20 | FPCOPROC | Controls IEEE-754 floating point behavior.


Both bits set to 1 gives IEEE-754 behavior. | | | R | 19:18 | reserved | Reserved | | | R | 17 | reserved | Reserved. | | | RW | 16:15 | HFI | L1 instruction prefetch.
| | | RW | 14:13 | HFD | L1 data cache prefetch.


Four levels are defined from disabled to aggressive.
Implementation defines how to interpret these levels.
| | | RW | 12 | PCMME | Enable packet counting in monitor mode. | | | RW | 11 | PCGME | Enable packet counting in guest mode. | | | RW | 10 | PCUME | Enable packet counting in user mode. | | | RW | 9:8 | LPCFGE | Hardware loop configuration.


Number of loop iterations (0 to 3) that remain before the
pipeline predicate should be set. | | | R | 7:6 | reserved | Reserved. | | | RW | 5 | FPINPF | Floating-point IEEE inexact sticky fag. Remains set until explicitly cleared. | | | RW | 4 | FPUNFF | Floating-point IEEE underflow sticky flag. Remains set until explicitly cleared. | | | RW | 3 | FPOVFF | Floating-point IEEE overflow sticky flag. Remains set until explicitly cleared. | | | RW | 2 | FPDBZF | Floating-point IEEE divide-by-zero sticky flag. Remains set until explicitly cleared. | | | RW | 1 | FPINVF | Floating-point IEEE invalid sticky flag. Remains set until explicitly cleared. | | | RW | 0 | OVF | Sticky saturation overflow.


Remains set until explicitly cleared. | ### Modifier registers The following addressing modes use the modifier registers (M0 and M1): #### Indirect auto-increment In [indirect with auto-increment register](https://docs.qualcomm.com/doc/80-N2040-60/topic/memory.html#v79-prm-indirect-with-auto-increment-register) addressing, the modifier registers store a signed 32-bit value that specifies the increment or decrement value. R2 = memw(R0++M1) Copy to clipboard Modifier registers used in indirect auto-increment addressing | **Register** | **Name** | **Description** | | --- | --- | --- | | M0, M1 | Increment | Signed auto-increment value. | #### Circular In [circular addressing](https://docs.qualcomm.com/doc/80-N2040-60/topic/memory.html#v79-prm-circular-with-auto-increment-immediate), the modifier registers store the circular buffer length and related “I” values. R2 = memw(R2++#8:circ(M0)) Copy to clipboard Modifier registers as used in circular addressing | **Name** | **RW** | **Bits** | **Field** | **Description** | | --- | --- | --- | --- | --- | | M0, M1 | | 32 | | Circular buffer specifier. | | | RW | 31:28 | I[10:7] | I value (MSB - see [cirular with auto-increment](https://docs.qualcomm.com/doc/80-N2040-60/topic/memory.html#v79-prm-circular-with-auto-increment-register)) | | | RW | 27:24 | | 0x0 | | | RW | 23:17 | I[6:0] | I value (LSB) | | | RW | 16:0 | Length | Circular buffer length | #### Bit-reversed In [bit-reversed addressing](https://docs.qualcomm.com/doc/80-N2040-60/topic/memory.html#v79-prm-bit-reversed-with-auto-increment-register), the modifier registers store a signed 32-bit value that specifies the increment or decrement value. R2 = memw(R0++M1:brev) Copy to clipboard Modifier registers as used in bit-reversed addressing | **Register** | **Name** | **Description** | | --- | --- | --- | | M0, M1 | Increment | Signed auto-increment value. | ### Predicate registers The predicate registers (P0 through P3) store the status results of the scalar and vector compare instructions ([Conditional execution](https://docs.qualcomm.com/doc/80-N2040-60/topic/conditional-execution.html)). For example: P1 = cmp.eq(R2, R3) // Scalar compare if (P1) jump end // Jump to address (conditional) R8 = P1 // Get compare status (P1 only) P3:0 = R4 // Set compare status (P0 through P3) Copy to clipboard Unlike the other control registers, the predicate registers are only 8 bits wide because instructions return a maximum of eight status results. The register quadruple (P3:0) accesses the four 8-bit predicates as a single 32-bit register. P3:0 = R4 // Set compare status (P0 through P3) Copy to clipboard Predicate registers | **Register** | **Bits** | **Description** | | --- | --- | --- | | P0, P1, P2, P3 | 8 | Compare status results. | | P3:0 | 32 | Compare status results. | | | 31:24 | P3 register | | | 23:16 | P2 register | | | 15:8 | P1 register | | | 7:0 | P0 register | ### Circular start registers The circular start registers (CS0 and CS1) store the start address of a circular buffer in [circular addressing](https://docs.qualcomm.com/doc/80-N2040-60/topic/memory.html#v79-prm-circular-with-auto-increment-immediate). For example: CS0 = R5 // Set circ start register M0 = R7 // Set modifier register R0 = memb(R2++#4:circ(M0)) // Load from circ buffer pointed // to by CS0 with size/K vals in M0 Copy to clipboard Circular start registers | **Register** | **Name** | **Description** | | --- | --- | --- | | CS0, CS1 | Circular start | Circular buffer start address. | ### User general pointer register The user general pointer (UGP) register is a general-purpose control register. For example: R9 = UGP // Get UGP UGP = R3 // Set UGP Copy to clipboard User general pointer register | **Register** | **Name** | **Description** | | --- | --- | --- | | UGP | User general pointer | General-purpose control register. | ### Global pointer GP-relative addressing uses the global pointer (GP). For example: GP = R7 // Set GP R2 = memw(GP+#200) // GP-relative load Copy to clipboard Global pointer register | **Name** | **R/W** | **Bits** | **Field** | **Description** | | --- | --- | --- | --- | --- | | GP | | 32 | | Global pointer register | | | R/W | 31:6 | GDP | [Global data pointer](https://docs.qualcomm.com/doc/80-N2040-60/topic/memory.html#v79-prm-global-pointer-relative). | | | R | 5:0 | reserved | Reserved. | ### Cycle count registers The cycle count registers UPCYCLELO and UPCYCLEHI together store a 64-bit value containing the current number of processor cycles executed since the Hexagon processor was last reset. For example: R5 = UPCYCLEHI // Get cycle count (high) R4 = UPCYCLELO // Get cycle count (low) R5:4 = UPCYCLE // Get cycle count Copy to clipboard System software controls access to these registers. When access is disabled, read operations return 0. Cycle count registers | **Register** | **Name** | **Description** | | --- | --- | --- | | UPCYCLELO | Cycle count (low) | Processor cycle count (low 32 bits) | | UPCYCLEHI | Cycle count (high) | Processor cycle count (high 32 bits) | | UPCYCLE | Cycle count | Processor cycle count (64 bits) | ### Frame limit register The FRAMELIMIT register stores the low address of the memory area reserved for the software stack ([stack bounds checking](https://docs.qualcomm.com/doc/80-N2040-60/topic/software-stack.html#v79-prm-stack-bounds-checking)). For example: R9 = FRAMELIMIT // Get frame limit register FRAMELIMIT = R3 // Set frame limit register Copy to clipboard Frame limit register | **Register** | **Name** | **Description** | | --- | --- | --- | | FRAMELIMIT | Frame limit | Low address of software stack area. | ### Frame key register The processor XORs the return address with the FRAMEKEY when pushing the address on the software stack ([stack smashing protection](https://docs.qualcomm.com/doc/80-N2040-60/topic/software-stack.html#v79-prm-stack-smashing-protection)). For example: R2 = FRAMEKEY // Get frame key register FRAMEKEY = R1 // Set frame key register Copy to clipboard Frame key register | **Register** | **Name** | **Description** | | --- | --- | --- | | FRAMEKEY | Frame key | Key to scramble return addresses stored on the software stack. | ### Packet count registers The packet count registers PKTCOUNTLO and PKTCOUNTHI store a 64-bit value containing the current number of instruction packets executed since a packet count register was last written. For example: R9 = PKTCOUNTHI // Get packet count (high) R8 = PKTCOUNTLO // Get packet count (low) R9:8 = PKTCOUNT // Get packet count Copy to clipboard Packet counting can be configured to operate only in specific sets of processor modes (for example, user mode only, or guest and monitor modes only). USR[12:10] [User status](https://docs.qualcomm.com/doc/80-N2040-60/topic/registers.html#user-status-register) [register](https://docs.qualcomm.com/doc/80-N2040-60/topic/registers.html#user-status-register) control the configuration for each mode. Packets with exceptions are not counted as committed packets. System software controls access to these register. When access is disabled, read operations return 0. When a value is written to a packet count register, the 64-bit packet count value is incremented before the value is stored in the register. Packet count registers | **Register** | **Name** | **Description** | | --- | --- | --- | | PKTCOUNTLO | Packet count (low) | Processor packet count (low 32 bits) | | PKTCOUNTHI | Packet count (high) | Processor packet count (high 32 bits) | | PKTCOUNT | Cycle count | Processor packet count (64 bits) | ### QTimer registers The QTimer registers UTIMERLO and UTIMERHI provide access to the QTimer global reference count value. The QTimer registers enable Hexagon software to read the 64-bit time value without having to perform an advanced high-performance bus (AHB) load. For example: R5 = UTIMERHI // Get QTimer reference count (high) R4 = UTIMERLO // Get QTimer reference count (low) R5:4 = UTIMER // Get QTimer reference count Copy to clipboard These registers are read only and hardware automatically updates these registers with the current QTimer value. System software controls access to these registers. When access is disabled, read operations return 0. QTimer registers | **Register** | **Name** | **Description** | | --- | --- | --- | | UTIMERLO | QTimer (low) | QTimer global reference count (low 32 bits) | | UTIMERHI | QTimer (high) | QTimer global reference count (high 32 bits) | | UTIMER | QTimer | QTimer global reference count (64 bits) | ### UPMUCNT registers The eight 32-bit read-only User PMU Count (UPMUCNT) registers count performance events. The counters increment each time a selected event occurs and wrap-around on overflow. These registers have undefined value on reset. SSR.PE enables access to the UPMUCNT registers. UPMU counter registers | **Register** | **Fields** | **Access** | | --- | --- | --- | | UPMUCNT0 | [31:0] PMU Counter 0 | Monitor CR map RW | | UPMUCNT1 | [31:0] PMU Counter 1 | Monitor CR map RW | | UPMUCNT2 | [31:0] PMU Counter 2 | Monitor CR map RW | | UPMUCNT3 | [31:0] PMU Counter 3 | Monitor CR map RW | | UPMUCNT4 | [31:0] PMU Counter 4 | Monitor CR map RW | | UPMUCNT5 | [31:0] PMU Counter 5 | Monitor CR map RW | | UPMUCNT6 | [31:0] PMU Counter 6 | Monitor CR map RW | | UPMUCNT7 | [31:0] PMU Counter 7 | Monitor CR map RW | Last Published: Jan 16, 2025 [Previous Topic Revision history](https://docs.qualcomm.com/bundle/publicresource/80-N2040-60/topics/revision.md) [Next Topic Instructions](https://docs.qualcomm.com/bundle/publicresource/80-N2040-60/topics/instructions.md) Source: [https://docs.qualcomm.com/doc/80-N2040-60/topic/registers.html](https://docs.qualcomm.com/doc/80-N2040-60/topic/registers.html)