using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Anonymus.x86
{
public enum GetNodePosMode
{
Default,
StrOnly,
RetNull,
}
public class x86Compiler : Compiler
{
public x86Architecture Arch;
public x86Compiler(x86Architecture Arch, CompilerState State)
: base(State)
{
this.Arch = Arch;
}
public override string JumpStr(string Label)
{
return "\tjmp " + Label + "\n";
}
public override string LabelStr(string Label)
{
return Label + ":\n";
}
public override void DeclareUnknownBytes(int Bytes)
{
var Size = 8;
while (Size > 0)
{
if (Bytes >= Size)
{
var Ins = "\t" + x86Architecture.GetDataTypeString(Size) + " ?";
var Count = Bytes / Size;
for (var i = 1; i < Count; i++)
Ins += ", ?";
Bytes = Bytes % Size;
Append(Ins + "\n");
}
Size /= 2;
}
}
public unsafe override void Declare(Type Type, ConstData Data)
{
var TypeStr = x86Architecture.GetDataTypeString(Type.Size);
if (Data == null)
{
Append("\t" + TypeStr + " ?\n");
return;
}
var DefStr = Data.GetDefString();
if (Type is FloatType && Type.Size == 4)
{
var FloatData = (float)Data.DoubleData;
DefStr = (*(uint*)(&FloatData)).ToString();
}
Append("\t" + TypeStr + " " + DefStr + "\n");
}
public override void DeclareLabelPtr(string Label)
{
var TypeStr = x86Architecture.GetDataTypeString(Arch.RegSize);
Append("\t" + TypeStr + " " + Label + "\n");
}
public override void DeclareLabelPtr(int Label)
{
var TypeStr = x86Architecture.GetDataTypeString(Arch.RegSize);
Append("\t" + TypeStr + " _" + Label + "\n");
}
void MoveData(x86MoveCondBranch Branch, string Cond = null)
{
MoveData(Branch.Dst, Branch.Src, Branch.Scope, Branch.SrcSigned, Cond);
}
public override void GetConditionCode(ExpressionNode Condition, CondBranch Then,
CondBranch Else, bool ThenAllPathJumpAway = false, bool LinkedNodesCalced = false,
int NextLabel = -1)
{
var Data = Condition.ArchData as x86NodeData;
var OpNode = Condition as OpExpressionNode;
if (OpNode == null) throw new Exception("ERROR");
var Op = OpNode.Operator;
var Ch = OpNode.Children;
if (!LinkedNodesCalced) CalcLinkedNodes(Condition);
if (ConditionalMove(Then, Else, Data, Op, Ch)) return;
if (JumpCondition(OpNode, Then, Else)) return;
StdCondition(OpNode, Then, Else, ThenAllPathJumpAway, NextLabel);
}
private bool JumpCondition(OpExpressionNode OpNode, CondBranch Then, CondBranch Else)
{
var JumpThen = Then as JumpCodeBranch;
var JumpElse = Else as JumpCodeBranch;
if (JumpThen == null && JumpElse == null) return false;
var ThenLbl = JumpThen == null ? State.NextLabelIndex : JumpThen.Label;
var ElseLbl = JumpElse == null ? State.NextLabelIndex : JumpElse.Label;
var Op = OpNode.Operator;
var Last = Op == Operator.Or;
if (JumpThen != null) Last = !Last;
CalcCondAsmCode(OpNode, ThenLbl, ElseLbl, Operator.Nothing, Last, true);
if (JumpThen == null)
{
Label(ThenLbl);
GetBranchCode(Then);
}
else if (JumpElse == null)
{
Label(ElseLbl);
GetBranchCode(Else);
}
else
{
GetBranchCode(Else);
}
return true;
}
private void StdCondition(OpExpressionNode OpNode, CondBranch Then, CondBranch Else,
bool ThenAllPathJumpAway, int NextLabel)
{
var Op = OpNode.Operator;
var ThenLabel = State.NextLabelIndex;
var ElseLabel = State.NextLabelIndex;
var NextLblCreated = false;
if (NextLabel == -1)
{
NextLabel = State.NextLabelIndex;
NextLblCreated = true;
}
CalcCondAsmCode(OpNode, ThenLabel, ElseLabel, Operator.Nothing,
Op == Operator.Or, true);
GetLblsCode(OpNode, ThenLabel, ElseLabel,
NextLabel, Then, Else, ThenAllPathJumpAway);
if (NextLblCreated) Label(NextLabel);
}
private bool ConditionalMove(CondBranch Then, CondBranch Else, x86NodeData Data, Operator Op, List<ExpressionNode> Ch)
{
if (Operators.IsRelEqualityOp(Op) && Then is x86MoveCondBranch &&
(Else == null || Else is x86MoveCondBranch))
{
var ThenB = Then as x86MoveCondBranch;
var ElseB = Else as x86MoveCondBranch;
#if DEBUG
if (ThenB.Src.Size != ThenB.Dst.Size || ElseB.Src.Size != ElseB.Dst.Size)
throw new Exception("ERROR");
#endif
if (ElseB == null || ThenB.Dst.IsEqual(ElseB.Dst))
{
if (ThenB.Src.IsEqual(ThenB.Dst))
{
Op = Operators.NegateOp(Op);
var Str = GetCmpCode(Ch, Data.Scope.TmpReg, Op);
MoveData(ElseB, Str);
}
else
{
var Str = GetCmpCode(Ch, Data.Scope.TmpReg, Op);
if (Else != null) MoveData(ElseB);
MoveData(ThenB, Str);
}
return true;
}
}
return false;
}
void GetBranchCode(CondBranch Branch)
{
if (Branch is CodeCondBranch)
{
var CodeB = Branch as CodeCondBranch;
CodeB.GetCode(this);
}
else if (Branch is JumpCodeBranch)
{
var JumpB = Branch as JumpCodeBranch;
Jump(JumpB.Label);
}
else if (Branch is x86MoveCondBranch)
{
MoveData(Branch as x86MoveCondBranch);
}
}
void GetLblsCode(ExpressionNode Condition, int ThenLabel, int ElseLabel,
int NextLabel, CondBranch Then, CondBranch Else, bool ThenAllPathJumpAway)
{
if (Then != null)
{
Label(ThenLabel);
GetBranchCode(Then);
}
if (Else != null)
{
var ElseCompiler = Arch.CreateCompiler(State, Container) as x86Compiler;
ElseCompiler.GetBranchCode(Else);
if (ElseCompiler.Instructions.Count > 0)
{
if (!ThenAllPathJumpAway) Jump(NextLabel);
Label(ElseLabel);
Append(ElseCompiler);
return;
}
}
Label(ElseLabel);
}
private string GetCmpCode(x86DataPosition Dst, x86DataPosition Src, x86DataPosition TmpReg,
Operator Instruction, Type DstType, Type SrcType)
{
string StrInstruction;
if (DstType is FloatType)
{
FloatOp("comp", Src, SrcType is FloatType, false);
Append("\tfnstsw ax\n");
Append("\tsahf\n");
StrInstruction = x86Architecture.OpInstruction(Instruction, false);
}
else
{
StrInstruction = x86Architecture.OpInstruction(Instruction, DstType is SignedType);
StdMem2MemOp("\tcmp ", Dst, Src, TmpReg);
}
return StrInstruction;
}
private string GetCmpCode(List<ExpressionNode> Ch, x86DataPosition TmpReg, Operator Instruction)
{
var Type = Ch[0].Type;
if (Type is FloatType)
{
GetNodePos_Float(Ch[0], LoadIds: true);
return GetCmpCode(null, GetNodePos_Float(Ch[1]),
TmpReg, Instruction, Type, Ch[1].Type);
}
else
{
var Dst = GetNodePos(Ch[0]);
var Src = GetNodePos(Ch[1]);
return GetCmpCode(Dst, Src, TmpReg,
Instruction, Type, Ch[1].Type);
}
}
public override void CalcCondAsmCode(ExpressionNode Node, int Then, int Else,
Operator PrewOp, bool Last, bool LinkedNodesCalced = false)
{
if (!LinkedNodesCalced) CalcLinkedNodes(Node);
var OpNode = Node as OpExpressionNode;
if (OpNode == null || !Operators.IsBoolRetOp(OpNode.Operator))
{
var True = new ConstExpressionNode(Node.Type, true, null);
var NCh = new List<ExpressionNode>() { Node, True };
OpNode = new OpExpressionNode(Operator.Equal, NCh, null);
}
var Op = OpNode.Operator;
var Ch = OpNode.Children;
var Data = Node.ArchData as x86NodeData;
if (!Operators.IsLogicalOp(Op))
{
var Lbl = -1;
var Ins = Operator.Nothing;
if (PrewOp == Operator.And || PrewOp == Operator.Nothing)
{
Lbl = Last ? Then : Else;
Ins = Last ? Op : Operators.NegateOp(Op);
}
else if (PrewOp == Operator.Or)
{
Lbl = Last ? Else : Then;
Ins = Last ? Operators.NegateOp(Op) : Op;
}
else
{
throw new Exception("ERROR");
}
/*
var Lbl = Last ? Else : Then;
var Ins = Last ? Expressions.NegateOp(Op) : Op;
*/
var InsStr = (string)null;
var Type = Ch[0].Type;
var NextCond = State.NextLabelIndex;
var TmpReg = Data.Scope.TmpReg;
if (Type.Size > Arch.RegSize && Type is NonFltNumType)
{
var Dst = GetSplPositions(GetNodePos(Ch[0]), Arch.RegSize);
var Src = GetSplPositions(GetNodePos(Ch[1]), Arch.RegSize);
var Len = Dst.Length;
if (Len != Src.Length) throw new Exception("ERROR");
for (var i = 0; i < Len - 1; i++)
{
InsStr = GetCmpCode(Dst[i], Src[i], TmpReg, Ins, Type, Ch[1].Type);
if (Ins == Operator.Equal || Ins == Operator.Nonequal)
{
Append(new x86ConditionalJump(Lbl, InsStr));
}
else
{
var Signed = i == 0 && Type is SignedType;
var Greater = x86Architecture.OpInstruction(Operator.Greater, Signed);
var Less = x86Architecture.OpInstruction(Operator.Less, Signed);
if (Ins == Operator.Less || Ins == Operator.LessEqual)
{
Append(new x86ConditionalJump(NextCond, Greater));
Append(new x86ConditionalJump(Lbl, Less));
}
else if (Ins == Operator.Greater || Ins == Operator.GreaterEqual)
{
Append(new x86ConditionalJump(Lbl, Greater));
Append(new x86ConditionalJump(NextCond, Less));
}
else
{
throw new Exception("ERROR");
}
}
}
InsStr = GetCmpCode(Dst[Len - 1], Src[Len - 1], TmpReg, Ins, Type, Ch[1].Type);
}
else
{
InsStr = GetCmpCode(Ch, TmpReg, Ins);
}
Append(new x86ConditionalJump(Lbl, InsStr));
Label(NextCond);
}
else
{
var Ch0 = Ch[0] as OpExpressionNode;
var Ch1 = Ch[1] as OpExpressionNode;
var NewLabel = State.NextLabelIndex;
var nLast0 = Ch0 != null && Ch0.Operator != Op && Operators.IsLogicalOp(Ch0.Operator);
var nLast1 = Last || (Ch1 != null && Ch1.Operator != Op && Operators.IsLogicalOp(Ch1.Operator));
if (Op == Operator.And) CalcCondAsmCode(Ch[0], NewLabel, Else, Op, nLast0);
else if (Op == Operator.Or) CalcCondAsmCode(Ch[0], Then, NewLabel, Op, nLast0);
else throw new Exception("Not implemented operator");
Label(NewLabel);
CalcCondAsmCode(Ch[1], Then, Else, Op, nLast1);
}
}
public x86DataPosition GetNodePos(ExpressionNode Node, GetNodePosMode Mode = GetNodePosMode.Default)
{
var Size = Node.Type.Size;
var OpNode = Node as OpExpressionNode;
var FuncScope = Container.FuncScope as x86FuncScopeNode;
var Data = Node.ArchData as x86NodeData;
if (Node is LinkingNode)
{
var LNode = Node as LinkingNode;
var LData = LNode.LinkedNode.ArchData as x86LinkedNodeData;
return LData.Position;
}
else if (OpNode != null)
{
var Op = OpNode.Operator;
var Ch = OpNode.Children;
var Type = OpNode.Type;
if (Op == Operator.Call)
{
if (Mode == GetNodePosMode.Default)
{
CalcLinkedNodes(OpNode);
GetCallExprCode(OpNode);
}
else if (Mode == GetNodePosMode.RetNull)
return null;
return Node.GetPosition();
}
else if (Op == Operator.Index)
{
var PtrAddr = GetNodePos(Ch[0]);
var Offset = GetNodePos(Ch[1]);
var MulBy = (Ch[1].ArchData as x86NodeData).MulBy;
return GetIndexNodePos(PtrAddr, Offset, Data.Scope.IndexReg, Mode, Size, MulBy);
}
else if (Op == Operator.Assignment)
{
if (Mode == GetNodePosMode.Default) GetExprCode(Node);
else if (Mode == GetNodePosMode.RetNull) return null;
var Ch0 = OpNode.Children[0] as IdExpressionNode;
return Ch0.Id.ArchData as x86DataPosition;
}
else if (Op == Operator.Member)
{
var TmpReg = Data.Scope.TmpReg;
var SrcPos = GetNodePos(Ch[0], Mode);
if (Ch[0].Type is ClassType)
{
var ClassType = Ch[0].Type as ClassType;
if (SrcPos is x86MemPosition)
{
Append("\tmov " + TmpReg + ", " + SrcPos + "\n");
SrcPos = TmpReg;
}
var InstanceSize = ClassType.VarSize;
SrcPos = new x86MemPosition(Arch, InstanceSize, SrcPos.ToString(), 0);
}
var Splitable = SrcPos as x86SplitablePosition;
if (Splitable == null) throw new Exception("ERROR");
var RId = Ch[1] as IdExpressionNode;
if (RId == null) throw new Exception("ERROR");
if (RId.Id is ConstructorFunction)
{
return RId.Id.ArchData as x86DataPosition;
}
else if (RId.Id is MemberVariable)
{
var MemVar = RId.Id as MemberVariable;
return Splitable.GetPart(MemVar.Offset, Size);
}
else if (RId.Id is MemberFunction)
{
var MemFunc = RId.Id as MemberFunction;
var FuncPtrs = Splitable.GetPart(0, Size);
Append("\tmov " + TmpReg + ", " + FuncPtrs + "\n");
return new x86MemPosition(Arch, Arch.RegSize, TmpReg.ToString(), MemFunc.Offset);
}
else
{
throw new Exception("ERROR");
}
}
}
else if (Node is ConstExpressionNode)
{
var ConstNode = Node as ConstExpressionNode;
return new x86ConstPosition(Arch, Size, ConstNode.Value, 0);
}
else if (Node is IdExpressionNode)
{
var RIdNode = Node as IdExpressionNode;
return RIdNode.Id.ArchData as x86DataPosition;
}
else if (Node is CastExpressionNode && Node.Type is NonFltNumType && Data.Index == -1)
{
var CastNode = Node as CastExpressionNode;
var Ch = CastNode.Child;
var Src = GetNodePos(Ch, Mode);
if (Src == null) return null;
if (Src.Size <= 8)
{
var Ret = Node.GetPosition();
if (Mode == GetNodePosMode.Default)
MoveData(Ret, Src, Data.Scope, Ch.Type is SignedType);
else if (Mode == GetNodePosMode.RetNull) return null;
return Ret;
}
else
{
throw new NotImplementedException();
}
}
if (Mode == GetNodePosMode.Default) GetExprCode(Node);
else if (Mode == GetNodePosMode.RetNull) return null;
return Node.GetPosition();
}
private x86DataPosition GetIndexNodePos(x86DataPosition PtrAddr, x86DataPosition Offset,
x86DataPosition IndexReg, GetNodePosMode Mode, int Size, int MulBy = 1)
{
if (PtrAddr.Size != Offset.Size)
throw new Exception("ERROR");
x86IndexPosition Ret = null;
if (PtrAddr is x86MemPosition)
{
if (Mode == GetNodePosMode.RetNull) return null;
if (IndexReg == null) throw new Exception("ERROR");
Ret = new x86IndexPosition(this, Size, 0, null, PtrAddr, IndexReg);
}
if (Offset is x86ConstPosition)
{
var ConstOffset = Offset as x86ConstPosition;
var o = (int)ConstOffset.Unsigned * MulBy;
if (Ret != null) { Ret.Offset = o; return Ret; }
return new x86MemPosition(Arch, Size, PtrAddr.ToString(), o);
}
else
{
var str_Offset = MulBy == 1 ? Offset.ToString() : Offset + " * " + MulBy;
if (Ret != null) { Ret.str_Offset = str_Offset; return Ret; }
return new x86MemPosition(Arch, Size, PtrAddr + " + " + str_Offset, 0);
}
}
private void GetCallExprCode(OpExpressionNode OpNode, x86DataPosition ValueTypeRet = null,
x86DataPosition Self = null, bool RefSelf = false)
{
var Data = OpNode.ArchData as x86NodeData;
var FuncScope = Container.FuncScope as x86FuncScopeNode;
var FuncData = FuncScope.ArchData as x86FuncContainerData;
var Ch = OpNode.Children;
var FuncType = Ch[0].Type as FunctionType;
var RetType = FuncType.RetType;
var RetSize = RetType.Size;
var OldPushedBytes = FuncData.FuncCallPushed;
var Accumulator = new x86RegPosition(Arch, Arch.RegSize, 0);
var AsCallParamIndex = 0;
//-------------------------------------------------------------------------------
if (Self == null)
{
var OpCh0 = Ch[0] as OpExpressionNode;
if (OpCh0 != null && OpCh0.Operator == Operator.Member)
{
var SelfNode = OpCh0.Children[0];
Self = GetNodePos(SelfNode, GetNodePosMode.StrOnly);
if (SelfNode.Type is ValueType) RefSelf = true;
}
}
var NCh = Ch;
var ParamComp = (x86Compiler)null;
if (FuncType.Conv == CallConv.AsCall)
{
ParamComp = Arch.CreateCompiler(State, Container) as x86Compiler;
NCh = Ch.ToList();
if (RetType is ValueType)
{
if (ValueTypeRet == null) throw new Exception("ERROR");
ParamComp.GetAddrOf(Arch.GetArgP(ref AsCallParamIndex, Arch.RegSize), ValueTypeRet);
ValueTypeRet = null;
}
else if (ValueTypeRet != null)
{
throw new Exception("ERROR");
}
if (Self != null)
{
var SelfPosition = Arch.GetArgP(ref AsCallParamIndex, !RefSelf ? Self.Size : Arch.RegSize);
if (!RefSelf) ParamComp.MoveData(SelfPosition, Self, Data.Scope);
else ParamComp.GetAddrOf(SelfPosition, Self);
Self = null;
}
var Types = FuncType.Params.GetTypes();
foreach (var e in Arch.EnumFirstAsCallParams(Types, AsCallParamIndex))
{
var P = FuncType.Params[e];
var Node = Ch[e + 1];
var Src = ParamComp.GetNodePos(Node);
var Dst = Arch.GetArgP(ref AsCallParamIndex, P.Type.Size);
ParamComp.MoveData(Dst, Src, Data.Scope, P.Type is SignedType);
NCh.Remove(Node);
}
}
//-------------------------------------------------------------------------------
var PreAllocatedBytes = 0;
Ch = NCh;
for (var i = Ch.Count - 1; i >= 1; i--)
{
if (PreAllocatedBytes == 0)
{
for (var j = i; j >= 1; j--)
{
var Ok = false;
if (Ch[j].Type is FloatType)
{
var nPos = GetNodePos_Float(Ch[j], GetNodePosMode.StrOnly);
if (nPos == null && !(Ch[i] is ConstExpressionNode)) Ok = true;
}
if (Ok) PreAllocatedBytes += Ch[j].Type.Size;
else break;
}
if (PreAllocatedBytes > 0)
{
Append("\tsub esp, " + PreAllocatedBytes + "\n");
FuncData.FuncCallPushed += PreAllocatedBytes;
}
}
var ChType = Ch[i].Type;
var OpCh = Ch[i] as OpExpressionNode;
if (OpCh != null && OpCh.Operator == Operator.Address)
{
GetAddrOf(Accumulator, GetNodePos(OpCh.Children[0]), true);
continue;
}
var Pos = (x86DataPosition)null;
if (ChType is FloatType)
{
Pos = GetNodePos_Float(Ch[i]);
if (Pos == null)
{
PreAllocatedBytes -= ChType.Size;
var TypeStr = x86Architecture.GetTypeString(ChType.Size);
if (PreAllocatedBytes == 0) Append("\tfstp " + TypeStr + "[esp]\n");
else Append("\tfstp " + TypeStr + "[esp + " + PreAllocatedBytes + "]\n");
continue;
}
}
if (Pos == null) Pos = GetNodePos(Ch[i]);
PushData(Pos);
}
//-------------------------------------------------------------------------------
if (ParamComp != null) Append(ParamComp);
if (FuncType.Conv != CallConv.AsCall)
{
if (Self != null)
{
if (!RefSelf) PushData(Self);
else GetAddrOf(Accumulator, Self, true);
}
if (RetType is ValueType)
{
if (ValueTypeRet == null) throw new Exception("ERROR");
GetAddrOf(Accumulator, ValueTypeRet, true);
}
else if (ValueTypeRet != null)
{
throw new Exception("ERROR");
}
}
//-------------------------------------------------------------------------------
var FPos = GetNodePos(Ch[0]);
Append("\tcall " + FPos + "\n");
if (FuncType.Conv == CallConv.CDecl)
{
var s = FuncData.FuncCallPushed - OldPushedBytes;
if (s > 0) Append("\tadd esp, " + s.ToString() + "\n");
}
FuncData.FuncCallPushed = OldPushedBytes;
}
void PushData(x86DataPosition Pos)
{
var FuncScope = Container.FuncScope as x86FuncScopeNode;
var FuncData = FuncScope.ArchData as x86FuncContainerData;
var Parts = GetSplPositions(Pos, Arch.RegSize);
for (var pi = Parts.Length - 1; pi >= 0; pi--)
{
Append("\tpush " + Parts[pi] + "\n");
FuncData.FuncCallPushed += Arch.RegSize;
}
}
void GetAddrOf(x86DataPosition Dst, x86DataPosition Pos, bool Push = false)
{
var MemPos = Pos as x86MemPosition;
if (MemPos == null || !MemPos.Ref)
throw new Exception("ERROR");
var IndexPos = Pos as x86IndexPosition;
if (IndexPos != null && Push && IndexPos.AllOffset == 0 &&
string.IsNullOrEmpty(IndexPos.str_Offset))
{
Append("\tpush " + IndexPos.Ptr + "\n");
return;
}
Pos = Pos.Extract();
if (MemPos.AllOffset != 0)
{
var OldSize = Pos.Size;
Pos.Size = 0;
Append("\tlea " + Dst + ", " + Pos + "\n");
Pos.Size = OldSize;
if (Push) Append("\tpush " + Dst + "\n");
}
else
{
if (!Push)
{
var SDst = Dst.ToString();
if (SDst != MemPos.Name)
Append("\tmov " + SDst + ", " + MemPos.Name + "\n");
return;
}
Append("\tpush " + MemPos.Name + "\n");
}
}
void CalcLinkedNodes(ExpressionNode Node)
{
if (Node.LinkedNodes != null)
{
var Data = Node.ArchData as x86NodeData;
foreach (var LNode in Node.LinkedNodes)
{
var LData = LNode.ArchData as x86LinkedNodeData;
var Src = GetNodePos(LNode.Node);
var Dst = LData.Position;
MoveData(Dst, Src, Data.Scope, LNode.Node.Type is SignedType);
}
}
}
public override void GetExprCode(ExpressionNode Node)
{
// Append("\t; " + Node.Code.String + "\n");
CalcLinkedNodes(Node);
if (Node is OpExpressionNode) GetOpExprCode(Node as OpExpressionNode);
else if (Node is CastExpressionNode) GetCastExprCode(Node as CastExpressionNode);
}
private void GetCastExprCode(CastExpressionNode CastNode)
{
var T = CastNode.Type;
if (T is FloatType) GetCastExprCode_Float(CastNode);
else if (T is BoolType) GetCastExprCode_Bool(CastNode);
else GetCastExprCode_NonFloat(CastNode);
}
private void GetCastExprCode_Bool(CastExpressionNode CastNode)
{
var Dst = CastNode.GetPosition();
var Ch = CastNode.Child;
var Data = CastNode.ArchData as x86NodeData;
if (Ch.Type == CastNode.Type)
{
if (!MoveAndOp(Dst, Ch))
MoveData(Dst, GetNodePos(Ch), Data.Scope);
}
else
{
throw new Exception("ERROR");
}
}
private void GetCastExprCode_NonFloat(CastExpressionNode CastNode)
{
var Ch = CastNode.Child;
var FuncScope = Container.FuncScope as x86FuncScopeNode;
var Data = CastNode.ArchData as x86NodeData;
var SrcSize = Ch.Type.Size;
var DstSize = CastNode.Type.Size;
var Dst = CastNode.GetPosition();
if (Ch.Type is FloatType)
{
GetNodePos_Float(Ch, LoadIds: true);
if (Dst != null) FltStore(Dst, Data.Scope, true);
}
else if (!MoveAndOp(Dst, Ch))
{
var Src = GetNodePos(Ch);
MoveData(Dst, Src, Data.Scope, Ch.Type is SignedType);
}
}
bool MoveAndOp(x86DataPosition Dst, ExpressionNode Node, bool StrOnly = false)
{
var Data = Node.ArchData as x86NodeData;
var OpNode = Node as OpExpressionNode;
if (OpNode == null) return false;
var Ch = OpNode.Children;
var Op = OpNode.Operator;
//--------------------------------------------------------------------------------------------
if (Operators.IsBoolRetOp(Op))
{
CalcLinkedNodes(Node);
if (Operators.IsRelEqualityOp(Op))
{
var Type = Ch[0].Type;
if (Type is NonFltNumType && Type.Size > Arch.RegSize)
{
GetExprCondCode_BoolRet(Node, Dst);
}
else
{
var Str = GetCmpCode(Ch, Data.Scope.TmpReg, Op);
if (Dst.Size != 1)
{
var Dst2 = Dst.Copy(1);
Append("\tset" + Str + " " + Dst2 + "\n");
Append("\tand " + Dst + ", 0xFF\n");
}
else
{
Append("\tset" + Str + " " + Dst + "\n");
}
}
}
else
{
GetExprCondCode_BoolRet(Node, Dst);
}
return true;
}
//--------------------------------------------------------------------------------------------
else if (Op == Operator.New)
{
CalcLinkedNodes(Node);
var Type = Node.Type;
if (Type is TupleType)
{
ZeroMem(Dst, Data.Scope);
return true;
}
else if (Type is StructuredType)
{
var InitVal = Type.AsmName + "_%InitVal";
var InitPos = new x86MemPosition(Arch, Type.Size, InitVal, 0);
MoveData(Dst, InitPos, Data.Scope);
if (OpNode.Children.Count > 0)
GetCallExprCode(OpNode, Self: Dst, RefSelf: true);
return true;
}
else
{
ZeroMem(Dst, Data.Scope);
return true;
}
}
//--------------------------------------------------------------------------------------------
else if (Op == Operator.Call)
{
CalcLinkedNodes(Node);
var Type = Ch[0].Type as FunctionType;
var RetType = Type.RetType;
if (RetType is ValueType)
{
GetCallExprCode(OpNode, Dst);
return true;
}
}
//--------------------------------------------------------------------------------------------
else if (Op == Operator.Add || Op == Operator.Multiply || Operators.IsBitwiseOp(Op))
{
var ChDst = GetNodePos(Ch[0], GetNodePosMode.StrOnly);
var ChSrc = GetNodePos(Ch[1], GetNodePosMode.StrOnly);
if (ChSrc.IsEqual(Dst) && (!(Dst is x86MemPosition) || Data.DataCalcPos.HasFlag(x86DataCalcPos.Memory)))
{
CalcLinkedNodes(Node);
if (!StrOnly)
{
GetNodePos(Ch[0]);
GetNodePos(Ch[1]);
}
GetOpBaseCode_NonFloat(Op, Dst, ChDst, Data.Scope.TmpReg,
Ch[0].Type is SignedType, OpNode.Reverse);
return true;
}
}
return false;
}
x86DataPosition[] GetSplPositions(x86DataPosition Pos, int Size)
{
if (Pos is x86SplitablePosition)
{
var Spl = Pos as x86SplitablePosition;
return Spl.Split(Size);
}
else
{
return new x86DataPosition[] { Pos };
}
}
public void ZeroMem(x86DataPosition Dst, x86ExprScope Scope)
{
Dst = Dst.Extract();
if (Dst.Size > Arch.RegSize && Dst.Size % 4 == 0)
{
var SSEReg = Scope.SSETmpReg;
Append("\tpxor " + SSEReg + ", " + SSEReg + "\n");
ZeroMemSSE(Dst, Scope);
}
else
{
var TmpReg = Scope.TmpReg;
Append("\txor " + TmpReg + ", " + TmpReg + "\n");
ZeroMemGeneral(Dst, Scope);
}
}
void ZeroMemSSE(x86DataPosition Dst, x86ExprScope Scope)
{
var Size = Dst.Size;
if (Size < 16)
{
var P2 = (int)Helper.Pow2((uint)Size);
if (P2 != Size) Size = P2 / 2;
}
var DstParts = GetSplPositions(Dst, Size);
var SSEReg = Scope.SSETmpReg;
foreach (var D in DstParts)
{
if (D.Size == 16) Append((AlignedSSE(D) ? "\tmovdqa " : "\tmovdqu ") + D + ", " + SSEReg + "\n");
else if (D.Size == 8) Append("\tmovq " + D + ", " + SSEReg + "\n");
else if (D.Size == 4) Append("\tmovd " + D + ", " + SSEReg + "\n");
else ZeroMemGeneral(D, Scope);
}
}
void ZeroMemGeneral(x86DataPosition Dst, x86ExprScope Scope)
{
var DstParts = GetSplPositions(Dst, Arch.RegSize);
var TmpReg = Scope.TmpReg;
foreach (var D in DstParts)
Append("\tmov " + D + ", " + TmpReg + "\n");
}
public void MoveData(x86DataPosition Dst, x86DataPosition Src, x86ExprScope Scope,
bool SrcSigned = false, string Cond = null)
{
Dst = Dst.Extract();
Src = Src.Extract();
var DstSrcEqu = Src.IsEqual(Dst, false);
if (Dst.Size > Src.Size || !DstSrcEqu)
{
if (CanUseSSEMove(Dst, Src))
{
if (Cond != null) throw new Exception("ERROR");
MoveDataSSE(Dst, Src, Scope);
}
else if (Dst.Size > Arch.RegSize)
{
if (Cond != null) throw new Exception("ERROR");
MoveDataMultiParts(Dst, Src, Scope, SrcSigned);
}
else
{
MoveDataSinglePart(Dst, Src, Scope, SrcSigned, DstSrcEqu, Cond);
}
}
}
private bool CanUseSSEMove(x86DataPosition Dst, x86DataPosition Src)
{
if (!(Dst is x86MemPosition || Dst is x86SSERegPosition)) return false;
else if (!(Src is x86MemPosition || Src is x86SSERegPosition)) return false;
else if (Dst.Size <= Arch.RegSize || Dst.Size != Src.Size) return false;
else return true;
}
private bool AlignedSSE(x86DataPosition D)
{
var MemD = D as x86MemPosition;
return MemD != null && MemD.Align == 16;
}
private bool AlignedSSE(x86DataPosition D, x86DataPosition S)
{
return AlignedSSE(D) && AlignedSSE(S);
}
void MoveDataSSE(x86DataPosition Dst, x86DataPosition Src, x86ExprScope Scope)
{
var Size = Dst.Size;
if (Size < 16)
{
var P2 = (int)Helper.Pow2((uint)Size);
if (P2 != Size) Size = P2 / 2;
}
var DstParts = GetSplPositions(Dst, Size);
var SrcParts = GetSplPositions(Src, Size);
for (var i = 0; i < DstParts.Length; i++)
{
var D = DstParts[i];
var S = SrcParts[i];
if (D.Size == 16) StdMem2MemOp(AlignedSSE(D, S) ? "\tmovdqa " : "\tmovdqu ", D, S, Scope.SSETmpReg);
else if (D.Size == 8) StdMem2MemOp("\tmovq ", D, S, Scope.SSETmpReg);
else if (D.Size == 4) StdMem2MemOp("\tmovd ", D, S, Scope.SSETmpReg);
else if (D.Size % 4 == 0) MoveDataSSE(D, S, Scope);
else MoveDataSinglePart(D, S, Scope);
}
}
void MoveDataSinglePart(x86DataPosition Dst, x86DataPosition Src, x86ExprScope Scope,
bool SrcSigned = false, bool DstSrcEqu = false, string Cond = null)
{
var SrcSize = Src.Size;
var DstSize = Dst.Size;
if (Cond != null)
{
if (DstSize != SrcSize) throw new Exception("ERROR");
else StdMem2MemOp("\tcmov" + Cond + " ", Dst, Src, Scope.TmpReg);
return;
}
var ConstSrc = Src as x86ConstPosition;
if (ConstSrc != null && ConstSrc.Unsigned == 0 && !(Dst is x86MemPosition))
{
Append("\txor " + Dst + ", " + Dst + "\n");
}
else
{
string Ins;
if (DstSize > SrcSize && ConstSrc == null)
{
if (SrcSigned) Ins = "\tmovsx ";
else Ins = "\tmovzx ";
}
else
{
Ins = "\tmov ";
Src.Size = DstSize;
}
Dst.Size = DstSize;
if (Ins == "\tmovzx " && DstSrcEqu)
Append("\tand " + Dst + ", 0x" + Helper.Str_SizeMask[SrcSize] + "\n");
else StdMem2MemOp(Ins, Dst, Src, Scope.TmpReg);
}
}
void MoveDataMultiParts(x86DataPosition Dst, x86DataPosition Src,
x86ExprScope Scope, bool SrcSigned = false)
{
var MovIns = "\tmovzx ";
if (SrcSigned) MovIns = "\tmovsx ";
var RegSize = Arch.RegSize;
var Accumulator = new x86RegPosition(Arch, Arch.RegSize, 0);
var DstParts = GetSplPositions(Dst, Arch.RegSize);
var SrcParts = GetSplPositions(Src, Arch.RegSize);
for (var i = 0; i < DstParts.Length; i++)
{
var D = DstParts[i];
if (i >= SrcParts.Length)
{
if (!SrcSigned) Append("\tmov " + D + ", 0\n");
else if (!x86Architecture.IsRegPos(D, 2))
Append("\tmov " + D + ", " + x86Architecture.RegStr(2, D.Size) + "\n");
}
else
{
x86DataPosition S = SrcParts[i];
if (SrcSigned && i == SrcParts.Length - 1 && DstParts.Length > SrcParts.Length)
{
if (S.Size < RegSize) Append(MovIns + Accumulator + ", " + S + "\n");
else if (!Accumulator.IsEqual(S)) Append("\tmov " + Accumulator + ", " + S + "\n");
Append("\tcdq\n");
S = new x86RegPosition(Arch, RegSize, 0);
}
var ConstSrc = S as x86ConstPosition;
if (ConstSrc != null && ConstSrc.Unsigned == 0 && !(D is x86MemPosition))
{
Append("\txor " + D + ", " + D + "\n");
}
else
{
if (D.Size > S.Size) StdMem2MemOp(MovIns, D, S, Scope.TmpReg);
else if (!D.IsEqual(S)) StdMem2MemOp("\tmov ", D, S, Scope.TmpReg);
}
}
}
}
private x86DataPosition Mem2Mem(x86DataPosition D, x86DataPosition S, x86DataPosition TmpReg)
{
if (D is x86MemPosition && S is x86MemPosition && TmpReg != null)
{
TmpReg.Size = S.Size;
if (TmpReg is x86SSERegPosition)
{
if (S.Size == 16) Append("\tmovdqu " + TmpReg + ", " + S + "\n");
else if (S.Size == 8) Append("\tmovq " + TmpReg + ", " + S + "\n");
else if (S.Size == 4) Append("\tmovd " + TmpReg + ", " + S + "\n");
}
else
{
Append("\tmov " + TmpReg + ", " + S + "\n");
}
S = TmpReg;
}
return S;
}
private void StdMem2MemOp(string Op, x86DataPosition D, x86DataPosition S, x86DataPosition TmpReg)
{
S = Mem2Mem(D, S, TmpReg);
Append(Op + D + ", " + S + "\n");
}
private void FltLoad(x86DataPosition Src, x86ExprScope Scope, bool Int)
{
if (!(Src is x86MemPosition))
{
var NSrc = Scope.TmpMem.Copy(Src.Size);
MoveData(NSrc, Src, Scope);
Src = NSrc;
}
if (Int) Append("\tfild " + Src + "\n");
else Append("\tfld " + Src + "\n");
}
private void FltStore(x86DataPosition Dst, x86ExprScope Scope, bool Int)
{
var NDst = Dst;
if (!(Dst is x86MemPosition))
NDst = Scope.TmpMem.Copy(Dst.Size);
if (Int) Append("\tfistp " + NDst + "\n");
else Append("\tfstp " + NDst + "\n");
if (NDst != Dst) MoveData(Dst, NDst, Scope);
}
private void GetCastExprCode_Float(CastExpressionNode CastNode)
{
var Data = CastNode.ArchData as x86NodeData;
var Ch = CastNode.Child;
var Src = GetNodePos(Ch);
var FuncScope = Container.FuncScope as x86FuncScopeNode;
var DstOut = Data.Output;
var Dst = DstOut == null ? null : CastNode.GetPosition();
if (!x86Architecture.NeedLoadFloatDst(Ch, true))
{
if (Ch.Type is NonFltNumType) FltLoad(Src, Data.Scope, true);
if (Dst != null) FltStore(Dst, Data.Scope, false);
}
else
{
if (Ch is ConstExpressionNode)
{
if (Dst == null)
{
var ConstCh = Ch as ConstExpressionNode;
LoadFltConst(ConstCh);
return;
}
else
{
Append("\tmov " + Dst + ", " + Src + "\n");
Src = Dst;
Dst = null;
}
}
if (Dst == null || !Dst.IsEqual(Src))
{
FltLoad(Src, Data.Scope, Ch.Type is NonFltNumType);
if (Dst != null) FltStore(Dst, Data.Scope, false);
}
}
}
private void GetOpExprCode(OpExpressionNode OpNode)
{
var Op = OpNode.Operator;
var Ch = OpNode.Children;
var Data = OpNode.ArchData as x86NodeData;
if (Op == Operator.CreateTuple)
{
if (Data.Index != -1)
{
var Type = OpNode.Type as ValueType;
if (Type == null) throw new Exception("ERROR");
var ChIndex = 0;
var Dst = OpNode.GetPosition();
var SDst = Dst as x86SplitablePosition;
foreach (var e in Type.Members)
if (e is MemberVariable)
{
var MemVar = e as MemberVariable;
var SrcNode = Ch[ChIndex];
var DstP = SDst.GetPart(MemVar.Offset, MemVar.Type.Size);
if (SrcNode.Type is FloatType)
{
GetNodePos_Float(SrcNode, LoadIds: true);
FltStore(DstP, Data.Scope, MemVar.Type is NonFltNumType);
}
else
{
var Src = GetNodePos(SrcNode);
MoveData(DstP, Src, Data.Scope, MemVar.Type is SignedType);
}
ChIndex++;
}
}
else
{
foreach (var e in Ch)
GetExprCode(e);
}
}
else if (Op == Operator.Condition)
{
var OpCondition = Ch[0] as OpExpressionNode;
var EnableMoveBranch = Operators.IsRelEqualityOp(OpCondition.Operator);
var Glb = Container.GlobalScope;
var T = Arch.GetNodeCondBrach(this, Glb, Ch[1], true, EnableMoveBranch: EnableMoveBranch);
var E = Arch.GetNodeCondBrach(this, Glb, Ch[2], false, EnableMoveBranch: EnableMoveBranch);
GetConditionCode(Ch[0], T, E);
}
else if (Op == Operator.Call)
{
GetCallExprCode(OpNode);
}
else
{
if (OpNode.Type is FloatType) GetOpBaseCode_Float(OpNode);
else GetOpBaseCode_NonFloat(OpNode);
}
}
private void GetExprCondCode_BoolRet(ExpressionNode Node, x86DataPosition Dst)
{
var Type = Node.Type as BoolType;
var FuncScope = Container.FuncScope as x86FuncScopeNode;
var Data = Node.ArchData as x86NodeData;
var Then = new x86MoveCondBranch(Dst, new x86ConstPosition(Arch, Dst.Size, Type.TrueData, 0), Data.Scope);
var Else = new x86MoveCondBranch(Dst, new x86ConstPosition(Arch, Dst.Size, Type.FalseData, 0), Data.Scope);
GetConditionCode(Node, Then, Else, LinkedNodesCalced: true);
}
x86DataPosition GetNodePos_Float(ExpressionNode Node, GetNodePosMode Mode = GetNodePosMode.Default, bool LoadIds = false)
{
var Data = Node.ArchData as x86NodeData;
if (Node is ConstExpressionNode)
{
var ConstNode = Node as ConstExpressionNode;
if (Mode == GetNodePosMode.Default)
LoadFltConst(ConstNode);
return null;
}
else if (Node is IdExpressionNode)
{
var RIdNode = Node as IdExpressionNode;
var Pos = RIdNode.Id.ArchData as x86DataPosition;
if (LoadIds)
{
if (Mode == GetNodePosMode.RetNull) return null;
else if (Mode == GetNodePosMode.StrOnly) return Pos;
FltLoad(Pos, Data.Scope, Node.Type is NonFltNumType);
}
return Pos;
}
else
{
if (Mode == GetNodePosMode.RetNull) return null;
var Pos = GetNodePos(Node, Mode);
if (LoadIds && Pos != null)
{
if (Mode == GetNodePosMode.RetNull) return null;
else if (Mode == GetNodePosMode.StrOnly) return Pos;
FltLoad(Pos, Data.Scope, Node.Type is NonFltNumType);
}
return Pos;
}
}
private void LoadFltConst(ConstExpressionNode ConstCh)
{
var V = ConstCh.Double;
if (V == 0.0) Append("\tfldz\n");
else if (V == 1.0) Append("\tfld1\n");
else if (V == Math.PI) Append("\tfldpi\n");
else throw new Exception("ERROR");
}
private void GetOpBaseCode_Float(OpExpressionNode OpNode)
{
var Data = OpNode.ArchData as x86NodeData;
var Ch = OpNode.Children;
switch (OpNode.Operator)
{
case Operator.Assignment:
var RetVar = false;
if (Ch[0] is IdExpressionNode)
{
var IdCh0 = Ch[0] as IdExpressionNode;
var Id = IdCh0.Id as LocalVariable;
if (Id != null && Id.RetVar) RetVar = true;
}
var ConstNode = Ch[1] as ConstExpressionNode;
if (!RetVar)
{
var Dst = GetNodePos(Ch[0]);
if (ConstNode != null)
{
var Value = ConstNode != null ? ConstNode.Value : null;
var Src = new x86ConstPosition(Arch, Ch[1].Type.Size, Value, 0);
MoveData(Dst, Src, Data.Scope);
}
else
{
GetNodePos_Float(Ch[1], LoadIds: true);
FltStore(Dst, Data.Scope, false);
}
}
else
{
GetNodePos_Float(Ch[1], LoadIds: true);
}
break;
case Operator.Neg:
GetNodePos_Float(Ch[0], LoadIds: true);
Append("\tfchs\n");
break;
case Operator.Abs:
GetNodePos_Float(Ch[0], LoadIds: true);
Append("\tfabs\n");
break;
case Operator.Sqrt:
GetNodePos_Float(Ch[0], LoadIds: true);
Append("\tfsqrt\n");
break;
case Operator.Sin:
GetNodePos_Float(Ch[0], LoadIds: true);
Append("\tfsin\n");
break;
case Operator.Cos:
GetNodePos_Float(Ch[0], LoadIds: true);
Append("\tfcos\n");
break;
case Operator.Tan:
GetNodePos_Float(Ch[0], LoadIds: true);
Append("\tfptan\n");
Append("\tffree st0\n");
Append("\tfincstp\n");
break;
case Operator.ATan:
GetNodePos_Float(Ch[0], LoadIds: true);
Append("\tfld1\n");
Append("\tfpatan\n");
break;
case Operator.ATan2:
GetNodePos_Float(Ch[0], LoadIds: true);
GetNodePos_Float(Ch[1], LoadIds: true);
Append("\tfpatan\n");
break;
default:
if (Operators.IsBitArithmOp(OpNode.Operator))
GetShiftArithmCode_Float(OpNode);
else
throw new Exception("Unknown operator");
break;
}
}
private void GetShiftArithmCode_Float(OpExpressionNode OpNode)
{
var Ch = OpNode.Children;
var Dst = GetNodePos_Float(Ch[0]);
var Src = GetNodePos_Float(Ch[1]);
var Op = OpNode.Operator;
var OpStr = "";
if (Op == Operator.Add) OpStr = "add";
else if (Op == Operator.Subract) OpStr = "sub";
else if (Op == Operator.Multiply) OpStr = "mul";
else if (Op == Operator.Divide) OpStr = "div";
else throw new NotImplementedException();
if (Dst != null)
{
if (Src != null) throw new Exception("ERROR");
var Reverse = !OpNode.Reverse && (Op == Operator.Subract || Op == Operator.Divide);
FloatOp(OpStr, Dst, Ch[1].Type is FloatType, Reverse);
}
else
{
FloatOp(OpStr, Src, Ch[1].Type is FloatType, OpNode.Reverse);
}
}
private void FloatOp(string Op, x86DataPosition Src, bool Float, bool Reverse)
{
if (Src == null)
{
if (!Reverse) Append("\tf" + Op + "p\n");
else Append("\tf" + Op + "rp\n");
return;
}
if (Float)
{
if (!Reverse) Append("\tf" + Op + " " + Src + "\n");
else Append("\tf" + Op + "r " + Src + "\n");
}
else
{
if (!Reverse) Append("\tfi" + Op + " " + Src + "\n");
else Append("\tfi" + Op + "r " + Src + "\n");
}
}
private void GetOpBaseCode_NonFloat(Operator Op, x86DataPosition Dst, x86DataPosition Src,
x86DataPosition TmpReg, bool Signed, bool Reverse)
{
if (Reverse)
{
var Tmp = Dst;
Dst = Src;
Src = Tmp;
}
var SplDst = GetSplPositions(Dst, Arch.RegSize);
var SplSrc = GetSplPositions(Src, Arch.RegSize);
if (SplDst != null && SplSrc != null)
{
if (SplDst.Length != SplSrc.Length)
throw new Exception("ERROR");
}
switch (Op)
{
case Operator.Neg:
if (SplDst.Length == 1) Append("\tneg " + SplDst[0] + "\n");
else throw new Exception("ERROR");
break;
case Operator.Complement:
EachPart(SplDst, SplSrc, TmpReg, "not");
break;
case Operator.Add:
case Operator.Subract:
var Val = GetVal(Src);
AddSubData(SplDst, SplSrc, TmpReg, Val, Op);
break;
case Operator.Multiply:
if (SplSrc.Length == 1)
{
var OldDst = Dst;
if (Dst is x86MemPosition)
{
Append("\tmov " + TmpReg + ", " + Dst + "\n");
Dst = TmpReg;
}
if (x86Architecture.IsRegPos(Dst, 0) && !(Src is x86ConstPosition))
Append("\timul " + Src + "\n");
else Append("\timul " + Dst + ", " + Src + "\n");
if (Dst != OldDst) Append("\tmov " + OldDst + ", " + Dst + "\n");
}
else
{
throw new NotImplementedException();
}
break;
case Operator.Divide:
case Operator.Modolus:
DivModData(SplDst, SplSrc, Signed);
break;
case Operator.BitwiseAnd:
EachPart(SplDst, SplSrc, TmpReg, "and");
break;
case Operator.BitwiseOr:
EachPart(SplDst, SplSrc, TmpReg, "or");
break;
case Operator.BitwiseXor:
EachPart(SplDst, SplSrc, TmpReg, "xor");
break;
case Operator.ShiftLeft:
if (SplDst.Length == 1)
{
StdMem2MemOp("\tshl ", SplDst[0], SplSrc[0], TmpReg);
}
else
{
throw new NotImplementedException();
}
break;
case Operator.ShiftRight:
if (SplDst.Length == 1)
{
if (!Signed) StdMem2MemOp("\tshr ", SplDst[0], SplSrc[0], TmpReg);
else StdMem2MemOp("\tsar ", SplDst[0], SplSrc[0], TmpReg);
}
else
{
throw new NotImplementedException();
}
break;
default:
throw new NotImplementedException();
}
}
private void EachPart(x86DataPosition[] SplDst, x86DataPosition[] SplSrc, x86DataPosition TmpReg, string Ins)
{
Ins = "\t" + Ins + " ";
if (SplSrc != null)
{
for (var i = 0; i < SplDst.Length; i++)
StdMem2MemOp(Ins, SplDst[i], SplSrc[i], TmpReg);
}
else
{
for (var i = 0; i < SplDst.Length; i++)
Append(Ins + SplDst[i] + "\n");
}
}
private void DivModData(x86DataPosition[] SplDst, x86DataPosition[] SplSrc, bool Signed)
{
if (SplDst.Length == 1)
{
var Dst0 = SplDst[0];
var Src0 = SplSrc[0];
var Size = Dst0.Size;
if (Size == 1) Dst0.Size = 2;
if (!x86Architecture.IsRegPos(Dst0, 0))
{
var Accumulator = x86Architecture.RegStr(0, Size);
Append("\tmov " + Accumulator + ", " + Dst0 + "\n");
}
if (!Signed)
{
if (Size == 1)
{
Append("\txor ah, ah\n");
}
else
{
var EDX = x86Architecture.RegStr(2, Size);
Append("\txor " + EDX + ", " + EDX + "\n");
}
Append("\tdiv " + Src0 + "\n");
}
else
{
if (Size == 1) Append("\tcbw\n");
else if (Size == 2) Append("\tcwd\n");
else if (Size == 4) Append("\tcdq\n");
else if (Size == 8) Append("\tcqo\n");
else throw new Exception("ERROR");
Append("\tidiv " + Src0 + "\n");
}
}
else
{
throw new NotImplementedException();
}
}
private void AddSubData(x86DataPosition[] SplDst, x86DataPosition[] SplSrc, x86DataPosition TmpReg, ulong Val, Operator Op)
{
if (Val != 0)
{
if (SplDst.Length == 1 && Val == 1)
{
if (Op == Operator.Add) Append("\tinc " + SplDst[0] + "\n");
else if (Op == Operator.Subract) Append("\tdec " + SplDst[0] + "\n");
else throw new NotImplementedException();
}
else
{
for (var i = 0; i < SplDst.Length; i++)
{
string Ins;
if (Op == Operator.Add) Ins = i == 0 ? "\tadd " : "\tadc ";
else if (Op == Operator.Subract) Ins = i == 0 ? "\tsub " : "\tsbb ";
else throw new NotImplementedException();
StdMem2MemOp(Ins, SplDst[i], SplSrc[i], TmpReg);
}
}
}
}
private void GetOpBaseCode_NonFloat(OpExpressionNode OpNode)
{
var Ch = OpNode.Children;
var Op = OpNode.Operator;
var Dst = GetNodePos(Ch[0]);
var Data = OpNode.ArchData as x86NodeData;
if (Op == Operator.Assignment)
{
if (!MoveAndOp(Dst, Ch[1]))
{
var Src = GetNodePos(Ch[1]);
MoveData(Dst, Src, Data.Scope, Ch[1].Type is SignedType);
}
}
else if (Op == Operator.Neg)
{
var Spl = GetSplPositions(Dst, Arch.RegSize);
for (var i = 0; i < Spl.Length; i++)
{
var P = Spl[i];
if (i > 0) Append("\tadc " + P + ", 0\n");
Append("\tneg " + P + "\n");
}
}
else if (Op == Operator.Address)
{
var Src = Dst;
Dst = GetNodePos(OpNode, GetNodePosMode.StrOnly);
GetAddrOf(Dst, Src);
}
else
{
x86DataPosition Src = null;
if (Ch.Count > 1) Src = GetNodePos(Ch[1]);
GetOpBaseCode_NonFloat(Op, Dst, Src, Data.Scope.TmpReg, Ch[0].Type is SignedType, OpNode.Reverse);
}
}
private static ulong GetVal(x86DataPosition Src)
{
var ConstSrc = Src as x86ConstPosition;
return ConstSrc != null ? ConstSrc.Unsigned : ulong.MaxValue;
}
public override bool Compile(CompilerState State, PString[] Lines)
{
State.Reset();
var PreState = new PreprocessorState(new MessageCollector(State.Messages));
var GlobalScope = new GlobalScopeNode(PreState, State, Lines);
var RetValue = GlobalScope.Process();
if (!PreState.CheckConditions()) RetValue = false;
if (RetValue) GetAsmCode(State, GlobalScope);
LibraryLoader.SaveLibrary(@"Txt\Lib.aslib", GlobalScope);
return RetValue;
}
private void GetAsmCode(CompilerState State, GlobalScopeNode GlobalScope)
{
if (State.Format == ImageFormat.MSCoff)
{
if (Arch.x86_64)
Append("\tformat MS64 COFF\n");
else Append("\tformat MS COFF\n");
}
else if (State.Format == ImageFormat.GUI)
{
if (Arch.x86_64)
Append("\tformat PE64 GUI 4.0\n");
else Append("\tformat PE GUI 4.0\n");
}
else if (State.Format == ImageFormat.Console)
{
if (Arch.x86_64)
Append("\tformat PE64 CONSOLE 4.0\n");
else Append("\tformat PE CONSOLE 4.0\n");
}
else if (State.Format == ImageFormat.DLL || State.Format == ImageFormat.AsDLL)
{
if (Arch.x86_64)
Append("\tformat PE64 DLL 4.0\n");
else Append("\tformat PE DLL 4.0\n");
}
else
{
throw new Exception("ERROR");
}
var ExternCode = GlobalScope.GetExternCode();
if (ExternCode.Length > 0) Append(ExternCode);
var Entry = GlobalScope.GetEntry();
if (Entry != null)
{
if (State.Format == ImageFormat.MSCoff)
Append("\tpublic " + Entry.AsmName + "\n");
else Append("\tentry " + Entry.AsmName + "\n");
}
Append("\t\n");
// -----------------------------------------------------------------
Append("section \"code\" code readable executable\n\n");
GlobalScope.GetAsmCode(this, GetAsmCodeMode.Code);
// -----------------------------------------------------------------
var DataCompiler = Arch.CreateCompiler(State);
GlobalScope.GetAsmCode(DataCompiler, GetAsmCodeMode.Data);
var DataCode = DataCompiler.GetAssembly();
if (DataCode.Length > 0)
{
Append("section \"data\" data readable writeable\n\n");
Append(DataCode);
}
// -----------------------------------------------------------------
var ImportCode = GlobalScope.GetImportCode();
if (ImportCode.Length > 0)
{
Append("section \"idata\" import data readable writeable\n\n");
Append(ImportCode);
}
}
}
}