private static void HandleReturnSystemVAbi(IntrusiveList <Node> nodes, Node node, Operation operation) { if (operation.SourcesCount == 0) { return; } Operand source = operation.GetSource(0); if (source.Type == OperandType.V128) { Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64); Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64); nodes.AddBefore(node, new Operation(Instruction.VectorExtract, retLReg, source, Const(0))); nodes.AddBefore(node, new Operation(Instruction.VectorExtract, retHReg, source, Const(1))); } else { Operand retReg = source.Type.IsInteger() ? Gpr(CallingConvention.GetIntReturnRegister(), source.Type) : Xmm(CallingConvention.GetVecReturnRegister(), source.Type); Operation retCopyOp = new Operation(Instruction.Copy, retReg, source); nodes.AddBefore(node, retCopyOp); } }
private static Node HandleCallSystemVAbi(IntrusiveList <Node> nodes, Node node, Operation operation) { Operand dest = operation.Destination; List <Operand> sources = new List <Operand> { operation.GetSource(0) }; int argsCount = operation.SourcesCount - 1; int intMax = CallingConvention.GetIntArgumentsOnRegsCount(); int vecMax = CallingConvention.GetVecArgumentsOnRegsCount(); int intCount = 0; int vecCount = 0; int stackOffset = 0; for (int index = 0; index < argsCount; index++) { Operand source = operation.GetSource(index + 1); bool passOnReg; if (source.Type.IsInteger()) { passOnReg = intCount < intMax; } else if (source.Type == OperandType.V128) { passOnReg = intCount + 1 < intMax; } else { passOnReg = vecCount < vecMax; } if (source.Type == OperandType.V128 && passOnReg) { // V128 is a struct, we pass each half on a GPR if possible. Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64); Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64); nodes.AddBefore(node, new Operation(Instruction.VectorExtract, argReg, source, Const(0))); nodes.AddBefore(node, new Operation(Instruction.VectorExtract, argReg2, source, Const(1))); continue; } if (passOnReg) { Operand argReg = source.Type.IsInteger() ? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type) : Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type); Operation copyOp = new Operation(Instruction.Copy, argReg, source); HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); sources.Add(argReg); } else { Operand offset = new Operand(stackOffset); Operation spillOp = new Operation(Instruction.SpillArg, null, offset, source); HandleConstantCopy(nodes, nodes.AddBefore(node, spillOp), spillOp); stackOffset += source.Type.GetSizeInBytes(); } } if (dest != null) { if (dest.Type == OperandType.V128) { Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64); Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64); node = nodes.AddAfter(node, new Operation(Instruction.VectorCreateScalar, dest, retLReg)); node = nodes.AddAfter(node, new Operation(Instruction.VectorInsert, dest, dest, retHReg, Const(1))); operation.Destination = null; } else { Operand retReg = dest.Type.IsInteger() ? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type) : Xmm(CallingConvention.GetVecReturnRegister(), dest.Type); Operation copyOp = new Operation(Instruction.Copy, dest, retReg); node = nodes.AddAfter(node, copyOp); operation.Destination = retReg; } } operation.SetSources(sources.ToArray()); return(node); }