public IList <Instruction> Generate(IList <BasicBlock> blocks, IList <LocalVariableDescriptor> localVariableTable, Z80MethodCodeNode methodCodeNode) { _context = new CodeGeneratorContext(localVariableTable, methodCodeNode, _configuration); AssignFrameOffsets(); var methodInstructions = new List <Instruction>(); GenerateStringMap(blocks); GenerateStringData(_context.Assembler); _context.Assembler.AddInstruction(new LabelInstruction(_nameMangler.GetMangledMethodName(_context.Method))); GenerateProlog(_context.Assembler); methodInstructions.AddRange(_context.Assembler.Instructions); foreach (var block in blocks) { _context.Assembler.Reset(); _context.Assembler.AddInstruction(new LabelInstruction(block.Label)); var visitorAdapter = new GenericStackEntryAdapter(this); var currentNode = block.FirstNode; while (currentNode != null) { currentNode.Accept(visitorAdapter); currentNode = currentNode.Next; } Optimize(_context.Assembler.Instructions); methodInstructions.AddRange(_context.Assembler.Instructions); } return(methodInstructions); }
private void OutputProlog(MethodDef entryMethod) { _out.WriteLine($"; INPUT FILE {_inputFilePath.ToUpper()}"); _out.WriteLine($"; {DateTime.Now}"); _out.WriteLine(); var org = GetOrgAddress(); _out.WriteLine(Instruction.Org(GetOrgAddress())); _out.WriteLine(new LabelInstruction("ENTRY")); _out.WriteLine(Instruction.Ld(R16.HL, "HEAP")); _out.WriteLine(Instruction.LdInd("HEAPNEXT", R16.HL)); if (!_configuration.IntegrationTests) { // Save original stack location _out.WriteLine(Instruction.LdInd("ORIGSP", R16.SP)); // Relocate the stack _out.WriteLine(Instruction.Ld(R16.SP, (short)_configuration.StackStart)); // Start the program _out.WriteLine(Instruction.Call("START")); // Restore the original stack _out.WriteLine(Instruction.LdInd(R16.SP, "ORIGSP")); // Return to the operating system _out.WriteLine(Instruction.Ret()); // Holds the original stack location _out.WriteLine(Instruction.Db(" ", "ORIGSP")); } else { _out.WriteLine(Instruction.Call("START")); _out.WriteLine(Instruction.Pop(R16.DE)); _out.WriteLine(Instruction.Pop(R16.HL)); _out.WriteLine(Instruction.Halt()); } var hasReturnCode = entryMethod.ReturnType.GetStackValueKind() == StackValueKind.Int32; if (hasReturnCode && _configuration.PrintReturnCode) { _out.WriteLine(Instruction.Db("Return Code:", "retcodemsg")); _out.WriteLine(Instruction.Db(0)); } // Include the runtime assembly code if (_configuration.DontInlineRuntime) { _out.WriteLine("include csharprt.asm"); if (_configuration.TargetCpm) { _out.WriteLine("include cpmrt.asm"); } else { _out.WriteLine("include trs80rt.asm"); } } _out.WriteLine(new LabelInstruction("START")); _out.WriteLine(Instruction.Call(_nameMangler.GetMangledMethodName(entryMethod))); if (hasReturnCode && _configuration.PrintReturnCode) { // Write string "Return Code:" _out.WriteLine(Instruction.Ld(R16.HL, "retcodemsg")); _out.WriteLine(Instruction.Call("PRINT")); _out.WriteLine(Instruction.Pop(R16.DE)); _out.WriteLine(Instruction.Pop(R16.HL)); _out.WriteLine(Instruction.Push(R16.HL)); _out.WriteLine(Instruction.Push(R16.DE)); _out.WriteLine(Instruction.Call("LTOA")); } if (hasReturnCode) { _out.WriteLine(Instruction.Pop(R16.BC)); // return value _out.WriteLine(Instruction.Pop(R16.DE)); _out.WriteLine(Instruction.Pop(R16.HL)); // return address _out.WriteLine(Instruction.Push(R16.DE)); _out.WriteLine(Instruction.Push(R16.BC)); _out.WriteLine(Instruction.Push(R16.HL)); } _out.WriteLine(Instruction.Ret()); }