private uint DecodeStoreOperand(Opcode opcode, byte type, ref uint operandPos) { uint address; switch (type) { case 0: // discard result WriteTrace("discard"); return 0; // case 1..4: unused case 5: address = image.ReadByte(operandPos++); WriteTrace("ptr_" + address.ToString()); break; case 6: address = image.ReadInt16(operandPos); operandPos += 2; WriteTrace("ptr_" + address.ToString()); break; case 7: address = image.ReadInt32(operandPos); operandPos += 4; WriteTrace("ptr_" + address.ToString()); break; // case 8: push onto stack case 8: // push onto stack WriteTrace("sp"); return 0; case 9: address = image.ReadByte(operandPos++); WriteTrace("local_" + address.ToString()); break; case 10: address = image.ReadInt16(operandPos); operandPos += 2; WriteTrace("local_" + address.ToString()); break; case 11: address = image.ReadInt32(operandPos); operandPos += 4; WriteTrace("local_" + address.ToString()); break; // case 12: unused case 13: address = image.RamStart + image.ReadByte(operandPos++); WriteTrace("ram_" + (address - image.RamStart).ToString()); break; case 14: address = image.RamStart + image.ReadInt16(operandPos); operandPos += 2; WriteTrace("ram_" + (address - image.RamStart).ToString()); break; case 15: address = image.RamStart + image.ReadInt32(operandPos); operandPos += 4; WriteTrace("ram_" + (address - image.RamStart).ToString()); break; default: throw new ArgumentException("Invalid operand type"); } return address; }
private uint DecodeLoadOperand(Opcode opcode, byte type, ref uint operandPos) { uint address, value; switch (type) { case 0: WriteTrace("zero"); return 0; case 1: value = (uint)(sbyte)image.ReadByte(operandPos++); WriteTrace("byte_" + value.ToString()); return value; case 2: operandPos += 2; value = (uint)(short)image.ReadInt16(operandPos - 2); WriteTrace("short_" + value.ToString()); return value; case 3: operandPos += 4; value = image.ReadInt32(operandPos - 4); WriteTrace("int_" + value.ToString()); return value; // case 4: unused case 5: address = image.ReadByte(operandPos++); WriteTrace("ptr"); goto LoadIndirect; case 6: address = image.ReadInt16(operandPos); operandPos += 2; WriteTrace("ptr"); goto LoadIndirect; case 7: address = image.ReadInt32(operandPos); operandPos += 4; WriteTrace("ptr"); LoadIndirect: WriteTrace("_" + address.ToString() + "("); switch (opcode.Attr.Rule) { case OpcodeRule.Indirect8Bit: value = image.ReadByte(address); break; case OpcodeRule.Indirect16Bit: value = image.ReadInt16(address); break; default: value = image.ReadInt32(address); break; } WriteTrace(value.ToString() + ")"); return value; case 8: if (sp <= fp + frameLen) throw new VMException("Stack underflow"); value = Pop(); WriteTrace("sp(" + value.ToString() + ")"); return value; case 9: address = image.ReadByte(operandPos++); goto LoadLocal; case 10: address = image.ReadInt16(operandPos); operandPos += 2; goto LoadLocal; case 11: address = image.ReadInt32(operandPos); operandPos += 4; LoadLocal: WriteTrace("local_" + address.ToString() + "("); address += fp + localsPos; switch (opcode.Attr.Rule) { case OpcodeRule.Indirect8Bit: if (address >= fp + frameLen) throw new VMException("Reading outside local storage bounds"); else value = stack[address]; break; case OpcodeRule.Indirect16Bit: if (address + 1 >= fp + frameLen) throw new VMException("Reading outside local storage bounds"); else value = BigEndian.ReadInt16(stack, address); break; default: if (address + 3 >= fp + frameLen) throw new VMException("Reading outside local storage bounds"); else value = ReadFromStack(address); break; } WriteTrace(value.ToString() + ")"); return value; // case 12: unused case 13: address = image.RamStart + image.ReadByte(operandPos++); WriteTrace("ram"); goto LoadIndirect; case 14: address = image.RamStart + image.ReadInt16(operandPos); operandPos += 2; WriteTrace("ram"); goto LoadIndirect; case 15: address = image.RamStart + image.ReadInt32(operandPos); operandPos += 4; WriteTrace("ram"); goto LoadIndirect; default: throw new ArgumentException("Invalid operand type"); } }