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