public Stack(int stackSize) { if (stackSize <= 0) { new SystemError("InvalidStackSize", "Stack size must be greater than zero.").WriteToError(); } this.bytes = ByteBlock.FromLength(stackSize); }
public Operand(Processor cpu, OperandType optype) { Type = optype; switch (Type) { case OperandType.AddressBlock: Address = new AddressBlock(cpu, cpu.ReadULong()); break; case OperandType.Register: // add break; case OperandType.StackIndex: // add break; case OperandType.NumericByte: Value = new ByteBlock(cpu.ReadByte()); break; case OperandType.NumericSByte: Value = new ByteBlock(cpu.ReadSByte()); break; case OperandType.NumericShort: Value = new ByteBlock(cpu.ReadShort()); break; case OperandType.NumericUShort: Value = new ByteBlock(cpu.ReadUShort()); break; case OperandType.NumericInt: Value = new ByteBlock(cpu.ReadInt()); break; case OperandType.NumericUInt: Value = new ByteBlock(cpu.ReadUInt()); break; case OperandType.NumericLong: Value = new ByteBlock(cpu.ReadLong()); break; case OperandType.NumericULong: Value = new ByteBlock(cpu.ReadULong()); break; case OperandType.NumericFloat: Value = new ByteBlock(cpu.ReadFloat()); break; case OperandType.NumericDouble: Value = new ByteBlock(cpu.ReadDouble()); break; case OperandType.LPString: uint length = cpu.ReadUInt(); ByteBlock bytes = cpu.Read(length); Value = new ByteBlock(System.Text.Encoding.UTF8.GetString(bytes.ToByteArray())); break; default: break; } }
public void WriteAt(ByteBlock bytes, int address) { if (address < 0 || address + bytes.Length >= this.Length) { throw new ArgumentOutOfRangeException(string.Format("Cannot write at 0x{0:X2}. Argument out of range.", address)); } for (int i = 0; i < bytes.Length; i++) { *(this.pointer + address) = *(bytes.pointer + i); address++; } }
public static ByteBlock FromLength(int length) { ByteBlock result = new ByteBlock(); result.pointer = (byte*)Marshal.AllocHGlobal(length); result.Length = length; for (int i = 0; i < length; i++) { *(result.pointer + i) = 0; } return result; }
public void Push(ByteBlock bytes) { this.objectSizes.Push(bytes.Length); this.bytes.WriteAt(bytes, this.stackPointer); this.stackPointer += bytes.Length; }
private void LongArithmeticInstruction(DataOpcode opcode, Operand left, Operand right, Operand dest) { if (left.Type == Operand.OperandType.LPString || right.Type == Operand.OperandType.LPString) { throw new ArgumentException("can't do arithmetic on strings"); } if (dest.Type != Operand.OperandType.AddressBlock && dest.Type != Operand.OperandType.Register && dest.Type != Operand.OperandType.StackIndex) { throw new ArgumentException("can't assign to a literal"); } ByteBlock op1 = GetValue(left); ByteBlock op2 = GetValue(right); ulong uresult; long sresult; double fresult; ByteBlock result; if ((left.Type == Operand.OperandType.NumericByte || left.Type == Operand.OperandType.NumericUShort || left.Type == Operand.OperandType.NumericUInt || left.Type == Operand.OperandType.NumericULong || left.Type == Operand.OperandType.Register || left.Type == Operand.OperandType.AddressBlock) && (right.Type == Operand.OperandType.NumericByte || right.Type == Operand.OperandType.NumericUShort || right.Type == Operand.OperandType.NumericUInt || right.Type == Operand.OperandType.NumericULong || right.Type == Operand.OperandType.Register || right.Type == Operand.OperandType.AddressBlock)) // for now, register & memory values are only treated as ulongs. Fix { uresult = UnsignedArithmetic(opcode, op1.ToULong(), op2.ToULong()); if (dest.Type == Operand.OperandType.Register) { result = new ByteBlock(uresult); WriteRegister((byte)dest.Value, result); } else { // this.Memory.WriteULongAt(uresult, (int)(((AddressBlock)dest.Value).Address)); fix } } else if ((left.Type == Operand.OperandType.NumericSByte || left.Type == Operand.OperandType.NumericShort || left.Type == Operand.OperandType.NumericInt || left.Type == Operand.OperandType.NumericLong) && (right.Type == Operand.OperandType.NumericSByte || right.Type == Operand.OperandType.NumericShort || right.Type == Operand.OperandType.NumericInt || right.Type == Operand.OperandType.NumericLong)) { sresult = SignedArithmetic(opcode, op1.ToLong(), op2.ToLong()); if (dest.Type == Operand.OperandType.Register) { result = new ByteBlock(sresult); WriteRegister((byte)dest.Value, result); } else { // this.Memory.WriteLongAt(sresult, (int)(((AddressBlock)dest.Value).Address)); fix } } else { fresult = FPArithmetic(opcode, op1.ToDouble(), op2.ToDouble()); if (dest.Type == Operand.OperandType.Register) { result = new ByteBlock(fresult); WriteRegister((byte)dest.Value, result); } else { // this.Memory.WriteDoubleAt(fresult, (int)(((AddressBlock)dest.Value).Address)); fix } } }
public void WriteRegister(byte register, ByteBlock value) { if (register >= 0x00 && register <= 0x07) { if (value.Length > 8) { new SystemError("InvalidWriteLength", string.Format("Cannot write a {0}-byte value to a standard 8-byte register.", value.Length)).WriteToError(); } } else if (register == 0x08) { if (value.Length > 4) { new SystemError("InvalidWriteLength", string.Format("Cannot write a {0}-byte value to the 4-byte instruction pointer.", value.Length)).WriteToError(); } } switch (register) { case 0x00: this.EAX = 0UL; this.EAX.WriteAt(value, 8 - value.Length); break; case 0x01: this.EBX = 0UL; this.EBX.WriteAt(value, 8 - value.Length); break; case 0x02: this.ECX = 0UL; this.ECX.WriteAt(value, 8 - value.Length); break; case 0x03: this.EDX = 0UL; this.EDX.WriteAt(value, 8 - value.Length); break; case 0x04: this.EEX = 0UL; this.EEX.WriteAt(value, 8 - value.Length); break; case 0x05: this.EFX = 0UL; this.EFX.WriteAt(value, 8 - value.Length); break; case 0x06: this.EGX = 0UL; this.EGX.WriteAt(value, 8 - value.Length); break; case 0x07: this.EHX = 0UL; this.EHX.WriteAt(value, 8 - value.Length); break; case 0x08: this.InstructionPointer = value.ToUInt(); break; case 0x09: break; } }