public void AssembleStatmentsWhenCalledWithSetRegisterWithDecimalLiteralGenertesCorrectProgram()
        {
            const string Code = "SET I, 10";
            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);
            
            var statments = parser.Parse();

            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            Assert.That(program.Count, Is.EqualTo(1));
            Assert.That(program.ToList()[0], Is.EqualTo(0xA861));
        }
        public void ParseWhenCalledWithSetRegisterWithDecimalLiteralGenertesCorrectStatments()
        {
            const string Code = "SET I, 10";
            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();

            var statment = statments.First();

            Assert.That(statment.Opcode, Is.EqualTo(BasicOpcode.OpSet));
            Assert.That(statment.OperandA is RegisterOperand);
            Assert.That(statment.OperandA.RegisterValue, Is.EqualTo((int)RegisterIdentifier.RegI));
            Assert.That(statment.OperandB is NextWordOperand);
            Assert.That(statment.OperandB.NextWord, Is.EqualTo(10));
        }
        public void ExecuteNextInstructionWhenCalledFiresInstructionDidExecuteIfWired()
        {
            var receivedEvents = new Dictionary<ushort, Instruction>();

            var reader = new StringReader("SET PUSH, 0x10");
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);
            var memory = new Memory();
            memory.LoadData(program);
            var cpu = new Cpu(builder) { Memory = memory };
            cpu.InstructionDidExecute += receivedEvents.Add;
            cpu.ExecuteNextInstruction();

            Assert.That(receivedEvents.Keys.First(), Is.EqualTo(program.ToList()[0]));
        }
        public void AssembleStatmentsWhenCalledWithDatGenertesCorrectProgram()
        {
            const string Code = @"DAT 0x10, 0x20, 0x30, 0x40, 0x50
                                 SET I, 0";
            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);
            
            var statments = parser.Parse();

            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            Assert.That(program.Count, Is.EqualTo(6));
            Assert.That(program.ToList()[0], Is.EqualTo(0x10));
            Assert.That(program.ToList()[1], Is.EqualTo(0x20));
            Assert.That(program.ToList()[2], Is.EqualTo(0x30));
            Assert.That(program.ToList()[3], Is.EqualTo(0x40));
            Assert.That(program.ToList()[4], Is.EqualTo(0x50));
        }
        public void ParseWhenCalledWithHelloWorldSampleGeneratesCorrectStatments()
        {
            const string Code = @"
; Assembler test for DCPU
; by Markus Persson

             set a, 0xbeef                        ; Assign 0xbeef to register a
             set [0x1000], a                      ; Assign memory at 0x1000 to value of register a
             ifn a, [0x1000]                      ; Compare value of register a to memory at 0x1000 ..
                 set PC, end                      ; .. and jump to end if they don't match

             set i, 0                             ; Init loop counter, for clarity
:nextchar    ife [data+i], 0                      ; If the character is 0 ..
                 set PC, end                      ; .. jump to the end
             set [0x8000+i], [data+i]             ; Video ram starts at 0x8000, copy char there
             add i, 1                             ; Increase loop counter
             set PC, nextchar                     ; Loop
  
:data        dat ""Hello world!"", 0              ; Zero terminated string

:end         SET A, 1                             ; Freeze the CPU forever";

            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();

            Assert.That(statments.Count, Is.EqualTo(12));

            var statment5 = statments.ToList()[5]; // ife [data+i], 0

            Assert.That(statment5.Opcode, Is.EqualTo(BasicOpcode.OpIfe));
            Assert.That(statment5.OperandA, Is.InstanceOf(typeof(IndirectNextWordOffsetOperand)));
            Assert.That(statment5.OperandA.Label, Is.EqualTo("data"));
            Assert.That(statment5.OperandA.RegisterValue, Is.EqualTo((int)RegisterIdentifier.RegI));
            Assert.That(statment5.OperandB, Is.InstanceOf(typeof(NextWordOperand)));
            Assert.That(statment5.OperandB.NextWord, Is.EqualTo(0));

            var statment7 = statments.ToList()[7]; // set [0x8000+i], [data+i]

            Assert.That(statment7.Opcode, Is.EqualTo(BasicOpcode.OpSet));
            Assert.That(statment7.OperandA, Is.InstanceOf(typeof(IndirectNextWordOffsetOperand)));
            Assert.That(statment7.OperandA.NextWord, Is.EqualTo(0x8000));
            Assert.That(statment7.OperandA.RegisterValue, Is.EqualTo((int)RegisterIdentifier.RegI));
            Assert.That(statment7.OperandB, Is.InstanceOf(typeof(IndirectNextWordOffsetOperand)));
            Assert.That(statment7.OperandB.Label, Is.EqualTo("data"));
            Assert.That(statment7.OperandB.RegisterValue, Is.EqualTo((int)RegisterIdentifier.RegI));
        }
        public void ParseWhenCalledWithDatContainingAStringGenertesCorrectStatments()
        {
            const string Code = @"DAT 0x10, ""Hello"", 0x20, 0x30, 0x40, 0x50
                                 SET I, 0";
            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers, new ConsumeTokenStrategy(new IgnoreWhiteSpaceTokenStrategy()));
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();

            var statment = statments.First();
            Assert.That(statment.Opcode, Is.EqualTo(BasicOpcode.OpDat));
            Assert.That(statment.OperandA, Is.Null);
            Assert.That(statment.OperandB, Is.Null);
            Assert.That(statment.Label, Is.Null);
            var statmentDat = statment.Dat.ToList();
            Assert.That(statmentDat[0], Is.EqualTo(0x10));
            Assert.That(statmentDat[1], Is.EqualTo((ushort)'"'));
            Assert.That(statmentDat[2], Is.EqualTo((ushort)'H'));
            Assert.That(statmentDat[3], Is.EqualTo((ushort)'e'));
            Assert.That(statmentDat[4], Is.EqualTo((ushort)'l'));
            Assert.That(statmentDat[5], Is.EqualTo((ushort)'l'));
            Assert.That(statmentDat[6], Is.EqualTo((ushort)'o'));
            Assert.That(statmentDat[7], Is.EqualTo((ushort)'"'));
            Assert.That(statmentDat[8], Is.EqualTo(0x20));
            Assert.That(statmentDat[9], Is.EqualTo(0x30));
            Assert.That(statmentDat[10], Is.EqualTo(0x40));
            Assert.That(statmentDat[11], Is.EqualTo(0x50));
        }
        public void ParseWhenCalledWithUnclosedBracketThrows()
        {
            const string Code = "SET [0x1000, 0x20";
            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            Assert.Throws<Exception>(() => parser.Parse());
        }
        public void ParseWhenCalledWithJsRandLabelRefGenertesCorrectStatments()
        {
            const string Code = "JSR testsub";
            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();

            var statment = statments.First();

            Assert.That(statment.Opcode, Is.EqualTo(BasicOpcode.OpJsr));
            Assert.That(statment.OperandA is NextWordOperand);
            Assert.That(statment.OperandA.Label, Is.EqualTo("testsub"));
            Assert.That(statment.OperandA.NextWord, Is.EqualTo(0));
        }
        public void ParseWhenCalledWithSetMemoryAddressWithLiteralGenertesCorrectStatments()
        {
            const string Code = "SET [0x1000], 0x20";
            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();

            var statment = statments.First();

            Assert.That(statment.Opcode, Is.EqualTo(BasicOpcode.OpSet));
            Assert.That(statment.OperandA is IndirectNextWordOperand);
            Assert.That(statment.OperandA.NextWord, Is.EqualTo(4096));
            Assert.That(statment.OperandB is NextWordOperand);
            Assert.That(statment.OperandB.NextWord, Is.EqualTo(32));
        }
        public void CanStepThrougthHelloWorldSample()
        {
            const string Code = @"
; Assembler test for DCPU
; by Markus Persson

             set a, 0xbeef                        ; Assign 0xbeef to register a
             set [0x1000], a                      ; Assign memory at 0x1000 to value of register a
             ifn a, [0x1000]                      ; Compare value of register a to memory at 0x1000 ..
                 set PC, end                      ; .. and jump to end if they don't match

             set i, 0                             ; Init loop counter, for clarity
:nextchar    ife [data+i], 0                      ; If the character is 0 ..
                 set PC, end                      ; .. jump to the end
             set [0x8000+i], [data+i]             ; Video ram starts at 0x8000, copy char there
             add i, 1                             ; Increase loop counter
             set PC, nextchar                     ; Loop
  
:data        dat ""Hello world!"", 0              ; Zero terminated string

:end         SET A, 1                             ; Freeze the CPU forever";

            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);
            var memory = new Memory();
            memory.LoadData(program);
            var cpu = new Cpu(builder) { Memory = memory };
            var receivedEvents = new Dictionary<int, ushort>();
            memory.VideoMemoryDidChange += receivedEvents.Add;

            var executed = true;

            while (executed)
            {
                executed = cpu.ExecuteNextInstruction();
            }

            const string ExpectedValues = "\"Helloworld!\"";

            var i = 0;
            foreach (var expectedValue in ExpectedValues)
            {
                Assert.That(receivedEvents[0x8000 + i], Is.EqualTo((ushort)expectedValue));
                i++;
            }
        }
        public void ExecuteWhenCalledAndOperationOverflowsSetsOverflowRegister(string code, int expectedValue)
        {
            var reader = new StringReader(code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);

            var memory = new Memory();
            memory.LoadData(program);
            var cpu = new Cpu(builder) { Memory = memory };
            var instruction1 = builder.Build(program.ToList()[0], cpu);
            var instruction2 = builder.Build(program.ToList()[1], cpu);
            instruction1.Execute();
            cpu.IncrementProgramCounter();
            instruction2.Execute();

            Assert.That(cpu.Overflow, Is.EqualTo(expectedValue));
        }
        public void InstructionBuilderWhenCalledWithNotchSampleGeneratesCorrectNumberOfInstructions()
        {
            const string Code =
                @"  ;Try some basic stuff
                                    SET A, 0x30              ; 7c01 0030
                                    SET [0x1000], 0x20       ; 7de1 1000 0020
                                    SUB A, [0x1000]          ; 7803 1000
                                    IFN A, 0x10              ; c00d
                                    SET PC, crash            ; 7dc1 001a [*]

                                    ; Do a loopy thing
                                    SET I, 10                ; a861
                                    SET A, 0x2000            ; 7c01 2000
                                    :loop         SET [0x2000+I], [A]      ; 2161 2000
                                    SUB I, 1                 ; 8463
                                    IFN I, 0                 ; 806d
                                    SET PC, loop             ; 7dc1 000d [*]

                                    ; Call a subroutine
                                    SET X, 0x4               ; 9031
                                    JSR testsub              ; 7c10 0018 [*]
                                    SET PC, crash            ; 7dc1 001a [*]

                                    :testsub      SHL X, 4   ; 9037
                                    SET PC, POP              ; 61c1

                                    ; Hang forever. X should now be 0x40 if everything went right.
                                    :crash        SET PC, crash            ; 7dc1 001a [*]";

            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var cpu = new Mock<ICpuStateOperations>();
            var operandFactory = new Mock<IInstructionOperandFactory>();
            var builder = new InstructionBuilder(operandFactory.Object);

            var instructions = program.Select(@ushort => builder.Build(@ushort, cpu.Object)).ToList();

            Assert.That(instructions.Count, Is.EqualTo(28));
        }
Example #13
0
        private static void AssembleFile(string inputFileName, string outputFileName)
        {
            string code;
            using (var myFile = new StreamReader(inputFileName))
            {
                code = myFile.ReadToEnd();
            }

            var reader = new StringReader(code);
            var lexer = new CodeLexer(reader, Matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);
            
            var data = new List<byte>();
            foreach (var word in program)
            {
                data.Add((byte)(word >> 8));
                data.Add((byte)(word & 0xFF));
            }

            File.WriteAllBytes(outputFileName, data.ToArray());
        }
        public void AssembleStatmentsWhenCalledWithHelloWorldSampleGeneratesCorrectProgram()
        {
            const string Code = @"
; Assembler test for DCPU
; by Markus Persson

             set a, 0xbeef                        ; Assign 0xbeef to register a
             set [0x1000], a                      ; Assign memory at 0x1000 to value of register a
             ifn a, [0x1000]                      ; Compare value of register a to memory at 0x1000 ..
                 set PC, end                      ; .. and jump to end if they don't match

             set i, 0                             ; Init loop counter, for clarity
:nextchar    ife [data+i], 0                      ; If the character is 0 ..
                 set PC, end                      ; .. jump to the end
             set [0x8000+i], [data+i]             ; Video ram starts at 0x8000, copy char there
             add i, 1                             ; Increase loop counter
             set PC, nextchar                     ; Loop
  
:data        dat ""Hello world!"", 0              ; Zero terminated string

:end         SET A, 1                             ; Freeze the CPU forever";

            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var expectedInstruction = new[]
                {
                    0x7c01, 0xbeef, 0x01e1, 0x1000, 0x780d, 0x1000, 0x7dc1, 0x0021, 
                    0x8061, 0x816c, 0x0013, 0x7dc1, 0x0021, 0x5961, 0x8000, 0x0013, 
                    0x8462, 0x7dc1, 0x0009, 0x0022, 0x0048, 0x0065, 0x006c, 0x006c, 
                    0x006f, 0x0077, 0x006f, 0x0072, 0x006c, 0x0064, 0x0021, 0x0022, 
                    0x0000, 0x8401
                };

            Assert.That(program.Count, Is.EqualTo(expectedInstruction.Length));
            
            for (var i = 0; i < 28; i++)
            {
                Assert.That(program.ToList()[i], Is.EqualTo(expectedInstruction[i]));
            }
        }
        public void AssembleStatmentsWhenCalledWithNotchSampleGeneratesCorrectProgram()
        {
            const string Code = @"  ;Try some basic stuff
                                    SET A, 0x30              ; 7c01 0030
                                    SET [0x1000], 0x20       ; 7de1 1000 0020
                                    SUB A, [0x1000]          ; 7803 1000
                                    IFN A, 0x10              ; c00d
                                    SET PC, crash            ; 7dc1 001a [*]

                                    ; Do a loopy thing
                                    SET I, 10                ; a861
                                    SET A, 0x2000            ; 7c01 2000
                                    :loop         SET [0x2000+I], [A]      ; 2161 2000
                                    SUB I, 1                 ; 8463
                                    IFN I, 0                 ; 806d
                                    SET PC, loop             ; 7dc1 000d [*]

                                    ; Call a subroutine
                                    SET X, 0x4               ; 9031
                                    JSR testsub              ; 7c10 0018 [*]
                                    SET PC, crash            ; 7dc1 001a [*]

                                    :testsub      SHL X, 4   ; 9037
                                    SET PC, POP              ; 61c1

                                    ; Hang forever. X should now be 0x40 if everything went right.
                                    :crash        SET PC, crash            ; 7dc1 001a [*]

                                    ; [*]: Note that these can be one word shorter and one cycle faster by using the short form (0x00-0x1f) of literals,\n\
                                    ;      but my assembler doesn't support short form labels yet.";

            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            Assert.That(program.Count, Is.EqualTo(28));

            var expectedInstruction = new[]
                {
                    0x7c01, 0x0030, 0x7de1, 0x1000, 0x0020, 0x7803, 0x1000, 0xc00d, 
                    0x7dc1, 0x001a, 0xa861, 0x7c01, 0x2000, 0x2161, 0x2000, 0x8463,
                    0x806d, 0x7dc1, 0x000d, 0x9031, 0x7c10, 0x0018, 0x7dc1, 0x001a, 
                    0x9037, 0x61c1, 0x7dc1, 0x001a
                };

            for (var i = 0; i < 28; i++)
            {
                Assert.That(program.ToList()[i], Is.EqualTo(expectedInstruction[i]));
            }
        }
        public void ExecuteWhenCalledWithJsrSetsProgramCounterToOperandValue()
        {
            var reader = new StringReader("JSR 0x04");
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);
            var memory = new Memory();
            memory.LoadData(program);
            var cpu = new Cpu(builder) { Memory = memory };
            cpu.SetProgramCounter(0x10);
            var instruction = builder.Build(program.ToList()[0], cpu);
            instruction.Execute();

            Assert.That(cpu.ProgramCounter, Is.EqualTo(0x04));
        }
        public void LoadProgramWhenCalledWhitValidProgramLoadsProgramInMemory()
        {
            const string Code =
                @"  ;Try some basic stuff
                                    SET A, 0x30              ; 7c01 0030
                                    SET [0x1000], 0x20       ; 7de1 1000 0020
                                    SUB A, [0x1000]          ; 7803 1000
                                    IFN A, 0x10              ; c00d
                                    SET PC, crash            ; 7dc1 001a [*]

                                    ; Do a loopy thing
                                    SET I, 10                ; a861
                                    SET A, 0x2000            ; 7c01 2000
                                    :loop         SET [0x2000+I], [A]      ; 2161 2000
                                    SUB I, 1                 ; 8463
                                    IFN I, 0                 ; 806d
                                    SET PC, loop             ; 7dc1 000d [*]

                                    ; Call a subroutine
                                    SET X, 0x4               ; 9031
                                    JSR testsub              ; 7c10 0018 [*]
                                    SET PC, crash            ; 7dc1 001a [*]

                                    :testsub      SHL X, 4   ; 9037
                                    SET PC, POP              ; 61c1

                                    ; Hang forever. X should now be 0x40 if everything went right.
									:crash        SET PC, crash            ; 7dc1 001a [*]";

            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var data = new List<byte>();
            foreach (var word in program)
            {
                data.Add((byte)(word >> 8));
                data.Add((byte)(word & 0xFF));
            }

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);
            var cpu = new Cpu(builder);
            var emulator = new Emulator(cpu);
            var receivedEvents = new Dictionary<int, ushort>();
            emulator.MemoryDidChange += receivedEvents.Add; 
            emulator.LoadProgram(data.ToArray());

            var expectedInstruction = new[]
                {
                    0x7c01, 0x0030, 0x7de1, 0x1000, 0x0020, 0x7803, 0x1000, 0xc00d, 
                    0x7dc1, 0x001a, 0xa861, 0x7c01, 0x2000, 0x2161, 0x2000, 0x8463,
                    0x806d, 0x7dc1, 0x000d, 0x9031, 0x7c10, 0x0018, 0x7dc1, 0x001a, 
                    0x9037, 0x61c1, 0x7dc1, 0x001a
                };

            for (var i = 0; i < 28; i++)
            {
                Assert.That(receivedEvents[i], Is.EqualTo(expectedInstruction[i]));
            }
        }
        public void ExecuteWhenCalledWithPeekDoesNotChangeStackPointer()
        {
            const string Code = @"SET PUSH, 0x10
								  SET I, PEEK";

            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);
            var memory = new Memory();
            memory.LoadData(program);
            var cpu = new Cpu(builder) { Memory = memory };
            var instruction1 = builder.Build(program.ToList()[0], cpu);
            var instruction2 = builder.Build(program.ToList()[1], cpu);
            instruction1.Execute();
            instruction2.Execute();

            Assert.That(cpu.StackPointer, Is.EqualTo(ushort.MaxValue));
        }
        public void CanStepThrougthModifiedNotchSample()
        {
            const string Code =
                @"  ;Try some basic stuff
                                    SET A, 0x30              ; 7c01 0030
                                    SET [0x1000], 0x20       ; 7de1 1000 0020
                                    SUB A, [0x1000]          ; 7803 1000
                                    IFN A, 0x10              ; c00d
                                    SET PC, crash            ; 7dc1 001a [*]

                                    ; Do a loopy thing
                                    SET I, 10                ; a861
                                    SET A, 0x2000            ; 7c01 2000
                                    :loop         SET [0x2000+I], [A]      ; 2161 2000
                                    SUB I, 1                 ; 8463
                                    IFN I, 0                 ; 806d
                                    SET PC, loop             ; 7dc1 000d [*]

                                    ; Call a subroutine
                                    SET X, 0x4               ; 9031
                                    JSR testsub              ; 7c10 0018 [*]
                                    SET PC, crash            ; 7dc1 001a [*]

                                    :testsub      SHL X, 4   ; 9037
                                    SET PC, POP              ; 61c1

                                    ; Hang forever. X should now be 0x40 if everything went right.
									:crash        SET A, 0            ; 7dc1 001a [*]";

            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);
            var memory = new Memory();
            memory.LoadData(program);
            var cpu = new Cpu(builder) { Memory = memory };

            var executed = true;

            while (executed)
            {
                executed = cpu.ExecuteNextInstruction();
            }

            Assert.That(cpu.ReadGeneralPursoseRegisterValue((ushort)RegisterIdentifier.RegX), Is.EqualTo(0x40));
        }
        public void ExecuteWhenCalledWithSetOffsetMemoryAddressWithNextWordSetsCorrectMemoryValue(
            string code, ushort memoryAddress, int expectedValue)
        {
            var reader = new StringReader(code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);
            var memory = new Memory();
            memory.LoadData(program);
            var cpu = new Cpu(builder) { Memory = memory };
            var instruction = builder.Build(program.ToList()[0], cpu);
            instruction.Execute();

            Assert.That(cpu.ReadMemoryValueAtAddress(memoryAddress), Is.EqualTo(expectedValue));
        }
        public void ParseWhenCalledWithSetPcRegisterWithLabelRefGenertesCorrectStatments()
        {
            const string Code = "SET PC, crash";
            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();

            var statment = statments.First();

            Assert.That(statment.Opcode, Is.EqualTo(BasicOpcode.OpSet));
            Assert.That(statment.OperandA is ProgramCounterOperand);
            Assert.That(statment.OperandB is NextWordOperand);
            Assert.That(statment.OperandB.Label, Is.EqualTo("crash"));
            Assert.That(statment.OperandB.NextWord, Is.EqualTo(0));
        }
        public void ExecuteWhenCalledWithSetPushWithLiteralSetsCorrectMemoryValue()
        {
            var reader = new StringReader("SET PUSH, 0x10");
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);
            var memory = new Memory();
            memory.LoadData(program);
            var cpu = new Cpu(builder) { Memory = memory };
            var instruction = builder.Build(program.ToList()[0], cpu);
            instruction.Execute();

            Assert.That(cpu.ReadMemoryValueAtAddress(cpu.StackPointer), Is.EqualTo(0x10));
        }
        public void ParseWhenCalledWithInvalidOperandThrowss()
        {
            const string Code = "JSM \"testsub\"";
            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            Assert.Throws<Exception>(() => parser.Parse());
        }
        public void BuildWhenCalledForRawInstructionBuildsExpectedInstructionToken(
            string code)
        {
            var reader = new StringReader(code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);
            var memory = new Memory();
            memory.LoadData(program);
            var cpu = new Cpu(builder) { Memory = memory };

            var instruction = builder.Build(program.ToList()[0], cpu);

            Assert.That(instruction.Token, Is.EqualTo(code.Substring(0, 3)));
        }
        public void ParseWhenCalledWithDatGenertesCorrectStatments()
        {
            const string Code = @"DAT 0x10, 0x20, 0x30, 0x40, 0x50
                                 SET I, 0";
            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();

            var statment = statments.First();
            Assert.That(statment.Opcode, Is.EqualTo(BasicOpcode.OpDat));
            Assert.That(statment.OperandA, Is.Null);
            Assert.That(statment.OperandB, Is.Null);
            Assert.That(statment.Label, Is.Null);
            var statmentDat = statment.Dat.ToList();
            Assert.That(statmentDat[0], Is.EqualTo(0x10));
            Assert.That(statmentDat[1], Is.EqualTo(0x20));
            Assert.That(statmentDat[2], Is.EqualTo(0x30));
            Assert.That(statmentDat[3], Is.EqualTo(0x40));
            Assert.That(statmentDat[4], Is.EqualTo(0x50));
        }
        public void ExecuteWhenCalledWithSetRegisterWithPopSetsCorrectRegistryValue()
        {
            const string Code = @"SET PUSH, 0x10
								  SET I, POP";

            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);
            var memory = new Memory();
            memory.LoadData(program);
            var cpu = new Cpu(builder) { Memory = memory };
            var instruction1 = builder.Build(program.ToList()[0], cpu);
            var instruction2 = builder.Build(program.ToList()[1], cpu);
            instruction1.Execute();
            instruction2.Execute();

            Assert.That(cpu.ReadGeneralPursoseRegisterValue((ushort)RegisterIdentifier.RegI), Is.EqualTo(0x10));
        }
        public void ParseWhenCalledWithNotchSampleGeneratesCorrectNumberOfStatments()
        {
            const string Code = @"  ;Try some basic stuff
                                    SET A, 0x30              ; 7c01 0030
                                    SET [0x1000], 0x20       ; 7de1 1000 0020
                                    SUB A, [0x1000]          ; 7803 1000
                                    IFN A, 0x10              ; c00d
                                    SET PC, crash            ; 7dc1 001a [*]

                                    ; Do a loopy thing
                                    SET I, 10                ; a861
                                    SET A, 0x2000            ; 7c01 2000
                                    :loop         SET [0x2000+I], [A]      ; 2161 2000
                                    SUB I, 1                 ; 8463
                                    IFN I, 0                 ; 806d
                                    SET PC, loop             ; 7dc1 000d [*]

                                    ; Call a subroutine
                                    SET X, 0x4               ; 9031
                                    JSR testsub              ; 7c10 0018 [*]
                                    SET PC, crash            ; 7dc1 001a [*]

                                    :testsub      SHL X, 4   ; 9037
                                    SET PC, POP              ; 61c1

                                    ; Hang forever. X should now be 0x40 if everything went right.
                                    :crash        SET PC, crash            ; 7dc1 001a [*]

                                    ; [*]: Note that these can be one word shorter and one cycle faster by using the short form (0x00-0x1f) of literals,\n\
                                    ;      but my assembler doesn't support short form labels yet.";

            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            
            Assert.That(statments.Count(), Is.EqualTo(17));
        }
        public void ExecuteWhenCalledWithSubLiteralToRegisterValueSetsCorrectRegisterValue(
            string code, ushort registerAddress, int expectedValue)
        {
            var reader = new StringReader(code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);
            var memory = new Memory();
            memory.LoadData(program);
            var cpu = new Cpu(builder) { Memory = memory };
            var instruction1 = builder.Build(program.ToList()[0], cpu);
            var instruction2 = builder.Build(program.ToList()[1], cpu);
            instruction1.Execute();
            instruction2.Execute();

            Assert.That(cpu.ReadGeneralPursoseRegisterValue(registerAddress), Is.EqualTo(expectedValue));
        }
        public void ExecuteWhenCalledWithIfEqualsAndResultIsFalseSetsIgnoreNextInstruction()
        {
            var reader = new StringReader("IFE A, 1");
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);

            var statments = parser.Parse();
            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            var operandFactory = new InstructionOperandFactory();
            var builder = new InstructionBuilder(operandFactory);
            var memory = new Memory();
            memory.LoadData(program);
            var cpu = new Cpu(builder) { Memory = memory };
            var instruction = builder.Build(program.ToList()[0], cpu);
            instruction.Execute();

            Assert.That(cpu.IgnoreNextInstruction, Is.EqualTo(true));
        }
        public void AssembleStatmentsWhenCalledWithhSetOffsetAddressWithAddresssGenertesCorrectProgram()
        {
            const string Code = "SET [0x2000+I], [A]";
            var reader = new StringReader(Code);
            var lexer = new CodeLexer(reader, this.matchers);
            var directOperandFactory = new DirectOperandFactory();
            var indirectOperandFactory = new IndirectOperandFactory();
            var parser = new Parser(lexer, directOperandFactory, indirectOperandFactory);
            
            var statments = parser.Parse();

            var assembler = new Assembler();
            var program = assembler.AssembleStatments(statments);

            Assert.That(program.Count, Is.EqualTo(2));
            Assert.That(program.ToList()[0], Is.EqualTo(0x2161));
            Assert.That(program.ToList()[1], Is.EqualTo(0x2000));
        }