DEV Community

Shaw
Shaw

Posted on

SIMD Opcodes Use LEB128

Most WebAssembly opcodes use a single byte.

i32.add = 0x6A
local.tee = 0x22

Some opcodes use two bytes.

memory.copy = 0xFC + 0x0A
i32.atomic.store = 0xFE + 0x17

SIMD opcodes use Leb128

This table seems to claim the following
v128.load = 0xFD + 0x00

But it actually is: 0xFD + encode_leb128(0x00)
which expands to: 0xFD + 0x80

LEB128 stands for little endian base 128, and is basically a number of bytes <0x80 (which each are taken for literal bits `total = total * 0x80 + byte`), and a byte >=0x80 that terminates the sequence (which is taken for bits, after masking off the 0x80 total = total * 0x80 + (byte | 0x7F))

Examples of LEB128

Examples of decoding LEB128:
decode_leb([0x80]) = 0x80 - 0x80 = 0
decode_leb([0x01, 0x80]) = 0x01 * 0x80 + 0x80 - 0x80 = 127
decode_leb([0x5F, 0x42, 0xFF]) = 0x5F * 0x80 * 0x80 + 0x42 * 0x80 + 0xFF - 0x80 = 0x17E17F

That's all i got. I hope that this can save someone from headache with WASM SIMD by hand.

Top comments (2)

Collapse
 
pengowray profile image
Pengo Wray

Hi. I made that table you linked pengowray.github.io/wasm-ops/. You'll be glad to know today I finally fixed it to show LEB128 values.

I happened to come across your post while looking to double check I had the LEB128 values correct. Hopefully there'll be less future headaches.

Collapse
 
shawsumma profile image
Shaw

Thank you so much. LEB128 is a tricky thing, and its nice to know when you're using it.