/// <summary> /// Pushes the given register to the operand stack /// </summary> /// <param name="register">The register</param> public void PushRegister(FloatRegister register) { this.operandTopIndex++; int stackOffset = GetStackOperandOffset(this.operandTopIndex); this.assembler.Move( new MemoryOperand(Register.BP, stackOffset), register); }
/// <summary> /// Pops an operand from the operand stack to the given register /// </summary> /// <param name="register">The register</param> public void PopRegister(FloatRegister register) { this.AssertNotEmpty(); int stackOffset = GetStackOperandOffset(this.operandTopIndex); this.assembler.Move( register, new MemoryOperand(Register.BP, stackOffset)); this.operandTopIndex--; }
/// <summary> /// Pops an operand from the operand stack to the given register /// </summary> /// <param name="register">The register</param> public void PopRegister(FloatRegister register) { this.AssertNotEmpty(); int stackOffset = GetStackOperandOffset(this.operandTopIndex); Assembler.Move( this.function.GeneratedCode, register, new MemoryOperand(Register.BP, stackOffset)); this.operandTopIndex--; }
/// <summary> /// Generates code for an instruction with a virtual register destination and fixed register source /// </summary> /// <param name="destinationRegister">The destination register</param> /// <param name="source">The source</param> /// <param name="skipIfSame">Indicates if the instruction will be skipped of destination == source.</param> public void GenerateTwoRegisterFixedSourceInstruction(VirtualRegister destinationRegister, FloatRegister source, Action<IList<byte>, FloatRegister, FloatRegister> inst1, Action<IList<byte>, MemoryOperand, FloatRegister> inst2, bool skipIfSame = false) { var generatedCode = compilationData.Function.GeneratedCode; var regAlloc = compilationData.RegisterAllocation; int? opStack = compilationData.RegisterAllocation.GetStackIndex(destinationRegister); if (!opStack.HasValue) { var opReg = this.GetFloatRegisterForVirtual(destinationRegister).Value; if (skipIfSame) { if (opReg != source) { inst1(generatedCode, opReg, source); } } else { inst1(generatedCode, opReg, source); } } else { var opStackOffset = CalculateStackOffset(opStack.Value); inst2(generatedCode, new MemoryOperand(Register.BP, opStackOffset), source); } }
/// <summary> /// Moves the content from a register to memory where the address is in a register + int offset /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="destinationMemoryRegister">The destination memory register</param> /// <param name="offset">The offset</param> /// <param name="source">The source register</param> public static void MoveRegisterToMemoryRegisterWithIntOffset( IList<byte> codeGenerator, Register destinationMemoryRegister, int offset, FloatRegister source) { codeGenerator.Add(0xf3); codeGenerator.Add(0x0f); codeGenerator.Add(0x11); if (destinationMemoryRegister != Register.SP) { codeGenerator.Add((byte)(0x80 | (byte)destinationMemoryRegister | (byte)((byte)source << 3))); } else { codeGenerator.Add((byte)(0x84 | (byte)((byte)source << 3))); codeGenerator.Add(0x24); } foreach (var component in BitConverter.GetBytes(offset)) { codeGenerator.Add(component); } }
/// <summary> /// Pops the given register /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="register">The register</param> public static void PopRegister(IList<byte> codeGenerator, FloatRegister register) { MoveMemoryByRegisterToRegister(codeGenerator, register, Register.SP); //movss <reg>, [rsp] AddByteToReg(codeGenerator, Register.SP, RegisterSize); //add rsp, <reg size> }
/// <summary> /// Divides the memory by the first register where the memory address is in the second register + offset /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="destination">The destination memory register</param> /// <param name="offset">The memory offset</param> /// <param name="sourceMemoryRegister">The source register</param> public static void DivMemoryRegisterWithIntOffsetFromRegister( IList<byte> codeGenerator, FloatRegister destination, Register sourceMemoryRegister, int offset) { if (sourceMemoryRegister != Register.SP) { codeGenerator.Add(0xf3); codeGenerator.Add(0x0f); codeGenerator.Add(0x5e); codeGenerator.Add((byte)(0x80 | (byte)sourceMemoryRegister | (byte)destination << 3)); } else { codeGenerator.Add(0xf3); codeGenerator.Add(0x0f); codeGenerator.Add(0x5e); codeGenerator.Add((byte)(0x84 | (byte)destination << 3)); codeGenerator.Add(0x24); } foreach (var component in BitConverter.GetBytes(offset)) { codeGenerator.Add(component); } }
/// <summary> /// Creates a new int register /// </summary> /// <param name="intRegister">The int register</param> public HardwareRegister(IntRegister intRegister) { this.IntRegister = intRegister; this.Type = HardwareRegisterType.Int; this.FloatRegister = FloatRegister.XMM0; }
/// <summary> /// Moves the content from memory where the address is in the second register to the first register /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="destination">The destination register</param> /// <param name="sourceMemoryRegister">The source memory register</param> public static void MoveMemoryByRegisterToRegister(IList<byte> codeGenerator, FloatRegister destination, Register sourceMemoryRegister) { codeGenerator.Add(0xf3); codeGenerator.Add(0x0f); codeGenerator.Add(0x10); switch (sourceMemoryRegister) { case Register.SP: codeGenerator.Add((byte)(0x04 | (byte)((byte)destination << 3))); codeGenerator.Add(0x24); break; case Register.BP: codeGenerator.Add((byte)(0x45 | (byte)((byte)destination << 3))); codeGenerator.Add(0x00); break; default: codeGenerator.Add((byte)((byte)sourceMemoryRegister | (byte)((byte)destination << 3))); break; } }
/// <summary> /// Moves the at the given memory address relative to the end of the current instruction to the given register /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="destination">The destination register</param> /// <param name="relativeAddress">The relative address</param> public static void MoveMemoryToRegister(IList<byte> codeGenerator, FloatRegister destination, int relativeAddress) { codeGenerator.Add(0xf3); codeGenerator.Add(0x0f); codeGenerator.Add(0x10); codeGenerator.Add((byte)(0x04 | (byte)((byte)destination << 3))); codeGenerator.Add(0x25); foreach (var component in BitConverter.GetBytes(relativeAddress)) { codeGenerator.Add(component); } }
/// <summary> /// Moves the content from a memory where the address is a register + int offset to a register /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="destination">The destination register</param> /// <param name="sourceMemoryRegister">The source memory register</param> /// <param name="offset">The offset</param> public static void MoveMemoryRegisterWithIntOffsetToRegister( IList<byte> codeGenerator, FloatRegister destination, ExtendedRegister sourceMemoryRegister, int offset) { codeGenerator.Add(0xf3); codeGenerator.Add(0x41); codeGenerator.Add(0x0f); codeGenerator.Add(0x10); codeGenerator.Add((byte)(0x80 | (byte)sourceMemoryRegister | (byte)((byte)destination << 3))); foreach (var component in BitConverter.GetBytes(offset)) { codeGenerator.Add(component); } }
/// <summary> /// Pushes the given register /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="register">The register</param> public static void PushRegister(IList<byte> codeGenerator, FloatRegister register) { SubByteFromRegister(codeGenerator, Register.SP, RegisterSize); //sub rsp, <reg size> MoveRegisterToMemoryRegisterWithByteOffset(codeGenerator, Register.SP, 0, register); //movss [rsp+0], <float reg> }
/// <summary> /// Converts the second register into an int and stores the result in the first register /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="destination">The destination</param> /// <param name="source">The source</param> public static void ConvertFloatToInt(IList<byte> codeGenerator, Register destination, FloatRegister source) { codeGenerator.Add(0xf3); codeGenerator.Add(0x48); codeGenerator.Add(0x0f); codeGenerator.Add(0x2c); codeGenerator.Add((byte)(0xc0 | (byte)source | (byte)((byte)destination << 3))); }
/// <summary> /// Compares a register and a memory address /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="register1">The first register</param> /// <param name="register2">The second register</param> /// <param name="register2MemoryOffset">The offset for register 2</param> public static void CompareRegisterToMemoryRegisterWithOffset( IList<byte> codeGenerator, FloatRegister register1, ExtendedRegister register2, int register2MemoryOffset) { codeGenerator.Add(0x41); codeGenerator.Add(0x0f); codeGenerator.Add(0x2e); codeGenerator.Add((byte)(0x80 | (byte)register2 | (byte)((byte)register1 << 3))); foreach (var component in BitConverter.GetBytes(register2MemoryOffset)) { codeGenerator.Add(component); } }
/// <summary> /// Compares the two registers /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="register1">The first register</param> /// <param name="register2">The second register</param> public static void CompareRegisterToRegister(IList<byte> codeGenerator, FloatRegister register1, FloatRegister register2) { codeGenerator.Add(0x0f); codeGenerator.Add(0x2e); codeGenerator.Add((byte)(0xc0 | (byte)register2 | (byte)((byte)register1 << 3))); }
/// <summary> /// Pushes the given register to the operand stack /// </summary> /// <param name="register">The register</param> public void PushRegister(FloatRegister register) { this.operandTopIndex++; int stackOffset = GetStackOperandOffset(this.operandTopIndex); //movss [rbp+<operand offset>], <reg> Assembler.Move( this.function.GeneratedCode, new MemoryOperand(Register.BP, stackOffset), register); }
/// <summary> /// Moves the content from a register to memory where the address is in a register + offset /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="destinationMemoryRegister">The destination memory register</param> /// <param name="offset">The offset</param> /// <param name="source">The source register</param> public static void MoveRegisterToMemoryRegisterWithOffset( IList<byte> codeGenerator, Register destinationMemoryRegister, int offset, FloatRegister source) { if (AssemblerHelpers.IsValidByteValue(offset)) { MoveRegisterToMemoryRegisterWithByteOffset(codeGenerator, destinationMemoryRegister, (byte)offset, source); } else { MoveRegisterToMemoryRegisterWithIntOffset(codeGenerator, destinationMemoryRegister, offset, source); } }
/// <summary> /// Moves the content from a register to memory where the address is in a register + byte offset /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="destinationMemoryRegister">The destination memory register</param> /// <param name="offset">The offset</param> /// <param name="source">The source register</param> public static void MoveRegisterToMemoryRegisterWithByteOffset( IList<byte> codeGenerator, Register destinationMemoryRegister, byte offset, FloatRegister source) { codeGenerator.Add(0xf3); codeGenerator.Add(0x0f); codeGenerator.Add(0x11); if (destinationMemoryRegister != Register.SP) { codeGenerator.Add((byte)(0x40 | (byte)destinationMemoryRegister | (byte)((byte)source << 3))); codeGenerator.Add(offset); } else { codeGenerator.Add((byte)(0x44 | (byte)((byte)source << 3))); codeGenerator.Add(0x24); codeGenerator.Add(offset); } }
/// <summary> /// Creates a new float register /// </summary> /// <param name="floatRegister">The float register</param> public HardwareRegister(FloatRegister floatRegister) { this.IntRegister = Register.AX; this.Type = HardwareRegisterType.Float; this.FloatRegister = floatRegister; }
/// <summary> /// Divides the second register from the first /// </summary> /// <param name="codeGenerator">The code generator</param> /// <param name="destination">The destination register</param> /// <param name="source">The source register</param> public static void DivRegisterFromRegister(IList<byte> codeGenerator, FloatRegister destination, FloatRegister source) { codeGenerator.Add(0xf3); codeGenerator.Add(0x0f); codeGenerator.Add(0x5e); codeGenerator.Add((byte)(0xc0 | (byte)source | (byte)((byte)destination << 3))); }