public void DecodesOpeningZorkInstruction() { using var file = File.OpenRead(@"Data\ZORK1.DAT"); var logger = NullLoggerFactory.GetLogger(); var machine = new Machine(logger, new SolveZorkInputStream()); machine.Load(file); var decoder = new InstructionDecoder(machine); var memory = machine.Memory.SpanAt(machine.PC); var instruction = decoder.Decode(memory); instruction.Prepare(memory); instruction.Execute(memory); Assert.NotNull(instruction as VarInstruction); Assert.Equal("Call", instruction.Operation.Name); Assert.Equal(0, instruction.OpCode); Assert.Equal(0, instruction.StoreResult); Assert.Equal(3, instruction.Operands.Count); Assert.Equal(0x5479, machine.PC); memory = machine.Memory.SpanAt(machine.PC); instruction = decoder.Decode(memory); instruction.Prepare(memory); instruction.Execute(memory); Assert.NotNull(instruction as VarInstruction); Assert.Equal("Call", instruction.Operation.Name); Assert.Equal(2, instruction.Operands.Count); Assert.Equal(3, instruction.StoreResult); Assert.Equal(OperandType.Variable, instruction.Operands[1].Type); Assert.Equal(1, instruction.Operands[1].RawValue); memory = machine.Memory.SpanAt(machine.PC); instruction = decoder.Decode(memory); instruction.Prepare(memory); instruction.Execute(memory); Assert.NotNull(instruction as Op2Instruction); Assert.Equal("Add", instruction.Operation.Name); Assert.Equal(4, instruction.Size); Assert.Equal(2, instruction.Operands.Count); Assert.Equal(OperandType.Variable, instruction.Operands[0].Type); Assert.Equal(0x94, instruction.Operands[0].RawValue); Assert.Equal(OperandType.Small, instruction.Operands[1].Type); Assert.Equal(0xB4, instruction.Operands[1].RawValue); Assert.Equal(0x03, instruction.StoreResult); }
public void Test3() { // Arrange var instruction = new Byte2(-985); // Act var decodedInstruction = InstructionDecoder.Decode(instruction); // Assert decodedInstruction.ComputationInstruction.Should().BeTrue(); decodedInstruction.SourceMemory.Should().BeTrue(); decodedInstruction.Operation.zx.Should().BeTrue(); decodedInstruction.Operation.nx.Should().BeTrue(); decodedInstruction.Operation.zy.Should().BeFalse(); decodedInstruction.Operation.ny.Should().BeFalse(); decodedInstruction.Operation.Function.Should().BeFalse(); decodedInstruction.Operation.NegateOutput.Should().BeFalse(); decodedInstruction.Destination.A.Should().BeTrue(); decodedInstruction.Destination.D.Should().BeFalse(); decodedInstruction.Destination.Ram.Should().BeFalse(); decodedInstruction.Condition.GreaterThanZero.Should().BeTrue(); decodedInstruction.Condition.EqualToZero.Should().BeTrue(); decodedInstruction.Condition.LessThanZero.Should().BeTrue(); decodedInstruction.w.ToInt16().Should().Be(0); }
public ControlUnitOutput Do(Byte2 data, bool clock) { var decodedInstruction = InstructionDecoder.Decode(data); var selectedSourceMemory = Select16.Do(decodedInstruction.SourceMemory, _memoryOutput.Ram, _memoryOutput.A); _aluOutput = ArithmeticLogicUnit.Do(decodedInstruction.Operation, _memoryOutput.D, selectedSourceMemory); _selectedBasedOnComputationInstruction = Select16.Do(decodedInstruction.ComputationInstruction, _aluOutput, decodedInstruction.w); _memoryOutput = _memory.Do(decodedInstruction.Destination, _selectedBasedOnComputationInstruction, clock); var isCondition = ArithmeticLogicUnit.Evaluate(decodedInstruction.Condition, _aluOutput); return(new ControlUnitOutput(isCondition, _memoryOutput.A)); }
private static TInstruction AssertBytesDecodedAs <TInstruction>(byte[] bytes) where TInstruction : IInstruction { var(instruction, bytesRead) = InstructionDecoder.Decode(bytes); Assert.IsType <TInstruction>(instruction); var loadInstruction = (TInstruction)instruction; //Whole message was read Assert.Equal(bytes.Length, bytesRead); return(loadInstruction); }
public void FourBitOpcodeRegisterAInBits7To11(int register) { var decoder = new InstructionDecoder(); ForEachOpcode(FourBitOpcodes, opcode => { var encodedInstruction = (ushort)(opcode | (register << 8)); var decodedInstruction = decoder.Decode(encodedInstruction); decodedInstruction.RegisterA.Should().Be(register); }); }
void TestOpcodeParameter(IEnumerable <Opcode> opcodes, ushort rawValue, int expectedDecodedValue) { var decoder = new InstructionDecoder(); ForEachOpcode(opcodes, opcode => { var encodedInstruction = (ushort)(opcode | rawValue); var decodedInstruction = decoder.Decode(encodedInstruction); decodedInstruction.Value.Should().Be(expectedDecodedValue); }); }
public void EightBitOpcodeRegisterBInBits0To3(int register) { var decoder = new InstructionDecoder(); ForEachOpcode(EightBitOpcodes, opcode => { var encodedInstruction = (ushort)(opcode | (register << 0)); var decodedInstruction = decoder.Decode(encodedInstruction); decodedInstruction.RegisterB.Should().Be(register); }); }
public void For_data_instruction_W_returns_input() { // Arrange var instruction = new Byte2(17); // Act var decodedInstruction = InstructionDecoder.Decode(instruction); // Assert decodedInstruction.w.ToInt16().Should().Be(17); }
private void updateMemoryDisplay() { DataTable dt = new DataTable(); dt.Columns.Add(new DataColumn("address", typeof(string))); dt.Columns.Add(new DataColumn("value", typeof(string))); dt.Columns.Add(new DataColumn("instruction", typeof(String))); int start = _memoryDisplayStartAddress; int end = start + 1000; for (int address = start; address < end;) { if (_memoryDisplaySize == 4) { int machineCode = _vm.cpu.Memory.Get(address, false, 4); object[] firstRowData = new object[3]; firstRowData[0] = address; firstRowData[1] = machineCode; address += 4; Instruction instruction = InstructionDecoder.Decode(machineCode); if (instruction.HasImmediate) { instruction.Immediate = _vm.cpu.Memory.Get(address, false, 4); address += 4; } firstRowData[2] = instruction.ToString(); dt.Rows.Add(firstRowData); if (instruction.HasImmediate) { dt.Rows.Add(address - 4, instruction.Immediate, "[immediate value]"); } } else { int value = BitHelper.ExtractBytes(_vm.cpu.Memory.Get(address, false, 1), 1); dt.Rows.Add(address, value, ""); address++; } } memoryGridView.Invoke((MethodInvoker)(() => { memoryGridView.DataSource = dt; })); }
public void Decode_Works() { var instructionDecoder = new InstructionDecoder(); var decodedInstruction = instructionDecoder.Decode(0x12, 0x34); Assert.That(decodedInstruction.InstructionCode, Is.EqualTo(0x1234)); Assert.That(decodedInstruction.nnn, Is.EqualTo(0x234)); Assert.That(decodedInstruction.n, Is.EqualTo(0x4)); Assert.That(decodedInstruction.x, Is.EqualTo(0x2)); Assert.That(decodedInstruction.y, Is.EqualTo(0x3)); Assert.That(decodedInstruction.kk, Is.EqualTo(0x34)); Assert.That(decodedInstruction.OpCode, Is.EqualTo(0x1)); }
public void Step() { try { int machineCode = Fetch(); _currentInstruction = InstructionDecoder.Decode(machineCode); if (_currentInstruction is Break) { _debugging = true; _debuggingNotification(); } if (_currentInstruction.HasImmediate) { _currentInstruction.Immediate = Fetch(); } _currentInstruction.Execute(this); if (Interrupts.Count > 0) { lock (Interrupts) { throw new InterruptException(Interrupts.Dequeue()); } } } catch (InterruptException ex) { //Index into Interrupt Descriptor Table int interrupt = ex.InterruptNumber; KernelMode = true; //TODO: Need to switch to kernel stack? Should this be handled by IR common stub? //Similar to a call, stored the address where code should resume executing on the stack Memory[Registers[Register.SP]] = Registers[Register.IP]; Registers[Register.SP] += 4; //Set IP to fixed interrupt handler address Registers[Register.IP] = Memory[IDTPointer + interrupt * 4]; } if (_stepNotification != null && _debugging) { _stepNotification(); } }
private Instruction getNextInstruction() { int address = _vm.cpu.Registers[Register.IP]; int machineCode = _vm.cpu.Memory.Get(address, false, 4); address += 4; Instruction instruction = InstructionDecoder.Decode(machineCode); if (instruction.HasImmediate) { instruction.Immediate = _vm.cpu.Memory.Get(address, false, 4); } return(instruction); }
public void decode_logical_and_instruction(byte instruction) { var result = InstructionDecoder.Decode(instruction); Assert.Equal(InstructionMnemonic.ANA, result); }
public void Decode_NotSupportedOpcode_ThrowOpcodeReadException(Opcode opcode) { var bytes = InstructionByteBuilder.Create().Opcode(opcode).ToArray(); Assert.Throws <OpcodeDecodeException>(() => InstructionDecoder.Decode(bytes)); }
public void Decode_ZeroBytesToDecode_RaiseArgumentException() { Assert.Throws <ArgumentException>(() => InstructionDecoder.Decode(Array.Empty <byte>())); }
public void store_accumulator_indirect_instruction(byte instruction) { var result = InstructionDecoder.Decode(instruction); Assert.Equal(InstructionMnemonic.STAX, result); }
public void Run(IEnumerable <byte> program) { // Init the core Memory.Write(BaseAddres, program); Register.WriteUnsignedInt(Register.ProgramCounter, BaseAddres); var decoder = new InstructionDecoder(EndianCoding); var typeDecoder = new TypeDecoder(); // Create a simple bootstrap CPU var cpu = new Cpu64(); cpu.AssignMemory(Memory); cpu.AssignRegister(Register); cpu.AssignEEI(Environment); cpu.AssignRasStack(RasStack); cpu.AssignCrs(CsrRegister); cpu.Init(); // Fetch the first instruction and run the loop var pc = Register.ReadUnsignedInt(Register.ProgramCounter); // Get the first 2 Bytes from the Base Address aka PC var instructionCoding = Memory.GetHalfWord(pc); while (ContinueIfValid(instructionCoding)) { // Loop for the commands var instruction = decoder.Decode(instructionCoding); InstructionsProcessed.Add(instruction); // If the decoder cannot decode the parameter pattern, throw an exception if (instruction.Type == InstructionType.Unknown) { string unknownOpCodeErrorMessage = String.Format("Error: OpCode = {0}", instruction.OpCode); throw new OpCodeNotSupportedException(unknownOpCodeErrorMessage) { Coding = instructionCoding, Type = instruction.Type, OpCode = instruction.OpCode }; } // Reload the other bytes if required! if (instruction.InstructionLength == 4) { // Read the complete 32 Bit instruction set for the decoding var inst32Coding = Memory.GetWord(pc); var payload = typeDecoder.DecodeType(instruction, inst32Coding); if (payload == null) { throw new RiscVSimException("No Payload available!"); } // For UnitTesting: Add the result to the list InstructionPayloads.Add(payload); // Execute the command cpu.Execute(instruction, payload); } // Done. Next run. pc = Register.ReadUnsignedInt(Register.ProgramCounter); instructionCoding = Memory.GetHalfWord(pc); } }
public void decode_decrement_register_pair(byte instruction) { var result = InstructionDecoder.Decode(instruction); Assert.Equal(InstructionMnemonic.DCX, result); }
public void move_immediate_instruction(byte instruction) { var result = InstructionDecoder.Decode(instruction); Assert.Equal(InstructionMnemonic.MVI, result); }
public void decode_double_add_instruction(byte instruction) { var result = InstructionDecoder.Decode(instruction); Assert.Equal(InstructionMnemonic.DAD, result); }
public void decode_add_with_carry_instruction(byte instruction) { var result = InstructionDecoder.Decode(instruction); Assert.Equal(InstructionMnemonic.ADC, result); }
public void pop_instruction(byte instruction) { var result = InstructionDecoder.Decode(instruction); Assert.Equal(InstructionMnemonic.POP, result); }
public void decode_exclusive_or_instruction(byte instruction) { var result = InstructionDecoder.Decode(instruction); Assert.Equal(InstructionMnemonic.XRA, result); }
public void decode_restart_instruction(byte instruction) { var result = InstructionDecoder.Decode(instruction); Assert.Equal(InstructionMnemonic.RST, result); }
public void decode_increment_instruction(byte instruction) { var result = InstructionDecoder.Decode(instruction); Assert.Equal(InstructionMnemonic.INR, result); }
public void decode_subtract_with_borrow_instruction(byte instruction) { var result = InstructionDecoder.Decode(instruction); Assert.Equal(InstructionMnemonic.SBB, result); }
/// <summary> /// The generic fetch method for all hart implementations /// </summary> private void Fetch() { // Done! // Fetch the first instruction and run the loop. Get the first 2 Bytes from the Base Address aka PC var pc = register.ReadUnsignedInt(register.ProgramCounter); var instructionCoding = memory.GetHalfWord(pc); Logger.Info("Instruction {ins:X} fetched", BitConverter.ToString(instructionCoding.ToArray())); while (ContinueIfValid(instructionCoding)) { // Loop for the commands var instruction = instructionDecoder.Decode(instructionCoding); if (rvMode) { var isCustom = (instructionCoding.First() & 0x7F) == 0x00; if (isCustom) { Logger.Info("Processing RV custom command."); var customCoding = memory.GetWord(pc); var isHalt = customCoding.SequenceEqual(new byte[] { 0x00, 0x00, 0x00, 0x00 }); if (isHalt) { // Stop the simulation! break; } var payload = typeDecoder.DecodeCustom(instruction, customCoding); var rvOpcode = new RvOpcode(memory, register, environment); var inc = rvOpcode.Execute(instruction, payload); if (inc) { // Go to the next instruction... register.NextInstruction(4); } } else { // Handle instruction as usual.. HandleCompliantMode(pc, instructionCoding, instruction); } } else { HandleCompliantMode(pc, instructionCoding, instruction); } // Stop the instruction fetch if an error occured or the state is stopped var currentState = environment.GetCurrentState(); if (currentState == State.FatalError || currentState == State.Stopped) { break; } // Done. Next run. pc = register.ReadUnsignedInt(register.ProgramCounter); instructionCoding = memory.GetHalfWord(pc); Logger.Info("Instruction {ins:X} fetched", BitConverter.ToString(instructionCoding.ToArray())); } if (environment.GetCurrentState() == State.FatalError) { Console.Error.WriteLine("# FATAL ERROR occured : " + environment.GetStateDescription()); } if (environment.GetCurrentState() == State.Stopped) { Console.Out.WriteLine("# Hart Stopped"); } environment.NotifyStopped(); }