Introduction
Special registers hold the processor state: the status word PS, the shift amount SAR, the window registers, the loop
registers, the exception and interrupt registers, the debug registers. They are numbered 0 to 255 and reached with three instructions
that take an address register; the explorer writes the register's name after a dot (rsr.ps a2). A number with no name on
the chosen chip is not an instruction. User registers (0 to 255) are the coprocessor and extension state, reached with
RUR and WUR. Most special registers are privileged: they trap in user mode.
Reading and writing registers
| Instruction | Encoding | What it does |
|---|---|---|
rsr.name at | 0 3 n n t 0 | Read special register number n (8 bits, r:s) into at. |
wsr.name at | 1 3 n n t 0 | Write at to special register n. |
xsr.name at | 6 1 n n t 0 | Exchange at with special register n. |
rur.name ar | e 3 r u u 0 | Read user register u (8 bits, s:t) into ar. |
wur.name at | f 3 u u t 0 | Write at to user register u (r:s). |
Special registers
Names and numbers are what the Espressif toolchain's objdump prints for each chip, and the cores' configuration files list. Access:
r RSR, w WSR, x XSR; register 226 is INTERRUPT when read and INTSET when written.
Chips: all four, 32/S3 the ESP32 and ESP32-S3, not 8266 the three newer ones.
| Number | Name | Access | Chips | Holds |
|---|---|---|---|---|
| 0 | lbeg | rwx | 32/S3 | Loop begin. |
| 1 | lend | rwx | 32/S3 | Loop end. |
| 2 | lcount | rwx | 32/S3 | Loop count. |
| 3 | sar | rwx | all | Shift amount. |
| 4 | br | rwx | 32/S3 | The boolean registers. |
| 5 | litbase | rwx | all | Literal base. |
| 12 | scompare1 | rwx | 32/S3 | The value S32C1I compares with. |
| 16, 17 | acclo, acchi | rwx | 32/S3 | MAC16 accumulator. |
| 32 to 35 | m0 to m3 | rwx | 32/S3 | MAC16 registers. |
| 72 | windowbase | rwx | not 8266 | Window base. |
| 73 | windowstart | rwx | not 8266 | Window start bits. |
| 89 | mmid | w | all | Memory-map ID. |
| 95 | eraccess | rwx | S2, S3 | External register access. |
| 96 | ibreakenable | rwx | all | Instruction breakpoint enable. |
| 97 | memctl | rwx | not 8266 | Memory control. |
| 99 | atomctl | rwx | 32/S3 | Atomic-operation control. |
| 104 | ddr | rwx | all | Debug data register. |
| 128, 129 | ibreaka0, ibreaka1 | rwx | 1 on 8266 | Instruction breakpoint addresses. |
| 144, 145 | dbreaka0, dbreaka1 | rwx | 1 on 8266 | Data breakpoint addresses. |
| 160, 161 | dbreakc0, dbreakc1 | rwx | 1 on 8266 | Data breakpoint control. |
| 176 | configid0 | rw | all | Configuration ID. |
| 177 to 183 | epc1 to epc7 | rwx | 1 to 3 on 8266 | Exception program counters. |
| 192 | depc | rwx | all | Double-exception program counter. |
| 194 to 199 | eps2 to eps7 | rwx | 2, 3 on 8266 | Saved processor state. |
| 208 | configid1 | r | all | Configuration ID. |
| 209 to 215 | excsave1 to excsave7 | rwx | 1 to 3 on 8266 | Exception scratch registers. |
| 224 | cpenable | rwx | not 8266 | Coprocessor enable. |
| 226 | interrupt / intset | r / w | all | Pending interrupts / set interrupt bits. |
| 227 | intclear | w | all | Clear edge-triggered interrupts. |
| 228 | intenable | rwx | all | Interrupt enable. |
| 230 | ps | rwx | all | Processor state: INTLEVEL (bits 3:0), EXCM (4), UM (5), RING (7:6), OWB (11:8), CALLINC (17:16), WOE (18). |
| 231 | vecbase | rwx | all | Base of the exception vectors. |
| 232 | exccause | rwx | all | Cause of the last exception. |
| 233 | debugcause | rwx | all | Cause of the last debug exception. |
| 234 | ccount | rwx | all | Cycle counter. |
| 235 | prid | r | all | Processor ID (which core). |
| 236, 237 | icount, icountlevel | rwx | all | Instruction counter and its level. |
| 238 | excvaddr | rwx | all | Faulting address. |
| 240 to 242 | ccompare0 to ccompare2 | rwx | 1 on 8266 | Cycle-count compare (timer interrupts). |
| 244 to 247 | misc0 to misc3 | rwx | not 8266 | Scratch registers. |
User registers
| Number | Name | Chips | Holds |
|---|---|---|---|
| 230 | expstate | ESP32 | GPIO export state (Espressif). |
| 231 | threadptr | not 8266 | Thread pointer (thread-local storage). |
| 232, 233 | fcr, fsr | ESP32, ESP32-S3 | Floating-point control and status. |
| 234 to 236 | f64r_lo, f64r_hi, f64s | ESP32 | The F64 helper registers. |
| 0 | gpio_out | ESP32-S2 | GPIO output. |
| 12 | gpio_out | ESP32-S3 | GPIO output. |
| 0 to 11, 13 to 18 | accx_0, accx_1, qacc_h_0 to qacc_l_4, sar_byte, fft_bit_width, ua_state_0 to ua_state_3 | ESP32-S3 | The vector (PIE) state. |
Exceptions, interrupts and synchronisation
| Instruction | Encoding | What it does |
|---|---|---|
ill | 0 0 0 0 0 0 | Illegal instruction: always raises the illegal-instruction exception (an all-zero word). |
syscall | 0 0 5 0 0 0 | System-call exception. |
simcall | 0 0 5 1 0 0 | Simulator call (used under an instruction-set simulator). |
break s, t | 0 0 4 s t 0 | Debug breakpoint exception with two immediates. |
rfe | 0 0 3 0 0 0 | Return from an exception: resume at EPC1, restoring PS. |
rfde | 0 0 3 2 0 0 | Return from a double exception (from DEPC). |
rfi level | 0 0 3 s 1 0 | Return from a high-priority interrupt of the given level (from EPCn and EPSn). |
rsil at, level | 0 0 6 s t 0 | Read PS into at and set the interrupt level to s: the usual critical section. |
waiti level | 0 0 7 s 0 0 | Set the interrupt level and wait for an interrupt. |
isync | 0 0 2 0 0 0 | Instruction-fetch synchronisation (after code is written). |
rsync | 0 0 2 0 1 0 | Wait for earlier special-register writes. |
esync | 0 0 2 0 2 0 | Exception synchronisation. |
dsync | 0 0 2 0 3 0 | Data synchronisation. |
excw | 0 0 2 0 8 0 | Exception wait: earlier instructions that can raise an exception finish first. |
memw | 0 0 2 0 c 0 | Memory wait: earlier loads and stores finish first (the barrier used around peripheral registers). |
extw | 0 0 2 0 d 0 | External wait: earlier external accesses finish first. |
nop | 0 0 2 0 f 0 | No operation. |
Debug and translation buffers
| Instruction | Encoding | What it does |
|---|---|---|
rer at, as | 4 0 6 s t 0 | Read an external register (address in as). |
wer at, as | 4 0 7 s t 0 | Write an external register. |
lddr32.p as | 0 0 7 s e 0 | On-chip-debug load (not on the ESP8266). |
sddr32.p as | 0 0 7 s f 0 | On-chip-debug store (not on the ESP8266). |
rfdo n | f 1 e s 0 0 | Return from debug exception (on-chip debug). |
rfdd | f 1 e z 1 0 | Return from debug exception, double. |
ritlb0 at, as | 5 0 3 s t 0 | Read an instruction-TLB entry (virtual part). |
iitlb as | 5 0 4 s 0 0 | Invalidate an instruction-TLB entry. |
pitlb at, as | 5 0 5 s t 0 | Probe the instruction TLB. |
witlb at, as | 5 0 6 s t 0 | Write an instruction-TLB entry. |
ritlb1 at, as | 5 0 7 s t 0 | Read an instruction-TLB entry (translation part). |
rdtlb0 at, as | 5 0 b s t 0 | Read a data-TLB entry (virtual part). |
idtlb as | 5 0 c s 0 0 | Invalidate a data-TLB entry. |
pdtlb at, as | 5 0 d s t 0 | Probe the data TLB. |
wdtlb at, as | 5 0 e s t 0 | Write a data-TLB entry. |
rdtlb1 at, as | 5 0 f s t 0 | Read a data-TLB entry (translation part). |
Not described
Known, not yet covered
- Reference: the bit fields of every special register other than
PS, the exception cause numbers, the vector layout, and the ESP chips' interrupt matrix. - Reference: the cache and prefetch instructions and the MMU registers of the generic Xtensa configuration (no ESP chip has them).
Unknown
- Reference: the
PSbit positions are from the Xtensa manual as remembered; no tool checks them. - Reference: the ESP32-S2 register list comes from objdump's behaviour; it has no core configuration file here.
- Reference: the TLB instructions are in every ESP chip's toolchain, but whether the hardware implements a TLB (the ESP chips have a fixed memory map) is not established.
Links
Reference
- ESP-IDF documentation – Espressif's documentation of the chips