[Vm-dev] [commit] r2377 - Fix checkin snafu; submit the correct SqueakFFIPrims from ReentrantIA32FFIPlugin

commits at squeakvm.org commits at squeakvm.org
Fri Apr 1 19:51:41 UTC 2011


Author: eliot
Date: 2011-04-01 12:51:41 -0700 (Fri, 01 Apr 2011)
New Revision: 2377

Modified:
   branches/Cog/src/plugins/SqueakFFIPrims/SqueakFFIPrims.c
Log:
Fix checkin snafu; submit the correct SqueakFFIPrims from ReentrantIA32FFIPlugin


Modified: branches/Cog/src/plugins/SqueakFFIPrims/SqueakFFIPrims.c
===================================================================
--- branches/Cog/src/plugins/SqueakFFIPrims/SqueakFFIPrims.c	2011-04-01 19:39:21 UTC (rev 2376)
+++ branches/Cog/src/plugins/SqueakFFIPrims/SqueakFFIPrims.c	2011-04-01 19:51:41 UTC (rev 2377)
@@ -1,9 +1,9 @@
 /* Automatically generated by
 	VMPluginCodeGenerator VMMaker-oscog.54 uuid: 73c095bd-7fa5-4ef9-b9fc-60378cae64c7
    from
-	ThreadedARMFFIPlugin VMMaker-oscog.54 uuid: 73c095bd-7fa5-4ef9-b9fc-60378cae64c7
+	ReentrantIA32FFIPlugin VMMaker-oscog.54 uuid: 73c095bd-7fa5-4ef9-b9fc-60378cae64c7
  */
-static char __buildInfo[] = "ThreadedARMFFIPlugin VMMaker-oscog.54 uuid: 73c095bd-7fa5-4ef9-b9fc-60378cae64c7 " __DATE__ ;
+static char __buildInfo[] = "ReentrantIA32FFIPlugin VMMaker-oscog.54 uuid: 73c095bd-7fa5-4ef9-b9fc-60378cae64c7 " __DATE__ ;
 
 
 
@@ -53,26 +53,20 @@
 # define setsp(ignored) 0
 #endif 
 
-#if !defined(STACK_ALIGN_BYTES)
-# if __APPLE__ && __MACH__ && __i386__
-#  define STACK_ALIGN_BYTES 16
-# elif __linux__ && __i386__
-#  define STACK_ALIGN_BYTES 16
-# elif defined(__amd64__) || defined(__x86_64__) ||  defined(__amd64) || defined(__x86_64)
-#  define STACK_ALIGN_BYTES 16
-# elif defined(powerpc) || defined(__powerpc__) || defined(_POWER) || defined(__POWERPC__) || defined(__PPC__)
-#  define STACK_ALIGN_BYTES 16
-# elif defined(__sparc64__) || defined(__sparcv9__) || defined(__sparc_v9__) /* must preceed 32-bit sparc defs */
-#  define STACK_ALIGN_BYTES 16
-# elif defined(sparc) || defined(__sparc__) || defined(__sparclite__)
-#  define STACK_ALIGN_BYTES 8
-# else
-#  define STACK_ALIGN_BYTES 0
-# endif
-#endif /* !defined(STACK_ALIGN_BYTES) */
-
-#if !defined(STACK_OFFSET_BYTES)
-# define STACK_OFFSET_BYTES 0
+#if __APPLE__ && __MACH__ && __i386__
+# define STACK_ALIGN_BYTES 16
+#elif __linux__ && __i386__
+# define STACK_ALIGN_BYTES 16
+#elif defined(__amd64__) || defined(__x86_64__) ||  defined(__amd64) || defined(__x86_64)
+# define STACK_ALIGN_BYTES 16
+#elif defined(powerpc) || defined(__powerpc__) || defined(_POWER) || defined(__POWERPC__) || defined(__PPC__)
+# define STACK_ALIGN_BYTES 16
+#elif defined(__sparc64__) || defined(__sparcv9__) || defined(__sparc_v9__) /* must preceed 32-bit sparc defs */
+# define STACK_ALIGN_BYTES 16
+#elif defined(sparc) || defined(__sparc__) || defined(__sparclite__)
+# define STACK_ALIGN_BYTES 8
+#else
+# define STACK_ALIGN_BYTES 0
 #endif
 
 #if defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__)
@@ -124,11 +118,9 @@
 	sqInt	ffiRetHeader;
 	sqInt	stringArgIndex;
 	char *stringArgs[15];
-	sqInt	regIndex;
-	sqInt		integerRegisters[8];
  } CalloutState;
 
-#define ThreadedFFICalloutStateForARM CalloutState
+#define ReentrantFFICalloutState CalloutState
 
 
 
@@ -141,7 +133,6 @@
 #define ExternalFunctionStackSizeIndex 3
 #define FFIAtomicTypeMask 0xF000000
 #define FFIAtomicTypeShift 24
-#define FFICallFlagThreaded null
 #define FFICallTypeApi 1
 #define FFIErrorAddressNotFound 13
 #define FFIErrorAttemptToPassVoid 14
@@ -152,6 +143,7 @@
 #define FFIErrorBadExternalFunction 17
 #define FFIErrorBadExternalLibrary 16
 #define FFIErrorBadReturn 10
+#define FFIErrorCallFrameTooBig 19
 #define FFIErrorCallType 9
 #define FFIErrorCoercionFailed 6
 #define FFIErrorIntAsPointer 4
@@ -182,7 +174,6 @@
 #define PrimErrBadNumArgs 5
 #define PrimErrBadReceiver 2
 #define PrimErrNoCMemory 10
-#define PrimErrObjectMayMove 14
 
 
 /*** Function Prototypes ***/
@@ -194,7 +185,7 @@
 static sqInt ffiArgumentSpecClassin(sqInt oop, sqInt argSpec, sqInt argClass, CalloutState *calloutState);
 static sqInt ffiAtomicArgByReferenceClassin(sqInt oop, sqInt oopClass, CalloutState *calloutState);
 static sqInt ffiAtomicStructByReferenceClassin(sqInt oop, sqInt oopClass, CalloutState *calloutState);
-static sqInt ffiCalloutToSpecOnStackin(void *procAddr, sqInt specOnStack, sqInt calloutState);
+static sqInt ffiCalloutToSpecOnStackin(void *procAddr, sqInt specOnStack, CalloutState *calloutState);
 static sqInt ffiCallArgArrayOrNilNumArgs(sqInt externalFunction, sqInt argArrayOrNil, sqInt nArgs);
 static sqInt ffiCheckReturnWithin(sqInt retSpec, sqInt retClass, CalloutState *calloutState);
 static sqInt ffiContentsOfHandleerrCode(sqInt oop, sqInt errCode);
@@ -207,16 +198,16 @@
 static sqInt ffiLoadCalloutModule(sqInt module);
 static void ffiLogCallout(sqInt lit);
 EXPORT(sqInt) ffiLogCallsTo(char*fileName);
-static sqInt ffiPushDoubleFloatin(sqInt value, sqInt calloutState);
+static sqInt ffiPushDoubleFloatin(double value, CalloutState *calloutState);
 static sqInt ffiPushPointerContentsOfin(sqInt oop, CalloutState *calloutState);
-static sqInt ffiPushPointerin(sqInt value, CalloutState *calloutState);
+static sqInt ffiPushPointerin(void *pointer, CalloutState *calloutState);
 static sqInt ffiPushSignedBytein(sqInt value, CalloutState *calloutState);
 static sqInt ffiPushSignedCharin(sqInt value, CalloutState *calloutState);
 static sqInt ffiPushSignedIntin(sqInt value, CalloutState *calloutState);
 static sqInt ffiPushSignedLongLongOopin(sqInt oop, CalloutState *calloutState);
-static sqInt ffiPushSignedLongLongin(sqLong value, CalloutState *calloutState);
+static sqInt ffiPushSignedLongLongin(usqLong value, CalloutState *calloutState);
 static sqInt ffiPushSignedShortin(sqInt value, CalloutState *calloutState);
-static sqInt ffiPushSingleFloatin(sqInt value, CalloutState *calloutState);
+static sqInt ffiPushSingleFloatin(float value, CalloutState *calloutState);
 static sqInt ffiPushStringOfLengthin(char *pointer, sqInt length, CalloutState *calloutState);
 static sqInt ffiPushStructureContentsOfin(sqInt oop, CalloutState *calloutState);
 static sqInt ffiPushStructureofSizetypeSpecofLengthin(void *pointer, sqInt structSize, sqInt *argSpec, sqInt argSpecSize, CalloutState *calloutState);
@@ -225,12 +216,11 @@
 static sqInt ffiPushUnsignedIntin(sqInt value, CalloutState *calloutState);
 static sqInt ffiPushUnsignedLongLongOopin(sqInt oop, CalloutState *calloutState);
 static sqInt ffiPushUnsignedLongLongin(usqLong value, CalloutState *calloutState);
-static sqInt ffiPushUnsignedLongin(sqInt value, CalloutState *calloutState);
 static sqInt ffiPushUnsignedShortin(sqInt value, CalloutState *calloutState);
 static sqInt ffiPushVoidin(sqInt ignored, CalloutState *calloutState);
 static sqInt ffiReturnCStringFrom(sqInt cPointer);
 static sqInt ffiReturnPointerofTypein(usqLong retVal, sqInt retType, CalloutState *calloutState);
-static sqInt ffiReturnStructofTypein(usqLong longLongRet, sqInt ffiRetClass, CalloutState *calloutState);
+static sqInt ffiReturnStructofTypein(usqLong longLongRet, sqInt ffiRetType, CalloutState *calloutState);
 static sqInt ffiReturnType(sqInt specOnStack);
 static sqInt ffiSupportsCallingConvention(sqInt aCallingConvention);
 static sqInt ffiValidateExternalDataAtomicType(sqInt oop, sqInt atomicType);
@@ -238,7 +228,6 @@
 EXPORT(const char*) getModuleName(void);
 static sqInt halt(void);
 EXPORT(sqInt) initialiseModule(void);
-static void initialize(CalloutState * self_in_initialize);
 static sqInt isAlien(sqInt anOop);
 static sqInt isAtomicType(sqInt typeSpec);
 static sqInt isDirectAlien(sqInt oop);
@@ -261,7 +250,6 @@
 EXPORT(sqInt) primitiveLogCallsTo(void);
 EXPORT(sqInt) primitiveSetManualSurfacePointer(void);
 static sqInt registerArgsSlop(void);
-static sqInt returnStructInRegisters(sqInt returnStructSize);
 EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter);
 static sqInt sizeField(sqInt oop);
 static sqInt startOfData(sqInt oop);
@@ -292,6 +280,7 @@
 #define ffiAlloc(bytes) (usqInt)malloc(bytes)
 #define ffiFree(pointer) free((void *)(pointer))
 #define isCalleePopsConvention(callType) (PLATFORM_API_USES_CALLEE_POPS_CONVENTION && (callType) == FFICallTypeApi)
+#define returnStructInRegisters(sz) (WIN32_X86_STRUCT_RETURN && (sz) <= 8 && !((sz)&((sz)-1)))
 
 
 static sqInt
@@ -472,12 +461,20 @@
 	}
 	if (atomicType == FFITypeSingleFloat) {
 		/* begin ffiPushSingleFloat:in: */
-		error("shouldBeImplemented");
+		if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+			return FFIErrorCallFrameTooBig;
+		}
+		storeSingleFloatAtPointerfrom((calloutState->currentArg), floatValue);
+		(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 		return 0;
 	}
 	else {
 		/* begin ffiPushDoubleFloat:in: */
-		error("shouldBeImplemented");
+		if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+			return FFIErrorCallFrameTooBig;
+		}
+		storeFloatAtPointerfrom((calloutState->currentArg), floatValue);
+		(calloutState->currentArg = ((calloutState->currentArg)) + 8);
 		return 0;
 	}
 }
@@ -510,9 +507,14 @@
     sqInt oopClass1;
     sqInt oopClass2;
     char *pointer;
+    void *pointer1;
+    void *pointer2;
+    void *pointer3;
     sqInt ptrAddress;
     sqInt ptrClass;
     sqInt ptrType;
+    sqInt roundedSize;
+    sqInt roundedSize1;
     sqInt spec;
     sqInt specOop;
     sqInt specType;
@@ -521,9 +523,6 @@
     sqInt typeSpec;
     sqInt typeSpec1;
     sqInt typeSpec2;
-    sqInt value;
-    sqInt value1;
-    sqInt value2;
     sqInt valueOop;
     sqInt valueOop1;
 
@@ -599,8 +598,13 @@
 			structSize = ((calloutState->ffiArgHeader)) & FFIStructSizeMask;
 			argSpec2 = (calloutState->ffiArgSpec);
 			argSpecSize = (calloutState->ffiArgSpecSize);
-			subclassResponsibility();
-			return null;
+			roundedSize = (structSize + 3) & (~3);
+			if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) {
+				return FFIErrorCallFrameTooBig;
+			}
+			memcpy((calloutState->currentArg), ((void *) ptrAddress), structSize);
+			(calloutState->currentArg = ((calloutState->currentArg)) + roundedSize);
+			return 0;
 		}
 		if (ptrClass == (interpreterProxy->classByteArray())) {
 			if (!((interpreterProxy->byteSizeOf(valueOop)) == (((calloutState->ffiArgHeader)) & FFIStructSizeMask))) {
@@ -608,16 +612,17 @@
 			}
 			ptrAddress = ((int) (interpreterProxy->firstIndexableField(valueOop)));
 			if (!(((calloutState->ffiArgHeader)) & FFIFlagPointer)) {
-				if ((((calloutState->callFlags)) & FFICallFlagThreaded)
-				 && (interpreterProxy->isYoung(valueOop))) {
-					return -PrimErrObjectMayMove;
-				}
 				/* begin ffiPushStructure:ofSize:typeSpec:ofLength:in: */
 				structSize1 = ((calloutState->ffiArgHeader)) & FFIStructSizeMask;
 				argSpec1 = (calloutState->ffiArgSpec);
 				argSpecSize1 = (calloutState->ffiArgSpecSize);
-				subclassResponsibility();
-				return null;
+				roundedSize1 = (structSize1 + 3) & (~3);
+				if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) {
+					return FFIErrorCallFrameTooBig;
+				}
+				memcpy((calloutState->currentArg), ((void *) ptrAddress), structSize1);
+				(calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1);
+				return 0;
 			}
 			if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == 4)) {
 				return FFIErrorStructSize;
@@ -627,7 +632,11 @@
 				return FFIErrorInvalidPointer;
 			}
 			/* begin ffiPushPointer:in: */
-			error("shouldBeImplemented");
+			if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+				return FFIErrorCallFrameTooBig;
+			}
+			longAtput((calloutState->currentArg), ptrAddress);
+			(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 			return 0;
 		}
 		return FFIErrorBadArg;
@@ -638,7 +647,11 @@
 		}
 		if (oop == (interpreterProxy->nilObject())) {
 			/* begin ffiPushPointer:in: */
-			error("shouldBeImplemented");
+			if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+				return FFIErrorCallFrameTooBig;
+			}
+			longAtput((calloutState->currentArg), null);
+			(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 			return 0;
 		}
 		if (((calloutState->ffiArgHeader)) & FFIFlagAtomic) {
@@ -732,32 +745,38 @@
 						((calloutState->stringArgs))[(calloutState->stringArgIndex)] = copy;
 						(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) + 1);
 						/* begin ffiPushPointer:in: */
-						error("shouldBeImplemented");
+						if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+							return FFIErrorCallFrameTooBig;
+						}
+						longAtput((calloutState->currentArg), copy);
+						(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 						return 0;
 					}
 					atomicType2 = FFITypeUnsignedByte;
 				}
-				if ((((calloutState->callFlags)) & FFICallFlagThreaded)
-				 && (((!isAlien)
- || (isDirectAlien(oop)))
- && (interpreterProxy->isYoung(oop)))) {
-					return -PrimErrObjectMayMove;
-				}
 				if ((atomicType2 == FFITypeVoid)
 				 || ((((usqInt) atomicType2) >> 1) == (((usqInt) FFITypeSignedByte) >> 1))) {
 					if (isString
 					 || (oopClass == (interpreterProxy->classByteArray()))) {
 						/* begin ffiPushPointer:in: */
-						value = interpreterProxy->firstIndexableField(oop);
-						error("shouldBeImplemented");
+						pointer1 = interpreterProxy->firstIndexableField(oop);
+						if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+							return FFIErrorCallFrameTooBig;
+						}
+						longAtput((calloutState->currentArg), pointer1);
+						(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 						return 0;
 					}
 					if (isAlien) {
 						/* begin ffiPushPointer:in: */
-						value1 = pointerForOop(((longAt(oop + BaseHeaderSize)) > 0
+						pointer2 = pointerForOop(((longAt(oop + BaseHeaderSize)) > 0
 							? (oop + BaseHeaderSize) + BytesPerOop
 							: longAt((oop + BaseHeaderSize) + BytesPerOop)));
-						error("shouldBeImplemented");
+						if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+							return FFIErrorCallFrameTooBig;
+						}
+						longAtput((calloutState->currentArg), pointer2);
+						(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 						return 0;
 					}
 					if (!(atomicType2 == FFITypeVoid)) {
@@ -768,8 +787,12 @@
 				 || (atomicType2 == FFITypeSingleFloat)) {
 					if (interpreterProxy->isWords(oop)) {
 						/* begin ffiPushPointer:in: */
-						value2 = interpreterProxy->firstIndexableField(oop);
-						error("shouldBeImplemented");
+						pointer3 = interpreterProxy->firstIndexableField(oop);
+						if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+							return FFIErrorCallFrameTooBig;
+						}
+						longAtput((calloutState->currentArg), pointer3);
+						(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 						return 0;
 					}
 				}
@@ -880,12 +903,20 @@
 		}
 		if (atomicType1 == FFITypeSingleFloat) {
 			/* begin ffiPushSingleFloat:in: */
-			error("shouldBeImplemented");
+			if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+				return FFIErrorCallFrameTooBig;
+			}
+			storeSingleFloatAtPointerfrom((calloutState->currentArg), floatValue);
+			(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 			return 0;
 		}
 		else {
 			/* begin ffiPushDoubleFloat:in: */
-			error("shouldBeImplemented");
+			if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+				return FFIErrorCallFrameTooBig;
+			}
+			storeFloatAtPointerfrom((calloutState->currentArg), floatValue);
+			(calloutState->currentArg = ((calloutState->currentArg)) + 8);
 			return 0;
 		}
 	}
@@ -908,10 +939,10 @@
     sqInt isString;
     sqInt length;
     char *pointer;
+    void *pointer1;
+    void *pointer2;
+    void *pointer3;
     sqInt typeSpec;
-    sqInt value;
-    sqInt value1;
-    sqInt value2;
 
 	/* begin atomicTypeOf: */
 	typeSpec = (calloutState->ffiArgHeader);
@@ -939,32 +970,38 @@
 			((calloutState->stringArgs))[(calloutState->stringArgIndex)] = copy;
 			(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) + 1);
 			/* begin ffiPushPointer:in: */
-			error("shouldBeImplemented");
+			if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+				return FFIErrorCallFrameTooBig;
+			}
+			longAtput((calloutState->currentArg), copy);
+			(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 			return 0;
 		}
 		atomicType = FFITypeUnsignedByte;
 	}
-	if ((((calloutState->callFlags)) & FFICallFlagThreaded)
-	 && (((!isAlien)
- || (isDirectAlien(oop)))
- && (interpreterProxy->isYoung(oop)))) {
-		return -PrimErrObjectMayMove;
-	}
 	if ((atomicType == FFITypeVoid)
 	 || ((((usqInt) atomicType) >> 1) == (((usqInt) FFITypeSignedByte) >> 1))) {
 		if (isString
 		 || (oopClass == (interpreterProxy->classByteArray()))) {
 			/* begin ffiPushPointer:in: */
-			value = interpreterProxy->firstIndexableField(oop);
-			error("shouldBeImplemented");
+			pointer1 = interpreterProxy->firstIndexableField(oop);
+			if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+				return FFIErrorCallFrameTooBig;
+			}
+			longAtput((calloutState->currentArg), pointer1);
+			(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 			return 0;
 		}
 		if (isAlien) {
 			/* begin ffiPushPointer:in: */
-			value1 = pointerForOop(((longAt(oop + BaseHeaderSize)) > 0
+			pointer2 = pointerForOop(((longAt(oop + BaseHeaderSize)) > 0
 				? (oop + BaseHeaderSize) + BytesPerOop
 				: longAt((oop + BaseHeaderSize) + BytesPerOop)));
-			error("shouldBeImplemented");
+			if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+				return FFIErrorCallFrameTooBig;
+			}
+			longAtput((calloutState->currentArg), pointer2);
+			(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 			return 0;
 		}
 		if (!(atomicType == FFITypeVoid)) {
@@ -975,8 +1012,12 @@
 	 || (atomicType == FFITypeSingleFloat)) {
 		if (interpreterProxy->isWords(oop)) {
 			/* begin ffiPushPointer:in: */
-			value2 = interpreterProxy->firstIndexableField(oop);
-			error("shouldBeImplemented");
+			pointer3 = interpreterProxy->firstIndexableField(oop);
+			if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+				return FFIErrorCallFrameTooBig;
+			}
+			longAtput((calloutState->currentArg), pointer3);
+			(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 			return 0;
 		}
 	}
@@ -1062,17 +1103,155 @@
 }
 
 
-/*	Perform the callout, collect the result and and create the return value.
-	If a threaded call, disown and own VM around the call. If there are
-	floating-point arguments that are passed in registers then call a dummy
-	function to load them.
-	This *must* be inlined because of the alloca of the outgoing stack frame
-	in ffiCall:SpecOnStack:Flags:NumArgs:Args:AndTypes: */
+/*	Go out, call this guy and create the return value. This *must* be inlined
+	because of
+	the alloca of the outgoing stack frame in
+	ffiCall:WithFlags:NumArgs:Args:AndTypes: 
+ */
 
 static sqInt
-ffiCalloutToSpecOnStackin(void *procAddr, sqInt specOnStack, sqInt calloutState)
+ffiCalloutToSpecOnStackin(void *procAddr, sqInt specOnStack, CalloutState *calloutState)
 {
-	subclassResponsibility();
+    sqInt argTypes;
+    sqInt argTypes1;
+    sqInt atomicType;
+    sqInt atomicType1;
+    sqInt classOop;
+    char *cString;
+    sqInt ffiRetType;
+    double floatRet;
+    sqInt i;
+    usqLong intRet;
+    sqInt oop;
+    sqInt oop1;
+    sqInt *ptr;
+    sqInt retClass;
+    sqInt retClass1;
+    sqInt retOop;
+    sqInt retOop1;
+    sqInt retType;
+    sqInt specLiteral;
+    sqInt specLiteral1;
+    sqInt strLen;
+    sqInt strOop;
+    char *strPtr;
+    sqInt typeSpec;
+    sqInt typeSpec1;
+
+	if ((0 + (cStackAlignment())) > 0) {
+		setsp((calloutState->argVector));
+	}
+	/* begin atomicTypeOf: */
+	typeSpec = (calloutState->ffiRetHeader);
+	atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+	if ((atomicType == FFITypeSingleFloat)
+	 || (atomicType == FFITypeDoubleFloat)) {
+		floatRet = dispatchFunctionPointer(((double (*)()) procAddr));
+	}
+	else {
+		intRet = dispatchFunctionPointer(((usqLong (*)()) procAddr));
+	}
+	if (isCalleePopsConvention((calloutState->callFlags))) {
+		setsp((calloutState->argVector));
+	}
+	if (((calloutState->ffiRetHeader)) & FFIFlagPointer) {
+		/* begin ffiReturnPointer:ofType:in: */
+		/* begin ffiReturnType: */
+		specLiteral1 = (specOnStack
+			? interpreterProxy->stackValue(1)
+			: interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+		argTypes1 = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral1);
+		retType = interpreterProxy->fetchPointerofObject(0, argTypes1);
+		retClass1 = interpreterProxy->fetchPointerofObject(1, retType);
+		if (retClass1 == (interpreterProxy->nilObject())) {
+			/* begin atomicTypeOf: */
+			typeSpec1 = (calloutState->ffiRetHeader);
+			atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+			if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) {
+				/* begin ffiReturnCStringFrom: */
+				if ((((usqInt) intRet)) == null) {
+					return interpreterProxy->methodReturnValue(interpreterProxy->nilObject());
+				}
+				cString = ((char *) (((usqInt) intRet)));
+				strLen = 0;
+				while (!((cString[strLen]) == 0)) {
+					strLen += 1;
+				}
+				strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen);
+				strPtr = interpreterProxy->firstIndexableField(strOop);
+				for (i = 0; i <= (strLen - 1); i += 1) {
+					strPtr[i] = (cString[i]);
+				}
+				return interpreterProxy->methodReturnValue(strOop);
+			}
+			interpreterProxy->pushRemappableOop(retType);
+			oop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4);
+			ptr = interpreterProxy->firstIndexableField(oop1);
+			ptr[0] = (((sqInt) intRet));
+			interpreterProxy->pushRemappableOop(oop1);
+			retOop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0);
+
+			/* external address */
+
+			oop1 = interpreterProxy->popRemappableOop();
+			interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+
+			/* return type */
+
+			oop1 = interpreterProxy->popRemappableOop();
+			interpreterProxy->storePointerofObjectwithValue(1, retOop1, oop1);
+			return interpreterProxy->methodReturnValue(retOop1);
+		}
+		interpreterProxy->pushRemappableOop(retClass1);
+		if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+			classOop = interpreterProxy->classByteArray();
+		}
+		else {
+			classOop = interpreterProxy->classExternalAddress();
+		}
+		oop1 = interpreterProxy->instantiateClassindexableSize(classOop, 4);
+		ptr = interpreterProxy->firstIndexableField(oop1);
+		ptr[0] = (((sqInt) intRet));
+
+		/* return class */
+
+		retClass1 = interpreterProxy->popRemappableOop();
+		interpreterProxy->pushRemappableOop(oop1);
+		retOop1 = interpreterProxy->instantiateClassindexableSize(retClass1, 0);
+
+		/* external address */
+
+		oop1 = interpreterProxy->popRemappableOop();
+		interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+		return interpreterProxy->methodReturnValue(retOop1);
+	}
+	if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+		/* begin ffiReturnStruct:ofType:in: */
+		/* begin ffiReturnType: */
+		specLiteral = (specOnStack
+			? interpreterProxy->stackValue(1)
+			: interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+		argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral);
+		ffiRetType = interpreterProxy->fetchPointerofObject(0, argTypes);
+		retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType);
+		retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0);
+		interpreterProxy->pushRemappableOop(retOop);
+		oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize));
+		if (returnStructInRegisters((calloutState->structReturnSize))) {
+			memcpy(interpreterProxy->firstIndexableField(oop), (&intRet), (calloutState->structReturnSize));
+		}
+		else {
+			memcpy(interpreterProxy->firstIndexableField(oop), (calloutState->limit), (calloutState->structReturnSize));
+		}
+		retOop = interpreterProxy->popRemappableOop();
+		interpreterProxy->storePointerofObjectwithValue(0, retOop, oop);
+		return interpreterProxy->methodReturnValue(retOop);
+	}
+	if ((atomicType == FFITypeSingleFloat)
+	 || (atomicType == FFITypeDoubleFloat)) {
+		return interpreterProxy->methodReturnValue(interpreterProxy->floatObjectOf(floatRet));
+	}
+	return interpreterProxy->methodReturnValue(ffiCreateIntegralResultOopofAtomicTypein(intRet, atomicType, calloutState));
 }
 
 
@@ -1092,18 +1271,43 @@
     sqInt argSpec;
     sqInt argType;
     sqInt argTypeArray;
+    sqInt argTypes;
+    sqInt argTypes1;
+    sqInt atomicType;
+    sqInt atomicType1;
     CalloutState *calloutState;
+    sqInt classOop;
+    char *cString;
     sqInt err;
+    sqInt ffiRetType;
     sqInt flags;
+    double floatRet;
     sqInt functionName;
     sqInt i;
+    sqInt i1;
+    usqLong intRet;
     sqInt oop;
+    sqInt oop1;
+    sqInt oop2;
+    void *pointer;
     int *ptr;
+    sqInt *ptr1;
     sqInt requiredStackSize;
     sqInt result;
+    sqInt retClass;
+    sqInt retClass1;
+    sqInt retOop;
+    sqInt retOop1;
+    sqInt retType;
+    sqInt specLiteral;
+    sqInt specLiteral1;
     sqInt stackSize;
+    sqInt strLen;
+    sqInt strOop;
+    char *strPtr;
     CalloutState theCalloutState;
-    sqInt value;
+    sqInt typeSpec;
+    sqInt typeSpec1;
 
 	if (!(interpreterProxy->isKindOfClass(externalFunction, interpreterProxy->classExternalFunction()))) {
 		return ffiFail(FFIErrorNotFunction);
@@ -1132,21 +1336,21 @@
 	/* begin ffiContentsOfHandle:errCode: */
 	if ((addressPtr & 1)) {
 		address1 = ffiFail(FFIErrorBadAddress);
-		goto l2;
+		goto l3;
 	}
 	if (!(interpreterProxy->isBytes(addressPtr))) {
 		address1 = ffiFail(FFIErrorBadAddress);
-		goto l2;
+		goto l3;
 	}
 	if (!((interpreterProxy->byteSizeOf(addressPtr)) == 4)) {
 		address1 = ffiFail(FFIErrorBadAddress);
-		goto l2;
+		goto l3;
 	}
 	address1 = interpreterProxy->fetchPointerofObject(0, addressPtr);
-l2:	/* end ffiContentsOfHandle:errCode: */;
+l3:	/* end ffiContentsOfHandle:errCode: */;
 	if (interpreterProxy->failed()) {
 		address = 0;
-		goto l3;
+		goto l4;
 	}
 	if (address1 == 0) {
 		if (externalFunctionInstSize > ExternalFunctionStackSizeIndex) {
@@ -1154,18 +1358,18 @@
 		}
 		if ((interpreterProxy->slotSizeOf(externalFunction)) < 5) {
 			address = ffiFail(FFIErrorNoModule);
-			goto l3;
+			goto l4;
 		}
 		address1 = ffiLoadCalloutAddressFrom(externalFunction);
 		if (interpreterProxy->failed()) {
 			address = 0;
-			goto l3;
+			goto l4;
 		}
 		ptr = interpreterProxy->firstIndexableField(addressPtr);
 		ptr[0] = address1;
 	}
 	address = address1;
-l3:	/* end ffiLoadCalloutAddress: */;
+l4:	/* end ffiLoadCalloutAddress: */;
 	if (interpreterProxy->failed()) {
 		return 0;
 	}
@@ -1205,8 +1409,13 @@
 	 && (1
  && (!(returnStructInRegisters((calloutState->structReturnSize)))))) {
 		/* begin ffiPushPointer:in: */
-		value = (calloutState->limit);
-		error("shouldBeImplemented");
+		pointer = (calloutState->limit);
+		if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+			goto l1;
+		}
+		longAtput((calloutState->currentArg), pointer);
+		(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+	l1:	/* end ffiPushPointer:in: */;
 	}
 	for (i = 1; i <= nArgs; i += 1) {
 		argType = interpreterProxy->fetchPointerofObject(i, argTypeArray);
@@ -1221,9 +1430,6 @@
 			while (((calloutState->stringArgIndex)) > 0) {
 				free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
 			}
-			if (err == (-PrimErrObjectMayMove)) {
-				return PrimErrObjectMayMove;
-			}
 			return ffiFail(err);
 		}
 	}
@@ -1232,18 +1438,138 @@
 	if (ffiLogEnabled) {
 		functionName = interpreterProxy->fetchPointerofObject(externalFunctionInstSize, externalFunction);
 		if (!(interpreterProxy->isBytes(functionName))) {
-			goto l1;
+			goto l2;
 		}
 		ffiLogCallOfLength(interpreterProxy->firstIndexableField(functionName), interpreterProxy->byteSizeOf(functionName));
 	}
-l1:	/* end ffiLogCallout: */;
+l2:	/* end ffiLogCallout: */;
 	if ((requiredStackSize < 0)
 	 && (externalFunctionInstSize > ExternalFunctionStackSizeIndex)) {
 		stackSize = ((calloutState->currentArg)) - ((calloutState->argVector));
 		interpreterProxy->storeIntegerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, stackSize);
 	}
 	/* begin ffiCalloutTo:SpecOnStack:in: */
-	subclassResponsibility();
+	if ((0 + (cStackAlignment())) > 0) {
+		setsp((calloutState->argVector));
+	}
+	/* begin atomicTypeOf: */
+	typeSpec = (calloutState->ffiRetHeader);
+	atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+	if ((atomicType == FFITypeSingleFloat)
+	 || (atomicType == FFITypeDoubleFloat)) {
+		floatRet = dispatchFunctionPointer(((double (*)()) address));
+	}
+	else {
+		intRet = dispatchFunctionPointer(((usqLong (*)()) address));
+	}
+	if (isCalleePopsConvention((calloutState->callFlags))) {
+		setsp((calloutState->argVector));
+	}
+	if (((calloutState->ffiRetHeader)) & FFIFlagPointer) {
+		/* begin ffiReturnPointer:ofType:in: */
+		/* begin ffiReturnType: */
+		specLiteral1 = (argArrayOrNil != null
+			? interpreterProxy->stackValue(1)
+			: interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+		argTypes1 = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral1);
+		retType = interpreterProxy->fetchPointerofObject(0, argTypes1);
+		retClass1 = interpreterProxy->fetchPointerofObject(1, retType);
+		if (retClass1 == (interpreterProxy->nilObject())) {
+			/* begin atomicTypeOf: */
+			typeSpec1 = (calloutState->ffiRetHeader);
+			atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+			if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) {
+				/* begin ffiReturnCStringFrom: */
+				if ((((usqInt) intRet)) == null) {
+					result = interpreterProxy->methodReturnValue(interpreterProxy->nilObject());
+					goto l5;
+				}
+				cString = ((char *) (((usqInt) intRet)));
+				strLen = 0;
+				while (!((cString[strLen]) == 0)) {
+					strLen += 1;
+				}
+				strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen);
+				strPtr = interpreterProxy->firstIndexableField(strOop);
+				for (i1 = 0; i1 <= (strLen - 1); i1 += 1) {
+					strPtr[i1] = (cString[i1]);
+				}
+				result = interpreterProxy->methodReturnValue(strOop);
+				goto l5;
+			}
+			interpreterProxy->pushRemappableOop(retType);
+			oop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4);
+			ptr1 = interpreterProxy->firstIndexableField(oop1);
+			ptr1[0] = (((sqInt) intRet));
+			interpreterProxy->pushRemappableOop(oop1);
+			retOop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0);
+
+			/* external address */
+
+			oop1 = interpreterProxy->popRemappableOop();
+			interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+
+			/* return type */
+
+			oop1 = interpreterProxy->popRemappableOop();
+			interpreterProxy->storePointerofObjectwithValue(1, retOop1, oop1);
+			result = interpreterProxy->methodReturnValue(retOop1);
+			goto l5;
+		}
+		interpreterProxy->pushRemappableOop(retClass1);
+		if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+			classOop = interpreterProxy->classByteArray();
+		}
+		else {
+			classOop = interpreterProxy->classExternalAddress();
+		}
+		oop1 = interpreterProxy->instantiateClassindexableSize(classOop, 4);
+		ptr1 = interpreterProxy->firstIndexableField(oop1);
+		ptr1[0] = (((sqInt) intRet));
+
+		/* return class */
+
+		retClass1 = interpreterProxy->popRemappableOop();
+		interpreterProxy->pushRemappableOop(oop1);
+		retOop1 = interpreterProxy->instantiateClassindexableSize(retClass1, 0);
+
+		/* external address */
+
+		oop1 = interpreterProxy->popRemappableOop();
+		interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+		result = interpreterProxy->methodReturnValue(retOop1);
+		goto l5;
+	}
+	if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+		/* begin ffiReturnStruct:ofType:in: */
+		/* begin ffiReturnType: */
+		specLiteral = (argArrayOrNil != null
+			? interpreterProxy->stackValue(1)
+			: interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+		argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral);
+		ffiRetType = interpreterProxy->fetchPointerofObject(0, argTypes);
+		retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType);
+		retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0);
+		interpreterProxy->pushRemappableOop(retOop);
+		oop2 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize));
+		if (returnStructInRegisters((calloutState->structReturnSize))) {
+			memcpy(interpreterProxy->firstIndexableField(oop2), (&intRet), (calloutState->structReturnSize));
+		}
+		else {
+			memcpy(interpreterProxy->firstIndexableField(oop2), (calloutState->limit), (calloutState->structReturnSize));
+		}
+		retOop = interpreterProxy->popRemappableOop();
+		interpreterProxy->storePointerofObjectwithValue(0, retOop, oop2);
+		result = interpreterProxy->methodReturnValue(retOop);
+		goto l5;
+	}
+	if ((atomicType == FFITypeSingleFloat)
+	 || (atomicType == FFITypeDoubleFloat)) {
+		result = interpreterProxy->methodReturnValue(interpreterProxy->floatObjectOf(floatRet));
+		goto l5;
+	}
+	result = interpreterProxy->methodReturnValue(ffiCreateIntegralResultOopofAtomicTypein(intRet, atomicType, calloutState));
+l5:	/* end ffiCalloutTo:SpecOnStack:in: */;
 	/* begin cleanupCalloutState: */
 	while (((calloutState->stringArgIndex)) > 0) {
 		free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
@@ -1700,9 +2026,13 @@
 }
 
 static sqInt
-ffiPushDoubleFloatin(sqInt value, sqInt calloutState)
+ffiPushDoubleFloatin(double value, CalloutState *calloutState)
 {
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	storeFloatAtPointerfrom((calloutState->currentArg), value);
+	(calloutState->currentArg = ((calloutState->currentArg)) + 8);
 	return 0;
 }
 
@@ -1725,60 +2055,80 @@
 			return FFIErrorInvalidPointer;
 		}
 		/* begin ffiPushPointer:in: */
-		error("shouldBeImplemented");
+		if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+			return FFIErrorCallFrameTooBig;
+		}
+		longAtput((calloutState->currentArg), ptrAddress);
+		(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 		return 0;
 	}
 	if (ptrClass == (interpreterProxy->classByteArray())) {
-		if ((((calloutState->callFlags)) & FFICallFlagThreaded)
-		 && (interpreterProxy->isYoung(oop))) {
-			return -PrimErrObjectMayMove;
-		}
 		ptrAddress = ((int) (interpreterProxy->firstIndexableField(oop)));
 		/* begin ffiPushPointer:in: */
-		error("shouldBeImplemented");
+		if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+			return FFIErrorCallFrameTooBig;
+		}
+		longAtput((calloutState->currentArg), ptrAddress);
+		(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 		return 0;
 	}
 	if (interpreterProxy->includesBehaviorThatOf(ptrClass, interpreterProxy->classAlien())) {
-		if ((((calloutState->callFlags)) & FFICallFlagThreaded)
-		 && ((isDirectAlien(oop))
- && (interpreterProxy->isYoung(oop)))) {
-			return -PrimErrObjectMayMove;
-		}
 		ptrAddress = ((longAt(oop + BaseHeaderSize)) > 0
 			? (oop + BaseHeaderSize) + BytesPerOop
 			: longAt((oop + BaseHeaderSize) + BytesPerOop));
 		/* begin ffiPushPointer:in: */
-		error("shouldBeImplemented");
+		if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+			return FFIErrorCallFrameTooBig;
+		}
+		longAtput((calloutState->currentArg), ptrAddress);
+		(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 		return 0;
 	}
 	return FFIErrorBadArg;
 }
 
 static sqInt
-ffiPushPointerin(sqInt value, CalloutState *calloutState)
+ffiPushPointerin(void *pointer, CalloutState *calloutState)
 {
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), pointer);
+	(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 	return 0;
 }
 
 static sqInt
 ffiPushSignedBytein(sqInt value, CalloutState *calloutState)
 {
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), ((signed char) value));
+	(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 	return 0;
 }
 
 static sqInt
 ffiPushSignedCharin(sqInt value, CalloutState *calloutState)
 {
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), ((signed char) value));
+	(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 	return 0;
 }
 
 static sqInt
 ffiPushSignedIntin(sqInt value, CalloutState *calloutState)
 {
-	subclassResponsibility();
+	if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), value);
+	(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+	return 0;
 }
 
 
@@ -1806,28 +2156,46 @@
 		}
 	}
 	/* begin ffiPushSignedLongLong:in: */
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), ((usqInt) value));
+	longAtput(((calloutState->currentArg)) + 4, ((usqInt) (((unsigned sqLong )value) >> 32)));
+	(calloutState->currentArg = ((calloutState->currentArg)) + 8);
 	return 0;
 }
 
 static sqInt
-ffiPushSignedLongLongin(sqLong value, CalloutState *calloutState)
+ffiPushSignedLongLongin(usqLong value, CalloutState *calloutState)
 {
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), ((usqInt) value));
+	longAtput(((calloutState->currentArg)) + 4, ((usqInt) (value >> 32)));
+	(calloutState->currentArg = ((calloutState->currentArg)) + 8);
 	return 0;
 }
 
 static sqInt
 ffiPushSignedShortin(sqInt value, CalloutState *calloutState)
 {
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), ((signed short) value));
+	(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 	return 0;
 }
 
 static sqInt
-ffiPushSingleFloatin(sqInt value, CalloutState *calloutState)
+ffiPushSingleFloatin(float value, CalloutState *calloutState)
 {
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	storeSingleFloatAtPointerfrom((calloutState->currentArg), value);
+	(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 	return 0;
 }
 
@@ -1848,7 +2216,11 @@
 	((calloutState->stringArgs))[(calloutState->stringArgIndex)] = copy;
 	(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) + 1);
 	/* begin ffiPushPointer:in: */
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), copy);
+	(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 	return 0;
 }
 
@@ -1864,6 +2236,8 @@
     sqInt argSpecSize1;
     sqInt ptrAddress;
     sqInt ptrClass;
+    sqInt roundedSize;
+    sqInt roundedSize1;
     sqInt structSize;
     sqInt structSize1;
 
@@ -1882,8 +2256,13 @@
 		structSize = ((calloutState->ffiArgHeader)) & FFIStructSizeMask;
 		argSpec = (calloutState->ffiArgSpec);
 		argSpecSize = (calloutState->ffiArgSpecSize);
-		subclassResponsibility();
-		return null;
+		roundedSize = (structSize + 3) & (~3);
+		if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) {
+			return FFIErrorCallFrameTooBig;
+		}
+		memcpy((calloutState->currentArg), ((void *) ptrAddress), structSize);
+		(calloutState->currentArg = ((calloutState->currentArg)) + roundedSize);
+		return 0;
 	}
 	if (ptrClass == (interpreterProxy->classByteArray())) {
 		if (!((interpreterProxy->byteSizeOf(oop)) == (((calloutState->ffiArgHeader)) & FFIStructSizeMask))) {
@@ -1891,16 +2270,17 @@
 		}
 		ptrAddress = ((int) (interpreterProxy->firstIndexableField(oop)));
 		if (!(((calloutState->ffiArgHeader)) & FFIFlagPointer)) {
-			if ((((calloutState->callFlags)) & FFICallFlagThreaded)
-			 && (interpreterProxy->isYoung(oop))) {
-				return -PrimErrObjectMayMove;
-			}
 			/* begin ffiPushStructure:ofSize:typeSpec:ofLength:in: */
 			structSize1 = ((calloutState->ffiArgHeader)) & FFIStructSizeMask;
 			argSpec1 = (calloutState->ffiArgSpec);
 			argSpecSize1 = (calloutState->ffiArgSpecSize);
-			subclassResponsibility();
-			return null;
+			roundedSize1 = (structSize1 + 3) & (~3);
+			if ((((calloutState->currentArg)) + roundedSize1) > ((calloutState->limit))) {
+				return FFIErrorCallFrameTooBig;
+			}
+			memcpy((calloutState->currentArg), ((void *) ptrAddress), structSize1);
+			(calloutState->currentArg = ((calloutState->currentArg)) + roundedSize1);
+			return 0;
 		}
 		if (!((((calloutState->ffiArgHeader)) & FFIStructSizeMask) == 4)) {
 			return FFIErrorStructSize;
@@ -1910,7 +2290,11 @@
 			return FFIErrorInvalidPointer;
 		}
 		/* begin ffiPushPointer:in: */
-		error("shouldBeImplemented");
+		if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+			return FFIErrorCallFrameTooBig;
+		}
+		longAtput((calloutState->currentArg), ptrAddress);
+		(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 		return 0;
 	}
 	return FFIErrorBadArg;
@@ -1919,27 +2303,48 @@
 static sqInt
 ffiPushStructureofSizetypeSpecofLengthin(void *pointer, sqInt structSize, sqInt *argSpec, sqInt argSpecSize, CalloutState *calloutState)
 {
-	subclassResponsibility();
+    sqInt roundedSize;
+
+	roundedSize = (structSize + 3) & (~3);
+	if ((((calloutState->currentArg)) + roundedSize) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	memcpy((calloutState->currentArg), pointer, structSize);
+	(calloutState->currentArg = ((calloutState->currentArg)) + roundedSize);
+	return 0;
 }
 
 static sqInt
 ffiPushUnsignedBytein(sqInt value, CalloutState *calloutState)
 {
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), ((unsigned char) value));
+	(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 	return 0;
 }
 
 static sqInt
 ffiPushUnsignedCharin(sqInt value, CalloutState *calloutState)
 {
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), ((unsigned char) value));
+	(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 	return 0;
 }
 
 static sqInt
 ffiPushUnsignedIntin(sqInt value, CalloutState *calloutState)
 {
-	subclassResponsibility();
+	if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), value);
+	(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+	return 0;
 }
 
 
@@ -1967,28 +2372,35 @@
 		}
 	}
 	/* begin ffiPushUnsignedLongLong:in: */
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), ((usqInt) value));
+	longAtput(((calloutState->currentArg)) + 4, ((usqInt) (value >> 32)));
+	(calloutState->currentArg = ((calloutState->currentArg)) + 8);
 	return 0;
 }
 
 static sqInt
 ffiPushUnsignedLongLongin(usqLong value, CalloutState *calloutState)
 {
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 8) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), ((usqInt) value));
+	longAtput(((calloutState->currentArg)) + 4, ((usqInt) (value >> 32)));
+	(calloutState->currentArg = ((calloutState->currentArg)) + 8);
 	return 0;
 }
 
 static sqInt
-ffiPushUnsignedLongin(sqInt value, CalloutState *calloutState)
-{
-	error("shouldBeImplemented");
-	return 0;
-}
-
-static sqInt
 ffiPushUnsignedShortin(sqInt value, CalloutState *calloutState)
 {
-	error("shouldBeImplemented");
+	if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+		return FFIErrorCallFrameTooBig;
+	}
+	longAtput((calloutState->currentArg), ((unsigned short) value));
+	(calloutState->currentArg = ((calloutState->currentArg)) + 4);
 	return 0;
 }
 
@@ -2122,9 +2534,25 @@
 	alloca'ed space pointed to by the calloutState. */
 
 static sqInt
-ffiReturnStructofTypein(usqLong longLongRet, sqInt ffiRetClass, CalloutState *calloutState)
+ffiReturnStructofTypein(usqLong longLongRet, sqInt ffiRetType, CalloutState *calloutState)
 {
-	subclassResponsibility();
+    sqInt oop;
+    sqInt retClass;
+    sqInt retOop;
+
+	retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType);
+	retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0);
+	interpreterProxy->pushRemappableOop(retOop);
+	oop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize));
+	if (returnStructInRegisters((calloutState->structReturnSize))) {
+		memcpy(interpreterProxy->firstIndexableField(oop), (&longLongRet), (calloutState->structReturnSize));
+	}
+	else {
+		memcpy(interpreterProxy->firstIndexableField(oop), (calloutState->limit), (calloutState->structReturnSize));
+	}
+	retOop = interpreterProxy->popRemappableOop();
+	interpreterProxy->storePointerofObjectwithValue(0, retOop, oop);
+	return interpreterProxy->methodReturnValue(retOop);
 }
 
 
@@ -2255,16 +2683,6 @@
 	return 1;
 }
 
-static void
-initialize(CalloutState * self_in_initialize)
-{
-	(self_in_initialize->stringArgs) = on(CArrayAccessor, new(Array, maxNumArgs(ThreadedFFIPlugin)));
-	(self_in_initialize->stringArgIndex) = 0;
-	(self_in_initialize->structReturnSize) = 0;
-	(self_in_initialize->regIndex) = 0;
-	(self_in_initialize->integerRegisters) = on(CArrayAccessor, new(Array, numRegArgs(ThreadedARMFFIPlugin)));
-}
-
 static sqInt
 isAlien(sqInt anOop)
 {
@@ -2312,22 +2730,335 @@
 EXPORT(void)
 primitiveCallout(void)
 {
+    sqInt address;
+    sqInt address1;
+    sqInt addressPtr;
+    char *allocation;
+    sqInt argClass;
+    sqInt argSpec;
+    sqInt argType;
+    sqInt argTypeArray;
+    sqInt argTypes;
+    sqInt argTypes1;
+    sqInt atomicType;
+    sqInt atomicType1;
+    CalloutState *calloutState;
+    sqInt classOop;
+    char *cString;
+    sqInt err;
     sqInt externalFunction;
+    sqInt ffiRetType;
+    sqInt flags;
+    double floatRet;
+    sqInt functionName;
+    sqInt i;
+    sqInt i1;
+    usqLong intRet;
     sqInt meth;
     sqInt nArgs;
-    sqInt retryCount;
+    sqInt oop;
+    sqInt oop1;
+    sqInt oop2;
+    void *pointer;
+    int *ptr;
+    sqInt *ptr1;
+    sqInt requiredStackSize;
+    sqInt result;
+    sqInt retClass;
+    sqInt retClass1;
+    sqInt retOop;
+    sqInt retOop1;
+    sqInt retType;
+    sqInt specLiteral;
+    sqInt specLiteral1;
+    sqInt stackSize;
+    sqInt strLen;
+    sqInt strOop;
+    char *strPtr;
+    CalloutState theCalloutState;
+    sqInt typeSpec;
+    sqInt typeSpec1;
 
 	meth = interpreterProxy->primitiveMethod();
 	if (!((interpreterProxy->literalCountOf(meth)) > 0)) {
 		interpreterProxy->primitiveFailFor(PrimErrBadMethod); return;
 	}
 	externalFunction = interpreterProxy->literalofMethod(0, meth);
+	/* begin ffiCall:ArgArrayOrNil:NumArgs: */
 	nArgs = interpreterProxy->methodArgumentCount();
-	retryCount = 0;
-	while (((ffiCallArgArrayOrNilNumArgs(externalFunction, null, nArgs)) == PrimErrObjectMayMove)
- && (((retryCount += 1)) <= nArgs)) {
-		interpreterProxy->tenuringIncrementalGC();
+	if (!(interpreterProxy->isKindOfClass(externalFunction, interpreterProxy->classExternalFunction()))) {
+		ffiFail(FFIErrorNotFunction);
+		goto l3;
 	}
+	flags = interpreterProxy->fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction);
+	if (interpreterProxy->failed()) {
+		ffiFail(FFIErrorBadArgs);
+		goto l3;
+	}
+
+	/* must be array of arg types */
+
+	argTypeArray = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, externalFunction);
+	if (!((interpreterProxy->isArray(argTypeArray))
+		 && ((interpreterProxy->slotSizeOf(argTypeArray)) == (nArgs + 1)))) {
+		ffiFail(FFIErrorBadArgs);
+		goto l3;
+	}
+	if (!(1)) {
+		ffiFail(FFIErrorCallType);
+		goto l3;
+	}
+	/* begin ffiLoadCalloutAddress: */
+
+	/* Lookup the address */
+	/* Make sure it's an external handle */
+
+	addressPtr = interpreterProxy->fetchPointerofObject(0, externalFunction);
+	/* begin ffiContentsOfHandle:errCode: */
+	if ((addressPtr & 1)) {
+		address1 = ffiFail(FFIErrorBadAddress);
+		goto l4;
+	}
+	if (!(interpreterProxy->isBytes(addressPtr))) {
+		address1 = ffiFail(FFIErrorBadAddress);
+		goto l4;
+	}
+	if (!((interpreterProxy->byteSizeOf(addressPtr)) == 4)) {
+		address1 = ffiFail(FFIErrorBadAddress);
+		goto l4;
+	}
+	address1 = interpreterProxy->fetchPointerofObject(0, addressPtr);
+l4:	/* end ffiContentsOfHandle:errCode: */;
+	if (interpreterProxy->failed()) {
+		address = 0;
+		goto l5;
+	}
+	if (address1 == 0) {
+		if (externalFunctionInstSize > ExternalFunctionStackSizeIndex) {
+			interpreterProxy->storePointerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, ((-1 << 1) | 1));
+		}
+		if ((interpreterProxy->slotSizeOf(externalFunction)) < 5) {
+			address = ffiFail(FFIErrorNoModule);
+			goto l5;
+		}
+		address1 = ffiLoadCalloutAddressFrom(externalFunction);
+		if (interpreterProxy->failed()) {
+			address = 0;
+			goto l5;
+		}
+		ptr = interpreterProxy->firstIndexableField(addressPtr);
+		ptr[0] = address1;
+	}
+	address = address1;
+l5:	/* end ffiLoadCalloutAddress: */;
+	if (interpreterProxy->failed()) {
+		goto l3;
+	}
+	requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex
+		? interpreterProxy->fetchIntegerofObject(ExternalFunctionStackSizeIndex, externalFunction)
+		: -1);
+	if (interpreterProxy->failed()) {
+		interpreterProxy->primitiveFailFor((null == null
+			? PrimErrBadMethod
+			: PrimErrBadReceiver));
+		goto l3;
+	}
+	stackSize = (requiredStackSize < 0
+		? DefaultMaxStackSize
+		: requiredStackSize);
+	null;
+	calloutState = (&theCalloutState);
+		memset(calloutState, 0, sizeof(CalloutState));
+;
+	(calloutState->callFlags = flags);
+	argType = interpreterProxy->fetchPointerofObject(0, argTypeArray);
+	argSpec = interpreterProxy->fetchPointerofObject(0, argType);
+	argClass = interpreterProxy->fetchPointerofObject(1, argType);
+	if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) {
+		ffiFail(err);
+		goto l3;
+	}
+	allocation = alloca(((stackSize + ((calloutState->structReturnSize))) + 0) + (cStackAlignment()));
+	if (allocaLiesSoUseGetsp()) {
+		allocation = getsp();
+	}
+	if ((cStackAlignment()) != 0) {
+		allocation = ((char *) ((((usqInt)allocation)) & (~((cStackAlignment()) - 1))));
+	}
+	(calloutState->argVector = allocation);
+	(calloutState->currentArg = allocation + 0);
+	(calloutState->limit = (allocation + stackSize) + 0);
+	if ((((calloutState->structReturnSize)) > 0)
+	 && (1
+ && (!(returnStructInRegisters((calloutState->structReturnSize)))))) {
+		/* begin ffiPushPointer:in: */
+		pointer = (calloutState->limit);
+		if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+			goto l1;
+		}
+		longAtput((calloutState->currentArg), pointer);
+		(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+	l1:	/* end ffiPushPointer:in: */;
+	}
+	for (i = 1; i <= nArgs; i += 1) {
+		argType = interpreterProxy->fetchPointerofObject(i, argTypeArray);
+		argSpec = interpreterProxy->fetchPointerofObject(0, argType);
+		argClass = interpreterProxy->fetchPointerofObject(1, argType);
+		oop = (null == null
+			? interpreterProxy->stackValue(nArgs - i)
+			: interpreterProxy->fetchPointerofObject(i - 1, null));
+		err = ffiArgumentSpecClassin(oop, argSpec, argClass, calloutState);
+		if (err != 0) {
+			/* begin cleanupCalloutState: */
+			while (((calloutState->stringArgIndex)) > 0) {
+				free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
+			}
+			ffiFail(err);
+			goto l3;
+		}
+	}
+	assert(!(interpreterProxy->failed()));
+	/* begin ffiLogCallout: */
+	if (ffiLogEnabled) {
+		functionName = interpreterProxy->fetchPointerofObject(externalFunctionInstSize, externalFunction);
+		if (!(interpreterProxy->isBytes(functionName))) {
+			goto l2;
+		}
+		ffiLogCallOfLength(interpreterProxy->firstIndexableField(functionName), interpreterProxy->byteSizeOf(functionName));
+	}
+l2:	/* end ffiLogCallout: */;
+	if ((requiredStackSize < 0)
+	 && (externalFunctionInstSize > ExternalFunctionStackSizeIndex)) {
+		stackSize = ((calloutState->currentArg)) - ((calloutState->argVector));
+		interpreterProxy->storeIntegerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, stackSize);
+	}
+	/* begin ffiCalloutTo:SpecOnStack:in: */
+	if ((0 + (cStackAlignment())) > 0) {
+		setsp((calloutState->argVector));
+	}
+	/* begin atomicTypeOf: */
+	typeSpec = (calloutState->ffiRetHeader);
+	atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+	if ((atomicType == FFITypeSingleFloat)
+	 || (atomicType == FFITypeDoubleFloat)) {
+		floatRet = dispatchFunctionPointer(((double (*)()) address));
+	}
+	else {
+		intRet = dispatchFunctionPointer(((usqLong (*)()) address));
+	}
+	if (isCalleePopsConvention((calloutState->callFlags))) {
+		setsp((calloutState->argVector));
+	}
+	if (((calloutState->ffiRetHeader)) & FFIFlagPointer) {
+		/* begin ffiReturnPointer:ofType:in: */
+		/* begin ffiReturnType: */
+		specLiteral1 = (null != null
+			? interpreterProxy->stackValue(1)
+			: interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+		argTypes1 = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral1);
+		retType = interpreterProxy->fetchPointerofObject(0, argTypes1);
+		retClass1 = interpreterProxy->fetchPointerofObject(1, retType);
+		if (retClass1 == (interpreterProxy->nilObject())) {
+			/* begin atomicTypeOf: */
+			typeSpec1 = (calloutState->ffiRetHeader);
+			atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+			if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) {
+				/* begin ffiReturnCStringFrom: */
+				if ((((usqInt) intRet)) == null) {
+					result = interpreterProxy->methodReturnValue(interpreterProxy->nilObject());
+					goto l6;
+				}
+				cString = ((char *) (((usqInt) intRet)));
+				strLen = 0;
+				while (!((cString[strLen]) == 0)) {
+					strLen += 1;
+				}
+				strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen);
+				strPtr = interpreterProxy->firstIndexableField(strOop);
+				for (i1 = 0; i1 <= (strLen - 1); i1 += 1) {
+					strPtr[i1] = (cString[i1]);
+				}
+				result = interpreterProxy->methodReturnValue(strOop);
+				goto l6;
+			}
+			interpreterProxy->pushRemappableOop(retType);
+			oop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4);
+			ptr1 = interpreterProxy->firstIndexableField(oop1);
+			ptr1[0] = (((sqInt) intRet));
+			interpreterProxy->pushRemappableOop(oop1);
+			retOop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0);
+
+			/* external address */
+
+			oop1 = interpreterProxy->popRemappableOop();
+			interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+
+			/* return type */
+
+			oop1 = interpreterProxy->popRemappableOop();
+			interpreterProxy->storePointerofObjectwithValue(1, retOop1, oop1);
+			result = interpreterProxy->methodReturnValue(retOop1);
+			goto l6;
+		}
+		interpreterProxy->pushRemappableOop(retClass1);
+		if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+			classOop = interpreterProxy->classByteArray();
+		}
+		else {
+			classOop = interpreterProxy->classExternalAddress();
+		}
+		oop1 = interpreterProxy->instantiateClassindexableSize(classOop, 4);
+		ptr1 = interpreterProxy->firstIndexableField(oop1);
+		ptr1[0] = (((sqInt) intRet));
+
+		/* return class */
+
+		retClass1 = interpreterProxy->popRemappableOop();
+		interpreterProxy->pushRemappableOop(oop1);
+		retOop1 = interpreterProxy->instantiateClassindexableSize(retClass1, 0);
+
+		/* external address */
+
+		oop1 = interpreterProxy->popRemappableOop();
+		interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+		result = interpreterProxy->methodReturnValue(retOop1);
+		goto l6;
+	}
+	if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+		/* begin ffiReturnStruct:ofType:in: */
+		/* begin ffiReturnType: */
+		specLiteral = (null != null
+			? interpreterProxy->stackValue(1)
+			: interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+		argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral);
+		ffiRetType = interpreterProxy->fetchPointerofObject(0, argTypes);
+		retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType);
+		retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0);
+		interpreterProxy->pushRemappableOop(retOop);
+		oop2 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize));
+		if (returnStructInRegisters((calloutState->structReturnSize))) {
+			memcpy(interpreterProxy->firstIndexableField(oop2), (&intRet), (calloutState->structReturnSize));
+		}
+		else {
+			memcpy(interpreterProxy->firstIndexableField(oop2), (calloutState->limit), (calloutState->structReturnSize));
+		}
+		retOop = interpreterProxy->popRemappableOop();
+		interpreterProxy->storePointerofObjectwithValue(0, retOop, oop2);
+		result = interpreterProxy->methodReturnValue(retOop);
+		goto l6;
+	}
+	if ((atomicType == FFITypeSingleFloat)
+	 || (atomicType == FFITypeDoubleFloat)) {
+		result = interpreterProxy->methodReturnValue(interpreterProxy->floatObjectOf(floatRet));
+		goto l6;
+	}
+	result = interpreterProxy->methodReturnValue(ffiCreateIntegralResultOopofAtomicTypein(intRet, atomicType, calloutState));
+l6:	/* end ffiCalloutTo:SpecOnStack:in: */;
+	/* begin cleanupCalloutState: */
+	while (((calloutState->stringArgIndex)) > 0) {
+		free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
+	}
+l3:	/* end ffiCall:ArgArrayOrNil:NumArgs: */;
 	return;
 }
 
@@ -2338,26 +3069,338 @@
 EXPORT(void)
 primitiveCalloutWithArgs(void)
 {
+    sqInt address;
+    sqInt address1;
+    sqInt addressPtr;
+    char *allocation;
     sqInt argArray;
+    sqInt argClass;
+    sqInt argSpec;
+    sqInt argType;
+    sqInt argTypeArray;
+    sqInt argTypes;
+    sqInt argTypes1;
+    sqInt atomicType;
+    sqInt atomicType1;
+    CalloutState *calloutState;
+    sqInt classOop;
+    char *cString;
+    sqInt err;
     sqInt externalFunction;
+    sqInt ffiRetType;
+    sqInt flags;
+    double floatRet;
+    sqInt functionName;
+    sqInt i;
+    sqInt i1;
+    usqLong intRet;
     sqInt nArgs;
-    sqInt retryCount;
+    sqInt oop;
+    sqInt oop1;
+    sqInt oop2;
+    void *pointer;
+    int *ptr;
+    sqInt *ptr1;
+    sqInt requiredStackSize;
+    sqInt result;
+    sqInt retClass;
+    sqInt retClass1;
+    sqInt retOop;
+    sqInt retOop1;
+    sqInt retType;
+    sqInt specLiteral;
+    sqInt specLiteral1;
+    sqInt stackSize;
+    sqInt strLen;
+    sqInt strOop;
+    char *strPtr;
+    CalloutState theCalloutState;
+    sqInt typeSpec;
+    sqInt typeSpec1;
 
 	if (!((interpreterProxy->methodArgumentCount()) == 1)) {
 		interpreterProxy->primitiveFailFor(PrimErrBadNumArgs); return;
 	}
-	retryCount = 0;
-	while (1) {
-		externalFunction = interpreterProxy->stackValue(1);
-		argArray = interpreterProxy->stackValue(0);
-		if (!(interpreterProxy->isArray(argArray))) {
-			interpreterProxy->primitiveFailFor(PrimErrBadArgument); return;
+	externalFunction = interpreterProxy->stackValue(1);
+	argArray = interpreterProxy->stackValue(0);
+	if (!(interpreterProxy->isArray(argArray))) {
+		interpreterProxy->primitiveFailFor(PrimErrBadArgument); return;
+	}
+	nArgs = interpreterProxy->slotSizeOf(argArray);
+	/* begin ffiCall:ArgArrayOrNil:NumArgs: */
+	if (!(interpreterProxy->isKindOfClass(externalFunction, interpreterProxy->classExternalFunction()))) {
+		ffiFail(FFIErrorNotFunction);
+		goto l3;
+	}
+	flags = interpreterProxy->fetchIntegerofObject(ExternalFunctionFlagsIndex, externalFunction);
+	if (interpreterProxy->failed()) {
+		ffiFail(FFIErrorBadArgs);
+		goto l3;
+	}
+
+	/* must be array of arg types */
+
+	argTypeArray = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, externalFunction);
+	if (!((interpreterProxy->isArray(argTypeArray))
+		 && ((interpreterProxy->slotSizeOf(argTypeArray)) == (nArgs + 1)))) {
+		ffiFail(FFIErrorBadArgs);
+		goto l3;
+	}
+	if (!(1)) {
+		ffiFail(FFIErrorCallType);
+		goto l3;
+	}
+	/* begin ffiLoadCalloutAddress: */
+
+	/* Lookup the address */
+	/* Make sure it's an external handle */
+
+	addressPtr = interpreterProxy->fetchPointerofObject(0, externalFunction);
+	/* begin ffiContentsOfHandle:errCode: */
+	if ((addressPtr & 1)) {
+		address1 = ffiFail(FFIErrorBadAddress);
+		goto l4;
+	}
+	if (!(interpreterProxy->isBytes(addressPtr))) {
+		address1 = ffiFail(FFIErrorBadAddress);
+		goto l4;
+	}
+	if (!((interpreterProxy->byteSizeOf(addressPtr)) == 4)) {
+		address1 = ffiFail(FFIErrorBadAddress);
+		goto l4;
+	}
+	address1 = interpreterProxy->fetchPointerofObject(0, addressPtr);
+l4:	/* end ffiContentsOfHandle:errCode: */;
+	if (interpreterProxy->failed()) {
+		address = 0;
+		goto l5;
+	}
+	if (address1 == 0) {
+		if (externalFunctionInstSize > ExternalFunctionStackSizeIndex) {
+			interpreterProxy->storePointerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, ((-1 << 1) | 1));
 		}
-		nArgs = interpreterProxy->slotSizeOf(argArray);
-		if (!(((ffiCallArgArrayOrNilNumArgs(externalFunction, argArray, nArgs)) == PrimErrObjectMayMove)
- && (((retryCount += 1)) <= nArgs))) break;
-		interpreterProxy->tenuringIncrementalGC();
+		if ((interpreterProxy->slotSizeOf(externalFunction)) < 5) {
+			address = ffiFail(FFIErrorNoModule);
+			goto l5;
+		}
+		address1 = ffiLoadCalloutAddressFrom(externalFunction);
+		if (interpreterProxy->failed()) {
+			address = 0;
+			goto l5;
+		}
+		ptr = interpreterProxy->firstIndexableField(addressPtr);
+		ptr[0] = address1;
 	}
+	address = address1;
+l5:	/* end ffiLoadCalloutAddress: */;
+	if (interpreterProxy->failed()) {
+		goto l3;
+	}
+	requiredStackSize = (externalFunctionInstSize > ExternalFunctionStackSizeIndex
+		? interpreterProxy->fetchIntegerofObject(ExternalFunctionStackSizeIndex, externalFunction)
+		: -1);
+	if (interpreterProxy->failed()) {
+		interpreterProxy->primitiveFailFor((argArray == null
+			? PrimErrBadMethod
+			: PrimErrBadReceiver));
+		goto l3;
+	}
+	stackSize = (requiredStackSize < 0
+		? DefaultMaxStackSize
+		: requiredStackSize);
+	null;
+	calloutState = (&theCalloutState);
+		memset(calloutState, 0, sizeof(CalloutState));
+;
+	(calloutState->callFlags = flags);
+	argType = interpreterProxy->fetchPointerofObject(0, argTypeArray);
+	argSpec = interpreterProxy->fetchPointerofObject(0, argType);
+	argClass = interpreterProxy->fetchPointerofObject(1, argType);
+	if (((err = ffiCheckReturnWithin(argSpec, argClass, calloutState))) != 0) {
+		ffiFail(err);
+		goto l3;
+	}
+	allocation = alloca(((stackSize + ((calloutState->structReturnSize))) + 0) + (cStackAlignment()));
+	if (allocaLiesSoUseGetsp()) {
+		allocation = getsp();
+	}
+	if ((cStackAlignment()) != 0) {
+		allocation = ((char *) ((((usqInt)allocation)) & (~((cStackAlignment()) - 1))));
+	}
+	(calloutState->argVector = allocation);
+	(calloutState->currentArg = allocation + 0);
+	(calloutState->limit = (allocation + stackSize) + 0);
+	if ((((calloutState->structReturnSize)) > 0)
+	 && (1
+ && (!(returnStructInRegisters((calloutState->structReturnSize)))))) {
+		/* begin ffiPushPointer:in: */
+		pointer = (calloutState->limit);
+		if ((((calloutState->currentArg)) + 4) > ((calloutState->limit))) {
+			goto l1;
+		}
+		longAtput((calloutState->currentArg), pointer);
+		(calloutState->currentArg = ((calloutState->currentArg)) + 4);
+	l1:	/* end ffiPushPointer:in: */;
+	}
+	for (i = 1; i <= nArgs; i += 1) {
+		argType = interpreterProxy->fetchPointerofObject(i, argTypeArray);
+		argSpec = interpreterProxy->fetchPointerofObject(0, argType);
+		argClass = interpreterProxy->fetchPointerofObject(1, argType);
+		oop = (argArray == null
+			? interpreterProxy->stackValue(nArgs - i)
+			: interpreterProxy->fetchPointerofObject(i - 1, argArray));
+		err = ffiArgumentSpecClassin(oop, argSpec, argClass, calloutState);
+		if (err != 0) {
+			/* begin cleanupCalloutState: */
+			while (((calloutState->stringArgIndex)) > 0) {
+				free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
+			}
+			ffiFail(err);
+			goto l3;
+		}
+	}
+	assert(!(interpreterProxy->failed()));
+	/* begin ffiLogCallout: */
+	if (ffiLogEnabled) {
+		functionName = interpreterProxy->fetchPointerofObject(externalFunctionInstSize, externalFunction);
+		if (!(interpreterProxy->isBytes(functionName))) {
+			goto l2;
+		}
+		ffiLogCallOfLength(interpreterProxy->firstIndexableField(functionName), interpreterProxy->byteSizeOf(functionName));
+	}
+l2:	/* end ffiLogCallout: */;
+	if ((requiredStackSize < 0)
+	 && (externalFunctionInstSize > ExternalFunctionStackSizeIndex)) {
+		stackSize = ((calloutState->currentArg)) - ((calloutState->argVector));
+		interpreterProxy->storeIntegerofObjectwithValue(ExternalFunctionStackSizeIndex, externalFunction, stackSize);
+	}
+	/* begin ffiCalloutTo:SpecOnStack:in: */
+	if ((0 + (cStackAlignment())) > 0) {
+		setsp((calloutState->argVector));
+	}
+	/* begin atomicTypeOf: */
+	typeSpec = (calloutState->ffiRetHeader);
+	atomicType = ((usqInt) (typeSpec & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+	if ((atomicType == FFITypeSingleFloat)
+	 || (atomicType == FFITypeDoubleFloat)) {
+		floatRet = dispatchFunctionPointer(((double (*)()) address));
+	}
+	else {
+		intRet = dispatchFunctionPointer(((usqLong (*)()) address));
+	}
+	if (isCalleePopsConvention((calloutState->callFlags))) {
+		setsp((calloutState->argVector));
+	}
+	if (((calloutState->ffiRetHeader)) & FFIFlagPointer) {
+		/* begin ffiReturnPointer:ofType:in: */
+		/* begin ffiReturnType: */
+		specLiteral1 = (argArray != null
+			? interpreterProxy->stackValue(1)
+			: interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+		argTypes1 = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral1);
+		retType = interpreterProxy->fetchPointerofObject(0, argTypes1);
+		retClass1 = interpreterProxy->fetchPointerofObject(1, retType);
+		if (retClass1 == (interpreterProxy->nilObject())) {
+			/* begin atomicTypeOf: */
+			typeSpec1 = (calloutState->ffiRetHeader);
+			atomicType1 = ((usqInt) (typeSpec1 & FFIAtomicTypeMask)) >> FFIAtomicTypeShift;
+			if ((((usqInt) atomicType1) >> 1) == (((usqInt) FFITypeSignedChar) >> 1)) {
+				/* begin ffiReturnCStringFrom: */
+				if ((((usqInt) intRet)) == null) {
+					result = interpreterProxy->methodReturnValue(interpreterProxy->nilObject());
+					goto l6;
+				}
+				cString = ((char *) (((usqInt) intRet)));
+				strLen = 0;
+				while (!((cString[strLen]) == 0)) {
+					strLen += 1;
+				}
+				strOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), strLen);
+				strPtr = interpreterProxy->firstIndexableField(strOop);
+				for (i1 = 0; i1 <= (strLen - 1); i1 += 1) {
+					strPtr[i1] = (cString[i1]);
+				}
+				result = interpreterProxy->methodReturnValue(strOop);
+				goto l6;
+			}
+			interpreterProxy->pushRemappableOop(retType);
+			oop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalAddress(), 4);
+			ptr1 = interpreterProxy->firstIndexableField(oop1);
+			ptr1[0] = (((sqInt) intRet));
+			interpreterProxy->pushRemappableOop(oop1);
+			retOop1 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classExternalData(), 0);
+
+			/* external address */
+
+			oop1 = interpreterProxy->popRemappableOop();
+			interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+
+			/* return type */
+
+			oop1 = interpreterProxy->popRemappableOop();
+			interpreterProxy->storePointerofObjectwithValue(1, retOop1, oop1);
+			result = interpreterProxy->methodReturnValue(retOop1);
+			goto l6;
+		}
+		interpreterProxy->pushRemappableOop(retClass1);
+		if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+			classOop = interpreterProxy->classByteArray();
+		}
+		else {
+			classOop = interpreterProxy->classExternalAddress();
+		}
+		oop1 = interpreterProxy->instantiateClassindexableSize(classOop, 4);
+		ptr1 = interpreterProxy->firstIndexableField(oop1);
+		ptr1[0] = (((sqInt) intRet));
+
+		/* return class */
+
+		retClass1 = interpreterProxy->popRemappableOop();
+		interpreterProxy->pushRemappableOop(oop1);
+		retOop1 = interpreterProxy->instantiateClassindexableSize(retClass1, 0);
+
+		/* external address */
+
+		oop1 = interpreterProxy->popRemappableOop();
+		interpreterProxy->storePointerofObjectwithValue(0, retOop1, oop1);
+		result = interpreterProxy->methodReturnValue(retOop1);
+		goto l6;
+	}
+	if (((calloutState->ffiRetHeader)) & FFIFlagStructure) {
+		/* begin ffiReturnStruct:ofType:in: */
+		/* begin ffiReturnType: */
+		specLiteral = (argArray != null
+			? interpreterProxy->stackValue(1)
+			: interpreterProxy->literalofMethod(0, interpreterProxy->primitiveMethod()));
+		argTypes = interpreterProxy->fetchPointerofObject(ExternalFunctionArgTypesIndex, specLiteral);
+		ffiRetType = interpreterProxy->fetchPointerofObject(0, argTypes);
+		retClass = interpreterProxy->fetchPointerofObject(1, ffiRetType);
+		retOop = interpreterProxy->instantiateClassindexableSize(retClass, 0);
+		interpreterProxy->pushRemappableOop(retOop);
+		oop2 = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classByteArray(), (calloutState->structReturnSize));
+		if (returnStructInRegisters((calloutState->structReturnSize))) {
+			memcpy(interpreterProxy->firstIndexableField(oop2), (&intRet), (calloutState->structReturnSize));
+		}
+		else {
+			memcpy(interpreterProxy->firstIndexableField(oop2), (calloutState->limit), (calloutState->structReturnSize));
+		}
+		retOop = interpreterProxy->popRemappableOop();
+		interpreterProxy->storePointerofObjectwithValue(0, retOop, oop2);
+		result = interpreterProxy->methodReturnValue(retOop);
+		goto l6;
+	}
+	if ((atomicType == FFITypeSingleFloat)
+	 || (atomicType == FFITypeDoubleFloat)) {
+		result = interpreterProxy->methodReturnValue(interpreterProxy->floatObjectOf(floatRet));
+		goto l6;
+	}
+	result = interpreterProxy->methodReturnValue(ffiCreateIntegralResultOopofAtomicTypein(intRet, atomicType, calloutState));
+l6:	/* end ffiCalloutTo:SpecOnStack:in: */;
+	/* begin cleanupCalloutState: */
+	while (((calloutState->stringArgIndex)) > 0) {
+		free(((calloutState->stringArgs))[(calloutState->stringArgIndex = ((calloutState->stringArgIndex)) - 1)]);
+	}
+l3:	/* end ffiCall:ArgArrayOrNil:NumArgs: */;
 	return;
 }
 
@@ -2870,8 +3913,7 @@
 /*	Answer any space needed to prevent the alloca'ed outgoing arguments
 	marshalling area from
 	being overwritten by any register arguments during calls during
-	marshalling. On ARM we
-	believe this is zero. */
+	marshalling. On x86 this is 0 */
 
 static sqInt
 registerArgsSlop(void)
@@ -2880,15 +3922,6 @@
 }
 
 
-/*	Answer if a struct result of a given size is returned in memory or not. */
-
-static sqInt
-returnStructInRegisters(sqInt returnStructSize)
-{
-	return subclassResponsibility();
-}
-
-
 /*	Note: This is coded so that is can be run from Squeak. */
 
 EXPORT(sqInt)



More information about the Vm-dev mailing list