/*
* Copyright 2008 Cadence Design Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the ''License''); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/
/*
* dabusiness.h
*
* Written by Eliot Miranda 11/07.
* Changes by John M McIntosh 12/1/08 to support powerpc
*
* Body of the various callIA32XXXReturn functions.
* Call a foreign function according to IA32-ish ABI rules.
*/
long i, size;
double floatStorageArea[13];
sqInt funcAlien, resultMaybeAlien;
char *argvec;
#if STACK_ALIGN_BYTES
char *argstart;
#endif
for (i = numArgs, size = 0; --i >= 0;) {
sqInt arg = argVector[i];
if (objIsAlien(arg) && sizeField(arg))
size += moduloPOT(sizeof(long),abs(sizeField(arg)));
else if (interpreterProxy->isFloatObject(arg)) {
if (hasTypeArray)
size += figureOutFloatSize(typeSignatureArray,i);
else
size += sizeof(double);
}
else /* assume an integebr or pointer. check below. */
size += sizeof(long);
}
#if STACK_ALIGN_BYTES
/* At point of call stack must be aligned to STACK_ALIGN_BYTES. So alloca
* at least enough for this plus the argvector, and start writing argvector
* at aligned point. Then just prior to call cut-back stack to aligned.
*/
argvec = alloca(STACK_ALIGN_BYTES + moduloPOT(STACK_ALIGN_BYTES,size));
argvec = alignModuloPOT(STACK_ALIGN_BYTES, argvec);
argstart = argvec;
#endif
gpRegCount = 0;
fpRegCount = 0;
for (i = 0; i < numArgs; i++) {
sqInt arg = argVector[i];
if (isSmallInt(arg)) {
*(long *)argvec = intVal(arg);
if (gpRegCount < 8) gpRegCount++;
argvec += sizeof(long);
}
else if (objIsAlien(arg)) {
long argByteSize;
if (!(size = sizeField(arg)))
size = argByteSize = sizeof(void *);
else
argByteSize = abs(size);
switch (argByteSize) {
case (1):
memcpy(argvec+3, startOfDataWithSize(arg,size), argByteSize);
break;
case (2):
memcpy(argvec+2, startOfDataWithSize(arg,size), argByteSize);
break;
case (3):
memcpy(argvec+1, startOfDataWithSize(arg,size), argByteSize);
break;
default:
memcpy(argvec, startOfDataWithSize(arg,size), argByteSize);
}
long internalSructureSize = moduloPOT(sizeof(long), argByteSize);
if (gpRegCount < 8) gpRegCount += (internalSructureSize+3)/4;
if (gpRegCount > 8) gpRegCount = 8;
if (hasTypeArray) {
double v;
int sizeOfFloat = figureOutFloatSize(typeSignatureArray,i);
if (sizeOfFloat > 0) {
if (sizeOfFloat == sizeof(float)) {
float fv = *(float*)argvec;
v = fv;
} else {
v = *(double*)argvec;
}
if (fpRegCount < 13) { /* 13 registers for floating point numbers */
floatStorageArea[fpRegCount++] = v;
}
}
}
argvec += internalSructureSize;
}
else if (interpreterProxy->isFloatObject(arg)) {
double v = interpreterProxy->floatValueOf(arg);
if (interpreterProxy->failed())
return PrimErrBadArgument;
if (hasTypeArray && figureOutFloatSize(typeSignatureArray,i) == sizeof(float)) {
float floatv = v;
*(float *)argvec = floatv;
argvec += sizeof(float);
if (gpRegCount < 8) gpRegCount += 1;
} else {
*(double *)argvec = v;
argvec += sizeof(double);
if (gpRegCount < 8) gpRegCount += 2;
}
if (fpRegCount < 13) { /* 13 registers for floating point numbers */
floatStorageArea[fpRegCount++] = v;
}
if (gpRegCount > 8) gpRegCount = 8;
} else if (objIsUnsafeAlien(arg)) {
sqInt bitsObj = interpreterProxy->fetchPointerofObject(0,arg);
void *v = interpreterProxy->firstIndexableField(bitsObj);
*(void **)argvec = v;
if (gpRegCount < 8) gpRegCount++;
argvec += sizeof(long);
}else {
long v = interpreterProxy->signed32BitValueOf(arg);
if (interpreterProxy->failed())
return PrimErrBadArgument;
*(long *)argvec = v;
gpRegCount++;
if (gpRegCount < 8) gpRegCount++;
argvec += sizeof(long);
}
}
funcAlien = interpreterProxy->stackValue(funcOffset);
ffiStackIndex = (argvec-argstart)/4;
GPRegsLocation = ffiStackLocation = (long *) argstart;
FPRegsLocation = &floatStorageArea[0];
f = *(void **)startOfParameterData(funcAlien);
#if STACK_ALIGN_BYTES
/* cut stack back to start of aligned args */
// setsp(0);
#endif
ffiCallAddressOf(f);
|