我正在开发一个实验性的虚拟机,现在我对每种类型的所有数据类型操作都有一个单独的指令,只是为了安全起见。例如,我有一个针对 8、16、32 和 64 位有符号和无符号整数以及浮点、双精度和长双精度的 ADD 指令。这是一项操作的 11 条指令。现在确实有些操作只支持某些类型,但即便如此,我最终还是得到了很多指令和很少的空间。
所以我想知道是否有一些指令可以运行而不管下面的类型如何,所以我可以减少数量并为将来迫切需要的更多指令腾出空间,因为我不想超过一个字节为指示。
我正在开发一个实验性的虚拟机,现在我对每种类型的所有数据类型操作都有一个单独的指令,只是为了安全起见。例如,我有一个针对 8、16、32 和 64 位有符号和无符号整数以及浮点、双精度和长双精度的 ADD 指令。这是一项操作的 11 条指令。现在确实有些操作只支持某些类型,但即便如此,我最终还是得到了很多指令和很少的空间。
所以我想知道是否有一些指令可以运行而不管下面的类型如何,所以我可以减少数量并为将来迫切需要的更多指令腾出空间,因为我不想超过一个字节为指示。
而不是每个数据类型都有ADD
,SUB
等。为什么不让它们在“寄存器”上操作,并且MOV
对所有数据类型都有类似的指令,这些指令将归零/符号扩展寄存器的其余部分(如果有的话)。
这当然是假设您的虚拟机中有类似的东西。您可能想为您的问题添加更多信息。
你没有太多的选择,除非每个表达式在运行时都带有它自己的类型信息。
真正的处理器如何做到这一点是有一个操作码,然后是一种告诉处理器使用哪种操作数的操作数代码。例如,你可能会说
enum Operator {
Add,
Sub,
And,
...
};
enum Operand {
Memory,
Immediate,
Reg1,
Reg2,
...
};
struct Instruction {
Operator op;
Operand lhs;
Operand rhs;
};
此外,一些指令如 add 和 sub 不需要知道有符号和无符号之间的区别。这是 2 的补码的优点之一。
通常,每个寄存器的宽度都是固定的(例如 x86 为 32 位),然后如果您想对最低 8 位进行操作,则首先使用 AND 操作屏蔽其他 24 位。当然,在 x86 上,我认为在某些情况下,您仍然可以使用 8 位、16 位寄存器来引用 32 位寄存器的一部分。
Java VM 解决了这个问题,只支持某些操作ADD
,例如(64) 、(64 fp) 和(32)SUB
类型的, 。然后它提供了一些转换指令来将 32 位类型转换为 16 位和 8 位(有符号和无符号)。long
double
int
当然,这种方法只有在所需的转换操作的数量少于如果您对每种类型都有特殊ADD
的 , SUB
,MUL
等时最终需要的操作数量时才有优势。DIV
如果需要添加两个 16 位变量,您可以使用16_to_32
指令将它们移动到 32 位寄存器并执行 32 位ADD_32
。然后您将结果转换为 16 位变量,并通过32_to_16
位操作截断结果以适合 16 位变量。
然后,您的x_to_y
指令可以处理有符号或无符号转换所需的符号扩展或零扩展。
如果您对 jvm 如何执行此操作感兴趣,请查看jvm 规范。