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); }
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); }
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); }
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); }
public Clear(FieldSRef field) { if (field.AsDirectField() == null) { throw new ArgumentOutOfRangeException("field", "can only be a register field"); } this.field = field; }
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)); } }
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); }
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)); }
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); }
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(); } }
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(); }