Introduction
These instructions are in every Xtensa core. Each is 3 bytes. In the encodings below the six groups are the 24-bit word's
nibbles from the top (op2 op1 r s t op0); a digit is fixed, a letter is a field. ar, as and
at are the address registers named by the fields r, s and t. See
formats and the op0 tree. Instructions that write a register from two others take the destination first:
add a2, a3, a4 is a2 = a3 + a4.
Arithmetic, logic and moves
| Instruction | Encoding | What it does |
|---|---|---|
add ar, as, at | 8 0 r s t 0 | ar = as + at. |
addx2 ar, as, at | 9 0 r s t 0 | ar = (as << 1) + at. |
addx4 ar, as, at | a 0 r s t 0 | ar = (as << 2) + at. |
addx8 ar, as, at | b 0 r s t 0 | ar = (as << 3) + at. |
sub ar, as, at | c 0 r s t 0 | ar = as - at. |
subx2 ar, as, at | d 0 r s t 0 | ar = (as << 1) - at. |
subx4 ar, as, at | e 0 r s t 0 | ar = (as << 2) - at. |
subx8 ar, as, at | f 0 r s t 0 | ar = (as << 3) - at. |
and ar, as, at | 1 0 r s t 0 | Bitwise AND. |
or ar, as, at | 2 0 r s t 0 | Bitwise OR. With as = at the assembler writes mov. |
xor ar, as, at | 3 0 r s t 0 | Bitwise exclusive OR. |
neg ar, at | 6 0 r 0 t 0 | ar = 0 - at. |
abs ar, at | 6 0 r 1 t 0 | Absolute value. |
addi at, as, imm8 | i i c s t 2 | Add a signed 8-bit immediate (-128 to 127). |
addmi at, as, imm | i i d s t 2 | Add a signed 8-bit immediate shifted left 8 (-32768 to 32512). |
movi at, imm12 | i i a m t 2 | Load a signed 12-bit immediate (-2048 to 2047); m:i is the 12 bits. |
moveqz ar, as, at | 8 3 r s t 0 | ar = as if at is zero. |
movnez ar, as, at | 9 3 r s t 0 | ar = as if at is not zero. |
movltz ar, as, at | a 3 r s t 0 | ar = as if at is negative. |
movgez ar, as, at | b 3 r s t 0 | ar = as if at is not negative. |
min ar, as, at | 4 3 r s t 0 | Signed minimum (MINMAX option). |
max ar, as, at | 5 3 r s t 0 | Signed maximum. |
minu ar, as, at | 6 3 r s t 0 | Unsigned minimum. |
maxu ar, as, at | 7 3 r s t 0 | Unsigned maximum. |
clamps ar, as, n | 3 3 r s t 0 | Clamp to a signed range of n bits; the written n is the field plus 7 (8 to 23). |
sext ar, as, n | 2 3 r s t 0 | Sign-extend from bit n; the written n is the field plus 7 (7 to 22). |
nsa at, as | 4 0 e s t 0 | The number of redundant sign bits of as (0 to 31). |
nsau at, as | 4 0 f s t 0 | The number of leading zero bits of as (0 to 32). |
Shifts and bit extraction
The variable shifts use the shift amount register SAR (5 bits); the ss instructions load it.
| Instruction | Encoding | What it does |
|---|---|---|
slli ar, as, 1..32 | 000h 1 r s h 0 | Shift left logical by an immediate; the field h:t (5 bits) holds 32 minus the amount. |
srai ar, at, 0..31 | 001h 1 r s t 0 | Shift right arithmetic; the amount is h:s. |
srli ar, at, 0..15 | 4 1 r s t 0 | Shift right logical; the amount is s. |
extui ar, at, shift, mask | m 010h r s t 0 | ar = (at >> shift) and a mask of m+1 one bits; the shift is h:s. |
sll ar, as | a 1 r s 0 0 | Shift left logical by 32 minus SAR. |
srl ar, at | 9 1 r 0 t 0 | Shift right logical by SAR. |
sra ar, at | b 1 r 0 t 0 | Shift right arithmetic by SAR. |
src ar, as, at | 8 1 r s t 0 | Funnel shift: the low 32 bits of (as:at) >> SAR. |
ssr as | 4 0 0 s 0 0 | SAR = the low 5 bits of as. |
ssl as | 4 0 1 s 0 0 | SAR = 32 minus the low 5 bits of as. |
ssa8l as | 4 0 2 s 0 0 | SAR = 8 times the low 2 bits of as. |
ssa8b as | 4 0 3 s 0 0 | SAR = 32 minus 8 times the low 2 bits of as. |
ssai 0..31 | 4 0 4 s 000h 0 | SAR = the immediate h:s. |
Loads, stores and literals
Offsets are unsigned and scaled by the access size. L32R reads a literal that sits before the instruction:
the address is ((pc + 3) & ~3) + ((0xFFFF0000 | imm16) << 2), a negative word offset from 4 to 262,144 bytes back. The explorer
shows that address as the operand and as the instruction's reference.
| Instruction | Encoding | What it does |
|---|---|---|
l8ui at, as, 0..255 | i i 0 s t 2 | Load a byte, zero-extended. |
l16ui at, as, 0..510 | i i 1 s t 2 | Load a halfword, zero-extended; the offset is i times 2. |
l32i at, as, 0..1020 | i i 2 s t 2 | Load a word; the offset is i times 4. |
s8i at, as, 0..255 | i i 4 s t 2 | Store the low byte. |
s16i at, as, 0..510 | i i 5 s t 2 | Store the low halfword. |
s32i at, as, 0..1020 | i i 6 s t 2 | Store a word. |
l16si at, as, 0..510 | i i 9 s t 2 | Load a halfword, sign-extended. |
l32ai at, as, 0..1020 | i i b s t 2 | Load a word with acquire ordering (not on the ESP8266). |
s32ri at, as, 0..1020 | i i f s t 2 | Store a word with release ordering (not on the ESP8266). |
s32c1i at, as, 0..1020 | i i e s t 2 | Compare-and-swap: if the word equals SCOMPARE1 it becomes at; at gets the old value (ESP32 and ESP32-S3). |
l32r at, address | i i i i t 1 | Load a literal word from a PC-relative address before the instruction (16-bit field i). |
Jumps, calls and branches
A branch target is pc + 4 + offset (a signed 8-bit offset, or 12 bits for the compare-with-zero forms). J has
an 18-bit offset, so it reaches 128 KB either way. CALL0 is relative to the word-aligned address:
((pc & ~3) + 4) + (offset18 << 2), so its target is always word-aligned. The windowed calls are on the
windowed registers page.
| Instruction | Encoding | What it does |
|---|---|---|
j target | o o o o oo00 6 | Jump to a PC-relative address. |
jx as | 0 0 0 s a 0 | Jump to the address in as. |
call0 target | o o o o oo00 5 | Call: a0 receives the return address (the call0 ABI, and the ESP8266's only call). |
callx0 as | 0 0 0 s c 0 | Call the address in as; a0 receives the return address. |
ret | 0 0 0 0 8 0 | Return: jump to a0. |
beqz as, target | i i i s 1 6 | Branch if as is zero (12-bit offset). |
bnez as, target | i i i s 5 6 | Branch if as is not zero. |
bltz as, target | i i i s 9 6 | Branch if as is negative. |
bgez as, target | i i i s d 6 | Branch if as is not negative. |
beqi as, c, target | i i r s 2 6 | Branch if as equals the constant c chosen by r: -1, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256. |
bnei as, c, target | i i r s 6 6 | Branch if as does not equal the constant. |
blti as, c, target | i i r s a 6 | Branch if as is less than the constant (signed). |
bgei as, c, target | i i r s e 6 | Branch if as is not less than the constant (signed). |
bltui as, c, target | i i r s b 6 | Branch if as is less than the unsigned constant: 32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256. |
bgeui as, c, target | i i r s f 6 | Branch if as is not less than the unsigned constant. |
bnone as, at, target | i i 0 s t 7 | Branch if (as AND at) is zero. |
beq as, at, target | i i 1 s t 7 | Branch if as equals at. |
blt as, at, target | i i 2 s t 7 | Branch if as is less than at (signed). |
bltu as, at, target | i i 3 s t 7 | Branch if as is less than at (unsigned). |
ball as, at, target | i i 4 s t 7 | Branch if every bit set in at is set in as. |
bbc as, at, target | i i 5 s t 7 | Branch if the bit of as numbered by at is clear. |
bbci as, bit, target | i i 011h s t 7 | Branch if the given bit (0 to 31, h:t) of as is clear. |
bany as, at, target | i i 8 s t 7 | Branch if (as AND at) is not zero. |
bne as, at, target | i i 9 s t 7 | Branch if as does not equal at. |
bge as, at, target | i i a s t 7 | Branch if as is not less than at (signed). |
bgeu as, at, target | i i b s t 7 | Branch if as is not less than at (unsigned). |
bnall as, at, target | i i c s t 7 | Branch if some bit set in at is clear in as. |
bbs as, at, target | i i d s t 7 | Branch if the bit of as numbered by at is set. |
bbsi as, bit, target | i i 111h s t 7 | Branch if the given bit of as is set. |
Not described
Known, not yet covered
- Reference: which flags and registers each instruction reads or writes are in the viewer's notes, not in this table.
- Reference: exceptions an instruction can raise (alignment, load/store faults).
Unknown
- Reference: the descriptions are written from the instruction set manual as remembered and checked against objdump's decoding, not against the manual's text.
Links
Reference
- Tensilica – the Xtensa architecture