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