Xtensa instructions (ESP32-S3, ESP32)

Instruction reference: i386 · x64 · ARM32 (Thumb-2) · ARM64 (AArch64) · RISC-V (RV32) · Xtensa

224 instructions for .arch xtensa: name, operands, the bit encoding (24 bits, 16 bits for the short instructions) and a short description with the operation in pseudo code. Included is what the cores of the ESP32-S3 (Xtensa LX7) run for ordinary programs: the core set, the 16-bit instructions (code density), the windowed registers, the zero-overhead loops, multiplication and division, minimum and maximum, the boolean registers, the floating point instructions (single precision), the special and user registers and the instructions for exceptions, interrupts and the debugger. The ESP32 (Xtensa LX6) has the same encodings; only salt and saltu are missing there (they are marked). Not included are the vector instructions of the ESP32-S3 (ee.*) and MAC16.

How to read the table

An Xtensa instruction has 24 bits (three bytes) or 16 bits; the lowest 4 bits (op0) tell which: 0 to 7 are 24 bits, 8 to 13 the 16-bit instructions with .n in their name. In memory the lowest byte comes first. The encoding shows the bits from left (highest bit number) to right: fixed bits as digits, the names are fields; hover a field to see its range of bits. The registers are in three fields of 4 bits, r (bits 15 to 12), s (11 to 8) and t (7 to 4): ar, as, at are the address registers a0 to a15, fr … the float registers f0 to f15, br … the boolean registers b0 to b15. Below are the value of the fixed bits and the mask in hex: an instruction belongs to this form if (word & mask) == value.

Register windows. The 16 registers a0 to a15 are a window onto 64 registers. call8 keeps the return address and the wish to turn the window by 8; the first instruction of the function, entry, turns it and makes the stack frame. Then a10 to a15 of the caller are a2 to a7 of the function (the arguments), a1 is the stack pointer, a0 the return address, whose two top bits tell the turn. retw turns back. Without windows, call0 and ret work.

Constants. movi loads 12 bits with a sign, movi.n -32 to 95. Larger constants and addresses come with l32r from a literal pool: a word with dd before the instruction (up to 256 KB before it, its address a multiple of 4). The branches with a constant (beqi, bltui …) take only the 16 values of the table b4const or b4constu. As GNU as does, Asmonite writes the 16-bit form when the operands fit (add becomes add.n, l32i with a small offset l32i.n …).

Every encoding in this table is checked against the decoder of Asmonite (with random values in the fields it gives this instruction again), and the decoder against GNU objdump of Espressif (more than a million instruction words, without a difference). The special registers (rsr.ps a3, wsr.epc6 a2 …) are those of the ESP32-S3; the ESP32 has nearly the same. The pseudo code is written in English like source code; <s and <u compare signed and unsigned, mem32[x] is the word in memory at address x.

InstructionOperandsEncodingDescription
absar, at01100000 ar 0001 at 00000x600100 / mask 0xFF0F0FAbsolute valuear = |at|Arithmetic
abs.sfr, fs11111010 fr fs 000100000xFA0010 / mask 0xFF00FFFloating point absolute valuefr = |fs|Floating point (scalar)
addar, as, at10000000 ar as at 00000x800000 / mask 0xFF000FAddition of two registersar = as + atArithmetic
add.nar, as, atar as at 10100x000A / mask 0x000FAddition of two registers (16 bit)ar = as + at16-bit instructions (code density)
add.sfr, fs, ft00001010 fr fs ft 00000x0A0000 / mask 0xFF000FFloating point additionfr = fs + ftFloating point (scalar)
addexp.sfr, fs11111010 fr fs 111000000xFA00E0 / mask 0xFF00FFAdd the exponents (step of division and square root)Floating point (scalar)
addexpm.sfr, fs11111010 fr fs 111100000xFA00F0 / mask 0xFF00FFAdd the exponents, from the mantissa (step of division and square root)Floating point (scalar)
addiat, as, imm8imm8 1100 as at 00100x00C002 / mask 0x00F00FAddition of a constant (8 bit, signed); with -1 or 1..15 the assembler writes addi.n, with 0 mov.nat = as + sext(imm8)Arithmetic
addi.nar, as, immar as imm4 10110x000B / mask 0x000FAddition of a constant -1 or 1..15 (16 bit; the field 0 is -1)ar = as + imm16-bit instructions (code density)
addmiat, as, immimm8 1101 as at 00100x00D002 / mask 0x00F00FAddition of a constant times 256 (-32768..32512)at = as + (sext(imm8) << 8)Arithmetic
addx2ar, as, at10010000 ar as at 00000x900000 / mask 0xFF000FAddition, the first register times 2 (the address of a halfword)ar = (as << 1) + atArithmetic
addx4ar, as, at10100000 ar as at 00000xA00000 / mask 0xFF000FAddition, the first register times 4 (the address of a word)ar = (as << 2) + atArithmetic
addx8ar, as, at10110000 ar as at 00000xB00000 / mask 0xFF000FAddition, the first register times 8ar = (as << 3) + atArithmetic
all4bt, bs000000001001 bs bt 00000x009000 / mask 0xFFF00F1 if all 4 boolean registers are 1bt = bs & bs+1 & bs+2 & bs+3Boolean registers
all8bt, bs000000001011 bs bt 00000x00B000 / mask 0xFFF00F1 if all 8 boolean registers are 1bt = bs & ... & bs+7Boolean registers
andar, as, at00010000 ar as at 00000x100000 / mask 0xFF000FANDar = as & atLogic and bits
andbbr, bs, bt00000010 br bs bt 00000x020000 / mask 0xFF000FAND of boolean registersbr = bs & btBoolean registers
andbcbr, bs, bt00010010 br bs bt 00000x120000 / mask 0xFF000FAND with the complement of the secondbr = bs & ~btBoolean registers
any4bt, bs000000001000 bs bt 00000x008000 / mask 0xFFF00F1 if any of 4 boolean registers is 1 (the group from b0, b4, b8, b12)bt = bs | bs+1 | bs+2 | bs+3Boolean registers
any8bt, bs000000001010 bs bt 00000x00A000 / mask 0xFFF00F1 if any of 8 boolean registers is 1 (from b0 or b8)bt = bs | ... | bs+7Boolean registers
ballas, at, labelimm8 0100 as at 01110x004007 / mask 0x00F00FBranch if all bits of the mask are setif (~as & at) == 0: pc = labelBranches and calls
banyas, at, labelimm8 1000 as at 01110x008007 / mask 0x00F00FBranch if any bit of the mask is setif (as & at) != 0: pc = labelBranches and calls
bbcas, at, labelimm8 0101 as at 01110x005007 / mask 0x00F00FBranch if the bit (its number in a register) is 0if as[at & 31] == 0: pc = labelBranches and calls
bbcias, bit, labelimm8 011 bit[4] as bit[3-0] 01110x006007 / mask 0x00E00FBranch if the bit (a constant 0..31) is 0if as[bit] == 0: pc = labelBranches and calls
bbsas, at, labelimm8 1101 as at 01110x00D007 / mask 0x00F00FBranch if the bit (its number in a register) is 1if as[at & 31] == 1: pc = labelBranches and calls
bbsias, bit, labelimm8 111 bit[4] as bit[3-0] 01110x00E007 / mask 0x00E00FBranch if the bit (a constant 0..31) is 1if as[bit] == 1: pc = labelBranches and calls
beqas, at, labelimm8 0001 as at 01110x001007 / mask 0x00F00FBranch if equal (-128..127 bytes away)if as == at: pc = labelBranches and calls
beqias, b4const, labelimm8 r as 001001100x000026 / mask 0x0000FFBranch if equal to a constant (-1, 1..8, 10, 12, 16, 32, 64, 128, 256)if as == b4const: pc = labelBranches and calls
beqzas, labelimm12 as 000101100x000016 / mask 0x0000FFBranch if zero (up to 2 KB away)if as == 0: pc = labelBranches and calls
beqz.nas, labelimm[3-0] as 10 imm[5-4] 11000x008C / mask 0x00CFBranch if zero, forward only, 0..63 bytes (16 bit)if as == 0: pc = label16-bit instructions (code density)
bfbs, labelimm8 0000 bs 011101100x000076 / mask 0x00F0FFBranch if the boolean register is 0if not bs: pc = labelBoolean registers
bgeas, at, labelimm8 1010 as at 01110x00A007 / mask 0x00F00FBranch if greater or equal (signed)if as >=s at: pc = labelBranches and calls
bgeias, b4const, labelimm8 r as 111001100x0000E6 / mask 0x0000FFBranch if greater than or equal to a constant (signed)if as >=s b4const: pc = labelBranches and calls
bgeuas, at, labelimm8 1011 as at 01110x00B007 / mask 0x00F00FBranch if greater or equal (unsigned)if as >=u at: pc = labelBranches and calls
bgeuias, b4constu, labelimm8 r as 111101100x0000F6 / mask 0x0000FFBranch if greater than or equal to an unsigned constantif as >=u b4constu: pc = labelBranches and calls
bgezas, labelimm12 as 110101100x0000D6 / mask 0x0000FFBranch if not negativeif as >=s 0: pc = labelBranches and calls
bltas, at, labelimm8 0010 as at 01110x002007 / mask 0x00F00FBranch if less (signed)if as <s at: pc = labelBranches and calls
bltias, b4const, labelimm8 r as 101001100x0000A6 / mask 0x0000FFBranch if less than a constant (signed)if as <s b4const: pc = labelBranches and calls
bltuas, at, labelimm8 0011 as at 01110x003007 / mask 0x00F00FBranch if less (unsigned)if as <u at: pc = labelBranches and calls
bltuias, b4constu, labelimm8 r as 101101100x0000B6 / mask 0x0000FFBranch if less than an unsigned constant (2..8, 10, 12, 16, 32, 64, 128, 256, 32768, 65536)if as <u b4constu: pc = labelBranches and calls
bltzas, labelimm12 as 100101100x000096 / mask 0x0000FFBranch if negativeif as <s 0: pc = labelBranches and calls
bnallas, at, labelimm8 1100 as at 01110x00C007 / mask 0x00F00FBranch if not all bits of the mask are setif (~as & at) != 0: pc = labelBranches and calls
bneas, at, labelimm8 1001 as at 01110x009007 / mask 0x00F00FBranch if not equalif as != at: pc = labelBranches and calls
bneias, b4const, labelimm8 r as 011001100x000066 / mask 0x0000FFBranch if not equal to a constantif as != b4const: pc = labelBranches and calls
bnezas, labelimm12 as 010101100x000056 / mask 0x0000FFBranch if not zeroif as != 0: pc = labelBranches and calls
bnez.nas, labelimm[3-0] as 11 imm[5-4] 11000x00CC / mask 0x00CFBranch if not zero, forward only, 0..63 bytes (16 bit)if as != 0: pc = label16-bit instructions (code density)
bnoneas, at, labelimm8 0000 as at 01110x000007 / mask 0x00F00FBranch if no bit of the mask is setif (as & at) == 0: pc = labelBranches and calls
breakimm4, imm4000000000100 imm4 00000x004000 / mask 0xFFF00FBreakpoint: stops in the debugger (debug exception), the numbers tell the handler the reasonSystem and privileged
break.nimm41111 imm4 001011010xF02D / mask 0xF0FFBreakpoint (16 bit); Asmonite puts it for breakpoints on 16-bit instructions16-bit instructions (code density)
btbs, labelimm8 0001 bs 011101100x001076 / mask 0x00F0FFBranch if the boolean register is 1if bs: pc = labelBoolean registers
call0labeloffset 0001010x000005 / mask 0x00003FCall without register window: the return address in a0 (the target a multiple of 4)a0 = pc + 3; pc = labelBranches and calls
call12labeloffset 1101010x000035 / mask 0x00003FCall that turns the register window by 12a12 = return address (top bits: 3); PS.CALLINC = 3; pc = labelWindowed registers (call4/8/12, entry, retw)
call4labeloffset 0101010x000015 / mask 0x00003FCall that turns the register window by 4 (when the function runs entry): a4..a7 of the caller are its a0..a3a4 = return address (top bits: 1); PS.CALLINC = 1; pc = labelWindowed registers (call4/8/12, entry, retw)
call8labeloffset 1001010x000025 / mask 0x00003FCall that turns the register window by 8: a10..a15 of the caller are the arguments a2..a7 of the functiona8 = return address (top bits: 2); PS.CALLINC = 2; pc = labelWindowed registers (call4/8/12, entry, retw)
callx0as000000000000 as 110000000x0000C0 / mask 0xFFF0FFCall of the address in the register, without register windowa0 = pc + 3; pc = asBranches and calls
callx12as000000000000 as 111100000x0000F0 / mask 0xFFF0FFcall12 to the address in the registera12 = return address; PS.CALLINC = 3; pc = asWindowed registers (call4/8/12, entry, retw)
callx4as000000000000 as 110100000x0000D0 / mask 0xFFF0FFcall4 to the address in the registera4 = return address; PS.CALLINC = 1; pc = asWindowed registers (call4/8/12, entry, retw)
callx8as000000000000 as 111000000x0000E0 / mask 0xFFF0FFcall8 to the address in the registera8 = return address; PS.CALLINC = 2; pc = asWindowed registers (call4/8/12, entry, retw)
ceil.sar, fs, imm410111010 ar fs imm4 00000xBA0000 / mask 0xFF000FConvert to an integer, rounded upar = ceil(fs * 2^imm4)Floating point (scalar)
clampsar, as, bits00110011 ar as b-7 00000x330000 / mask 0xFF000FClamp to the range of a signed number of b+1 bits (7..22)ar = min(max(as, -2^b), 2^b - 1)Arithmetic
const.sfr, imm411111010 fr imm4 001100000xFA0030 / mask 0xFF00FFLoad a float constant (0, 1, 2, 0.5 ... by imm4)fr = constant[imm4]Floating point (scalar)
div0.sfr, fs11111010 fr fs 011100000xFA0070 / mask 0xFF00FFStart value for a divisionFloating point (scalar)
divn.sfr, fs, ft01111010 fr fs ft 00000x7A0000 / mask 0xFF000FLast step of a division (after div0.s, nexp01.s ...)Floating point (scalar)
dsync0000000000100000001100000x002030 / mask 0xFFFFFFWait until written special registers apply to memory accessesBarriers and others
entryas, framesizeimm12 as 001101100x000036 / mask 0x0000FFThe first instruction of a function with register window: turns the window by PS.CALLINC * 4 and makes its stack frame (framesize 0..32760, a multiple of 8; the address a multiple of 4)WINDOWBASE += PS.CALLINC; as = as(old window) - framesizeWindowed registers (call4/8/12, entry, retw)
esync0000000000100000001000000x002020 / mask 0xFFFFFFWait until written special registers apply to the executionBarriers and others
excw0000000000100000100000000x002080 / mask 0xFFFFFFWait until the exceptions of the instructions before are raisedBarriers and others
extuiar, at, shift, widthw-1 010 sh[4] ar sh[3-0] at 00000x040000 / mask 0x0E000FExtract an unsigned bit field: width bits from bit shift (shift + width up to 32)ar = (at >> shift) & ((1 << width) - 1)Shift and rotate
extw0000000000100000110100000x0020D0 / mask 0xFFFFFFWait until all earlier accesses have reached the outsideBarriers and others
float.sfr, as, imm411001010 fr as imm4 00000xCA0000 / mask 0xFF000FConvert a signed integer to float, divided by 2^imm4fr = float(as) / 2^imm4Floating point (scalar)
floor.sar, fs, imm410101010 ar fs imm4 00000xAA0000 / mask 0xFF000FConvert to an integer, rounded downar = floor(fs * 2^imm4)Floating point (scalar)
idtlbas010100001100 as 000000000x50C000 / mask 0xFFF0FFInvalidate an entry of the data TLBinvalidate DTLB[as]System and privileged
iitlbas010100000100 as 000000000x504000 / mask 0xFFF0FFInvalidate an entry of the instruction TLBinvalidate ITLB[as]System and privileged
ill0000000000000000000000000x000000 / mask 0xFFFFFFIllegal instruction: raises an exceptionSystem and privileged
ill.n11110000011011010xF06D / mask 0xFFFFIllegal instruction (16 bit)16-bit instructions (code density)
isync0000000000100000000000000x002000 / mask 0xFFFFFFFetch the instructions again (after changed code or special registers)Barriers and others
jlabeloffset 0001100x000006 / mask 0x00003FJump (up to 128 KB away)pc = labelBranches and calls
jxas000000000000 as 101000000x0000A0 / mask 0xFFF0FFJump to the address in the registerpc = asBranches and calls
l16siat, as, offsetimm8 1001 as at 00100x009002 / mask 0x00F00FLoad of a halfword, signedat = sext(mem16[as + (imm8 << 1)])Loads and stores
l16uiat, as, offsetimm8 0001 as at 00100x001002 / mask 0x00F00FLoad of a halfword, unsigned (offset 0..510, even)at = zext(mem16[as + (imm8 << 1)])Loads and stores
l32aiat, as, offsetimm8 1011 as at 00100x00B002 / mask 0x00F00FLoad of a word with acquire ordering (later accesses only after it)at = mem32[as + (imm8 << 2)]; acquireLoads and stores
l32eat, as, offset00001001 imm4 as at 00000x090000 / mask 0xFF000FLoad for the handlers of the window exceptions (offset -64..-4)at = mem32[as + ((imm4 << 2) - 64)]Windowed registers (call4/8/12, entry, retw)
l32iat, as, offsetimm8 0010 as at 00100x002002 / mask 0x00F00FLoad of a word (offset 0..1020, a multiple of 4); with a small offset the assembler writes l32i.nat = mem32[as + (imm8 << 2)]Loads and stores
l32i.nat, as, offsetimm4 as at 10000x0008 / mask 0x000FLoad of a word, offset 0..60 (16 bit)at = mem32[as + (imm4 << 2)]16-bit instructions (code density)
l32rat, labelimm16 at 00010x000001 / mask 0x00000FLoad of a word from the literal pool: a constant up to 256 KB before the instruction (its address a multiple of 4); the way of 32-bit constants into a registerat = mem32[((pc + 3) & ~3) + (0xFFFF0000 | imm16) * 4]Loads and stores
l8uiat, as, imm8imm8 0000 as at 00100x000002 / mask 0x00F00FLoad of a byte, unsignedat = zext(mem8[as + imm8])Loads and stores
lddr32.pas000000000111 as 111000000x0070E0 / mask 0xFFF0FFDebug mode: load a word into DDR and add 4 to the address (fast memory reads of the debugger)DDR = mem32[as]; as += 4System and privileged
loopas, labelimm8 1000 as 011101100x008076 / mask 0x00F0FFZero-overhead loop: the part up to label runs as times (as = 0: 2^32 times); LBEG, LEND, LCOUNTLCOUNT = as - 1; LBEG = pc + 3; LEND = labelZero-overhead loops (loop)
loopgtzas, labelimm8 1010 as 011101100x00A076 / mask 0x00F0FFLoop as loop, skipped if as is not greater than 0if as <=s 0: pc = label else loopZero-overhead loops (loop)
loopnezas, labelimm8 1001 as 011101100x009076 / mask 0x00F0FFLoop as loop, skipped if as = 0if as == 0: pc = label else loopZero-overhead loops (loop)
lsift, as, offsetimm8 0000 as ft 00110x000003 / mask 0x00F00FLoad of a floatft = mem32[as + (imm8 << 2)]Floating point (scalar)
lsipft, as, offsetimm8 1000 as ft 00110x008003 / mask 0x00F00FLoad of a float, then add to the addressft = mem32[as]; as += imm8 << 2Floating point (scalar)
lsxfr, as, at00001000 fr as at 00000x080000 / mask 0xFF000FLoad of a float, the address from two registersfr = mem32[as + at]Floating point (scalar)
lsxpfr, as, at00011000 fr as at 00000x180000 / mask 0xFF000FLoad of a float, then add to the addressfr = mem32[as]; as += atFloating point (scalar)
madd.sfr, fs, ft01001010 fr fs ft 00000x4A0000 / mask 0xFF000FMultiply and addfr = fr + fs * ftFloating point (scalar)
maddn.sfr, fs, ft01101010 fr fs ft 00000x6A0000 / mask 0xFF000FMultiply and add, rounded to nearest (a step of division and square root)fr = round(fr + fs * ft)Floating point (scalar)
maxar, as, at01010011 ar as at 00000x530000 / mask 0xFF000FMaximum, signedar = (as >s at) ? as : atCompare and exchange
maxuar, as, at01110011 ar as at 00000x730000 / mask 0xFF000FMaximum, unsignedar = (as >u at) ? as : atCompare and exchange
memw0000000000100000110000000x0020C0 / mask 0xFFFFFFMemory barrier: earlier accesses before later ones (for peripheral registers)Barriers and others
minar, as, at01000011 ar as at 00000x430000 / mask 0xFF000FMinimum, signedar = (as <s at) ? as : atCompare and exchange
minuar, as, at01100011 ar as at 00000x630000 / mask 0xFF000FMinimum, unsignedar = (as <u at) ? as : atCompare and exchange
mkdadj.sfr, fs11111010 fr fs 110100000xFA00D0 / mask 0xFF00FFMake the exponent adjustment for a divisionFloating point (scalar)
mksadj.sfr, fs11111010 fr fs 110000000xFA00C0 / mask 0xFF00FFMake the exponent adjustment for a square rootFloating point (scalar)
mov.nat, as0000 as at 11010x000D / mask 0xF00FCopy of a register (16 bit)at = as16-bit instructions (code density)
mov.sfr, fs11111010 fr fs 000000000xFA0000 / mask 0xFF00FFCopy a float registerfr = fsFloating point (scalar)
moveqzar, as, at10000011 ar as at 00000x830000 / mask 0xFF000FCopy if the third register is 0if at == 0: ar = asConditional select
moveqz.sfr, fs, at10001011 fr fs at 00000x8B0000 / mask 0xFF000FCopy a float register if at is 0if at == 0: fr = fsFloating point (scalar)
movfar, as, bt11000011 ar as bt 00000xC30000 / mask 0xFF000FCopy if the boolean register is 0if not bt: ar = asConditional select
movf.sfr, fs, bt11001011 fr fs bt 00000xCB0000 / mask 0xFF000FCopy a float register if the boolean register is 0if not bt: fr = fsFloating point (scalar)
movgezar, as, at10110011 ar as at 00000xB30000 / mask 0xFF000FCopy if the third register is not negativeif at >=s 0: ar = asConditional select
movgez.sfr, fs, at10111011 fr fs at 00000xBB0000 / mask 0xFF000FCopy a float register if at is not negativeif at >=s 0: fr = fsFloating point (scalar)
moviat, imm12imm[7-0] 1010 imm[11-8] at 00100x00A002 / mask 0x00F00FLoad of a constant (12 bit, signed, -2048..2047); larger ones come with l32rat = sext(imm12)Constants and addresses
movi.nas, imm7imm[3-0] as 0 imm[6-4] 11000x000C / mask 0x008FLoad of a constant -32..95 (16 bit)as = imm716-bit instructions (code density)
movltzar, as, at10100011 ar as at 00000xA30000 / mask 0xFF000FCopy if the third register is negativeif at <s 0: ar = asConditional select
movltz.sfr, fs, at10101011 fr fs at 00000xAB0000 / mask 0xFF000FCopy a float register if at is negativeif at <s 0: fr = fsFloating point (scalar)
movnezar, as, at10010011 ar as at 00000x930000 / mask 0xFF000FCopy if the third register is not 0if at != 0: ar = asConditional select
movnez.sfr, fs, at10011011 fr fs at 00000x9B0000 / mask 0xFF000FCopy a float register if at is not 0if at != 0: fr = fsFloating point (scalar)
movspat, as000000000001 as at 00000x001000 / mask 0xFFF00FSet the stack pointer so that the register windows of the callers are saved firstat = as (after spilling the windows when needed)Windowed registers (call4/8/12, entry, retw)
movtar, as, bt11010011 ar as bt 00000xD30000 / mask 0xFF000FCopy if the boolean register is 1if bt: ar = asConditional select
movt.sfr, fs, bt11011011 fr fs bt 00000xDB0000 / mask 0xFF000FCopy a float register if the boolean register is 1if bt: fr = fsFloating point (scalar)
msub.sfr, fs, ft01011010 fr fs ft 00000x5A0000 / mask 0xFF000FMultiply and subtractfr = fr - fs * ftFloating point (scalar)
mul.sfr, fs, ft00101010 fr fs ft 00000x2A0000 / mask 0xFF000FFloating point multiplicationfr = fs * ftFloating point (scalar)
mul16sar, as, at11010001 ar as at 00000xD10000 / mask 0xFF000FMultiplication of the low 16 bits, signedar = sext(as[15:0]) * sext(at[15:0])Arithmetic
mul16uar, as, at11000001 ar as at 00000xC10000 / mask 0xFF000FMultiplication of the low 16 bits, unsignedar = zext(as[15:0]) * zext(at[15:0])Arithmetic
mullar, as, at10000010 ar as at 00000x820000 / mask 0xFF000FMultiplication, the low 32 bitsar = (as * at)[31:0]Arithmetic
mulshar, as, at10110010 ar as at 00000xB20000 / mask 0xFF000FMultiplication, signed, the high 32 bitsar = (as *s at)[63:32]Arithmetic
muluhar, as, at10100010 ar as at 00000xA20000 / mask 0xFF000FMultiplication, unsigned, the high 32 bitsar = (as *u at)[63:32]Arithmetic
negar, at01100000 ar 0000 at 00000x600000 / mask 0xFF0F0FNegationar = -atArithmetic
neg.sfr, fs11111010 fr fs 011000000xFA0060 / mask 0xFF00FFFloating point negationfr = -fsFloating point (scalar)
nexp01.sfr, fs11111010 fr fs 101100000xFA00B0 / mask 0xFF00FFBring the mantissa to 1..2 and negate the exponent (step of division and square root)Floating point (scalar)
nop0000000000100000111100000x0020F0 / mask 0xFFFFFFNo effect; written as nop.nBarriers and others
nop.n11110000001111010xF03D / mask 0xFFFFNo effect (16 bit)16-bit instructions (code density)
nsaat, as010000001110 as at 00000x40E000 / mask 0xFFF00FNumber of the sign bits less 1 (normalize, signed)at = count of the leading bits equal to as[31], less 1Logic and bits
nsauat, as010000001111 as at 00000x40F000 / mask 0xFFF00FNumber of the leading zero bits (32 for 0)at = clz(as)Logic and bits
oeq.sbr, fs, ft00101011 br fs ft 00000x2B0000 / mask 0xFF000FComparison: 1 if equal (no NaN)br = fs == ftFloating point (scalar)
ole.sbr, fs, ft01101011 br fs ft 00000x6B0000 / mask 0xFF000FComparison: 1 if less or equal (no NaN)br = fs <= ftFloating point (scalar)
olt.sbr, fs, ft01001011 br fs ft 00000x4B0000 / mask 0xFF000FComparison: 1 if less (no NaN)br = fs < ftFloating point (scalar)
orar, as, atalso shown as: mov00100000 ar as at 00000x200000 / mask 0xFF000FOR; with the same source twice the copy of a register (mov, as mov.n)ar = as | atLogic and bits
orbbr, bs, bt00100010 br bs bt 00000x220000 / mask 0xFF000FOR of boolean registersbr = bs | btBoolean registers
orbcbr, bs, bt00110010 br bs bt 00000x320000 / mask 0xFF000FOR with the complement of the secondbr = bs | ~btBoolean registers
pdtlbat, as010100001101 as at 00000x50D000 / mask 0xFFF00FProbe the data TLB for an addressat = probe DTLB(as)System and privileged
pitlbat, as010100000101 as at 00000x505000 / mask 0xFFF00FProbe the instruction TLB for an addressat = probe ITLB(as)System and privileged
quosar, as, at11010010 ar as at 00000xD20000 / mask 0xFF000FDivision, signedar = as /s atArithmetic
quouar, as, at11000010 ar as at 00000xC20000 / mask 0xFF000FDivision, unsigned (by 0: an exception)ar = as /u atArithmetic
rdtlb0at, as010100001011 as at 00000x50B000 / mask 0xFFF00FRead an entry of the data TLB (virtual address)at = DTLB[as].vaddrSystem and privileged
rdtlb1at, as010100001111 as at 00000x50F000 / mask 0xFFF00FRead an entry of the data TLB (translation)at = DTLB[as].paddrSystem and privileged
recip0.sfr, fs11111010 fr fs 100000000xFA0080 / mask 0xFF00FFStart value for a reciprocalFloating point (scalar)
remsar, as, at11110010 ar as at 00000xF20000 / mask 0xFF000FRemainder of the division, signedar = as %s atArithmetic
remuar, as, at11100010 ar as at 00000xE20000 / mask 0xFF000FRemainder of the division, unsignedar = as %u atArithmetic
rerat, as010000000110 as at 00000x406000 / mask 0xFFF00FRead an external registerat = ER[as]System and privileged
ret000000000000 s 100000000x000080 / mask 0xFFF0FFReturn after call0 (to a0); written as ret.npc = a0Branches and calls
ret.n1111 s 000011010xF00D / mask 0xF0FFReturn after call0 (16 bit)pc = a016-bit instructions (code density)
retw000000000000 s 100100000x000090 / mask 0xFFF0FFReturn from a function with register window: turns the window back; written as retw.npc = a0 (top bits from pc); WINDOWBASE -= a0[31:30]Windowed registers (call4/8/12, entry, retw)
retw.n1111 s 000111010xF01D / mask 0xF0FFReturn with register window (16 bit)pc = a0; WINDOWBASE -= a0[31:30]16-bit instructions (code density)
rfdd111100011110 s 000100000xF1E010 / mask 0xFFF0FFReturn from a debug exception in the debug modeSystem and privileged
rfde0000000000110010000000000x003200 / mask 0xFFFFFFReturn from a double exceptionpc = DEPCSystem and privileged
rfdoimm4111100011110 imm4 000000000xF1E000 / mask 0xFFF0FFReturn from the debug mode (OCD: the debugger lets the core run)pc = EPC6; PS = EPS6System and privileged
rfe0000000000110000000000000x003000 / mask 0xFFFFFFReturn from an exception of level 1pc = EPC1; PS.EXCM = 0System and privileged
rfiimm4000000000011 imm4 000100000x003010 / mask 0xFFF0FFReturn from an interrupt of level imm4pc = EPC[imm4]; PS = EPS[imm4]System and privileged
rfrar, fs11111010 ar fs 010000000xFA0040 / mask 0xFF00FFCopy a float register to an address register (the bits)ar = bits(fs)Floating point (scalar)
rfwo0000000000110100000000000x003400 / mask 0xFFFFFFReturn from the handler of a window overflowWindowed registers (call4/8/12, entry, retw)
rfwu0000000000110101000000000x003500 / mask 0xFFFFFFReturn from the handler of a window underflowWindowed registers (call4/8/12, entry, retw)
ritlb0at, as010100000011 as at 00000x503000 / mask 0xFFF00FRead an entry of the instruction TLB (virtual address)at = ITLB[as].vaddrSystem and privileged
ritlb1at, as010100000111 as at 00000x507000 / mask 0xFFF00FRead an entry of the instruction TLB (translation)at = ITLB[as].paddrSystem and privileged
rotwimm40100000010000000 imm4 00000x408000 / mask 0xFFFF0FTurn the register window (in the handlers of the window exceptions)WINDOWBASE += imm4Windowed registers (call4/8/12, entry, retw)
round.sar, fs, imm410001010 ar fs imm4 00000x8A0000 / mask 0xFF000FConvert to an integer, rounded (times 2^imm4)ar = round(fs * 2^imm4)Floating point (scalar)
rsilat, imm4000000000110 imm4 at 00000x006000 / mask 0xFFF00FRead PS and set the interrupt level (interrupts up to imm4 off)at = PS; PS.INTLEVEL = imm4System and privileged
rsqrt0.sfr, fs11111010 fr fs 101000000xFA00A0 / mask 0xFF00FFStart value for a reciprocal square rootFloating point (scalar)
rsrsr, at00000011 sr at 00000x030000 / mask 0xFF000FRead a special register; also written rsr.name at (rsr.ps a3)at = SR[sr]Special and user registers
rsync0000000000100000000100000x002010 / mask 0xFFFFFFWait until written special registers apply to register readsBarriers and others
rurar, ur11100011 ar ur 00000xE30000 / mask 0xFF000FRead a user register (threadptr, fcr, fsr ...); also rur.name arar = UR[ur]Special and user registers
s16iat, as, offsetimm8 0101 as at 00100x005002 / mask 0x00F00FStore of a halfwordmem16[as + (imm8 << 1)] = at[15:0]Loads and stores
s32c1iat, as, offsetimm8 1110 as at 00100x00E002 / mask 0x00F00FConditional store (compare and swap): stores at if the word equals SCOMPARE1; at gets the old valueold = mem32[a]; if old == SCOMPARE1: mem32[a] = at; at = oldLoads and stores
s32eat, as, offset01001001 imm4 as at 00000x490000 / mask 0xFF000FStore for the handlers of the window exceptions (offset -64..-4)mem32[as + ((imm4 << 2) - 64)] = atWindowed registers (call4/8/12, entry, retw)
s32iat, as, offsetimm8 0110 as at 00100x006002 / mask 0x00F00FStore of a word; with a small offset the assembler writes s32i.nmem32[as + (imm8 << 2)] = atLoads and stores
s32i.nat, as, offsetimm4 as at 10010x0009 / mask 0x000FStore of a word, offset 0..60 (16 bit)mem32[as + (imm4 << 2)] = at16-bit instructions (code density)
s32nbat, as, offset01011001 imm4 as at 00000x590000 / mask 0xFF000FStore of a word that bypasses the write buffer (offset 0..60)mem32[as + (imm4 << 2)] = atLoads and stores
s32riat, as, offsetimm8 1111 as at 00100x00F002 / mask 0x00F00FStore of a word with release ordering (earlier accesses first)release; mem32[as + (imm8 << 2)] = atLoads and stores
s8iat, as, imm8imm8 0100 as at 00100x004002 / mask 0x00F00FStore of a bytemem8[as + imm8] = at[7:0]Loads and stores
saltar, as, at01110010 ar as at 00000x720000 / mask 0xFF000FSigned comparison: 1 if less (ESP32-S3 only, not the ESP32)ar = (as <s at) ? 1 : 0Compare and exchange
saltuar, as, at01100010 ar as at 00000x620000 / mask 0xFF000FUnsigned comparison: 1 if less (ESP32-S3 only, not the ESP32)ar = (as <u at) ? 1 : 0Compare and exchange
sddr32.pas000000000111 as 111100000x0070F0 / mask 0xFFF0FFDebug mode: store DDR and add 4 to the addressmem32[as] = DDR; as += 4System and privileged
sextar, as, bits00100011 ar as b-7 00000x230000 / mask 0xFF000FSign extension from bit b (7..22)ar = sext(as[b:0])Arithmetic
simcall0000000001010001000000000x005100 / mask 0xFFFFFFCall of a simulator (no effect on the chip)System and privileged
sllar, as10100001 ar as 000000000xA10000 / mask 0xFF00FFShift left by 32 less SAR (SAR set by ssl)ar = as << (32 - SAR)Shift and rotate
slliar, as, sa000 sa[4] 0001 ar as sa[3-0] 00000x010000 / mask 0xEF000FShift left by a constant (1..31; the fields hold 32 less sa)ar = as << saShift and rotate
sqrt0.sfr, fs11111010 fr fs 100100000xFA0090 / mask 0xFF00FFStart value for a square rootFloating point (scalar)
sraar, at10110001 ar 0000 at 00000xB10000 / mask 0xFF0F0FShift right signed by SARar = at >>s SARShift and rotate
sraiar, at, sa001 sa[4] 0001 ar sa[3-0] at 00000x210000 / mask 0xEF000FShift right signed by a constant (0..31)ar = at >>s saShift and rotate
srcar, as, at10000001 ar as at 00000x810000 / mask 0xFF000FShift right across two registers (64 bit) by SAR; with the same register twice a rotationar = ((as : at) >> SAR)[31:0]Shift and rotate
srlar, at10010001 ar 0000 at 00000x910000 / mask 0xFF0F0FShift right unsigned by SARar = at >>u SARShift and rotate
srliar, at, imm401000001 ar imm4 at 00000x410000 / mask 0xFF000FShift right unsigned by a constant (0..15; more with extui)ar = at >>u imm4Shift and rotate
ssa8bas010000000011 as 000000000x403000 / mask 0xFFF0FFSet SAR for a shift by whole bytes (big endian)SAR = 32 - as[1:0] * 8Shift and rotate
ssa8las010000000010 as 000000000x402000 / mask 0xFFF0FFSet SAR for a shift by whole bytes (little endian)SAR = as[1:0] * 8Shift and rotate
ssaisa010000000100 sa[3-0] 000 sa[4] 00000x404000 / mask 0xFFF0EFSet SAR to a constantSAR = saShift and rotate
ssift, as, offsetimm8 0100 as ft 00110x004003 / mask 0x00F00FStore of a floatmem32[as + (imm8 << 2)] = ftFloating point (scalar)
ssipft, as, offsetimm8 1100 as ft 00110x00C003 / mask 0x00F00FStore of a float, then add to the addressmem32[as] = ft; as += imm8 << 2Floating point (scalar)
sslas010000000001 as 000000000x401000 / mask 0xFFF0FFSet SAR for a shift leftSAR = 32 - as[4:0]Shift and rotate
ssras010000000000 as 000000000x400000 / mask 0xFFF0FFSet SAR for a shift right (from the low 5 bits)SAR = as[4:0]Shift and rotate
ssxfr, as, at01001000 fr as at 00000x480000 / mask 0xFF000FStore of a float, the address from two registersmem32[as + at] = frFloating point (scalar)
ssxpfr, as, at01011000 fr as at 00000x580000 / mask 0xFF000FStore of a float, then add to the addressmem32[as] = fr; as += atFloating point (scalar)
subar, as, at11000000 ar as at 00000xC00000 / mask 0xFF000FSubtraction of two registersar = as - atArithmetic
sub.sfr, fs, ft00011010 fr fs ft 00000x1A0000 / mask 0xFF000FFloating point subtractionfr = fs - ftFloating point (scalar)
subx2ar, as, at11010000 ar as at 00000xD00000 / mask 0xFF000FSubtraction, the first register times 2ar = (as << 1) - atArithmetic
subx4ar, as, at11100000 ar as at 00000xE00000 / mask 0xFF000FSubtraction, the first register times 4ar = (as << 2) - atArithmetic
subx8ar, as, at11110000 ar as at 00000xF00000 / mask 0xFF000FSubtraction, the first register times 8ar = (as << 3) - atArithmetic
syscall0000000001010000000000000x005000 / mask 0xFFFFFFSystem call: raises the exception SYSCALLSystem and privileged
trunc.sar, fs, imm410011010 ar fs imm4 00000x9A0000 / mask 0xFF000FConvert to an integer, truncatedar = trunc(fs * 2^imm4)Floating point (scalar)
ueq.sbr, fs, ft00111011 br fs ft 00000x3B0000 / mask 0xFF000FComparison: 1 if equal or NaNbr = fs == ft or unorderedFloating point (scalar)
ufloat.sfr, as, imm411011010 fr as imm4 00000xDA0000 / mask 0xFF000FConvert an unsigned integer to float, divided by 2^imm4fr = ufloat(as) / 2^imm4Floating point (scalar)
ule.sbr, fs, ft01111011 br fs ft 00000x7B0000 / mask 0xFF000FComparison: 1 if less or equal or NaNbr = fs <= ft or unorderedFloating point (scalar)
ult.sbr, fs, ft01011011 br fs ft 00000x5B0000 / mask 0xFF000FComparison: 1 if less or NaNbr = fs < ft or unorderedFloating point (scalar)
un.sbr, fs, ft00011011 br fs ft 00000x1B0000 / mask 0xFF000FComparison: 1 if one of the numbers is NaNbr = isnan(fs) or isnan(ft)Floating point (scalar)
utrunc.sar, fs, imm411101010 ar fs imm4 00000xEA0000 / mask 0xFF000FConvert to an unsigned integer, truncatedar = utrunc(fs * 2^imm4)Floating point (scalar)
waitiimm4000000000111 imm4 000000000x007000 / mask 0xFFF0FFSet the interrupt level and wait for an interrupt (saves power)PS.INTLEVEL = imm4; waitSystem and privileged
wdtlbat, as010100001110 as at 00000x50E000 / mask 0xFFF00FWrite an entry of the data TLBDTLB[as] = atSystem and privileged
werat, as010000000111 as at 00000x407000 / mask 0xFFF00FWrite an external registerER[as] = atSystem and privileged
wfrfr, as11111010 fr as 010100000xFA0050 / mask 0xFF00FFCopy an address register to a float register (the bits)fr = bits(as)Floating point (scalar)
witlbat, as010100000110 as at 00000x506000 / mask 0xFFF00FWrite an entry of the instruction TLBITLB[as] = atSystem and privileged
wsrsr, at00010011 sr at 00000x130000 / mask 0xFF000FWrite a special register; also wsr.name atSR[sr] = atSpecial and user registers
wurur, at11110011 ur at 00000xF30000 / mask 0xFF000FWrite a user register; also wur.name atUR[ur] = atSpecial and user registers
xorar, as, at00110000 ar as at 00000x300000 / mask 0xFF000FExclusive ORar = as ^ atLogic and bits
xorbbr, bs, bt01000010 br bs bt 00000x420000 / mask 0xFF000FExclusive OR of boolean registersbr = bs ^ btBoolean registers
xsrsr, at01100001 sr at 00000x610000 / mask 0xFF000FExchange a special register and a register; also xsr.name att = SR[sr]; SR[sr] = at; at = tSpecial and user registers