Exemple #1
0
        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);
        }
Exemple #2
0
        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());
        }