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