I'm writing a bytecode compiler and a VM. I'm able to use constants by placing any non-integer values in a constant pool and pushing the 4-byte integer address on to the stack. That part is fine.
But now I'm adding global variables which get stored in a virtual memory area which I call "Ram". The values I store there will, of course, also be indexed by address just like the constants. So let's say I push two addresses on to operand stack and then run my FADD (Floating Add) - when the instruction pops the two addresses off the stack to perform the addition, how does it know if those addresses come from the global memory as opposed to the constant pool? What is the standard approach?
FADD
shouldn't be popping addresses of the stack, it should be popping values.
You should have instructions for constants and for reading memory. Those instructions should push the resulting value onto the stack - not the index in the constant table or an address. The index of a constant should never be pushed onto the stack - the value of the constant itself should.
FADD
should then simply pop two values from the stack and add them - it shouldn't need to look up anything in the constant table or in memory because that should already have been handled by instructions dedicated to that.
For example, given the constant table [0: 1.0, 1: 0x10]
, the instructions for adding 1.0
to whichever value is stored at the address 0x10
(let's say 4.2) could look like this (assuming CONST
instructions that push the value at the given index in the constant table onto the stack and LOAD
instructions that pops an address of the stack and push the value at that address onto the stack):
FCONST 0 // Stack: [1.0]
ICONST 1 // Stack: [1.0, 0x10]
FLOAD // Stack: [1.0, 4.2]
FADD // Stack: [5.2]