예제 #1
0
        public void TestHalt()
        {
            // Arrange
            var cpu = new CPU();

            var random = new Random();

            var memory = new Memory(random);

            var consoleOutput = new ConsoleOutput();

            var interpreter = new Interpreter(cpu, memory, random, consoleOutput);

            var instruction = new Instruction
            {
                ExecutionPossibility = 100,
                FirstRegister = 0,
                MemoryAddress = 0,
                OpCode = OpCodes.Halt,
                SecondRegister = 0,
                ThirdRegister = 0
            };

            // Act
            interpreter.ExecuteInstruction(instruction);

            // Assert
            // Expected exception specified in method attribute
        }
예제 #2
0
        public void TestComparison()
        {
            // Arrange
            var cpu = new CPU();

            cpu.C = 0;
            cpu.R[2] = 100;
            cpu.R[3] = 200;

            var random = new Random();

            var memory = new Memory(random);

            var consoleOutput = new ConsoleOutput();

            var interpreter = new Interpreter(cpu, memory, random, consoleOutput);

            var instruction = new Instruction
            {
                ExecutionPossibility = 100,
                FirstRegister = 2,
                MemoryAddress = 0,
                OpCode = OpCodes.Compare,
                SecondRegister = 3,
                ThirdRegister = 0
            };

            // Act
            interpreter.ExecuteInstruction(instruction);

            // Assert
            Assert.AreEqual(-1, cpu.C);
        }
예제 #3
0
 public bool Equals(Instruction other)
 {
     return OpCode == other.OpCode &&
            FirstRegister == other.FirstRegister &&
            SecondRegister == other.SecondRegister &&
            ThirdRegister == other.ThirdRegister &&
            ExecutionPossibility == other.ExecutionPossibility &&
            MemoryAddress == other.MemoryAddress;
 }
예제 #4
0
        public void TestParsingFromWordWithUnusedBits()
        {
            // Arrange
            const int word = 0x20F3B05F;

            var targetResult = new Instruction
            {
                OpCode = OpCodes.Compare,
                FirstRegister = 3,
                SecondRegister = 11,
                ThirdRegister = 0,
                ExecutionPossibility = 95
            };

            // Act
            var instruction = Instruction.FromWord(word);

            // Assert
            Assert.AreEqual(targetResult, instruction);
        }
예제 #5
0
        public void TestParsingTwoWordInstruction()
        {
            // Arrange
            const int word1 = 0x40050064;
            const int word2 = 0x12345678;

            var targetResult = new Instruction
            {
                OpCode = OpCodes.LoadByMem,
                FirstRegister = 5,
                SecondRegister = 0,
                ThirdRegister = 0,
                ExecutionPossibility = 100,
                MemoryAddress = 0x12345678
            };

            // Act
            var instruction = Instruction.FromWord(word1, word2);

            // Assert
            Assert.AreEqual(targetResult, instruction);
        }
예제 #6
0
        public void ExecuteInstruction(Instruction instruction)
        {
            _cpu.AdvancePC();

            if (instruction.OpCode == OpCodes.LoadByMem || instruction.OpCode == OpCodes.StoreByMem)
            {
                _cpu.AdvancePC();
            }

            if (instruction.OpCode == OpCodes.Halt)
            {
                throw new VmHaltException();
            }
            else if ((instruction.ExecutionPossibility == 0) || (_random.Next(0, 100) > instruction.ExecutionPossibility))
            {
                return;
            }

            switch (instruction.OpCode)
            {
                case OpCodes.Add:
                    _cpu.R[instruction.FirstRegister] = _cpu.R[instruction.SecondRegister] + _cpu.R[instruction.ThirdRegister];
                    break;

                case OpCodes.And:
                    _cpu.R[instruction.FirstRegister] = _cpu.R[instruction.SecondRegister] & _cpu.R[instruction.ThirdRegister];
                    break;

                case OpCodes.Compare:
                    int subtractionResult = _cpu.R[instruction.FirstRegister] - _cpu.R[instruction.SecondRegister];
                    _cpu.C = (sbyte) Math.Sign(subtractionResult);
                    break;

                case OpCodes.Decrease:
                    _cpu.R[instruction.FirstRegister]--;
                    break;

                case OpCodes.Divide:
                    _cpu.R[instruction.FirstRegister] = _cpu.R[instruction.SecondRegister] / _cpu.R[instruction.ThirdRegister];
                    break;

                case OpCodes.Increase:
                    _cpu.R[instruction.FirstRegister]++;
                    break;

                case OpCodes.Jump:
                    _cpu.PC = (uint) _cpu.R[instruction.FirstRegister];
                    break;

                case OpCodes.JumpIfEqual:
                    if (_cpu.C == 0)
                    {
                        _cpu.PC = (uint) _cpu.R[instruction.FirstRegister];
                    }
                    break;

                case OpCodes.JumpIfGreater:
                    if (_cpu.C == 1)
                    {
                        _cpu.PC = (uint) _cpu.R[instruction.FirstRegister];
                    }
                    break;

                case OpCodes.JumpIfLess:
                    if (_cpu.C == -1)
                    {
                        _cpu.PC = (uint) _cpu.R[instruction.FirstRegister];
                    }
                    break;

                case OpCodes.JumpIfNotEqual:
                    if (_cpu.C != 0)
                    {
                        _cpu.PC = (uint) _cpu.R[instruction.FirstRegister];
                    }
                    break;

                case OpCodes.LoadByMem:
                    _cpu.R[instruction.FirstRegister] = _memory.ReadWord(instruction.MemoryAddress);
                    break;

                case OpCodes.LoadByReg:
                    _cpu.R[instruction.FirstRegister] = _memory.ReadWord((uint) _cpu.R[instruction.SecondRegister]);
                    break;

                case OpCodes.Modulo:
                    _cpu.R[instruction.FirstRegister] = _cpu.R[instruction.SecondRegister] % _cpu.R[instruction.ThirdRegister];
                    break;

                case OpCodes.Multiply:
                    _cpu.R[instruction.FirstRegister] = _cpu.R[instruction.SecondRegister] * _cpu.R[instruction.ThirdRegister];
                    break;

                case OpCodes.Negate:
                    _cpu.R[instruction.FirstRegister] = ~ _cpu.R[instruction.SecondRegister];
                    break;

                case OpCodes.Or:
                    _cpu.R[instruction.FirstRegister] = _cpu.R[instruction.SecondRegister] | _cpu.R[instruction.ThirdRegister];
                    break;

                case OpCodes.PrintNumber:
                    _output.Write(_cpu.R[instruction.FirstRegister].ToString());
                    break;

                case OpCodes.PrintString:
                    var bytes = BitConverter.GetBytes(_cpu.R[instruction.FirstRegister]);
                    Array.Reverse(bytes);
                    var text = Encoding.ASCII.GetString(bytes);
                    _output.Write(text);
                    break;

                case OpCodes.RandomizedAdd:
                    _cpu.R[instruction.FirstRegister] = Randomize(_cpu.R[instruction.SecondRegister] + _cpu.R[instruction.ThirdRegister]);
                    break;

                case OpCodes.RandomizedDivide:
                    _cpu.R[instruction.FirstRegister] = Randomize(_cpu.R[instruction.SecondRegister] / _cpu.R[instruction.ThirdRegister]);
                    break;

                case OpCodes.RandomizedModulo:
                    _cpu.R[instruction.FirstRegister] = Randomize(_cpu.R[instruction.SecondRegister] % _cpu.R[instruction.ThirdRegister]);
                    break;

                case OpCodes.RandomizedMultiply:
                    _cpu.R[instruction.FirstRegister] = Randomize(_cpu.R[instruction.SecondRegister] * _cpu.R[instruction.ThirdRegister]);
                    break;

                case OpCodes.RandomizedSubtract:
                    _cpu.R[instruction.FirstRegister] = Randomize(_cpu.R[instruction.SecondRegister] - _cpu.R[instruction.ThirdRegister]);
                    break;

                case OpCodes.StoreByMem:
                    _memory.WriteWord(instruction.MemoryAddress, _cpu.R[instruction.FirstRegister]);
                    break;

                case OpCodes.StoreByReg:
                    _memory.WriteWord((uint)_cpu.R[instruction.SecondRegister], _cpu.R[instruction.FirstRegister]);
                    break;

                case OpCodes.Subtract:
                    _cpu.R[instruction.FirstRegister] = _cpu.R[instruction.SecondRegister] - _cpu.R[instruction.ThirdRegister];
                    break;

                case OpCodes.Xor:
                    _cpu.R[instruction.FirstRegister] = _cpu.R[instruction.SecondRegister] ^ _cpu.R[instruction.ThirdRegister];
                    break;
            }
        }
예제 #7
0
        public void TestJumpIfGreater()
        {
            // Arrange
            var cpu = new CPU();

            cpu.C = 1;
            cpu.PC = 0;

            unchecked
            {
                cpu.R[0] = (int) 0x98513691;
            }

            var random = new Random();

            var memory = new Memory(random);

            var consoleOutput = new ConsoleOutput();

            var interpreter = new Interpreter(cpu, memory, random, consoleOutput);

            var instruction = new Instruction
            {
                ExecutionPossibility = 100,
                FirstRegister = 0,
                MemoryAddress = 0,
                OpCode = OpCodes.JumpIfGreater,
                SecondRegister = 0,
                ThirdRegister = 0
            };

            // Act
            interpreter.ExecuteInstruction(instruction);

            // Assert
            Assert.AreEqual(0x98513691, cpu.PC);
        }
예제 #8
0
        public void TestStoreByMem()
        {
            // Arrange
            var cpu = new CPU();

            cpu.R[0] = 0x0A0B0C0D;

            var random = new Random();

            var memory = new Memory(random);

            var consoleOutput = new ConsoleOutput();

            var interpreter = new Interpreter(cpu, memory, random, consoleOutput);

            var instruction = new Instruction
            {
                ExecutionPossibility = 100,
                FirstRegister = 0,
                MemoryAddress = 0x87654320,
                OpCode = OpCodes.StoreByMem,
                SecondRegister = 1,
                ThirdRegister = 2
            };

            // Act
            interpreter.ExecuteInstruction(instruction);

            var valueInMemory = memory.ReadWord(0x87654320);

            // Assert
            Assert.AreEqual(0x0A0B0C0D, valueInMemory);
        }
예제 #9
0
        public void TestRandomizedAdd()
        {
            // Arrange
            var cpu = new CPU();

            cpu.R[0] = 0;
            cpu.R[1] = 200;
            cpu.R[2] = 300;

            var random = new Random();

            var memory = new Memory(random);

            var consoleOutput = new ConsoleOutput();

            var interpreter = new Interpreter(cpu, memory, random, consoleOutput);

            var instruction = new Instruction
            {
                ExecutionPossibility = 100,
                FirstRegister = 0,
                MemoryAddress = 0,
                OpCode = OpCodes.RandomizedAdd,
                SecondRegister = 1,
                ThirdRegister = 2
            };

            // Act
            interpreter.ExecuteInstruction(instruction);

            // Assert
            Assert.That(cpu.R[0], Is.EqualTo(500).Within(1).Percent);
        }
예제 #10
0
        public void TestMultiplication()
        {
            // Arrange
            var cpu = new CPU();

            cpu.R[0] = 0;
            cpu.R[1] = 200;
            cpu.R[2] = 300;

            var random = new Random();

            var memory = new Memory(random);

            var consoleOutput = new ConsoleOutput();

            var interpreter = new Interpreter(cpu, memory, random, consoleOutput);

            var instruction = new Instruction
            {
                ExecutionPossibility = 100,
                FirstRegister = 0,
                MemoryAddress = 0,
                OpCode = OpCodes.Multiply,
                SecondRegister = 1,
                ThirdRegister = 2
            };

            // Act
            interpreter.ExecuteInstruction(instruction);

            // Assert
            Assert.AreEqual(60000, cpu.R[0]);
        }
예제 #11
0
        public void TestLogicalOrWithZeroProbability()
        {
            // Arrange
            var cpu = new CPU();

            cpu.R[10] = 0;
            cpu.R[11] = 0x02040608;
            cpu.R[12] = 0x10305070;

            var random = new Random();

            var memory = new Memory(random);

            var consoleOutput = new ConsoleOutput();

            var interpreter = new Interpreter(cpu, memory, random, consoleOutput);

            var instruction = new Instruction
            {
                ExecutionPossibility = 0,
                FirstRegister = 10,
                MemoryAddress = 0,
                OpCode = OpCodes.Or,
                SecondRegister = 11,
                ThirdRegister = 12
            };

            // Act
            interpreter.ExecuteInstruction(instruction);

            // Assert
            Assert.AreEqual(0, cpu.R[10]);
        }