// reg = T(L, R) static Tile makeRegisterAssignmentBinopTile <T, L, R>(Func <RegisterNode, L, R, IEnumerable <Instruction> > tileMaker) where T : BinaryOperatorNode where L : Node where R : Node { return(new Tile(typeof(AssignmentNode), new[] { makeTile <RegisterNode> (), makeTile <T> ( makeTile <L> (), makeTile <R> () ) }, (regNode, node) => { var assignment = node as AssignmentNode; var dst = assignment.Target as RegisterNode; var binop = assignment.Source as T; var l = binop.LeftOperand as L; var r = binop.RightOperand as R; var insn = new LinkedList <Instruction> (tileMaker(dst, l, r)); insn.AddLast(InstructionFactory.Move(regNode, dst)); return insn; } )); }
public static Tile Reg_Const() { return(new Tile(typeof(AssignmentNode), new[] { makeTile <RegisterNode> (), makeTile <ConstantNode <long> > () }, (regNode, node) => { var root = node as AssignmentNode; var target = root.Target as RegisterNode; var valNode = root.Source as ConstantNode <long>; if (valNode.Value == 0L) { return new [] { InstructionFactory.Xor(target, target), InstructionFactory.Move(regNode, target) }; } else { return new [] { InstructionFactory.Move(target, valNode), InstructionFactory.Move(regNode, target) }; } } )); }
// reg = T1(T2(L, M), R) static Tile makeRegisterAssignmentTriop2Tile <T1, T2, L, M, R>( Func <RegisterNode, L, M, R, IEnumerable <Instruction> > tileMaker ) where T1 : BinaryOperatorNode where T2 : BinaryOperatorNode where L : Node where M : Node where R : Node { return(new Tile(typeof(AssignmentNode), new[] { makeTile <RegisterNode> (), makeTile <T1> ( makeTile <T2> ( makeTile <L>(), makeTile <M>() ), makeTile <R>() ) }, (regNode, node) => { var assignment = node as AssignmentNode; var dst = assignment.Target as RegisterNode; var t1 = assignment.Source as T1; var t2 = t1.LeftOperand as T2; var l = t2.LeftOperand as L; var m = t2.RightOperand as M; var r = t1.RightOperand as R; var insn = new LinkedList <Instruction> (tileMaker(dst, l, m, r)); insn.AddLast(InstructionFactory.Move(regNode, dst)); return insn; } )); }
public static Tile Plus_Reg() { return(makeUnopTile <UnaryPlusOperatorNode, RegisterNode> ( (regNode, root, left) => new [] { InstructionFactory.Move(regNode, left) } )); }
public static Tile ConstReg() { return(makeBinopTile <LogAndOperatorNode, ConstantNode <long>, RegisterNode> ( (regNode, left, right) => left.Value == 0L ? new[] { InstructionFactory.Xor(regNode, regNode) } // l == 0 -> all = 0 : new[] { InstructionFactory.Move(regNode, right) } // l != 0 -> all = r )); }
public static Tile RegConst() { return(makeBinopTile <LogAndOperatorNode, RegisterNode, ConstantNode <long> > ( (regNode, left, right) => right.Value == 0L ? new[] { InstructionFactory.Xor(regNode, regNode) } // r == 0 -> all = 0 : new[] { InstructionFactory.Move(regNode, left) } // r != 0 -> all = l )); }
public static Tile Dec_Reg() { return(makeUnopTile <DecOperatorNode, RegisterNode> ( (regNode, root, left) => new [] { InstructionFactory.Dec(left), InstructionFactory.Move(regNode, left) } )); }
public static Tile ConstTile <T>() { return(new Tile(typeof(ConstantNode <T>), new Tile[] { }, (regNode, node) => new[] { InstructionFactory.Move(regNode, node as ConstantNode <T>) } )); }
public static Tile Neg_Reg() { return(makeUnopTile <NegOperatorNode, RegisterNode> ( (regNode, root, left) => new [] { InstructionFactory.Move(regNode, left), InstructionFactory.Neg(regNode) } )); }
public static Tile RegReg() { return(makeBinopTile <MulOperatorNode, RegisterNode, RegisterNode> ( (regNode, left, right) => new[] { InstructionFactory.Move(Target.RAX, left), // RAX = left InstructionFactory.Mul(right), // RDX:RAX = left * right InstructionFactory.Move(regNode, Target.RAX) // result = RAX } )); }
static Tile makeBinopConstRegTile <T, C>(Func <RegisterNode, RegisterNode, Instruction> specificInsn) where T : BinaryOperatorNode { return(makeBinopTile <T, ConstantNode <C>, RegisterNode> ( (regNode, left, right) => new[] { InstructionFactory.Move(regNode, left), specificInsn(regNode, right) } )); }
public static Tile ConstReg <T>() { return(makeBinopTile <ModOperatorNode, ConstantNode <T>, RegisterNode> ( (regNode, left, right) => new[] { InstructionFactory.Xor(Target.RDX, Target.RDX), // RDX = 0 InstructionFactory.Move(Target.RAX, left), // RDX:RAX = left InstructionFactory.Div(right), // RDX = left % right InstructionFactory.Move(regNode, Target.RDX) // result = RDX } )); }
public static Tile RegConst <T>() { return(makeBinopTile <DivOperatorNode, RegisterNode, ConstantNode <T> > ( (regNode, left, right) => new[] { InstructionFactory.Xor(Target.RDX, Target.RDX), // RDX = 0 InstructionFactory.Move(Target.RAX, left), // RDX:RAX = left InstructionFactory.Move(regNode, right), // reg = rigth InstructionFactory.Div(regNode), // RAX = left / reg = left / right InstructionFactory.Move(regNode, Target.RAX) // result = RAX } )); }
public static Tile RegReg() { // l = 0 -> first instruction sets reg to 0 // r = 0 but l > 0 -> fourth instruction sets reg to 0 // l > 0 and r > 0 -> first instruction sets reg = l > 0 and nothing changes return(makeBinopTile <LogAndOperatorNode, RegisterNode, RegisterNode> ( (regNode, left, right) => new[] { InstructionFactory.Move(regNode, left), // reg = left InstructionFactory.Xor(left, left), // left = 0 InstructionFactory.Cmp(right, left), // if right == 0 InstructionFactory.Cmove(regNode, left) // then reg = 0 } )); }
public static Tile Reg_Reg() { return(new Tile(typeof(AssignmentNode), new[] { makeTile <RegisterNode> (), makeTile <RegisterNode> () }, (regNode, node) => { var root = node as AssignmentNode; var target = root.Target as RegisterNode; var source = root.Source as RegisterNode; return new [] { InstructionFactory.Move(target, source), InstructionFactory.Move(regNode, target) }; } )); }
public static Tile MemReg_Reg() { return(new Tile(typeof(AssignmentNode), new[] { makeTile <MemoryNode> ( makeTile <RegisterNode> () ), makeTile <RegisterNode> () }, (regNode, node) => { var root = node as AssignmentNode; var mem = root.Target as MemoryNode; var dst = mem.Address as RegisterNode; var src = root.Source as RegisterNode; return new[] { InstructionFactory.MoveToMemory(dst, src), InstructionFactory.Move(regNode, src) }; } )); }
static IEnumerable <Instruction> EffectiveMultiplication(RegisterNode dst, RegisterNode mul_reg, ConstantNode <long> mul_val) { switch (mul_val.Value) { case 2L: case 4L: case 8L: return(new [] { InstructionFactory.Lea_Mul(dst, mul_reg, mul_val) }); case 3L: case 5L: case 9L: var tmp_val = new ConstantNode <long> (mul_val.Value - 1L); return(new [] { InstructionFactory.Lea_MulAdd(dst, mul_reg, tmp_val, mul_reg) }); case 1L: return(new [] { InstructionFactory.Move(dst, mul_reg) }); case 0L: return(new [] { InstructionFactory.Xor(dst, dst) }); default: // dst = mul_reg * mul_val return(new [] { InstructionFactory.Move(Target.RAX, mul_val), // RAX = mul_val InstructionFactory.Mul(mul_reg), // RDX:RAX = mul_reg * mul_val InstructionFactory.Move(dst, Target.RAX) // dst = RAX }); } }
public static Tile Reg_RegRegConstConst() { return(new Tile(typeof(AssignmentNode), new[] { makeTile <RegisterNode> (), makeTile <AddOperatorNode>( makeTile <AddOperatorNode>( makeTile <RegisterNode>(), makeTile <MulOperatorNode> ( makeTile <RegisterNode> (), makeTile <ConstantNode <long> > () ) ), makeTile <ConstantNode <long> >() ) }, (regNode, node) => { var assignment = node as AssignmentNode; var dst = assignment.Target as RegisterNode; var add1 = assignment.Source as AddOperatorNode; var add2 = add1.LeftOperand as AddOperatorNode; var reg1 = add2.LeftOperand as RegisterNode; var mul = add2.RightOperand as MulOperatorNode; var mul_reg = mul.LeftOperand as RegisterNode; var mul_val = mul.RightOperand as ConstantNode <long>; var val2 = add1.RightOperand as ConstantNode <long>; return new [] { new Instruction( map => string.Format("lea {0}, [{1}+{2}*{3}+{4}]", map [dst], map [reg1], map[mul_reg], mul_val.Value, val2.Value), use(dst, mul_reg), define(dst)), InstructionFactory.Move(regNode, dst) }; } )); }
// reg1 = reg2 - const public static Tile Reg_SubConst() { return(new Tile(typeof(AssignmentNode), new[] { makeTile <RegisterNode> (), makeTile <SubOperatorNode> ( makeTile <RegisterNode> (), makeTile <ConstantNode <long> > () ) }, (regNode, node) => { var root = node as AssignmentNode; var reg1 = root.Target as RegisterNode; var subop = root.Source as SubOperatorNode; var reg2 = subop.LeftOperand as RegisterNode; var val = subop.RightOperand as ConstantNode <long>; // reg = reg - 1 -> reg-- if (reg1 == reg2 && val.Value == 1L) { return new[] { InstructionFactory.Dec(reg1), InstructionFactory.Move(regNode, reg1) }; } else { return new[] { InstructionFactory.Move(reg1, reg2), // r = left InstructionFactory.Sub(reg1, val), // r = left - right InstructionFactory.Move(regNode, reg1) }; } } )); }