/// <summary> /// Pops an operand from the operand stack to the given register /// </summary> /// <param name="register">The register to pop to</param> public void PopRegister(IntRegister register) { this.AssertNotEmpty(); int stackOffset = GetStackOperandOffset(this.operandTopIndex); Assembler.Move( this.function.GeneratedCode, register, new MemoryOperand(Register.BP, stackOffset)); //mov <reg>, [rbp+<operand offset>] this.operandTopIndex--; }
/// <summary> /// Moves an argument to the stack /// </summary> /// <param name="compilationData">The compilation data</param> /// <param name="argumentIndex">The argument index</param> /// <param name="argumentType">The type of the argument</param> private void MoveArgumentToStack(CompilationData compilationData, int argumentIndex, VMType argumentType) { var generatedCode = compilationData.Function.GeneratedCode; int argStackOffset = -(1 + argumentIndex) * Assembler.RegisterSize; if (argumentIndex >= numRegisterArguments) { int stackArgumentIndex = this.GetStackArgumentIndex(compilationData, argumentIndex); var argStackSource = new MemoryOperand( Register.BP, Assembler.RegisterSize * (6 + stackArgumentIndex)); HardwareRegister tmpReg; if (argumentType.IsPrimitiveType(PrimitiveTypes.Float)) { tmpReg = compilationData.VirtualAssembler.GetFloatSpillRegister(); } else { tmpReg = new IntRegister(Register.AX); } Assembler.Move(generatedCode, tmpReg, argStackSource); Assembler.Move(generatedCode, new MemoryOperand(Register.BP, argStackOffset), tmpReg); } else { //var argReg = floatArgumentRegisters[argumentIndex]; HardwareRegister argReg; if (argumentType.IsPrimitiveType(PrimitiveTypes.Float)) { argReg = floatArgumentRegisters[argumentIndex]; } else { argReg = intArgumentRegisters[argumentIndex]; } Assembler.Move(generatedCode, new MemoryOperand(Register.BP, argStackOffset), argReg); } }
/// <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> /// Pushes the given register to the operand stack /// </summary> /// <param name="register">The register</param> public void PushRegister(IntRegister register) { this.operandTopIndex++; int stackOffset = GetStackOperandOffset(this.operandTopIndex); //mov [rbp+<operand offset>], <reg> Assembler.Move( this.function.GeneratedCode, new MemoryOperand(Register.BP, stackOffset), register); }
/// <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, IntRegister source, Action<IList<byte>, IntRegister, IntRegister> inst1, Action<IList<byte>, MemoryOperand, IntRegister> 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.GetIntRegisterForVirtual(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); } }