【问题标题】:What is the bit width of a single webassembly instruction?单个 WebAssembly 指令的位宽是多少?
【发布时间】:2022-08-07 10:58:13
【问题描述】:
我知道 webassembly 目前支持 32 位架构,所以我假设它的基本指令集像 RISCV32 一样具有 32 位宽的指令(当然,RISCV32 支持 16 位压缩指令和 48 位压缩指令) )。 RISC-V 的指令主要被解释为左端(就位索引而言)。
例如,在 RISC-V 中,我们可以有一个类似 lui(将高位立即数加载到寄存器)的指令,它将 20 位立即数嵌入到指令中,有一个 5 位字段来编码目标寄存器,并且用于指定操作码的 7 位格式。除其他外,操作码在开头包含两个位,表示指令是否被压缩。这是在规范中编码的,其中lui 有一个LUI 操作码:
RISC-V指令在规范中也有多种不同的布局,例如lui指令采用\"U\"格式,所以我们知道20位字段在哪里,5位字段在哪里-bit 目标寄存器在序列化中:
wasm 指令的位宽是多少? wasm 指令有哪些可能的布局?是否有用于 webassembly 的压缩指令格式,例如非常常见的操作的 16 位指令?
如果 webassembly 指令是可变宽度的,那么解释器的指令宽度是如何编码的?
标签:
serialization
webassembly
bytecode
instruction-set
【解决方案1】:
二进制 WASM 字节码具有可变长度指令,而不是像 RISC CPU 那样的固定宽度。 https://en.wikipedia.org/wiki/WebAssembly#Code_representation 有一个例子。
它不打算直接执行,而是 JIT 到本机机器代码中,因此对于某些 32 位或 64 位常量需要多条指令的固定宽度格式将为 JIT 优化器提供更多工作。并且在 WASM 二进制格式中会不那么紧凑,并且需要更多的解析指令。
让 JIT 优化器知道最终目标是实现一个完整的常量要好得多,因为一些 ISA 将能够在一条指令中做到这一点,而另一些则需要根据 ISA 将其拆分为不同的部分。例如RISC-V 为 20:12,ARM movw/movk 或 MIPS 为 16:16,或者如果常量仅在狭窄区域中设置位,则 ARM 循环立即数可能仍然使用一条指令。或者 AArch64 位模式立即数可以在单个 32 位指令中实现像 0x01010101(或 0x0101010101010101)这样的常量。
TL:DR: 不要让 JIT 在分解为适用于目标机器的 asm 之前将各个部分重新组合在一起。
通常,对于无论如何将由软件解析一次的流来说,可变长度并不是什么大问题,而不是每次通过循环时都由硬件重复解码。
【解决方案2】:
webassembly 中的很多指令都是单字节指令。例如,left shift WASM instructions 是i32.shl 和i64.shl 并采用单字节操作码0x74 和0x86:
| Instruction |
Opcode |
i32.const |
0x41 |
i64.const |
0x42 |
f32.const |
0x43 |
f64.const |
0x44 |
| - |
- |
i32.shl |
0x74 |
i64.shl |
0x86 |
| - |
- |
i32.eqz |
0x45 |
i32.eq |
0x46 |
i64.eqz |
0x50 |
i64.eq |
0x51 |
等等。这些值取自 MDN 网站。见Numeric Instructions