[Vm-dev] [commit][3405] Update the Alien call-in/out support for ARM.

commits at squeakvm.org commits at squeakvm.org
Thu Jul 16 18:54:53 UTC 2015


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



More information about the Vm-dev mailing list