Cosmos/source/XSharp.Compiler/XS.cs
Matthijs ter Woord 9a2f6714b5 .
2016-06-14 20:58:19 -04:00

761 lines
26 KiB
C#

using System;
using System.Diagnostics.CodeAnalysis;
using Cosmos.Assembler;
using Cosmos.Assembler.x86;
using Cosmos.Assembler.x86.x87;
using static XSharp.Compiler.XSRegisters;
namespace XSharp.Compiler
{
[SuppressMessage("ReSharper", "ObjectCreationAsStatement")]
public static partial class XS
{
public static void Label(string labelName)
{
new Label(labelName);
}
public static void Return()
{
new Return();
}
public static void InterruptReturn()
{
new IRET();
}
#region InstructionWithDestinationAndSourceAndSize
private static void Do<T>(string destination, Register source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize? size = null)
where T : InstructionWithDestinationAndSourceAndSize, new()
{
if (destinationDisplacement != null)
{
destinationIsIndirect = true;
if (destinationDisplacement == 0)
{
destinationDisplacement = null;
}
}
if (sourceDisplacement != null)
{
sourceIsIndirect = true;
if (sourceDisplacement == 0)
{
sourceDisplacement = null;
}
}
if (destinationIsIndirect && sourceIsIndirect)
{
throw new Exception("Both destination and source cannot be indirect!");
}
new T
{
Size = (byte)source.Size,
DestinationRef = ElementReference.New(destination),
DestinationIsIndirect = destinationIsIndirect,
DestinationDisplacement = destinationDisplacement,
SourceReg = source.RegEnum,
SourceIsIndirect = sourceIsIndirect,
SourceDisplacement = sourceDisplacement
};
}
private static void Do<T>(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
where T : InstructionWithDestinationAndSourceAndSize, new()
{
if (destinationDisplacement != null)
{
destinationIsIndirect = true;
if (destinationDisplacement == 0)
{
destinationDisplacement = null;
}
}
if (sourceDisplacement != null)
{
sourceIsIndirect = true;
if (sourceDisplacement == 0)
{
sourceDisplacement = null;
}
}
if (destinationIsIndirect && sourceIsIndirect)
{
throw new Exception("Both destination and source cannot be indirect!");
}
new T
{
Size = (byte)size,
DestinationRef = ElementReference.New(destination),
DestinationIsIndirect = destinationIsIndirect,
DestinationDisplacement = destinationDisplacement,
SourceValue = value,
SourceIsIndirect = sourceIsIndirect,
SourceDisplacement = sourceDisplacement,
};
}
private static void Do<T>(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
where T : InstructionWithDestinationAndSourceAndSize, new()
{
if (destinationDisplacement != null)
{
destinationIsIndirect = true;
if (destinationDisplacement == 0)
{
destinationDisplacement = null;
}
}
if (sourceDisplacement != null)
{
sourceIsIndirect = true;
if (sourceDisplacement == 0)
{
sourceDisplacement = null;
}
}
if (destinationIsIndirect && sourceIsIndirect)
{
throw new Exception("Both destination and source cannot be indirect!");
}
new T
{
Size = (byte)size,
DestinationRef = ElementReference.New(destination),
DestinationIsIndirect = destinationIsIndirect,
DestinationDisplacement = destinationDisplacement,
SourceRef = ElementReference.New(source),
SourceIsIndirect = sourceIsIndirect,
SourceDisplacement = sourceDisplacement,
};
}
private static void Do<T>(Register destination, string sourceLabel, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize? size = null)
where T: InstructionWithDestinationAndSourceAndSize, new()
{
if (destinationDisplacement != null)
{
destinationIsIndirect = true;
if (destinationDisplacement == 0)
{
destinationDisplacement = null;
}
}
if (sourceDisplacement != null)
{
sourceIsIndirect = true;
if (sourceDisplacement == 0)
{
sourceDisplacement = null;
}
}
if (size == null)
{
if (destinationIsIndirect)
{
throw new Exception("No size specified!");
}
size = destination.Size;
}
new T
{
Size = (byte)size.Value,
DestinationReg = destination.RegEnum,
DestinationIsIndirect = destinationIsIndirect,
DestinationDisplacement = destinationDisplacement,
SourceRef = ElementReference.New(sourceLabel),
SourceIsIndirect = sourceIsIndirect,
SourceDisplacement = sourceDisplacement
};
}
private static void Do<T>(Register destination, uint value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize? size = null)
where T: InstructionWithDestinationAndSourceAndSize, new()
{
if (destinationDisplacement != null)
{
destinationIsIndirect = true;
if (destinationDisplacement == 0)
{
destinationDisplacement = null;
}
}
if (sourceDisplacement != null)
{
sourceIsIndirect = true;
if (sourceDisplacement == 0)
{
sourceDisplacement = null;
}
}
if (size == null)
{
if (destinationIsIndirect)
{
throw new Exception("No size specified!");
}
size = destination.Size;
}
new T
{
Size = (byte)size,
DestinationReg = destination.RegEnum,
DestinationIsIndirect = destinationIsIndirect,
DestinationDisplacement = destinationDisplacement,
SourceValue = value,
SourceIsIndirect = sourceIsIndirect,
SourceDisplacement = sourceDisplacement,
};
}
private static void Do<T>(Register destination,
Register source,
bool destinationIsIndirect = false,
int? destinationDisplacement = null,
bool sourceIsIndirect = false,
int? sourceDisplacement = null,
bool skipSizeCheck = false)
where T : InstructionWithDestinationAndSourceAndSize, new()
{
if (destinationDisplacement != null)
{
destinationIsIndirect = true;
if (destinationDisplacement == 0)
{
destinationDisplacement = null;
}
}
if (sourceDisplacement != null)
{
sourceIsIndirect = true;
if (sourceDisplacement == 0)
{
sourceDisplacement = null;
}
}
if (!skipSizeCheck
&& !(destinationIsIndirect || sourceIsIndirect)
&& destination.Size != source.Size)
{
throw new Exception("Register sizes must match!");
}
if (destinationIsIndirect && sourceIsIndirect)
{
throw new Exception("Both destination and source cannot be indirect!");
}
RegisterSize xSize;
if (!destinationIsIndirect)
{
xSize = destination.Size;
}
else
{
xSize = source.Size;
}
new T
{
Size = (byte)xSize,
DestinationReg = destination.RegEnum,
DestinationIsIndirect = destinationIsIndirect,
DestinationDisplacement = destinationDisplacement,
SourceIsIndirect = sourceIsIndirect,
SourceDisplacement = sourceDisplacement,
SourceReg = source.RegEnum
};
}
#endregion InstructionWithDestinationAndSourceAndSize
#region InstructionWithDestinationAndSize
private static void Do<T>(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
where T: InstructionWithDestinationAndSize, new()
{
if (displacement != null)
{
isIndirect = true;
if (displacement == 0)
{
displacement = null;
}
}
new T
{
DestinationValue = destinationValue,
DestinationIsIndirect = isIndirect,
DestinationDisplacement = displacement,
Size = (byte)size
};
}
private static void Do<T>(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null)
where T: InstructionWithDestinationAndSize, new()
{
if (displacement != null)
{
isIndirect = true;
if (displacement == 0)
{
displacement = null;
}
}
if (size == null)
{
if (isIndirect)
{
throw new InvalidOperationException("No size specified!");
}
size = register.Size;
}
new T
{
DestinationReg = register.RegEnum,
DestinationIsIndirect = isIndirect,
DestinationDisplacement = displacement,
Size = (byte)size.Value
};
}
private static void Do<T>(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
where T: InstructionWithDestinationAndSize, new()
{
if (displacement != null)
{
isIndirect = true;
if (displacement == 0)
{
displacement = null;
}
}
new T
{
DestinationRef = ElementReference.New(label),
DestinationIsIndirect = isIndirect,
DestinationDisplacement = displacement,
Size = (byte)size
};
}
#endregion InstructionWithDestinationAndSize
#region Mov
public static void Set(string destination, Register source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize? size = null)
{
Do<Mov>(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void Set(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Mov>(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void Set(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Mov>(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void Set(Register destination, string sourceLabel, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize? size = null)
{
Do<Mov>(destination, sourceLabel, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void Set(Register destination, uint value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize? size = null)
{
Do<Mov>(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void Set(Register destination, Register source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
{
Do<Mov>(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
}
public static void SetByte(uint address, byte value)
{
new Mov { DestinationValue = address, DestinationIsIndirect = true, SourceValue = value };
}
#endregion Mov
public static void Jump(ConditionalTestEnum condition, string label)
{
new ConditionalJump { Condition = condition, DestinationLabel = label };
}
public static void Jump(string label)
{
new Jump { DestinationLabel = label };
}
public static void Comment(string comment)
{
Comment(comment);
}
public static void Call(string target)
{
new Call { DestinationLabel=target };
}
public static void Call(Register32 register)
{
new Call { DestinationReg = register.RegEnum };
}
public static void Const(string name, string value)
{
new LiteralAssemblerCode(name + " equ " + value);
}
public static void DataMember(string name, uint value = 0)
{
Assembler.CurrentInstance.DataMembers.Add(new DataMember(name, value));
}
public static void DataMember(string name, string value)
{
Assembler.CurrentInstance.DataMembers.Add(new DataMember(name, value));
}
public static void DataMember(string name, uint elementCount, string size, string value)
{
new LiteralAssemblerCode(name + ": TIMES " + elementCount + " " + size + " " + value);
}
public static void RotateRight(Register register, uint bitCount)
{
Do<RotateRight>(register, bitCount);
}
public static void RotateLeft(Register register, uint bitCount)
{
Do<RotateLeft>(register, bitCount);
}
public static void ShiftRight(Register register, byte bitCount)
{
Do<ShiftRight>(register, bitCount);
}
public static void ShiftRight(Register register, Register8 bitCount)
{
if (bitCount != CL)
{
throw new InvalidOperationException();
}
Do<ShiftRight>(register, bitCount, skipSizeCheck: true);
}
public static void ShiftLeft(Register register, byte bitCount)
{
Do<ShiftLeft>(register, bitCount);
}
public static void ShiftLeft(Register register, Register8 bitCount)
{
if (bitCount != CL)
{
throw new InvalidOperationException();
}
Do<ShiftLeft>(register, bitCount, skipSizeCheck: true);
}
public static void PushAllGeneralRegisters()
{
new Pushad();
}
public static void PopAllGeneralRegisters()
{
new Popad();
}
public static void WriteToPortDX(Register value)
{
new OutToDX()
{
DestinationReg = value.RegEnum
};
}
public static void ReadFromPortDX(Register value)
{
new InFromDX
{
DestinationReg = value.RegEnum
};
}
public static void Push(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Push>(destinationValue, isIndirect, displacement, size);
}
public static void Push(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null)
{
Do<Push>(register, isIndirect, displacement, size);
}
public static void Push(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Push>(label, isIndirect, displacement, size);
}
public static void Pop(Register value)
{
Do<Pop>(value);
}
public static void Increment(Register value)
{
Do<INC>(value);
}
public static void Decrement(Register value)
{
Do<Dec>(value);
}
public static void Add(Register register, uint valueToAdd)
{
Do<Add>(register, valueToAdd);
}
public static void Add(Register register, Register valueToAdd)
{
Do<Add>(register, valueToAdd);
}
public static void Sub(Register register, uint valueToAdd)
{
Do<Sub>(register, valueToAdd);
}
public static void Sub(Register register, Register valueToAdd)
{
Do<Sub>(register, valueToAdd);
}
public static void SubWithCarry(Register register, uint valueToAdd)
{
Do<SubWithCarry>(register, valueToAdd);
}
public static void SubWithCarry(Register register, Register valueToAdd)
{
Do<SubWithCarry>(register, valueToAdd);
}
public static void And(Register register, uint value)
{
Do<And>(register, value);
}
public static void And(Register register, Register value)
{
Do<And>(register, value);
}
public static void Or(Register register, uint value)
{
Do<Or>(register, value);
}
public static void Or(Register register, Register value)
{
Do<Or>(register, value);
}
public static void Xor(Register register, uint value)
{
Do<Xor>(register, value);
}
public static void Xor(Register register, Register value)
{
Do<Xor>(register, value);
}
public static void IntegerMultiply(Register register, uint valueToAdd)
{
Do<Imul>(register, valueToAdd);
}
public static void IntegerMultiply(Register register, Register registerToAdd)
{
Do<Imul>(register, registerToAdd);
}
#region Compare
public static void Compare(string destination, Register source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize? size = null)
{
Do<Compare>(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void Compare(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Compare>(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void Compare(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Compare>(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void Compare(Register destination, string sourceLabel, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize? size = null)
{
Do<Compare>(destination, sourceLabel, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void Compare(Register destination, uint value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize? size = null)
{
Do<Compare>(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void Compare(Register destination, Register source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
{
Do<Compare>(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
}
#endregion Compare
public static void LiteralCode(string code)
{
new LiteralAssemblerCode(code);
}
public static void Test(Register destination, uint source)
{
Test(OldToNewRegister(destination.RegEnum), source);
}
public static void Test(Register destination, string sourceRef, bool sourceIsIndirect = false)
{
new Test
{
DestinationReg = destination.RegEnum,
SourceRef = ElementReference.New(sourceRef),
SourceIsIndirect = sourceIsIndirect
};
}
public static void Divide(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Divide>(destinationValue, isIndirect, displacement, size);
}
public static void Divide(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null)
{
Do<Divide>(register, isIndirect, displacement, size);
}
public static void Divide(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Divide>(label, isIndirect, displacement, size);
}
public static void IntegerDivide(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<IDivide>(destinationValue, isIndirect, displacement, size);
}
public static void IntegerDivide(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null)
{
Do<IDivide>(register, isIndirect, displacement, size);
}
public static void IntegerDivide(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<IDivide>(label, isIndirect, displacement, size);
}
public static void Multiply(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Multiply>(destinationValue, isIndirect, displacement, size);
}
public static void Multiply(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null)
{
Do<Multiply>(register, isIndirect, displacement, size);
}
public static void Multiply(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Multiply>(label, isIndirect, displacement, size);
}
public static void Negate(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Neg>(destinationValue, isIndirect, displacement, size);
}
public static void Negate(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null)
{
Do<Neg>(register, isIndirect, displacement, size);
}
public static void Negate(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Neg>(label, isIndirect, displacement, size);
}
public static void Not(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Not>(destinationValue, isIndirect, displacement, size);
}
public static void Not(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null)
{
Do<Not>(register, isIndirect, displacement, size);
}
public static void Not(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<Not>(label, isIndirect, displacement, size);
}
public static void AddWithCarry(string destination, Register source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize? size = null)
{
Do<AddWithCarry>(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void AddWithCarry(string destination, UInt32 value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<AddWithCarry>(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void AddWithCarry(string destination, string source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize size = RegisterSize.Int32)
{
Do<AddWithCarry>(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void AddWithCarry(Register destination, string sourceLabel, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize? size = null)
{
Do<AddWithCarry>(destination, sourceLabel, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void AddWithCarry(Register destination, uint value, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null, RegisterSize? size = null)
{
Do<AddWithCarry>(destination, value, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size);
}
public static void AddWithCarry(Register destination, Register source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null)
{
Do<AddWithCarry>(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement);
}
}
}