public void ParseWhenCalledForEmptySourceReturnsEmptyStatmentCollection() { var lexer = new Mock<ILexer>(); var directOperandFactory = new Mock<IOperandFactory>(); var indirectOperandFactory = new Mock<IOperandFactory>(); var parser = new Parser(lexer.Object, directOperandFactory.Object, indirectOperandFactory.Object); Assert.That(parser.Parse(), Is.Empty); }
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 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 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)); }
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 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 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)); }