/// <summary> /// Generates code for an instruction with two virtual registers /// </summary> /// <param name="destinationRegister">The destination register</param> /// <param name="sourceRegister">The source register</param> /// <param name="memoryRewrite">Determines how an instruction with two memory operands will be rewritten into one memory operand.</param> public void GenerateTwoRegistersInstruction(VirtualRegister destinationRegister, VirtualRegister sourceRegister, Action<IList<byte>, IntRegister, IntRegister> inst1, Action<IList<byte>, IntRegister, MemoryOperand> inst2, Action<IList<byte>, MemoryOperand, IntRegister> inst3, MemoryRewrite memoryRewrite = MemoryRewrite.MemoryOnLeft) { var generatedCode = compilationData.Function.GeneratedCode; var regAlloc = compilationData.RegisterAllocation; int? op1Stack = compilationData.RegisterAllocation.GetStackIndex(destinationRegister); int? op2Stack = compilationData.RegisterAllocation.GetStackIndex(sourceRegister); if (!op1Stack.HasValue && !op2Stack.HasValue) { var op1Reg = this.GetIntRegisterForVirtual(destinationRegister).Value; var op2Reg = this.GetIntRegisterForVirtual(sourceRegister).Value; inst1(generatedCode, op1Reg, op2Reg); } else if (!op1Stack.HasValue && op2Stack.HasValue) { var op1Reg = this.GetIntRegisterForVirtual(destinationRegister).Value; var op2StackOffset = CalculateStackOffset(op2Stack.Value); inst2(generatedCode, op1Reg, new MemoryOperand(Register.BP, op2StackOffset)); } else if (op1Stack.HasValue && !op2Stack.HasValue) { var op1StackOffset = CalculateStackOffset(op1Stack.Value); var op2Reg = this.GetIntRegisterForVirtual(sourceRegister).Value; inst3(generatedCode, new MemoryOperand(Register.BP, op1StackOffset), op2Reg); } else { var op1StackOffset = CalculateStackOffset(op1Stack.Value); var op2StackOffset = CalculateStackOffset(op2Stack.Value); this.RewriteMemory( memoryRewrite, new MemoryOperand(Register.BP, op1StackOffset), new MemoryOperand(Register.BP, op2StackOffset), inst2, inst3); } }
/// <summary> /// Rewrites two memory operand instructions /// </summary> /// <param name="memoryRewrite">The memory rewrite rule</param> /// <param name="destination">The destination</param> /// <param name="source">The source</param> private void RewriteMemory(MemoryRewrite memoryRewrite, MemoryOperand destination, MemoryOperand source, Action<IList<byte>, FloatRegister, MemoryOperand> inst1, Action<IList<byte>, MemoryOperand, FloatRegister> inst2) { var generatedCode = compilationData.Function.GeneratedCode; var spillReg = this.GetFloatSpillRegister(); if (memoryRewrite == MemoryRewrite.MemoryOnLeft) { Assembler.Move(generatedCode, spillReg, source); inst2(generatedCode, destination, spillReg); } else { Assembler.Move(generatedCode, spillReg, destination); inst1(generatedCode, spillReg, source); Assembler.Move(generatedCode, destination, spillReg); } }
/// <summary> /// Generates code for an instruction with virtual register destination and memory source /// </summary> /// <param name="destinationRegister">The destination</param> /// <param name="source">The source</param> /// <param name="memoryRewrite">Determines how an instruction with two memory operands will be rewritten into one memory operand.</param> public void GenerateOneRegisterMemorySourceInstruction(VirtualRegister destinationRegister, MemoryOperand source, Action<IList<byte>, IntRegister, MemoryOperand> inst1, Action<IList<byte>, MemoryOperand, IntRegister> inst2, MemoryRewrite memoryRewrite = MemoryRewrite.MemoryOnLeft) { var generatedCode = compilationData.Function.GeneratedCode; var regAlloc = compilationData.RegisterAllocation; int? opStack = compilationData.RegisterAllocation.GetStackIndex(destinationRegister); if (!opStack.HasValue) { var destinationReg = this.GetIntRegisterForVirtual(destinationRegister).Value; inst1(generatedCode, destinationReg, source); } else { var opStackOffset = CalculateStackOffset(opStack.Value); RewriteMemory(memoryRewrite, new MemoryOperand(Register.BP, opStackOffset), source, inst1, inst2); } }