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> 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> 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); }