--- bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx	2007-02-07 16:08:49.000000000 +0100
+++ bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx	2007-02-08 14:54:32.000000000 +0100
@@ -55,149 +55,45 @@
 using namespace ::rtl;
 using namespace ::com::sun::star::uno;
 
-void dummy_can_throw_anything( char const * );
-
-// 6 integral parameters are passed in registers
-const sal_uInt32 GPR_COUNT = 6;
-
-// 8 floating point parameters are passed in SSE registers
-const sal_uInt32 FPR_COUNT = 8;
-
-static inline void
-invoke_count_words(char *		pPT,      // Parameter Types
-				   sal_uInt32 &	nr_gpr,   // Number of arguments in GPRs
-				   sal_uInt32 &	nr_fpr,   // Number of arguments in FPRs
-				   sal_uInt32 &	nr_stack) // Number of arguments in stack
-{
-	nr_gpr = 0;
-	nr_fpr = 0;
-	nr_stack = 0;
-	char c;
-	
-	while ((c = *pPT++) != 'X')
-	{
-		if (c == 'F' || c == 'D')
-		{
-            if (nr_fpr < FPR_COUNT)
-                nr_fpr++;
-            else
-                nr_stack++;
-		}
-		else
-		{
-            if (nr_gpr < GPR_COUNT)
-                nr_gpr++;
-            else
-                nr_stack++;
-		}
-	}
-}
-
-static void
-invoke_copy_to_stack(sal_uInt64 * pDS,  // Stack Storage
-					 char *       pPT,  // Parameter Types
-					 sal_uInt64 * pSV,  // Source Values
-					 sal_uInt64 * pGPR, // General Purpose Registers
-					 double *     pFPR) // Floating-Point Registers
-{
-	sal_uInt32 nr_gpr = 0;
-	sal_uInt32 nr_fpr = 0;
-	sal_uInt64 value;
-	char c;
-	
-	while ((c = *pPT++) != 'X')
-	{
-		switch (c)
-		{
-		case 'D': // Double
-			if (nr_fpr < FPR_COUNT)
-				pFPR[nr_fpr++] = *reinterpret_cast<double *>( pSV++ );
-			else
-				*pDS++ = *pSV++;
-			break;
-
-		case 'F': // Float
-			if (nr_fpr < FPR_COUNT)
-                // The value in %xmm register is already prepared to
-                // be retrieved as a float. Therefore, we pass the
-                // value verbatim, as a double without conversion.
-				pFPR[nr_fpr++] = *reinterpret_cast<double *>( pSV++ );
-			else
-				*pDS++ = *pSV++;
-			break;
-
-		case 'H': // 64-bit Word
-			if (nr_gpr < GPR_COUNT)
-				pGPR[nr_gpr++] = *pSV++;
-			else
-				*pDS++ = *pSV++;
-			break;
-
-		case 'I': // 32-bit Word
-			if (nr_gpr < GPR_COUNT)
-				pGPR[nr_gpr++] = *reinterpret_cast<sal_uInt32 *>( pSV++ );
-			else
-				*pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV++ );
-			break;
-
-		case 'S': // 16-bit Word
-			if (nr_gpr < GPR_COUNT)
-				pGPR[nr_gpr++] = *reinterpret_cast<sal_uInt16 *>( pSV++ );
-			else
-				*pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV++ );
-			break;
-
-		case 'B': // Byte
-			if (nr_gpr < GPR_COUNT)
-				pGPR[nr_gpr++] = *reinterpret_cast<sal_uInt8 *>( pSV++ );
-			else
-				*pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV++ );
-			break;
-
-		default: // Default, assume 64-bit values
-			if (nr_gpr < GPR_COUNT)
-				pGPR[nr_gpr++] = *pSV++;
-			else
-				*pDS++ = *pSV++;
-			break;
-		}
-	}
-}
-
 //==================================================================================================
+
 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
 							  void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn,
-							  char * pPT, sal_uInt64 * pStackLongs, sal_uInt32 nStackLongs)
+							  sal_uInt64 *pStack, sal_uInt32 nStack,
+							  sal_uInt64 *pGPR, sal_uInt32 nGPR,
+							  double *pFPR, sal_uInt32 nFPR)
 {
-	sal_uInt32 nr_gpr, nr_fpr, nr_stack;
-	invoke_count_words(pPT, nr_gpr, nr_fpr, nr_stack);
-
 	// Stack, if used, must be 16-bytes aligned
-	if (nr_stack)
-		nr_stack = (nr_stack + 1) & ~1;
+	if ( nStack )
+		nStack = ( nStack + 1 ) & ~1;
+
+	// Should not happen, but...
+	if ( nFPR > x86_64::MAX_SSE_REGS )
+		nFPR = x86_64::MAX_SSE_REGS;
+	if ( nGPR > x86_64::MAX_GPR_REGS )
+		nGPR = x86_64::MAX_GPR_REGS;
 	
 #if OSL_DEBUG_LEVEL > 1
 	// Let's figure out what is really going on here
-	fprintf(stderr,"callVirtualMethod() parameters string is %s\n", pPT);
 	{
-		sal_uInt32  k = nStackLongs;
-		sal_uInt64 *q = pStackLongs;
-		while (k > 0)
-		{
-			fprintf(stderr, "uno stack is: %lx\n", *q);
-			k--;
-			q++;
-		}
+		fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
+		for ( int i = 0; i < nGPR; ++i )
+			fprintf( stderr, "0x%lx, ", pGPR[i] );
+		fprintf( stderr, "\nFPR's (%d): ", nFPR );
+		for ( int i = 0; i < nFPR; ++i )
+			fprintf( stderr, "%f, ", pFPR[i] );
+		fprintf( stderr, "\nStack (%d): ", nStack );
+		for ( int i = 0; i < nStack; ++i )
+			fprintf( stderr, "0x%lx, ", pStack[i] );
+		fprintf( stderr, "\n" );
 	}
 #endif
 
 	// Load parameters to stack, if necessary
-    sal_uInt64 *stack = (sal_uInt64 *) __builtin_alloca(nr_stack * 8);
-    sal_uInt64 gpregs[GPR_COUNT];
-    double fpregs[FPR_COUNT];
-    invoke_copy_to_stack(stack, pPT, pStackLongs, gpregs, fpregs);
+    sal_uInt64 *stack = (sal_uInt64 *) __builtin_alloca( nStack * 8 );
+    memcpy( stack, pStack, nStack * 8 );
 
-    // Load FPR registers from fpregs[]
+    // Load SSE registers from pFPR[]
     register double d0 asm("xmm0");
     register double d1 asm("xmm1");
     register double d2 asm("xmm2");
@@ -207,9 +103,9 @@ static void callVirtualMethod(void * pTh
     register double d6 asm("xmm6");
     register double d7 asm("xmm7");
 
-    switch (nr_fpr) {
+    switch ( nFPR ) {
 #define ARG_FPR(N) \
-    case N+1: d##N = fpregs[N];
+    case N+1: d##N = pFPR[N];
         ARG_FPR(7);
         ARG_FPR(6);
         ARG_FPR(5);
@@ -222,7 +118,7 @@ static void callVirtualMethod(void * pTh
 #undef ARG_FPR
     }
     
-    // Load GPR registers from gpregs[]
+    // Load GPR registers from pGPR[]
     register sal_uInt64 a0 asm("rdi");
     register sal_uInt64 a1 asm("rsi");
     register sal_uInt64 a2 asm("rdx");
@@ -230,9 +126,9 @@ static void callVirtualMethod(void * pTh
     register sal_uInt64 a4 asm("r8");
     register sal_uInt64 a5 asm("r9");
     
-    switch (nr_gpr) {
+    switch ( nGPR ) {
 #define ARG_GPR(N) \
-    case N+1: a##N = gpregs[N];
+    case N+1: a##N = pGPR[N];
         ARG_GPR(5);
         ARG_GPR(4);
         ARG_GPR(3);
@@ -243,11 +139,6 @@ static void callVirtualMethod(void * pTh
 #undef ARG_GPR
     }
 
-	if ( bSimpleReturn )
-		a0 = (sal_uInt64) pThis;
-	else
-		a1 = (sal_uInt64) pThis;
-
     // Ensure that assignments to SSE registers won't be optimized away
     asm("" ::
         "x" (d0), "x" (d1), "x" (d2), "x" (d3),
@@ -258,16 +149,10 @@ static void callVirtualMethod(void * pTh
     pMethod += 8 * nVtableIndex;
     pMethod = *((sal_uInt64 *)pMethod);
 
-	union ReturnValue {
-		struct {
-			sal_uInt64 rax;
-			sal_uInt64 rdx;
-		} i;
-		struct {
-			double xmm0;
-			double xmm1;
-		} f;
-	};
+	typedef struct {
+		sal_uInt64 rax;
+		sal_uInt64 rdx;
+	} ReturnValue;
 
 	typedef ReturnValue (* FunctionCall )( sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64 );
 
@@ -278,42 +163,82 @@ static void callVirtualMethod(void * pTh
 	{
 	case typelib_TypeClass_HYPER:
 	case typelib_TypeClass_UNSIGNED_HYPER:
-		*reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = aRet.i.rax;
+		*reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = aRet.rax;
 		break;
 	case typelib_TypeClass_LONG:
 	case typelib_TypeClass_UNSIGNED_LONG:
 	case typelib_TypeClass_ENUM:
-		*reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &aRet.i.rax );
+		*reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &aRet.rax );
 		break;
 	case typelib_TypeClass_CHAR:
 	case typelib_TypeClass_SHORT:
 	case typelib_TypeClass_UNSIGNED_SHORT:
-		*reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &aRet.i.rax );
+		*reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &aRet.rax );
 		break;
 	case typelib_TypeClass_BOOLEAN:
 	case typelib_TypeClass_BYTE:
-		*reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &aRet.i.rax );
+		*reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &aRet.rax );
 		break;
 	case typelib_TypeClass_FLOAT:
-		*reinterpret_cast<float *>( pRegisterReturn ) = *reinterpret_cast<float*>( &aRet.f.xmm0 );
-		break;
 	case typelib_TypeClass_DOUBLE:
-		*reinterpret_cast<double *>( pRegisterReturn ) = *reinterpret_cast<double*>( &aRet.f.xmm0 );
+		*reinterpret_cast<double *>( pRegisterReturn ) = d0;
 		break;
-    default: {
-        sal_Int32 const nRetSize = pReturnTypeDescr->nSize;
-        if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0) {
-            if (nRetSize > 8)
-                static_cast<sal_uInt64 *>(pRegisterReturn)[1] = aRet.i.rdx;
-            static_cast<sal_uInt64 *>(pRegisterReturn)[0] = aRet.i.rax;
-        }
-        break;
-    }
+	default:
+		{
+			sal_Int32 const nRetSize = pReturnTypeDescr->nSize;
+			if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
+			{
+				if (nRetSize > 8)
+					static_cast<sal_uInt64 *>(pRegisterReturn)[1] = aRet.rdx;
+				static_cast<sal_uInt64 *>(pRegisterReturn)[0] = aRet.rax;
+			}
+			break;
+		}
 	}
 }
 
+//================================================================================================== 
+
+// Macros for easier insertion of values to registers or stack
+// pSV - pointer to the source
+// nr - order of the value [will be increased if stored to register]
+// pFPR, pGPR - pointer to the registers
+// pDS - pointer to the stack [will be increased if stored here]
+
+// The value in %xmm register is already prepared to be retrieved as a float,
+// thus we treat float and double the same
+#define INSERT_FLOAT_DOUBLE( pSV, nr, pFPR, pDS ) \
+	if ( nr < x86_64::MAX_SSE_REGS ) \
+		pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
+	else \
+		*pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
+
+#define INSERT_INT64( pSV, nr, pGPR, pDS ) \
+	if ( nr < x86_64::MAX_GPR_REGS ) \
+		pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
+	else \
+		*pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
+
+#define INSERT_INT32( pSV, nr, pGPR, pDS ) \
+	if ( nr < x86_64::MAX_GPR_REGS ) \
+		pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
+	else \
+		*pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
+
+#define INSERT_INT16( pSV, nr, pGPR, pDS ) \
+	if ( nr < x86_64::MAX_GPR_REGS ) \
+		pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
+	else \
+		*pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
+
+#define INSERT_INT8( pSV, nr, pGPR, pDS ) \
+	if ( nr < x86_64::MAX_GPR_REGS ) \
+		pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
+	else \
+		*pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
 
 //================================================================================================== 
+
 static void cpp_call(
 	bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
 	bridges::cpp_uno::shared::VtableSlot aVtableSlot,
@@ -322,54 +247,52 @@ static void cpp_call(
 	void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
 {
 	// Maxium space for [complex ret ptr], values | ptr ...
-  	char * pCppStack		= (char *)__builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) );
-  	char * pCppStackStart	= pCppStack;
+	// (but will be used less - some of the values will be in pGPR and pFPR)
+  	sal_uInt64 *pStack = (sal_uInt64 *)__builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) );
+  	sal_uInt64 *pStackStart = pStack;
 
-	// We need to know parameter types for callVirtualMethod() so generate a signature string
-	char * pParamType		= (char *)__builtin_alloca( nParams + 3 );
-	char * pPT				= pParamType;
+	sal_uInt64 pGPR[x86_64::MAX_GPR_REGS];
+	sal_uInt32 nGPR = 0;
+
+	double pFPR[x86_64::MAX_SSE_REGS];
+	sal_uInt32 nFPR = 0;
 
 	// Return
 	typelib_TypeDescription * pReturnTypeDescr = 0;
 	TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
 	OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
 	
-	void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
+	void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion (see below)
 
 	bool bSimpleReturn = true;	
-	if (pReturnTypeDescr)
+	if ( pReturnTypeDescr )
 	{
 		if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
 			bSimpleReturn = false;
 
-		if (bSimpleReturn)
+		if ( bSimpleReturn )
 			pCppReturn = pUnoReturn; // direct way for simple types
 		else
 		{
 			// complex return via ptr
-			pCppReturn = *(void **)pCppStack = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
-												? __builtin_alloca( pReturnTypeDescr->nSize )
-												: pUnoReturn); // direct way
-			*pPT++ = 'H';
-			pCppStack += sizeof(void *);
+			pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
+						 __builtin_alloca( pReturnTypeDescr->nSize ) : pUnoReturn;
+			INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack );
 		}
 	}
 
 	// Push "this" pointer
 	void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
-	*(void **)pCppStack = pAdjustedThisPtr;
-	*pPT++ = 'H';
-	pCppStack += sizeof(void *);
+	INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
 
-	// stack space
 	// Args
-	void ** pCppArgs  = (void **)alloca( 3 * sizeof(void *) * nParams );
+	void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
 	// Indizes of values this have to be converted (interface conversion cpp<=>uno)
 	sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
 	// Type descriptions for reconversions
 	typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
 	
-	sal_Int32 nTempIndizes   = 0;
+	sal_Int32 nTempIndizes = 0;
 	
 	for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
 	{
@@ -379,45 +302,32 @@ static void cpp_call(
 		
 		if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
 		{
-			uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr,
+			uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
 									pThis->getBridge()->getUno2Cpp() );
 			
 			switch (pParamTypeDescr->eTypeClass)
 			{
-				
-				// we need to know type of each param so that we know whether to use
-				// gpr or fpr to pass in parameters:
-				// Key: I - 32-bit value passed in gpr
-				//      B - byte value passed in gpr
-				//      S - short value passed in gpr
-				//      F - float value pass in fpr
-				//      D - double value pass in fpr
-				//      H - long value passed in gpr
-				//      X - indicates end of parameter description string
-				
+			case typelib_TypeClass_HYPER:
+			case typelib_TypeClass_UNSIGNED_HYPER:
+				INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack );
+				break;
 			case typelib_TypeClass_LONG:
 			case typelib_TypeClass_UNSIGNED_LONG:
 			case typelib_TypeClass_ENUM:
-				*pPT++ = 'I';
+				INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
 				break;
 			case typelib_TypeClass_SHORT:
 			case typelib_TypeClass_CHAR:
 			case typelib_TypeClass_UNSIGNED_SHORT:
-				*pPT++ = 'S';
+				INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
 				break;
 			case typelib_TypeClass_BOOLEAN:
 			case typelib_TypeClass_BYTE:
-				*pPT++ = 'B';
+				INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
 				break;
 			case typelib_TypeClass_FLOAT:
-				*pPT++ = 'F';
-				break;
 			case typelib_TypeClass_DOUBLE:
-				*pPT++ = 'D';
-				break;
-			case typelib_TypeClass_HYPER:
-			case typelib_TypeClass_UNSIGNED_HYPER:
-				*pPT++ = 'H';
+				INSERT_FLOAT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack );
 				break;
 			}
 
@@ -430,7 +340,7 @@ static void cpp_call(
 			{
 				// cpp out is constructed mem, uno out is not!
 				uno_constructData(
-					*(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
+					pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
 					pParamTypeDescr );
 				pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
 				// will be released at reconversion
@@ -440,7 +350,7 @@ static void cpp_call(
 			else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
 			{
 				uno_copyAndConvertData(
-					*(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
+					pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
 					pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
 				
 				pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
@@ -449,27 +359,22 @@ static void cpp_call(
 			}
 			else // direct way
 			{
-				*(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos];
+				pCppArgs[nPos] = pUnoArgs[nPos];
 				// no longer needed
 				TYPELIB_DANGER_RELEASE( pParamTypeDescr );
 			}
-			// FIXME: is this the right way to pass these?
-			*pPT++='H';
+			INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
 		}
-		pCppStack += sizeof(sal_uInt64); // standard parameter length
 	}
 	
-	// terminate the signature string
-	*pPT++ = 'X';
-	*pPT = 0;
-
 	try
 	{
-		OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 7), "UNALIGNED STACK !!! (Please DO panic)" );
 		callVirtualMethod(
 			pAdjustedThisPtr, aVtableSlot.index,
-			pCppReturn, pReturnTypeDescr, bSimpleReturn, pParamType,
-			(sal_uInt64 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_uInt64) );
+			pCppReturn, pReturnTypeDescr, bSimpleReturn,
+			pStackStart, ( pStack - pStackStart ),
+			pGPR, nGPR,
+			pFPR, nFPR );
 		// NO exception occured...
 		*ppUnoExc = 0;
 		
@@ -525,8 +430,8 @@ static void cpp_call(
 	}
 }
 
-
 //==================================================================================================
+
 namespace bridges { namespace cpp_uno { namespace shared {
 
 void unoInterfaceProxyDispatch(
