public List <Instruction> FetchToField(FieldSRef dest)
        {
            var code = new List <Instruction>();

            if (varref.AsReg() == null)
            {
                code.AddRange(varref.FetchToReg(RegVRef.rScratchTab));
                code.Add(new Instruction
                {
                    opcode = Opcode.Sub,
                    op1    = this.InRegister(RegVRef.rScratchTab),
                    op2    = dest,
                    dest   = dest,
                    acc    = true,
                });
            }
            else
            {
                code.Add(new Instruction
                {
                    opcode = Opcode.Sub,
                    op1    = this,
                    op2    = dest,
                    dest   = dest,
                    acc    = true,
                });
            }

            return(code);
        }
Beispiel #2
0
        public List <Instruction> CodeGen(int truejump, int falsejump)
        {
            var b = new List <Instruction>();

            var f1 = S1.AsDirectField() ?? (S1.IsConstant() ? FieldSRef.Imm1() : null);

            if (f1 == null)
            {
                f1 = FieldSRef.ScratchInt();
                b.AddRange(S1.FetchToField(f1));
            }

            var f2 = S2.AsDirectField() ?? (S2.IsConstant() ? FieldSRef.Imm2() : null);

            if (f2 == null)
            {
                f2 = FieldSRef.ScratchInt();
                b.AddRange(S2.FetchToField(f2));
            }

            b.Add(new Instruction
            {
                opcode = Opcode.Branch,
                op1    = f1,
                imm1   = S1.IsConstant() ? new IntSExpr(S1.Evaluate()) : null,
                op2    = f2,
                imm2   = S2.IsConstant() ? new IntSExpr(S2.Evaluate()) : null,
                rjmpeq = this.Op.HasFlag(CompSpec.Equal) ? truejump : falsejump,
                rjmplt = this.Op.HasFlag(CompSpec.Less) ? truejump : falsejump,
                rjmpgt = this.Op.HasFlag(CompSpec.Greater) ? truejump : falsejump,
            });

            return(b);
        }
        public List <Instruction> PutFromReg(RegVRef src)
        {
            var code = new List <Instruction>();

            FieldSRef addr = this.addr as FieldSRef;

            if (addr == null)
            {
                if (this.addr.IsConstant())
                {
                    addr = FieldSRef.Imm1();
                }
                else
                {
                    addr = FieldSRef.ScratchInt();
                    code.AddRange(this.addr.FetchToField(addr));
                }
            }

            code.Add(new Instruction
            {
                opcode = Opcode.MemWrite,
                op1    = addr,
                op2    = src,
                imm1   = this.addr.IsConstant() ? this.addr : null,
            });
            return(code);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        public List <Instruction> CodeGen()
        {
            var code = new List <Instruction>();

            if (source.IsConstant())
            {
                code.AddRange(target.PutFromInt(source.Evaluate()));
            }
            else
            {
                var src = source.AsDirectField();

                if (src == null)
                {
                    var tgt = target.AsDirectField();
                    if (tgt == null)
                    {
                        var scratch = FieldSRef.ScratchInt();
                        code.AddRange(source.FetchToField(scratch));
                        code.AddRange(target.PutFromField(scratch));
                    }
                    else
                    {
                        code.AddRange(source.FetchToField(tgt));
                    }
                }
                else
                {
                    code.AddRange(target.PutFromField(src));
                }
            }

            return(code);
        }
        public List <Instruction> FetchToReg(RegVRef dest)
        {
            var code = new List <Instruction>();

            FieldSRef addr = this.addr.AsDirectField();

            if (addr == null)
            {
                if (this.addr.IsConstant())
                {
                    addr = FieldSRef.Imm1();
                }
                else
                {
                    addr = FieldSRef.ScratchInt();
                    code.AddRange(this.addr.FetchToField(addr));
                }
            }

            code.Add(new Instruction
            {
                opcode = Opcode.MemRead,
                op1    = addr,
                dest   = dest,
                imm1   = this.addr.IsConstant() ? this.addr : null,
                idx    = this.addr.frame(),
            });
            return(code);
        }
Beispiel #7
0
 public Clear(FieldSRef field)
 {
     if (field.AsDirectField() == null)
     {
         throw new ArgumentOutOfRangeException("field", "can only be a register field");
     }
     this.field = field;
 }
Beispiel #8
0
        public List <Instruction> FetchToField(FieldSRef dest)
        {
            var code = CodeGen();

            code.AddRange(new SAssign {
                source = FieldSRef.SReturn, target = dest
            }.CodeGen());
            return(code);
        }
 public FieldSRef BaseField()
 {
     if (Program.CurrentFunction.localints.ContainsKey(name))
     {
         return(FieldSRef.LocalInt(Program.CurrentFunction.name, name));
     }
     else
     {
         return(FieldSRef.GlobalInt(name));
     }
 }
Beispiel #10
0
        public List <Instruction> CodeGen()
        {
            var b = new List <Instruction>();

            //int args or null in r8
            if (args.ints.Count > 0)
            {
                for (int i = 0; i < args.ints.Count; i++)
                {
                    b.AddRange(new SAssign
                    {
                        source = new ArithSExpr(args.ints[i], ArithSpec.Add, IntSExpr.Zero),
                        target = FieldSRef.VarField(RegVRef.rScratchInts, "signal-" + (i + 1)),
                    }.CodeGen());
                }
            }
            else
            {
                b.AddRange(new VAssign
                {
                    source = RegVRef.rNull,
                    target = RegVRef.rScratchInts,
                }.CodeGen());
            }

            //table arg or null in r7
            b.AddRange(new VAssign
            {
                source = args.vars.Count > 0? args.vars[1] : RegVRef.rNull,
                target = RegVRef.rVarArgs,
            }.CodeGen());

            //TODO: table args 2-n

            //jump to function, with return in r8.0
            b.Add(new Jump
            {
                target   = new AddrSExpr(name),
                callsite = FieldSRef.CallSite,
                frame    = PointerIndex.ProgConst,
            });

            // return values are in r7/r8 for use by following code

            //capture returned values
            //if (sreturn != null) b.AddRange(new SAssign { source = FieldSRef.SReturn, target = sreturn, }.CodeGen());
            //if (vreturn != null) b.AddRange(new VAssign { source = RegVRef.rVarArgs, target = (VRef)vreturn ?? RegVRef.rNull, }.CodeGen());

            return(b);
        }
        public List <Instruction> FetchToField(FieldSRef dest)
        {
            var code = new List <Instruction>();

            code.Add(new compiler.Instruction {
                opcode = Opcode.Sub,
                op1    = FieldSRef.Imm1(),
                imm1   = this,
                op2    = dest,
                dest   = dest,
                acc    = true
            });
            return(code);
        }
Beispiel #12
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);
        }
        public List <Instruction> PutFromInt(int value)
        {
            var code = new List <Instruction>();

            if (varref.IsLoaded)
            {
                code.Add(new Instruction
                {
                    opcode = Opcode.Sub,
                    imm1   = new IntSExpr(value),
                    op1    = FieldSRef.Imm1(),
                    op2    = this,
                    dest   = this,
                    acc    = true,
                });
            }
            else
            {
                code.AddRange(this.varref.FetchToReg(RegVRef.rScratchTab));

                var t = this.InRegister(RegVRef.rScratchTab);
                code.Add(new Instruction
                {
                    opcode = Opcode.Sub,
                    imm1   = new IntSExpr(value),
                    op1    = FieldSRef.Imm1(),
                    op2    = t,
                    dest   = t,
                    acc    = true,
                });

                code.AddRange(this.varref.PutFromReg(RegVRef.rScratchTab));
            }

            return(code);
        }
 public List <Instruction> PutFromField(FieldSRef src)
 {
     return(this.BaseField().PutFromField(src));
 }
 public List <Instruction> FetchToField(FieldSRef dest)
 {
     return(this.BaseField().FetchToField(dest));
 }
Beispiel #16
0
        public List <Instruction> FetchToReg(RegVRef dest)
        {
            var     code = new List <Instruction>();
            RegVRef other;

            if (dest == V1.AsReg())
            {
                other = V2.AsReg();
                if (other == null)
                {
                    other = RegVRef.rScratchTab;
                    code.AddRange(V2.FetchToReg(other));
                }
            }
            else if (dest == V2.AsReg())
            {
                other = V1.AsReg();
                if (other == null)
                {
                    other = RegVRef.rScratchTab;
                    code.AddRange(V1.FetchToReg(other));
                }
            }
            else
            {
                code.AddRange(V1.FetchToReg(dest));
                other = V2.AsReg();
                if (other == null)
                {
                    other = RegVRef.rScratchTab;
                    code.AddRange(V2.FetchToReg(other));
                }
            }

            switch (Op)
            {
            case ArithSpec.Add:
                code.Add(new Instruction {
                    opcode = Opcode.EachAddV, acc = true, op1 = other, dest = dest
                });
                break;

            case ArithSpec.Subtract:
                code.Add(new Instruction {
                    opcode = Opcode.EachMulV, acc = true, op1 = other, op2 = FieldSRef.Imm2(), imm2 = new IntSExpr(-1), dest = dest
                });
                break;

            case ArithSpec.Multiply:
                code.Add(new Instruction {
                    opcode = Opcode.VMul, op1 = dest, op2 = other, dest = dest
                });
                break;

            case ArithSpec.Divide:
                code.Add(new Instruction {
                    opcode = Opcode.VDiv, op1 = dest, op2 = other, dest = dest
                });
                break;

            default:
                throw new NotImplementedException();
            }

            return(code);
        }
        public List <Instruction> FetchToField(FieldSRef dest)
        {
            var code = new List <Instruction>();

            var f1 = S1.AsDirectField();

            if (f1 == null)
            {
                if (S1.IsConstant())
                {
                    f1 = FieldSRef.Imm1();
                }
                else
                {
                    f1 = FieldSRef.ScratchInt();
                    code.AddRange(S1.FetchToField(f1));
                }
            }

            var f2 = S2.AsDirectField();

            if (f2 == null)
            {
                if (S2.IsConstant())
                {
                    f2 = FieldSRef.Imm2();
                }
                else
                {
                    f2 = FieldSRef.ScratchInt();
                    code.AddRange(S2.FetchToField(f2));
                }
            }

            Opcode op;

            switch (Op)
            {
            case ArithSpec.Add:
                op = Opcode.Add;
                break;

            case ArithSpec.Subtract:
                op = Opcode.Sub;
                break;

            case ArithSpec.Multiply:
                op = Opcode.Mul;
                break;

            case ArithSpec.Divide:
                op = Opcode.Div;
                break;

            default:
                throw new InvalidOperationException();
            }

            var tmp = FieldSRef.ScratchInt();

            code.Add(new Instruction
            {
                opcode = op,
                op1    = f1,
                imm1   = S1.IsConstant() ? S1 : null,
                op2    = f2,
                imm2   = S2.IsConstant() ? S2 : null,
                dest   = tmp,
                acc    = true
            });

            //TODO: optimize this one day?
            code.AddRange(dest.PutFromField(tmp));

            return(code);
        }
Beispiel #18
0
        public List <Instruction> CodeGen(int truejump, int falsejump)
        {
            if (Op == CompSpec.Equal)
            {
                var b = new List <Instruction>();

                b.AddRange(V1.FetchToReg(RegVRef.rScratchTab));

                var r2 = V2.AsReg();
                if (r2 == null)
                {
                    // if V2 isn't already a register, borrow rScratchInts temporarily to fetch it
                    r2 = RegVRef.rScratchInts;
                    b.Add(new Push(RegVRef.rScratchInts));
                    b.AddRange(V2.FetchToReg(r2));
                }

                b.Add(new Instruction
                {
                    opcode = Opcode.EachMulV,
                    acc    = true,
                    dest   = RegVRef.rScratchTab,
                    op1    = r2,
                    op2    = FieldSRef.Imm2(),
                    imm2   = new IntSExpr(-1),
                });

                // restore rScratchInts if needed
                if (r2 == RegVRef.rScratchInts)
                {
                    b.Add(new Pop(RegVRef.rScratchInts));
                }
                var flag = FieldSRef.ScratchInt();

                // ensure flag is clear, in case this branch is used in a loop and is coming around again to reuse it
                b.Add(new Clear(flag));

                // set flag if every=0
                b.Add(new Instruction
                {
                    opcode = Opcode.EveryEqS2S1,
                    op1    = RegVRef.rScratchTab,
                    dest   = flag,
                    acc    = true,
                });


                b.Add(new Instruction
                {
                    opcode = Opcode.Branch,
                    op1    = flag,
                    rjmpeq = falsejump,
                    rjmplt = falsejump,                     // lt shouldn't happen at all, but...
                    rjmpgt = truejump,
                });

                return(b);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
Beispiel #19
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);
        }
 public List <Instruction> FetchToField(FieldSRef dest)
 {
     throw new NotImplementedException();
 }