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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(register, bitCount); } public static void RotateLeft(Register register, uint bitCount) { Do(register, bitCount); } public static void ShiftRight(Register register, byte bitCount) { Do(register, bitCount); } public static void ShiftRight(Register register, Register8 bitCount) { if (bitCount != CL) { throw new InvalidOperationException(); } Do(register, bitCount, skipSizeCheck: true); } public static void ShiftLeft(Register register, byte bitCount) { Do(register, bitCount); } public static void ShiftLeft(Register register, Register8 bitCount) { if (bitCount != CL) { throw new InvalidOperationException(); } Do(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(destinationValue, isIndirect, displacement, size); } public static void Push(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null) { Do(register, isIndirect, displacement, size); } public static void Push(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32) { Do(label, isIndirect, displacement, size); } public static void Pop(Register value) { Do(value); } public static void Increment(Register value) { Do(value); } public static void Decrement(Register value) { Do(value); } public static void Add(Register register, uint valueToAdd) { Do(register, valueToAdd); } public static void Add(Register register, Register valueToAdd) { Do(register, valueToAdd); } public static void Sub(Register register, uint valueToAdd) { Do(register, valueToAdd); } public static void Sub(Register register, Register valueToAdd) { Do(register, valueToAdd); } public static void SubWithCarry(Register register, uint valueToAdd) { Do(register, valueToAdd); } public static void SubWithCarry(Register register, Register valueToAdd) { Do(register, valueToAdd); } public static void And(Register register, uint value) { Do(register, value); } public static void And(Register register, Register value) { Do(register, value); } public static void Or(Register register, uint value) { Do(register, value); } public static void Or(Register register, Register value) { Do(register, value); } public static void Xor(Register register, uint value) { Do(register, value); } public static void Xor(Register register, Register value) { Do(register, value); } public static void IntegerMultiply(Register register, uint valueToAdd) { Do(register, valueToAdd); } public static void IntegerMultiply(Register register, Register registerToAdd) { Do(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(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(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(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(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(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(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(destinationValue, isIndirect, displacement, size); } public static void Divide(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null) { Do(register, isIndirect, displacement, size); } public static void Divide(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32) { Do(label, isIndirect, displacement, size); } public static void IntegerDivide(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32) { Do(destinationValue, isIndirect, displacement, size); } public static void IntegerDivide(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null) { Do(register, isIndirect, displacement, size); } public static void IntegerDivide(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32) { Do(label, isIndirect, displacement, size); } public static void Multiply(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32) { Do(destinationValue, isIndirect, displacement, size); } public static void Multiply(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null) { Do(register, isIndirect, displacement, size); } public static void Multiply(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32) { Do(label, isIndirect, displacement, size); } public static void Negate(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32) { Do(destinationValue, isIndirect, displacement, size); } public static void Negate(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null) { Do(register, isIndirect, displacement, size); } public static void Negate(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32) { Do(label, isIndirect, displacement, size); } public static void Not(uint destinationValue, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32) { Do(destinationValue, isIndirect, displacement, size); } public static void Not(Register register, bool isIndirect = false, int? displacement = null, RegisterSize? size = null) { Do(register, isIndirect, displacement, size); } public static void Not(string label, bool isIndirect = false, int? displacement = null, RegisterSize size = RegisterSize.Int32) { Do(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(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(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(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(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(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(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement); } } }