This is how I would implement it:
class Machine
{
short a, b, c, d;
short[] ram = new short[0x10000];
enum AddressType
{
Register,
DirectMemory,
}
// Gives the address for an operand or for the result.
// `addressType`and `addrCode` are extracted from instruction opcode
// `regPointers` and `ramPointer` are fixed pointers to registers and RAM.
private unsafe short* GetAddress(AddressType addressType, short addrCode, short*[] regPointers, short* ramPointer)
{
switch (addressType)
{
case AddressType.Register:
return regPointers[addrCode]; //just an example implementation
case AddressType.DirectMemory:
return ramPointer + addrCode; //just an example implementation
default:
return null;
}
}
public unsafe void tick()
{
fixed (short* ap = &a, bp = &b, cp = &c, dp = &d, ramPointer = ram)
{
short*[] regPointers = new short*[] { ap, bp, cp, dp };
short* pOperand1, pOperand2, pResult;
AddressType operand1AddrType, operand2AddrType, resultAddrType;
short operand1AddrCode, operand2AddrCode, resultAddrCode;
// ... decipher the instruction and extract the address types and codes
pOperand1 = GetAddress(operand1AddrType, operand1AddrCode, regPointers, ramPointer);
pOperand2 = GetAddress(operand2AddrType, operand2AddrCode, regPointers, ramPointer);
pResult = GetAddress(resultAddrType, resultAddrCode, regPointers, ramPointer);
// execute the instruction, using `*pOperand1` and `*pOperand2`, storing the result in `*pResult`.
}
}
}
To get the address of the registers and RAM array, you have to use the fixed
statement. Also you can only use the acquired pointers in the fixed
block. So you have to pass around the pointers.