public List <Instruction> CodeGen() { var code = new List <Instruction>(); var srcreg = source.AsReg(); var tgtreg = target.AsReg(); if (srcreg == null || (srcreg != null && tgtreg != null)) { code.AddRange(source.FetchToReg(tgtreg ?? RegVRef.rScratchTab)); } if (tgtreg == null) { code.AddRange(target.PutFromReg(srcreg ?? RegVRef.rScratchTab)); } 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> 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> 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); }