Revision: 3405
Author: eliot
Date: 2015-07-16 11:54:51 -0700 (Thu, 16 Jul 2015)
Log Message:
-----------
Update the Alien call-in/out support for ARM. In particular, add fp support for callbacks.
Modified Paths:
--------------
trunk/platforms/Cross/plugins/IA32ABI/arm32ia32abicc.c
trunk/platforms/Cross/plugins/IA32ABI/dabusinessARM.h
trunk/platforms/Cross/plugins/IA32ABI/ia32abi.h
Property Changed:
----------------
trunk/platforms/Cross/plugins/sqPluginsSCCSVersion.h
Modified: trunk/platforms/Cross/plugins/IA32ABI/arm32ia32abicc.c
===================================================================
--- trunk/platforms/Cross/plugins/IA32ABI/arm32ia32abicc.c 2015-07-16 15:25:58 UTC (rev 3404)
+++ trunk/platforms/Cross/plugins/IA32ABI/arm32ia32abicc.c 2015-07-16 18:54:51 UTC (rev 3405)
@@ -2,7 +2,7 @@
* armia32abicc.c
*
* Support for Call-outs and Call-backs from the Plugin on ARM.
- * Written by Eliot Miranda 07/15.
+ * Written by Eliot Miranda & Ryan Macnak, 07/15.
*/
#include <stdlib.h> /* for valloc */
@@ -22,79 +22,95 @@
# define min(a,b) ((a) < (b) ? (a) : (b))
#endif
+#define STACK_ALIGN_BYTES 8
+#define NUM_REG_ARGS 4
+#define NUM_DREG_ARGS 8
+
#ifdef SQUEAK_BUILTIN_PLUGIN
extern
-#endif
+#endif
struct VirtualMachine* interpreterProxy;
#ifdef _MSC_VER
# define alloca _alloca
#endif
-#if __GNUC__
-# define setsp(sp) asm volatile ("ldr %%sp, %0" : : "m"(sp))
-# define getsp() ({ void *sp; asm volatile ("movl %%sp,%0" : "=r"(sp) : ); sp;})
-#endif
-#if __linux__
-# define STACK_ALIGN_BYTES 16
-#endif
-#if !defined(setsp)
-# define setsp(ignored) 0
-#endif
+#define RoundUpPowerOfTwo(value, modulus) \
+ (((value) + (modulus) - 1) & ~((modulus) - 1))
-#define moduloPOT(m,v) (((v)+(m)-1) & ~((m)-1))
-#define alignModuloPOT(m,v) ((void *)moduloPOT(m,(unsigned long)(v)))
+#define IsAlignedPowerOfTwo(value, modulus) \
+ (((value) & ((modulus) - 1)) == 0)
-#define objIsAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classAlien()))
-#define objIsUnsafeAlien(anOop) (interpreterProxy->includesBehaviorThatOf(interpreterProxy->fetchClassOf(anOop), interpreterProxy->classUnsafeAlien()))
+#define objIsAlien(anOop) \
+ (interpreterProxy->includesBehaviorThatOf( \
+ interpreterProxy->fetchClassOf(anOop), \
+ interpreterProxy->classAlien()))
-#define sizeField(alien) (*(long *)pointerForOop((sqInt)(alien) + BaseHeaderSize))
-#define dataPtr(alien) pointerForOop((sqInt)(alien) + BaseHeaderSize + BytesPerOop)
-#if 0 /* obsolete after adding pointer Aliens with size field == 0 */
-# define isIndirectOrPointer(alien) (sizeField(alien) <= 0)
-# define startOfData(alien) (isIndirectOrPointer(alien) \
- ? *(void **)dataPtr(alien) \
- : (void *)dataPtr(alien))
-#endif
-#define isIndirect(alien) (sizeField(alien) < 0)
-#define startOfParameterData(alien) (isIndirect(alien) \
- ? *(void **)dataPtr(alien) \
- : (void *)dataPtr(alien))
-#define isIndirectSize(size) ((size) < 0)
-#define startOfDataWithSize(alien,size) (isIndirectSize(size) \
- ? *(void **)dataPtr(alien) \
- : (void *)dataPtr(alien))
+#define objIsUnsafeAlien(anOop) \
+ (interpreterProxy->includesBehaviorThatOf( \
+ interpreterProxy->fetchClassOf(anOop), \
+ interpreterProxy->classUnsafeAlien()))
-#define isSmallInt(oop) ((oop)&1)
-#define intVal(oop) (((long)(oop))>>1)
+#define sizeField(alien) \
+ (*(long*)pointerForOop((sqInt)(alien) + BaseHeaderSize))
+#define dataPtr(alien) \
+ pointerForOop((sqInt)(alien) + BaseHeaderSize + BytesPerOop)
+
+#define isIndirect(alien) \
+ (sizeField(alien) < 0)
+
+#define startOfParameterData(alien) \
+ (isIndirect(alien) ? *(void **)dataPtr(alien) \
+ : (void *)dataPtr(alien))
+
+#define isIndirectSize(size) \
+ ((size) < 0)
+
+#define startOfDataWithSize(alien, size) \
+ (isIndirectSize(size) ? *(void **)dataPtr(alien) \
+ : (void *)dataPtr(alien))
+
+#define isSmallInt(oop) \
+ ((oop)&1)
+
+#define intVal(oop) \
+ (((long)(oop))>>1)
+
/*
- * Call a foreign function that answers an integral result in %eax (and
- * possibly %edx) according to IA32-ish ABI rules.
+ * Call a foreign function that answers an integral result in r0 according to
+ * ARM EABI rules.
*/
-sqInt
-callIA32IntegralReturn(SIGNATURE) {
-long long (*f)(long a,long b,long c,long d), r;
+sqInt callIA32IntegralReturn(SIGNATURE) {
+ long (*f)(long r0, long r1, long r2, long r3,
+ double d0, double d1, double d2, double d3,
+ double d4, double d5, double d6, double d7);
+ long r;
#include "dabusinessARM.h"
}
/*
* Call a foreign function that answers a single-precision floating-point
- * result in %f0 according to IA32-ish ABI rules.
+ * result in VFP's s0 according to ARM EABI rules.
*/
-sqInt
-callIA32FloatReturn(SIGNATURE) {
-float (*f)(long a,long b,long c,long d), r;
+sqInt callIA32FloatReturn(SIGNATURE) {
+ float (*f)(long r0, long r1, long r2, long r3,
+ double d0, double d1, double d2, double d3,
+ double d4, double d5, double d6, double d7);
+ float r;
#include "dabusinessARM.h"
}
/*
* Call a foreign function that answers a double-precision floating-point
- * result in %f0 according to IA32-ish ABI rules.
+ * result in VFP's d0 according to ARM EABI rules.
*/
sqInt
callIA32DoubleReturn(SIGNATURE) {
-double (*f)(long a,long b,long c,long d), r;
+ double (*f)(long r0, long r1, long r2, long r3,
+ double d0, double d1, double d2, double d3,
+ double d4, double d5, double d6, double d7);
+ double r;
#include "dabusinessARM.h"
}
@@ -112,109 +128,92 @@
#define getRMCC(t) mostRecentCallbackContext
#define setRMCC(t) (mostRecentCallbackContext = (void *)(t))
+extern void error(char *s);
+
/*
- * Entry-point for call-back thunks. Args are thunk address and stack pointer,
- * where the stack pointer is pointing one word below the return address of the
- * thunk's callee, 4 bytes below the thunk's first argument. The stack is:
- * callback
- * arguments
- * retpc (thunk) <--\
- * address of retpc-/ <--\
- * address of address of ret pc-/
- * thunkp
- * esp->retpc (thunkEntry)
+ * Entry-point for call-back thunks. Args are register args, thunk address
+ * and stack pointer.
+ * The stack is:
+ * stackp
+ * sp->thunk address
*
- * The stack pointer is pushed twice to keep the stack alignment to 16 bytes, a
- * requirement on platforms using SSE2 such as Mac OS X, and harmless elsewhere.
- *
- * This function's roles are to use setjmp/longjmp to save the call point
- * and return to it, to correct C stack pointer alignment if necessary (see
+ * This function's roles are to collect any register arguments (including
+ * floating point), to use setjmp/longjmp to save the point of call and
+ * return to it, to correct C stack pointer alignment if necessary (see
* STACK_ALIGN_HACK), and to return any of the various values from the callback.
- *
- * Looking forward to support for x86-64, which typically has 6 register
- * arguments, the function would take 8 arguments, the 6 register args as
- * longs, followed by the thunkp and stackp passed on the stack. The register
- * args would get copied into a struct on the stack. A pointer to the struct
- * is then passed as an element of the VMCallbackContext.
*/
long
-thunkEntry(long r0, long r1, long r2, long r3, void *thunkp, long *stackp)
+thunkEntry(long r0, long r1, long r2, long r3,
+ double d0, double d1, double d2, double d3,
+ double d4, double d5, double d6, double d7,
+ void* thunkp, long* stackp)
{
- VMCallbackContext vmcc;
- VMCallbackContext *previousCallbackContext;
- int flags, returnType;
- long regArgs[4];
+ VMCallbackContext vmcc;
+ VMCallbackContext* previousCallbackContext;
+ int flags;
+ int returnType;
+ long regArgs[NUM_REG_ARGS];
+ double dregArgs[NUM_DREG_ARGS];
-#if STACK_ALIGN_HACK
- { void *sp = getsp();
- int offset = (unsigned long)sp & (STACK_ALIGN_BYTES - 1);
- if (offset) {
-# if __GNUC__
- asm("sub %0,%%sp" : : "m"(offset));
-# else
-# error need to subtract offset from esp
-# endif
- sp = getsp();
- assert(!((unsigned long)sp & (STACK_ALIGN_BYTES - 1)));
- }
- }
-#endif /* STACK_ALIGN_HACK */
+ regArgs[0] = r0;
+ regArgs[1] = r1;
+ regArgs[2] = r2;
+ regArgs[3] = r3;
- regArgs[0] = r0; regArgs[1] = r1; regArgs[2] = r2; regArgs[3] = r3;
+ dregArgs[0] = d0;
+ dregArgs[1] = d1;
+ dregArgs[2] = d2;
+ dregArgs[3] = d3;
+ dregArgs[4] = d4;
+ dregArgs[5] = d5;
+ dregArgs[6] = d6;
+ dregArgs[7] = d7;
- if ((flags = interpreterProxy->ownVM(0)) < 0) {
- fprintf(stderr,"Warning; callback failed to own the VM\n");
- return -1;
- }
+ flags = interpreterProxy->ownVM(0);
+ if (flags < 0) {
+ fprintf(stderr,"Warning; callback failed to own the VM\n");
+ return -1;
+ }
- if (!(returnType = setjmp(vmcc.trampoline))) {
- previousCallbackContext = getRMCC();
- setRMCC(&vmcc);
- vmcc.thunkp = thunkp;
- vmcc.stackp = stackp + 2; /* skip address of retpc & retpc (thunk) */
- vmcc.intregargsp = regArgs;
- vmcc.floatregargsp = 0;
- interpreterProxy->sendInvokeCallbackContext(&vmcc);
- fprintf(stderr,"Warning; callback failed to invoke\n");
- setRMCC(previousCallbackContext);
- interpreterProxy->disownVM(flags);
- return -1;
- }
- setRMCC(previousCallbackContext);
- interpreterProxy->disownVM(flags);
+ if ((returnType = setjmp(vmcc.trampoline)) == 0) {
+ previousCallbackContext = getRMCC();
+ setRMCC(&vmcc);
+ vmcc.thunkp = thunkp;
+ vmcc.stackp = stackp + 2; /* skip address of retpc & retpc (thunk) */
+ vmcc.intregargsp = regArgs;
+ vmcc.floatregargsp = dregArgs;
+ interpreterProxy->sendInvokeCallbackContext(&vmcc);
+ fprintf(stderr,"Warning; callback failed to invoke\n");
+ setRMCC(previousCallbackContext);
+ interpreterProxy->disownVM(flags);
+ return -1;
+ }
- switch (returnType) {
+ setRMCC(previousCallbackContext);
+ interpreterProxy->disownVM(flags);
- case retword: return vmcc.rvs.valword;
+ switch (returnType) {
+ case retword: {
+ return vmcc.rvs.valword;
+ }
+ case retword64: {
+ long long* valint64Ptr = (long long*)&vmcc.rvs.valleint64;
+ return *valint64Ptr;
+ }
+ case retdouble: {
+ double valflt64 = vmcc.rvs.valflt64;
+ error("Callback return double unimplemented");
+ return 0;
+ }
+ case retstruct: {
+ // wrong
+ memcpy( (void *)(stackp[1]), vmcc.rvs.valstruct.addr, vmcc.rvs.valstruct.size);
+ return stackp[1];
+ }
+ }
- case retword64: {
- long vhigh = vmcc.rvs.valleint64.high;
-#if __GNUC__
- asm("ldr %%r1,%0" : : "m"(vhigh));
-#else
-# error need to load r1 with vmcc.rvs.valleint64.high on this compiler
-#endif
- return vmcc.rvs.valleint64.low;
- }
-
- case retdouble: {
- double valflt64 = vmcc.rvs.valflt64;
-#if 0
-# error need to load float return register with vmcc.rvs.valflt64 on this compiler
-#else
- extern void error(char *s);
- error("need to load float return register with vmcc.rvs.valflt64 on this compiler");
-#endif
- return 0;
- }
-
- case retstruct: memcpy( (void *)(stackp[1]),
- vmcc.rvs.valstruct.addr,
- vmcc.rvs.valstruct.size);
- return stackp[1];
- }
- fprintf(stderr,"Warning; invalid callback return type\n");
- return 0;
+ fprintf(stderr, "Warning; invalid callback return type\n");
+ return 0;
}
/*
Modified: trunk/platforms/Cross/plugins/IA32ABI/dabusinessARM.h
===================================================================
--- trunk/platforms/Cross/plugins/IA32ABI/dabusinessARM.h 2015-07-16 15:25:58 UTC (rev 3404)
+++ trunk/platforms/Cross/plugins/IA32ABI/dabusinessARM.h 2015-07-16 18:54:51 UTC (rev 3405)
@@ -1,159 +1,191 @@
/*
* dabusinessARM.h
*
+ * Ryan Macnak, Eliot Miranda, 7/15
+ *
* Body of the various callIA32XXXReturn functions.
* Call a foreign function according to ARM-ish ABI rules.
* N.B. In Cog Stack and Cogit VMs numArgs is negative to access args from
* the downward-growing stack.
*/
- long i, size, regs[4];
- sqInt funcAlien, resultMaybeAlien;
- char *argvec;
-#if STACK_ALIGN_BYTES
- char *argstart;
-#endif
-#if STACKVM /* Need to access args downwards from first arg */
- if (numArgs < 0)
- for (i = size = 0; --i >= numArgs;) {
- sqInt arg = argVector[i+1];
- if (objIsAlien(arg) && sizeField(arg))
- size += moduloPOT(sizeof(long),abs(sizeField(arg)));
- else if (interpreterProxy->isFloatObject(arg))
- size += sizeof(double);
- else /* assume an integer or pointer. check below. */
- size += sizeof(long);
+ long i;
+ long size;
+ long nextReg;
+ long nextDReg;
+ long regs[NUM_REG_ARGS];
+ double dregs[NUM_DREG_ARGS];
+ sqInt funcAlien;
+ sqInt resultMaybeAlien;
+ long argvec;
+ long argstart;
+
+ assert(sizeof(long) == sizeof(void*));
+
+ if (numArgs < 0) {
+ /* Stack or Cog VM. Need to access args downwards from first arg. */
+ for (i = size = 0; --i >= numArgs;) {
+ sqInt arg = argVector[i + 1];
+ if (objIsAlien(arg) && (sizeField(arg) != 0))
+ /* Direct or indirect Alien. */
+ size += RoundUpPowerOfTwo(abs(sizeField(arg)), sizeof(long));
+ else if (interpreterProxy->isFloatObject(arg))
+ size += sizeof(double);
+ else
+ /* Assume an integer or pointer Alien. Check below. */
+ size += sizeof(long);
+ }
}
- else
-#endif /* STACKVM */
- 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))
- size += sizeof(double);
- else /* assume an integer or pointer. check below. */
- size += sizeof(long);
+ else {
+ /* Context Interpreter or array version of callout primitive. */
+ for (i = numArgs, size = 0; --i >= 0;) {
+ sqInt arg = argVector[i];
+ if (objIsAlien(arg) && (sizeField(arg) != 0))
+ /* Direct or indirect Alien. */
+ size += RoundUpPowerOfTwo(abs(sizeField(arg)), sizeof(long));
+ else if (interpreterProxy->isFloatObject(arg))
+ size += sizeof(double);
+ else
+ /* Assume an integer or pointer Alien. 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;
-#else
- argvec = alloca(moduloPOT(sizeof(long),size));
-# if defined(__MINGW32__) && (__GNUC__ >= 3)
- /*
- * cygwin & MinGW's gcc 3.4.x's alloca is a library routine that answers
- * %esp + 4, so the outgoing stack is offset by one word if uncorrected.
- * Grab the actual stack pointer to correct.
- */
- argvec = getsp();
-# endif
-#endif
+ argstart = argvec = (long)alloca(size);
-#if STACKVM /* Need to access args downwards from first arg */
- if (numArgs < 0)
- for (i = size = 0; --i >= numArgs;) {
- sqInt arg = argVector[i+1];
- if (isSmallInt(arg)) {
- *(long *)argvec = intVal(arg);
- argvec += sizeof(long);
- }
- else if (objIsAlien(arg)) {
- long argByteSize;
+ assert(IsAlignedPowerOfTwo(argvec, STACK_ALIGN_BYTES));
- if (!(size = sizeField(arg)))
- size = argByteSize = sizeof(void *);
- else
- argByteSize = abs(size);
- memcpy(argvec, startOfDataWithSize(arg,size), argByteSize);
- argvec += moduloPOT(sizeof(long), argByteSize);
- }
- else if (objIsUnsafeAlien(arg)) {
- sqInt bitsObj = interpreterProxy->fetchPointerofObject(0,arg);
- void *v = interpreterProxy->firstIndexableField(bitsObj);
- *(void **)argvec = v;
- argvec += sizeof(long);
- }
- else if (interpreterProxy->isFloatObject(arg)) {
- double d = interpreterProxy->floatValueOf(arg);
- *(double *)argvec = d;
- argvec += sizeof(double);
- }
- else {
- long v = interpreterProxy->signed32BitValueOf(arg);
- if (interpreterProxy->failed()) {
- interpreterProxy->primitiveFailFor(0);
- v = interpreterProxy->positive32BitValueOf(arg);
- if (interpreterProxy->failed())
- return PrimErrBadArgument;
+ nextReg = 0;
+ nextDReg = 0;
+
+#define MaybePassAsRegArg(expr) \
+ if (nextReg < NUM_REG_ARGS) \
+ regs[nextReg++] = expr; \
+ else { \
+ *(long*)argvec = expr; \
+ argvec += sizeof(long); \
+ }
+
+#define MaybePassAsDRegArg(expr) \
+ if (nextDReg < NUM_DREG_ARGS) \
+ dregs[nextDReg++] = expr; \
+ else { \
+ argvec = RoundUpPowerOfTwo(argvec, sizeof(double)); \
+ *(double*) argvec = expr; \
+ argvec += sizeof(double); \
+ }
+
+ if (numArgs < 0) {
+ /* Stack or Cog VM. Need to access args downwards from first arg. */
+ for (i = size = 0; --i >= numArgs;) {
+ sqInt arg = argVector[i+1];
+ if (isSmallInt(arg)) {
+ MaybePassAsRegArg(intVal(arg))
}
- *(long *)argvec = v;
- argvec += sizeof(long);
+ else if (objIsAlien(arg)) {
+ long argByteSize;
+ if ((size = sizeField(arg)) == 0) /* Pointer Alien. */
+ size = argByteSize = sizeof(void *);
+ else /* Direct or indirect Alien. */
+ argByteSize = abs(size);
+ /* TODO(rmacnak): Structs larger than word size should be split
+ * between remaining registers and the stack.
+ */
+ if ((argByteSize <= sizeof(long)) && (nextReg < NUM_REG_ARGS)) {
+ regs[nextReg++] = *(long*)startOfDataWithSize(arg, size);
+ }
+ else {
+ memcpy((void*)argvec, startOfDataWithSize(arg, size), argByteSize);
+ argvec += RoundUpPowerOfTwo(argByteSize, sizeof(long));
+ }
+ }
+ else if (objIsUnsafeAlien(arg)) {
+ sqInt bitsObj = interpreterProxy->fetchPointerofObject(0,arg);
+ long v = (long)interpreterProxy->firstIndexableField(bitsObj);
+ MaybePassAsRegArg(v)
+ }
+ else if (interpreterProxy->isFloatObject(arg)) {
+ double d = interpreterProxy->floatValueOf(arg);
+ MaybePassAsDRegArg(d)
+ }
+ else {
+ long v = interpreterProxy->signed32BitValueOf(arg);
+ if (interpreterProxy->failed()) {
+ interpreterProxy->primitiveFailFor(0);
+ v = interpreterProxy->positive32BitValueOf(arg);
+ if (interpreterProxy->failed()) {
+ return PrimErrBadArgument;
+ }
+ }
+ MaybePassAsDRegArg(v)
+ }
}
}
- else
-#endif /* STACKVM */
- for (i = 0; i < numArgs; i++) {
- sqInt arg = argVector[i];
- if (isSmallInt(arg)) {
- *(long *)argvec = intVal(arg);
- argvec += sizeof(long);
- }
- else if (objIsAlien(arg)) {
- long argByteSize;
-
- if (!(size = sizeField(arg)))
- size = argByteSize = sizeof(void *);
- else
- argByteSize = abs(size);
- memcpy(argvec, startOfDataWithSize(arg,size), argByteSize);
- argvec += moduloPOT(sizeof(long), argByteSize);
- }
- else if (objIsUnsafeAlien(arg)) {
- sqInt bitsObj = interpreterProxy->fetchPointerofObject(0,arg);
- void *v = interpreterProxy->firstIndexableField(bitsObj);
- *(void **)argvec = v;
- argvec += sizeof(long);
- }
- else if (interpreterProxy->isFloatObject(arg)) {
- double d = interpreterProxy->floatValueOf(arg);
- *(double *)argvec = d;
- argvec += sizeof(double);
- }
- else {
- long v = interpreterProxy->signed32BitValueOf(arg);
- if (interpreterProxy->failed()) {
- interpreterProxy->primitiveFailFor(0);
- v = interpreterProxy->positive32BitValueOf(arg);
- if (interpreterProxy->failed())
- return PrimErrBadArgument;
+ else {
+ /* Context Interpreter or array version of callout primitive. */
+ for (i = 0; i < numArgs; i++) {
+ sqInt arg = argVector[i];
+ if (isSmallInt(arg))
+ MaybePassAsDRegArg(intVal(arg))
+ else if (objIsAlien(arg)) {
+ long argByteSize;
+ if ((size = sizeField(arg)) == 0) /* Pointer Alien. */
+ size = argByteSize = sizeof(void *);
+ else /* Direct or indirect Alien. */
+ argByteSize = abs(size);
+ /* TODO(rmacnak): Structs larger than word size should be split between
+ remaining registers and the stack. */
+ if ((argByteSize <= sizeof(long)) && (nextReg < NUM_REG_ARGS)) {
+ regs[nextReg++] = *(long*)startOfDataWithSize(arg, size);
+ }
+ else {
+ memcpy((void*)argvec, startOfDataWithSize(arg, size), argByteSize);
+ argvec += RoundUpPowerOfTwo(argByteSize, sizeof(long));
+ }
}
- *(long *)argvec = v;
- argvec += sizeof(long);
+ else if (objIsUnsafeAlien(arg)) {
+ sqInt bitsObj = interpreterProxy->fetchPointerofObject(0,arg);
+ long v = (long)interpreterProxy->firstIndexableField(bitsObj);
+ MaybePassAsRegArg(v)
+ }
+ else if (interpreterProxy->isFloatObject(arg)) {
+ double d = interpreterProxy->floatValueOf(arg);
+ MaybePassAsDRegArg(d)
+ }
+ else {
+ long v = interpreterProxy->signed32BitValueOf(arg);
+ if (interpreterProxy->failed()) {
+ interpreterProxy->primitiveFailFor(0);
+ v = interpreterProxy->positive32BitValueOf(arg);
+ if (interpreterProxy->failed()) {
+ return PrimErrBadArgument;
+ }
+ }
+ MaybePassAsRegArg(v)
+ }
}
}
funcAlien = interpreterProxy->stackValue(funcOffset);
- f = *(void **)startOfParameterData(funcAlien);
-#if STACK_ALIGN_BYTES
- /* cut stack back to start of aligned args */
- setsp(argstart);
-#endif
- r = f(regs[0],regs[1],regs[2],regs[3]);
- /* post call need to refresh stack pointer in case of call-back and GC. */
+ f = *(void**)startOfParameterData(funcAlien);
+
+ /* Note that this call a) passes the integer reg args in regs in the core
+ * integer registers, and b) passes the floating point args in dregs in the
+ * floating-point co-processor registers. Neat.
+ */
+ r = f(regs[0], regs[1], regs[2], regs[3],
+ dregs[0], dregs[1], dregs[2], dregs[3],
+ dregs[4], dregs[5], dregs[6], dregs[7]);
+
+ /* Post call need to refresh stack pointer in case of call-back and GC. */
resultMaybeAlien = interpreterProxy->stackValue(resultOffset);
if (objIsAlien(resultMaybeAlien)) {
- if (!(size = sizeField(resultMaybeAlien)))
- size = sizeof(void *);
- memcpy(startOfDataWithSize(resultMaybeAlien,size),
- &r,
- min((unsigned)abs(size), sizeof(r)));
+ size = sizeField(resultMaybeAlien);
+ if (size == 0) /* Pointer Alien. */
+ size = sizeof(long);
+ memcpy(startOfDataWithSize(resultMaybeAlien, size),
+ &r,
+ min((unsigned)abs(size), sizeof(r)));
}
return PrimNoErr;
Modified: trunk/platforms/Cross/plugins/IA32ABI/ia32abi.h
===================================================================
--- trunk/platforms/Cross/plugins/IA32ABI/ia32abi.h 2015-07-16 15:25:58 UTC (rev 3404)
+++ trunk/platforms/Cross/plugins/IA32ABI/ia32abi.h 2015-07-16 18:54:51 UTC (rev 3405)
@@ -36,14 +36,18 @@
#if defined(i386) || defined(__i386) || defined(__i386__)
# define INT_REG_ARGS /* none */
+# define DBL_REG_ARGS /* none */
#elif defined(__amd64__) || defined(__x86_64__) || defined(__amd64) || defined(__x86_64)
# define INT_REG_ARGS long,long,long,long,long,long,
+# define DBL_REG_ARGS /* none */
#elif defined(__powerpc__) || defined(PPC) || defined(_POWER) || defined(_IBMR2) || defined(__ppc__)
# define INT_REG_ARGS long,long,long,long,long,long,long,long,
+# define DBL_REG_ARGS /* none */
#elif defined(__ARM_ARCH__) || defined(__arm__) || defined(__arm32__) || defined(ARM32)
# define INT_REG_ARGS long,long,long,long,
+# define DBL_REG_ARGS double,double,double,double,double,double,double,double,
#endif
-extern long thunkEntry (INT_REG_ARGS void *,long *);
+extern long thunkEntry (INT_REG_ARGS DBL_REG_ARGS void *,long *);
extern void *allocateExecutablePage(long *pagesize);
extern VMCallbackContext *getMostRecentCallbackContext(void);
Property changes on: trunk/platforms/Cross/plugins/sqPluginsSCCSVersion.h
___________________________________________________________________
Modified: checkindate
- Tue Jul 7 12:02:30 PDT 2015
+ Thu Jul 16 11:54:21 PDT 2015