Lua、JVM等虚拟机如何处理大类型数据?自制类ARM虚拟机设计求教
成熟虚拟机/指令集的常见解决思路
- 优先使用寄存器进行浮点运算,不直接在指令中嵌入浮点立即数
这是ARM、RISC-V等主流RISC架构,以及绝大多数虚拟机的通用设计:浮点运算指令默认只操作寄存器,32位/64位浮点立即数需要先通过单独的加载指令读取到寄存器中再参与计算。
你现有64位定长指令结构完全可以兼容这种设计:fadd指令的三个操作数只需存寄存器编号,16位的操作数字段远够存寄存器号,不需要修改现有编码规则。
加载立即数可以用两种方式实现:- 单独设计加载指令,将紧跟在当前指令之后的32位/64位立即数读到指定寄存器
- 提前把所有浮点常量存入常量池,加载指令只需存常量池的偏移量即可
- 采用可变长指令编码
不需要死守64位定长指令规则,遇到需要携带大立即数的指令(比如带浮点立即数的加法指令),直接把指令长度扩展为128位,多出来的64位空间可以放下两个32位浮点数,或者一个64位浮点数。JVM、Lua VM等成熟虚拟机都采用了可变长指令设计,硬件领域的ARM Thumb2、x86也都是可变长指令实现。 - 使用压缩浮点格式适配16位操作数字段
如果你确实需要在单条64位指令里嵌入浮点立即数,可以用IEEE 754半精度(16位浮点数):1位符号位、5位指数位、10位尾数位,精度覆盖大多数普通运算场景。C11标准已经原生支持_Float16类型,就算你用的编译器不支持,也可以自己写非常简单的转换逻辑,运算时先把16位半精度转成32位单精度运算,存回时再转换回去即可。 - 操作数字段做编码复用
可以给16位操作数字段留特殊标记位,标记当前字段是寄存器、整数立即数、还是浮点常量表偏移。比如最高2位为11时,剩下14位表示浮点常量表的偏移,最多可以索引16384个预存的32位浮点常量,完全满足普通玩具虚拟机的需求。
内容的提问来源于stack exchange,提问作者user41997
相关产品推荐
相关产品推荐

