public List <Instruction> CodeGen()
        {
            var b = new List <Instruction>();

            if (body.Count == 0)
            {
                // Empty loop, just wait on self until fails...

                b.AddRange(branch.CodeGen(0, 1));
            }
            else
            {
                FieldSRef.ResetScratchInts();
                b.AddRange(RegVRef.rScratchInts.PutFromReg(RegVRef.rNull));
                var flatbody = body.CodeGen();
                b.AddRange(branch.CodeGen(1, flatbody.Count + 2));
                b.AddRange(flatbody);
                b.Add(new Jump {
                    target = new IntSExpr(-b.Count), relative = true
                });
                b.AddRange(RegVRef.rScratchInts.PutFromReg(RegVRef.rNull));
                FieldSRef.ResetScratchInts();
            }

            return(b);
        }
Exemple #2
0
        public List <Instruction> FetchToReg(RegVRef dest)
        {
            var code = new List <Instruction>();
            var cmd  = Command.AsReg();

            if (cmd == null)
            {
                cmd = RegVRef.rScratchTab;
                code.AddRange(Command.FetchToReg(cmd));
            }

            var data = Data.AsReg();

            if (data == null)
            {
                data = cmd == RegVRef.rScratchTab ? RegVRef.rScratchInts : RegVRef.rScratchTab;
                if (data == RegVRef.rScratchInts)
                {
                    FieldSRef.ResetScratchInts();
                }
                code.AddRange(Data.FetchToReg(data));
            }

            code.Add(new Instruction
            {
                opcode = Opcode.ConMan,
                op1    = cmd,
                op2    = data,
                dest   = dest,
            });

            if (data == RegVRef.rScratchInts)
            {
                code.AddRange(data.PutFromReg(RegVRef.rNull));
            }

            return(code);
        }
Exemple #3
0
        public List <Instruction> BuildFunction()
        {
            var b = new List <Instruction>();

            // save call site (in r8.signal-0)
            b.Add(new Push(RegVRef.rScratchInts));

            if (localints.Count > 0)
            {
                // save parent localints
                b.Add(new Push(RegVRef.rLocalInts("parent")));
            }

            // push regs as needed
            foreach (var sym in locals.Where(s => s.type == SymbolType.Register))
            {
                if (sym.fixedAddr.HasValue)
                {
                    b.Add(new Push(new RegVRef(sym.fixedAddr.Value)));
                }
            }

            // wind stack down for locals if needed
            if (framesize > 0)
            {
                b.Add(new Instruction
                {
                    opcode = Opcode.Add,
                    op1    = FieldSRef.Imm1(),
                    imm1   = new IntSExpr(-framesize),
                    acc    = true,
                    dest   = FieldSRef.Pointer(PointerIndex.CallStack)
                });
            }

            // copy params if named
            //int args or null in r8
            var intparas = locals.Where(sym => sym.type == SymbolType.Parameter && sym.datatype == "int").ToList();

            if (intparas.Count() > 0)
            {
                for (int i = 0; i < intparas.Count(); i++)
                {
                    b.Add(new Instruction
                    {
                        opcode = Opcode.Add,
                        op1    = FieldSRef.IntArg(name, intparas[i].name),
                        dest   = FieldSRef.LocalInt(name, intparas[i].name),
                        acc    = i != 0,
                    });
                }
            }

            FieldSRef.ResetScratchInts();
            b.AddRange(RegVRef.rScratchInts.PutFromReg(RegVRef.rNull));

            // body
            b.AddRange(body.CodeGen());

            // convert rjmp __return => rjmp <integer> to here.
            for (int i = 0; i < b.Count; i++)
            {
                var inst = b[i];
                if ((inst.imm1 as AddrSExpr)?.symbol == "__return")
                {
                    inst.imm1 = new IntSExpr(b.Count - i);
                }
                if ((inst.imm2 as AddrSExpr)?.symbol == "__return")
                {
                    inst.imm2 = new IntSExpr(b.Count - i);
                }
                b[i] = inst;
            }

            // wind stack back up for locals if needed
            if (framesize > 0)
            {
                b.Add(new Instruction
                {
                    opcode = Opcode.Add,
                    op1    = FieldSRef.Imm1(),
                    imm1   = new IntSExpr(framesize),
                    acc    = true,
                    dest   = FieldSRef.Pointer(PointerIndex.CallStack)
                });
            }

            // restore registers
            foreach (var sym in locals.Where(s => s.type == SymbolType.Register).Reverse())
            {
                if (sym.fixedAddr.HasValue)
                {
                    b.Add(new Pop(new RegVRef(sym.fixedAddr.Value)));
                }
            }

            if (localints.Count > 0)
            {
                // restore parent localints
                b.Add(new Pop(RegVRef.rLocalInts("parent")));
            }

            // get return site
            b.Add(new Exchange(RegVRef.rScratchTab));
            b.Add(new Instruction
            {
                opcode = Opcode.Sub,
                op1    = FieldSRef.VarField(RegVRef.rScratchTab, "signal-0"),
                op2    = FieldSRef.CallSite,
                dest   = FieldSRef.CallSite,
                acc    = true
            });

            b.Add(new Pop(RegVRef.rScratchTab));

            // jump to return site
            b.Add(new Jump {
                target = FieldSRef.CallSite
            });

            return(b);
        }