mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Implement the real calling convention for ppc32 Altivec:
vectors go at the end of the memory area, after all non-vector parameters. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48364 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
029d9dafa0
commit
8f5422c24b
@ -1351,6 +1351,59 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op,
|
|||||||
|
|
||||||
const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32;
|
const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32;
|
||||||
|
|
||||||
|
// In 32-bit non-varargs functions, the stack space for vectors is after the
|
||||||
|
// stack space for non-vectors. We do not use this space unless we have
|
||||||
|
// too many vectors to fit in registers, something that only occurs in
|
||||||
|
// constructed examples:), but we have to walk the arglist to figure
|
||||||
|
// that out...for the pathological case, compute VecArgOffset as the
|
||||||
|
// start of the vector parameter area. Computing VecArgOffset is the
|
||||||
|
// entire point of the following loop.
|
||||||
|
// Altivec is not mentioned in the ppc32 Elf Supplement, so I'm not trying
|
||||||
|
// to handle Elf here.
|
||||||
|
unsigned VecArgOffset = ArgOffset;
|
||||||
|
if (!isVarArg && !isPPC64) {
|
||||||
|
for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e;
|
||||||
|
++ArgNo) {
|
||||||
|
MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType();
|
||||||
|
unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8;
|
||||||
|
ISD::ParamFlags::ParamFlagsTy Flags =
|
||||||
|
cast<ConstantSDNode>(Op.getOperand(ArgNo+3))->getValue();
|
||||||
|
unsigned isByVal = Flags & ISD::ParamFlags::ByVal;
|
||||||
|
|
||||||
|
if (isByVal) {
|
||||||
|
// ObjSize is the true size, ArgSize rounded up to multiple of regs.
|
||||||
|
ObjSize = (Flags & ISD::ParamFlags::ByValSize) >>
|
||||||
|
ISD::ParamFlags::ByValSizeOffs;
|
||||||
|
unsigned ArgSize =
|
||||||
|
((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
|
||||||
|
VecArgOffset += ArgSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(ObjectVT) {
|
||||||
|
default: assert(0 && "Unhandled argument type!");
|
||||||
|
case MVT::i32:
|
||||||
|
case MVT::f32:
|
||||||
|
VecArgOffset += isPPC64 ? 8 : 4;
|
||||||
|
break;
|
||||||
|
case MVT::i64: // PPC64
|
||||||
|
case MVT::f64:
|
||||||
|
VecArgOffset += 8;
|
||||||
|
break;
|
||||||
|
case MVT::v4f32:
|
||||||
|
case MVT::v4i32:
|
||||||
|
case MVT::v8i16:
|
||||||
|
case MVT::v16i8:
|
||||||
|
// Nothing to do, we're only looking at Nonvector args here.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We've found where the vector parameter area in memory is. Skip the
|
||||||
|
// first 12 parameters; these don't use that memory.
|
||||||
|
VecArgOffset = ((VecArgOffset+15)/16)*16;
|
||||||
|
VecArgOffset += 12*16;
|
||||||
|
|
||||||
// Add DAG nodes to load the arguments or copy them out of registers. On
|
// Add DAG nodes to load the arguments or copy them out of registers. On
|
||||||
// entry to a function on PPC, the arguments start after the linkage area,
|
// entry to a function on PPC, the arguments start after the linkage area,
|
||||||
// although the first ones are often in registers.
|
// although the first ones are often in registers.
|
||||||
@ -1535,11 +1588,16 @@ PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op,
|
|||||||
}
|
}
|
||||||
++VR_idx;
|
++VR_idx;
|
||||||
} else {
|
} else {
|
||||||
// Stack offset is aligned.
|
if (!isVarArg && !isPPC64) {
|
||||||
while (ArgOffset % 16 !=0) {
|
// Vectors go after all the nonvectors.
|
||||||
ArgOffset += PtrByteSize;
|
CurArgOffset = VecArgOffset;
|
||||||
|
VecArgOffset += 16;
|
||||||
|
} else {
|
||||||
|
// Vectors are aligned.
|
||||||
|
ArgOffset = ((ArgOffset+15)/16)*16;
|
||||||
|
CurArgOffset = ArgOffset;
|
||||||
|
ArgOffset += 16;
|
||||||
}
|
}
|
||||||
ArgOffset += 16;
|
|
||||||
needsLoad = true;
|
needsLoad = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1712,14 +1770,27 @@ SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG,
|
|||||||
unsigned NumBytes = PPCFrameInfo::getLinkageSize(isPPC64, isMachoABI);
|
unsigned NumBytes = PPCFrameInfo::getLinkageSize(isPPC64, isMachoABI);
|
||||||
|
|
||||||
// Add up all the space actually used.
|
// Add up all the space actually used.
|
||||||
|
// In 32-bit non-varargs calls, Altivec parameters all go at the end; usually
|
||||||
|
// they all go in registers, but we must reserve stack space for them for
|
||||||
|
// possible use by the caller. In varargs or 64-bit calls, parameters are
|
||||||
|
// assigned stack space in order, with padding so Altivec parameters are
|
||||||
|
// 16-byte aligned.
|
||||||
|
unsigned nAltivecParamsAtEnd = 0;
|
||||||
for (unsigned i = 0; i != NumOps; ++i) {
|
for (unsigned i = 0; i != NumOps; ++i) {
|
||||||
SDOperand Arg = Op.getOperand(5+2*i);
|
SDOperand Arg = Op.getOperand(5+2*i);
|
||||||
MVT::ValueType ArgVT = Arg.getValueType();
|
MVT::ValueType ArgVT = Arg.getValueType();
|
||||||
// Non-varargs Altivec parameters do not have corresponding stack space.
|
if (ArgVT==MVT::v4f32 || ArgVT==MVT::v4i32 ||
|
||||||
if (!isVarArg &&
|
ArgVT==MVT::v8i16 || ArgVT==MVT::v16i8) {
|
||||||
(ArgVT==MVT::v4f32 || ArgVT==MVT::v4i32 ||
|
if (!isVarArg && !isPPC64) {
|
||||||
ArgVT==MVT::v8i16 || ArgVT==MVT::v16i8))
|
// Non-varargs Altivec parameters go after all the non-Altivec parameters;
|
||||||
continue;
|
// do those last so we know how much padding we need.
|
||||||
|
nAltivecParamsAtEnd++;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// Varargs and 64-bit Altivec parameters are padded to 16 byte boundary.
|
||||||
|
NumBytes = ((NumBytes+15)/16)*16;
|
||||||
|
}
|
||||||
|
}
|
||||||
ISD::ParamFlags::ParamFlagsTy Flags =
|
ISD::ParamFlags::ParamFlagsTy Flags =
|
||||||
cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue();
|
cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue();
|
||||||
unsigned ArgSize =MVT::getSizeInBits(Op.getOperand(5+2*i).getValueType())/8;
|
unsigned ArgSize =MVT::getSizeInBits(Op.getOperand(5+2*i).getValueType())/8;
|
||||||
@ -1727,12 +1798,13 @@ SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG,
|
|||||||
ArgSize = (Flags & ISD::ParamFlags::ByValSize) >>
|
ArgSize = (Flags & ISD::ParamFlags::ByValSize) >>
|
||||||
ISD::ParamFlags::ByValSizeOffs;
|
ISD::ParamFlags::ByValSizeOffs;
|
||||||
ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
|
ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
|
||||||
// Varargs Altivec parameters are padded to a 16 byte boundary.
|
|
||||||
if (ArgVT==MVT::v4f32 || ArgVT==MVT::v4i32 ||
|
|
||||||
ArgVT==MVT::v8i16 || ArgVT==MVT::v16i8)
|
|
||||||
NumBytes = ((NumBytes+15)/16)*16;
|
|
||||||
NumBytes += ArgSize;
|
NumBytes += ArgSize;
|
||||||
}
|
}
|
||||||
|
// Allow for Altivec parameters at the end, if needed.
|
||||||
|
if (nAltivecParamsAtEnd) {
|
||||||
|
NumBytes = ((NumBytes+15)/16)*16;
|
||||||
|
NumBytes += 16*nAltivecParamsAtEnd;
|
||||||
|
}
|
||||||
|
|
||||||
// The prolog code of the callee may store up to 8 GPR argument registers to
|
// The prolog code of the callee may store up to 8 GPR argument registers to
|
||||||
// the stack, allowing va_start to index over them in memory if its varargs.
|
// the stack, allowing va_start to index over them in memory if its varargs.
|
||||||
@ -1984,23 +2056,48 @@ SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (VR_idx == NumVRs) {
|
// Non-varargs Altivec params generally go in registers, but have
|
||||||
// Out of V registers; these go aligned on the stack.
|
// stack space allocated at the end.
|
||||||
while (ArgOffset % 16 !=0) {
|
if (VR_idx != NumVRs) {
|
||||||
ArgOffset += PtrByteSize;
|
// Doesn't have GPR space allocated.
|
||||||
}
|
RegsToPass.push_back(std::make_pair(VR[VR_idx++], Arg));
|
||||||
|
} else if (nAltivecParamsAtEnd==0) {
|
||||||
|
// We are emitting Altivec params in order.
|
||||||
PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr,
|
PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr,
|
||||||
DAG.getConstant(ArgOffset, PtrVT));
|
DAG.getConstant(ArgOffset, PtrVT));
|
||||||
SDOperand Store = DAG.getStore(Chain, Arg, PtrOff, NULL, 0);
|
SDOperand Store = DAG.getStore(Chain, Arg, PtrOff, NULL, 0);
|
||||||
MemOpChains.push_back(Store);
|
MemOpChains.push_back(Store);
|
||||||
ArgOffset += 16;
|
ArgOffset += 16;
|
||||||
} else {
|
|
||||||
// Doesn't have memory or GPR space allocated
|
|
||||||
RegsToPass.push_back(std::make_pair(VR[VR_idx++], Arg));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If all Altivec parameters fit in registers, as they usually do,
|
||||||
|
// they get stack space following the non-Altivec parameters. We
|
||||||
|
// don't track this here because nobody below needs it.
|
||||||
|
// If there are more Altivec parameters than fit in registers emit
|
||||||
|
// the stores here.
|
||||||
|
if (!isVarArg && nAltivecParamsAtEnd > NumVRs) {
|
||||||
|
unsigned j = 0;
|
||||||
|
// Offset is aligned; skip 1st 12 params which go in V registers.
|
||||||
|
ArgOffset = ((ArgOffset+15)/16)*16;
|
||||||
|
ArgOffset += 12*16;
|
||||||
|
for (unsigned i = 0; i != NumOps; ++i) {
|
||||||
|
SDOperand Arg = Op.getOperand(5+2*i);
|
||||||
|
MVT::ValueType ArgType = Arg.getValueType();
|
||||||
|
if (ArgType==MVT::v4f32 || ArgType==MVT::v4i32 ||
|
||||||
|
ArgType==MVT::v8i16 || ArgType==MVT::v16i8) {
|
||||||
|
if (++j > NumVRs) {
|
||||||
|
SDOperand PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr,
|
||||||
|
DAG.getConstant(ArgOffset, PtrVT));
|
||||||
|
SDOperand Store = DAG.getStore(Chain, Arg, PtrOff, NULL, 0);
|
||||||
|
MemOpChains.push_back(Store);
|
||||||
|
ArgOffset += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!MemOpChains.empty())
|
if (!MemOpChains.empty())
|
||||||
Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
|
Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
|
||||||
&MemOpChains[0], MemOpChains.size());
|
&MemOpChains[0], MemOpChains.size());
|
||||||
|
Loading…
Reference in New Issue
Block a user