--- bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx.kendy	2007-02-15 10:18:52.000000000 +0100
+++ bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx	2007-02-16 11:31:30.000000000 +0100
@@ -56,145 +56,143 @@ using namespace ::rtl;
 using namespace ::com::sun::star::uno;
 
 //==================================================================================================
+static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
+                              void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn,
+                              sal_uInt64 *pStack, sal_uInt32 nStack,
+                              sal_uInt64 *pGPR, sal_uInt32 nGPR,
+                              double *pFPR, sal_uInt32 nFPR) __attribute__((noinline));
 
 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
-							  void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn,
-							  sal_uInt64 *pStack, sal_uInt32 nStack,
-							  sal_uInt64 *pGPR, sal_uInt32 nGPR,
-							  double *pFPR, sal_uInt32 nFPR)
+                              void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr, bool bSimpleReturn,
+                              sal_uInt64 *pStack, sal_uInt32 nStack,
+                              sal_uInt64 *pGPR, sal_uInt32 nGPR,
+                              double *pFPR, sal_uInt32 nFPR)
 {
-	// Stack, if used, must be 16-bytes aligned
-	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() =\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( nStack * 8 );
-    memcpy( stack, pStack, nStack * 8 );
-
-    // Load SSE registers from pFPR[]
-    register double d0 asm("xmm0");
-    register double d1 asm("xmm1");
-    register double d2 asm("xmm2");
-    register double d3 asm("xmm3");
-    register double d4 asm("xmm4");
-    register double d5 asm("xmm5");
-    register double d6 asm("xmm6");
-    register double d7 asm("xmm7");
-
-    switch ( nFPR ) {
-#define ARG_FPR(N) \
-    case N+1: d##N = pFPR[N];
-        ARG_FPR(7);
-        ARG_FPR(6);
-        ARG_FPR(5);
-        ARG_FPR(4);
-        ARG_FPR(3);
-        ARG_FPR(2);
-        ARG_FPR(1);
-        ARG_FPR(0);
-    case 0:;
-#undef ARG_FPR
-    }
-    
-    // Load GPR registers from pGPR[]
-    register sal_uInt64 a0 asm("rdi");
-    register sal_uInt64 a1 asm("rsi");
-    register sal_uInt64 a2 asm("rdx");
-    register sal_uInt64 a3 asm("rcx");
-    register sal_uInt64 a4 asm("r8");
-    register sal_uInt64 a5 asm("r9");
-    
-    switch ( nGPR ) {
-#define ARG_GPR(N) \
-    case N+1: a##N = pGPR[N];
-        ARG_GPR(5);
-        ARG_GPR(4);
-        ARG_GPR(3);
-        ARG_GPR(2);
-        ARG_GPR(1);
-        ARG_GPR(0);
-    case 0:;
-#undef ARG_GPR
+    // Let's figure out what is really going on here
+    {
+        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
 
-    // Ensure that assignments to SSE registers won't be optimized away
-    asm("" ::
-        "x" (d0), "x" (d1), "x" (d2), "x" (d3),
-        "x" (d4), "x" (d5), "x" (d6), "x" (d7));
+    // The call instruction within the asm section of callVirtualMethod may throw
+    // exceptions.  So that the compiler handles this correctly, it is important
+    // that (a) callVirtualMethod might call dummy_can_throw_anything (although this
+    // never happens at runtime), which in turn can throw exceptions, and (b)
+    // callVirtualMethod is not inlined at its call site (so that any exceptions are
+    // caught which are thrown from the instruction calling callVirtualMethod):
+    if ( !pThis )
+        CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything( "xxx" ); // address something
+
+    // 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;
 
     // Get pointer to method
     sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
     pMethod += 8 * nVtableIndex;
     pMethod = *((sal_uInt64 *)pMethod);
 
-	typedef struct {
-		sal_uInt64 rax;
-		sal_uInt64 rdx;
-	} ReturnValue;
+    // Load parameters to stack, if necessary
+    if ( nStack )
+    {
+        // 16-bytes aligned
+        sal_uInt32 nStackBytes = ( ( nStack + 1 ) >> 1 ) * 16;
+        sal_uInt64 *pCallStack = (sal_uInt64 *) __builtin_alloca( nStackBytes );
+        memcpy( pCallStack, pStack, nStackBytes );
+    }
 
-	typedef ReturnValue (* FunctionCall )( sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64 );
+    // Return values
+    sal_uInt64 rax;
+    sal_uInt64 rdx;
+    double xmm0;
 
-	// Perform the call
-	ReturnValue aRet = ( ( FunctionCall ) pMethod )( a0, a1, a2, a3, a4, a5 );
+    asm volatile (
+        
+        // Fill the xmm registers
+        "movq %2, %%rax\n\t"
 
-	switch (pReturnTypeDescr->eTypeClass)
-	{
-	case typelib_TypeClass_HYPER:
-	case typelib_TypeClass_UNSIGNED_HYPER:
-		*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.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.rax );
-		break;
-	case typelib_TypeClass_BOOLEAN:
-	case typelib_TypeClass_BYTE:
-		*reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &aRet.rax );
-		break;
-	case typelib_TypeClass_FLOAT:
-	case typelib_TypeClass_DOUBLE:
-		*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.rdx;
-				static_cast<sal_uInt64 *>(pRegisterReturn)[0] = aRet.rax;
-			}
-			break;
-		}
-	}
+        "movsd   (%%rax), %%xmm0\n\t"
+        "movsd  8(%%rax), %%xmm1\n\t"
+        "movsd 16(%%rax), %%xmm2\n\t"
+        "movsd 24(%%rax), %%xmm3\n\t"
+        "movsd 32(%%rax), %%xmm4\n\t"
+        "movsd 40(%%rax), %%xmm5\n\t"
+        "movsd 48(%%rax), %%xmm6\n\t"
+        "movsd 56(%%rax), %%xmm7\n\t"
+
+        // Fill the general purpose registers
+        "movq %1, %%rax\n\t"
+
+        "movq    (%%rax), %%rdi\n\t"
+        "movq   8(%%rax), %%rsi\n\t"
+        "movq  16(%%rax), %%rdx\n\t"
+        "movq  24(%%rax), %%rcx\n\t"
+        "movq  32(%%rax), %%r8\n\t"
+        "movq  40(%%rax), %%r9\n\t"
+
+        // Perform the call
+        "movq %0, %%r11\n\t"
+        "movq %3, %%rax\n\t"
+        "call *%%r11\n\t"
+
+        // Fill the return values
+        "movq   %%rax, %4\n\t"
+        "movq   %%rdx, %5\n\t"
+        "movsd %%xmm0, %6\n\t"
+        :
+        : "m" ( pMethod ), "m" ( pGPR ), "m" ( pFPR ), "m" ( nFPR ),
+          "m" ( rax ), "m" ( rdx ), "m" ( xmm0 )
+        : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r11"
+    );
+
+    switch (pReturnTypeDescr->eTypeClass)
+    {
+    case typelib_TypeClass_HYPER:
+    case typelib_TypeClass_UNSIGNED_HYPER:
+        *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = rax;
+        break;
+    case typelib_TypeClass_LONG:
+    case typelib_TypeClass_UNSIGNED_LONG:
+    case typelib_TypeClass_ENUM:
+        *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &rax );
+        break;
+    case typelib_TypeClass_CHAR:
+    case typelib_TypeClass_SHORT:
+    case typelib_TypeClass_UNSIGNED_SHORT:
+        *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &rax );
+        break;
+    case typelib_TypeClass_BOOLEAN:
+    case typelib_TypeClass_BYTE:
+        *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &rax );
+        break;
+    case typelib_TypeClass_FLOAT:
+    case typelib_TypeClass_DOUBLE:
+        *reinterpret_cast<double *>( pRegisterReturn ) = xmm0;
+        break;
+    default:
+        {
+            sal_Int32 const nRetSize = pReturnTypeDescr->nSize;
+            if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
+            {
+                if (nRetSize > 8)
+                    static_cast<sal_uInt64 *>(pRegisterReturn)[1] = rdx;
+                static_cast<sal_uInt64 *>(pRegisterReturn)[0] = rax;
+            }
+            break;
+        }
+    }
 }
 
 //================================================================================================== 
