public override bool Emit(EmitContext ec) { Expression.EmitToStack(ec); ec.EmitComment(Target + "=" + Expression.CommentString()); variable.EmitFromStack(ec); return(true); }
public override bool LoadEffectiveAddress(EmitContext ec) { ec.EmitComment("AddressOf Reference @BP+" + Offset); ec.EmitInstruction(new Mov() { DestinationReg = EmitContext.SI, SourceIsIndirect = true, Size = 16, SourceReg = EmitContext.BP, SourceDisplacement = Offset }); ec.EmitPush(EmitContext.SI); return(true); }
public override bool ValueOfStackAccess(EmitContext ec, int off) { if (ReferenceType == ReferenceKind.Field) { ec.EmitComment("ValueOf Access Field "); ec.EmitInstruction(new Mov() { DestinationReg = EmitContext.SI, SourceIsIndirect = true, Size = 16, SourceRef = ElementReference.New(Signature.ToString()) }); ec.EmitPop(EmitContext.SI, 16, true, off); } else if (ReferenceType == ReferenceKind.LocalVariable) { ec.EmitComment("ValueOf Stack Access @BP" + Offset); ec.EmitInstruction(new Mov() { DestinationReg = EmitContext.SI, SourceIsIndirect = true, Size = 16, SourceReg = EmitContext.BP, SourceDisplacement = Offset }); ec.EmitPop(EmitContext.SI, 16, true, off); } else if (ReferenceType == ReferenceKind.Register) { ec.EmitComment("ValueOf Stack Access @" + Register.ToString() + Offset); ec.EmitInstruction(new Mov() { DestinationReg = EmitContext.SI, SourceIsIndirect = true, Size = 16, SourceReg = Register, SourceDisplacement = Offset }); ec.EmitPop(EmitContext.SI, 16, true, off); } else { ec.EmitComment("ValueOf Access Stack @BP+" + Offset); ec.EmitInstruction(new Mov() { DestinationReg = EmitContext.SI, SourceIsIndirect = true, Size = 16, SourceReg = EmitContext.BP, SourceDisplacement = Offset }); ec.EmitPop(EmitContext.SI, 16, true, off); } return(true); }
public override bool LoadEffectiveAddress(EmitContext ec) { if (ReferenceType == ReferenceKind.Field) { ec.EmitComment("AddressOf Field "); ec.EmitInstruction(new Lea() { DestinationReg = EmitContext.SI, SourceIsIndirect = true, SourceDisplacement = Offset, Size = 16, SourceRef = ElementReference.New(Signature.ToString()) }); ec.EmitPush(EmitContext.SI); } else if (ReferenceType == ReferenceKind.LocalVariable) { ec.EmitComment("AddressOf @BP" + Offset); ec.EmitInstruction(new Lea() { DestinationReg = EmitContext.SI, SourceIsIndirect = true, Size = 16, SourceReg = EmitContext.BP, SourceDisplacement = Offset }); ec.EmitPush(EmitContext.SI); } else if (ReferenceType == ReferenceKind.Register) { ec.EmitComment("AddressOf @" + Register.ToString() + Offset); ec.EmitInstruction(new Lea() { DestinationReg = EmitContext.SI, SourceIsIndirect = true, Size = 16, SourceReg = Register, SourceDisplacement = Offset }); ec.EmitPush(EmitContext.SI); } else { ec.EmitComment("AddressOf @BP+" + Offset); ec.EmitInstruction(new Lea() { DestinationReg = EmitContext.SI, SourceIsIndirect = true, Size = 16, SourceReg = EmitContext.BP, SourceDisplacement = Offset }); ec.EmitPush(EmitContext.SI); } return(true); }
public override bool EmitFromStack(EmitContext ec) { ec.EmitComment("Pop Reference Parameter @BP " + Offset); if (InitialIndex != Offset) { BaseEmitter.Offset = InitialIndex; return(BaseEmitter.ValueOfStackAccess(ec, Offset - InitialIndex)); } else { BaseEmitter.Offset = Offset; return(BaseEmitter.ValueOfStack(ec)); } }
/// <summary> /// Emit code /// </summary> /// <returns>Success or fail</returns> public override bool Emit(EmitContext ec) { if (Expression is IntegralExpression) { EmitIfConstant(ec); } else { // emit expression branchable ec.EmitComment("if-expression evaluation"); Expression.EmitBranchable(ec, Else, false); ec.EmitComment("(" + Expression.CommentString() + ") is true"); TrueStatement.Emit(ec); ec.EmitInstruction(new Jump() { DestinationLabel = ExitIf.Name }); ec.MarkLabel(Else); ec.EmitComment("Else "); FalseStatement.Emit(ec); ec.MarkLabel(ExitIf); } return(true); }
public override bool ValueOfStack(EmitContext ec) { ec.EmitComment("ValueOf Reference Stack @BP+" + Offset); ec.EmitInstruction(new Mov() { DestinationReg = EmitContext.DI, SourceIsIndirect = true, Size = 16, SourceReg = EmitContext.BP, SourceDisplacement = Offset }); ec.EmitInstruction(new Mov() { DestinationReg = EmitContext.SI, SourceIsIndirect = true, Size = 16, SourceReg = EmitContext.DI }); ec.EmitPop(EmitContext.SI, 16, true); return(true); }
public override bool EmitToStack(EmitContext ec) { if (ReferenceType == ReferenceKind.Field) { ec.EmitComment("Push Field @" + Signature.ToString() + " " + Offset); ec.EmitInstruction(new Push() { DestinationRef = ElementReference.New(Signature.ToString()), DestinationDisplacement = Offset, DestinationIsIndirect = true, Size = 16 }); } else if (ReferenceType == ReferenceKind.LocalVariable) { ec.EmitComment("Push Var @BP" + Offset); ec.EmitInstruction(new Push() { DestinationReg = EmitContext.BP, DestinationDisplacement = Offset, DestinationIsIndirect = true, Size = 16 }); } else if (ReferenceType == ReferenceKind.Register) { ec.EmitComment("Push Var @" + Register.ToString() + Offset); ec.EmitInstruction(new Push() { DestinationReg = Register, DestinationDisplacement = Offset, DestinationIsIndirect = true, Size = 16 }); } else { ec.EmitComment("Push Parameter @BP " + Offset); ec.EmitInstruction(new Push() { DestinationReg = EmitContext.BP, Size = 16, DestinationDisplacement = Offset, DestinationIsIndirect = true }); } return(true); }
public override bool EmitToStack(EmitContext ec) { ec.EmitComment("Push Reference Parameter @ " + BaseEmitter.ToString() + " " + InitialIndex.ToString() + " " + Offset); if (InitialIndex != Offset) { BaseEmitter.Offset = InitialIndex; return(BaseEmitter.ValueOfAccess(ec, Offset - InitialIndex)); } else { BaseEmitter.Offset = Offset; return(BaseEmitter.ValueOf(ec)); } }
/// <summary> /// Emit code /// </summary> /// <returns>Success or fail</returns> public override bool Emit(EmitContext ec) { foreach (var variableDeclaration in Variables) { variableDeclaration.Emit(ec); } foreach (var methodDeclaration in Methods) { methodDeclaration.Emit(ec); } ec.EmitComment("Entry Point"); Block.Emit(ec); return(base.Emit(ec)); }
public override bool Emit(EmitContext ec) { Expression.EmitToStack(ec); ec.EmitComment("!" + Expression.CommentString()); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Not() { DestinationReg = RegistersEnum.AX, Size = 80 }); ec.EmitInstruction(new And() { DestinationReg = RegistersEnum.AX, SourceValue = 1, Size = 80 }); ec.EmitPush(RegistersEnum.AX); return(true); }
public bool PopAllToRef(EmitContext ec, ElementReference re, int size, int offset = 0) { ec.EmitComment("Pop Field [TypeOf " + re.Name + "] Offset=" + offset); int s = size / 2; for (int i = 0; i < s; i++) { ec.EmitInstruction(new Pop() { DestinationRef = re, DestinationDisplacement = offset + 2 * i, DestinationIsIndirect = true, Size = 16 }); } if (size % 2 != 0) { ec.EmitPop(RegistersEnum.DX); ec.EmitInstruction(new Mov() { DestinationRef = re, DestinationDisplacement = offset - 1 + size, DestinationIsIndirect = true, Size = 8, SourceReg = RegistersEnum.DL }); } return(true); }
public bool PushAllFromRef(EmitContext ec, ElementReference re, int size, int offset = 0) { ec.EmitComment("Push Field [TypeOf " + re.Name + "] Offset=" + offset); int s = size / 2; if (size % 2 != 0) { ec.EmitInstruction(new Mov() { DestinationReg = RegistersEnum.DL, SourceRef = re, SourceDisplacement = offset + size - 1, SourceIsIndirect = true, Size = 8 }); ec.EmitPush(RegistersEnum.DX); } for (int i = s - 1; i >= 0; i--) { ec.EmitInstruction(new Push() { DestinationRef = re, DestinationDisplacement = offset + 2 * i, DestinationIsIndirect = true, Size = 16 }); } return(true); }
/// <summary> /// Emit code /// </summary> /// <returns>Success or fail</returns> public override bool Emit(EmitContext ec) { Label mlb = ec.DefineLabel(Method.Signature.ToString()); mlb.Method = true; ec.MarkLabel(mlb); ec.EmitComment("Method: Name = " + Method.Name); // create stack frame ec.EmitComment("create stackframe"); ec.EmitInstruction(new Push() { DestinationReg = EmitContext.BP, Size = 80 }); ec.EmitInstruction(new Mov() { DestinationReg = EmitContext.BP, SourceReg = EmitContext.SP, Size = 80 }); // allocate variables ushort size = 0; List <VarSpec> locals = ec.CurrentResolve.GetLocals(); foreach (VarSpec v in locals) { size += 2; } if (size != 0) // no allocation { ec.EmitInstruction(new Sub() { DestinationReg = EmitContext.SP, SourceValue = size, Size = 80 }); } //EMit params var parameters = new List <ParameterSpec>(); if (Parameters.Count > 0) { ec.EmitComment("Parameters Definitions"); foreach (var par in Parameters) { ec.EmitComment("Parameter " + par.Name + " @BP" + par.ParameterName.StackIdx); parameters.Add(par.ParameterName); } } if (locals.Count > 0) { ec.EmitComment("Local Vars Definitions"); foreach (VarSpec v in locals) { ec.EmitComment("Local " + v.Name + " @BP" + v.VariableStackIndex); } } ec.EmitComment("Block"); // Emit Code if (Block != null) { Block.Emit(ec); } ec.EmitComment("return label"); // Return Label ec.MarkLabel(ec.DefineLabel(Method.Signature + "_ret")); // Destroy Stack Frame ec.EmitComment("destroy stackframe"); ec.EmitInstruction(new Leave()); // ret ccvh.EmitDecl(ec, ref parameters, CallingConventions.StdCall); return(true); }
/// <summary>Emit code</summary> /// <returns>Success or fail</returns> public override bool Emit(EmitContext ec) { Left.EmitToStack(ec); //ec.MarkOptimizable(); // Marks last instruction as last push Right.EmitToStack(ec); //ec.MarkOptimizable(); // Marks last instruction as last push ec.EmitComment(Left.CommentString() + " " + GetOperatorString() + " " + Right.CommentString()); if (Operator == Operators.Add) { ec.EmitPop(RegistersEnum.CX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Add() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.CX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitPush(RegistersEnum.AX); } else if (Operator == Operators.Sub) { ec.EmitPop(RegistersEnum.CX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Sub() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.CX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitPush(RegistersEnum.AX); } else if (Operator == Operators.Mul) { ec.EmitPop(RegistersEnum.CX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Multiply() { DestinationReg = RegistersEnum.CX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitPush(RegistersEnum.CX); } else if (Operator == Operators.Div) { ec.EmitPop(RegistersEnum.CX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Xor() { DestinationReg = EmitContext.D, SourceReg = EmitContext.D, Size = 80 }); ec.EmitInstruction(new Divide() { DestinationReg = RegistersEnum.CX, Size = 80 }); ec.EmitPush(RegistersEnum.CX); } else if (Operator == Operators.Mod) { ec.EmitPop(RegistersEnum.CX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Xor() { DestinationReg = EmitContext.D, SourceReg = EmitContext.D, Size = 80 }); ec.EmitInstruction(new Divide() { DestinationReg = RegistersEnum.CX, Size = 80 }); ec.EmitInstruction(new Mov() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.DX, Size = 80 }); ec.EmitPush(RegistersEnum.AX); } else if (Operator == Operators.And) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new And() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitPush(RegistersEnum.AX); } else if (Operator == Operators.Or) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Or() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitPush(RegistersEnum.AX); } // Comparison else if (Operator == Operators.Equal) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Compare() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitBoolean(RegistersEnum.AL, ConditionalTestEnum.Equal, ConditionalTestEnum.NotEqual); ec.EmitPush(RegistersEnum.AX); } else if (Operator == Operators.NotEqual) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Compare() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitBoolean(RegistersEnum.AL, ConditionalTestEnum.NotEqual, ConditionalTestEnum.Equal); ec.EmitPush(RegistersEnum.AX); } else if (Operator == Operators.LT) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Compare() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitBoolean(RegistersEnum.AL, ConditionalTestEnum.LessThan, ConditionalTestEnum.GreaterThanOrEqualTo); ec.EmitPush(RegistersEnum.AX); } else if (Operator == Operators.GT) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Compare() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitBoolean(RegistersEnum.AL, ConditionalTestEnum.GreaterThan, ConditionalTestEnum.LessThanOrEqualTo); ec.EmitPush(RegistersEnum.AX); } else if (Operator == Operators.GTE) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Compare() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitBoolean(RegistersEnum.AL, ConditionalTestEnum.GreaterThanOrEqualTo, ConditionalTestEnum.LessThan); ec.EmitPush(RegistersEnum.AX); } else if (Operator == Operators.LTE) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Compare() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitBoolean(RegistersEnum.AL, ConditionalTestEnum.LessThanOrEqualTo, ConditionalTestEnum.GreaterThan); ec.EmitPush(RegistersEnum.AX); } return(base.Emit(ec)); }
public override bool EmitBranchable(EmitContext ec, Label truecase, bool v) { Left.EmitToStack(ec); //ec.MarkOptimizable(); // Marks last instruction as last push Right.EmitToStack(ec); //ec.MarkOptimizable(); // Marks last instruction as last push ec.EmitComment(Operator + " " + Left.CommentString() + ", " + Right.CommentString()); if (Operator == Operators.Equal) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Compare() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitBooleanBranch(v, truecase, ConditionalTestEnum.Equal, ConditionalTestEnum.NotEqual); } else if (Operator == Operators.NotEqual) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Compare() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitBooleanBranch(v, truecase, ConditionalTestEnum.NotEqual, ConditionalTestEnum.Equal); } else if (Operator == Operators.LT) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Compare() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitBooleanBranch(v, truecase, ConditionalTestEnum.LessThan, ConditionalTestEnum.GreaterThanOrEqualTo); } else if (Operator == Operators.GT) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Compare() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitBooleanBranch(v, truecase, ConditionalTestEnum.GreaterThan, ConditionalTestEnum.LessThanOrEqualTo); } else if (Operator == Operators.GTE) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Compare() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitBooleanBranch(v, truecase, ConditionalTestEnum.GreaterThanOrEqualTo, ConditionalTestEnum.LessThan); } else if (Operator == Operators.LTE) { ec.EmitPop(RegistersEnum.BX); ec.EmitPop(RegistersEnum.AX); ec.EmitInstruction(new Compare() { DestinationReg = RegistersEnum.AX, SourceReg = RegistersEnum.BX, Size = 80, OptimizingBehaviour = OptimizationKind.PPO }); ec.EmitBooleanBranch(v, truecase, ConditionalTestEnum.LessThanOrEqualTo, ConditionalTestEnum.GreaterThan); } // jumps ec.EmitBooleanBranch(v, truecase, ConditionalTestEnum.Equal, ConditionalTestEnum.NotEqual); return(true); }