[Libreoffice-commits] .: Branch 'libreoffice-3-5' - bridges/source testtools/com testtools/source

René Engelhard rene at kemper.freedesktop.org
Mon Apr 16 04:50:17 PDT 2012


 bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S     |   18 +
 bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx     |   40 ++++
 bridges/source/cpp_uno/gcc3_linux_arm/share.hxx       |    2 
 bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx     |  167 +++++++++++++-----
 testtools/com/sun/star/comp/bridge/TestComponent.java |    4 
 testtools/source/bridgetest/bridgetest.cxx            |    5 
 testtools/source/bridgetest/cli/cli_cs_testobj.cs     |    5 
 testtools/source/bridgetest/cppobj.cxx                |    3 
 testtools/source/bridgetest/idl/bridgetest.idl        |    5 
 9 files changed, 197 insertions(+), 52 deletions(-)

New commits:
commit 062c8a02b0402e535dea3be0aeaf0c32b1964a03
Author: Rene Engelhard <rene at debian.org>
Date:   Mon Apr 16 13:47:52 2012 +0200

    merge armhf bridge fixes from master
    
    Signed-off-by: Bjoern Michaelsen <bjoern.michaelsen at canonical.com>

diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S b/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S
index d5faf15..27148dc 100644
--- a/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S
+++ b/bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S
@@ -10,6 +10,17 @@
 #  define UNWIND @
 #endif
 
+@ If the VFP ABI variant (armhf in Debian/Ubuntu) is used, an additional extra 64 bytes
+@ are taken up on the stack (the equivalent of the 8 double precision VFP registers)
+
+#ifdef __ARM_PCS_VFP
+#  define PAD 80
+#  define DISCARDED 84
+#else
+#  define PAD 16
+#  define DISCARDED 20
+#endif
+
 	.file	"armhelper.s"
 	.text
 	.align	4
@@ -19,9 +30,12 @@ privateSnippetExecutor:
 	UNWIND .fnstart            @ start of unwinder entry
 
 	stmfd sp!, {r0-r3}         @ follow other parameters on stack
-	UNWIND .pad  #16           @ throw this data away on exception
 	mov   r0, ip               @ r0 points to functionoffset/vtable
 	mov   r1, sp               @ r1 points to this and params
+#ifdef __ARM_PCS_VFP
+	vpush {d0-d7}              @ floating point parameter on stack
+#endif
+	UNWIND .pad  #PAD          @ throw this data away on exception
 	                           @ (see cppuno.cxx:codeSnippet())
 	stmfd sp!, {r4,lr}         @ save return address 
 	                           @ (r4 pushed to preserve stack alignment)
@@ -30,7 +44,7 @@ privateSnippetExecutor:
 	bl    cpp_vtable_call(PLT)
 
 	add   sp, sp, #4           @ no need to restore r4 (we didn't touch it)
-	ldr   pc, [sp], #20        @ return, discarding function arguments
+	ldr   pc, [sp], #DISCARDED @ return, discarding function arguments
 
 	UNWIND .fnend              @ end of unwinder entry
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx
index 9869bb5..0191e1b 100644
--- a/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx
@@ -66,6 +66,10 @@ namespace
         char * pTopStack = (char *)(pCallStack + 0);
         char * pCppStack = pTopStack;
 
+#ifdef __ARM_PCS_VFP
+        int dc = 0;
+        char * pFloatArgs = (char *)(pCppStack - 64);
+#endif
         // return
         typelib_TypeDescription * pReturnTypeDescr = 0;
         if (pReturnTypeRef)
@@ -122,7 +126,9 @@ namespace
                 {
                     case typelib_TypeClass_HYPER:
                     case typelib_TypeClass_UNSIGNED_HYPER:
+#ifndef __ARM_PCS_VFP
                     case typelib_TypeClass_DOUBLE:
+#endif
             if ((pCppStack - pTopStack) % 8) pCppStack+=sizeof(sal_Int32); //align to 8
                         break;
                     default:
@@ -130,13 +136,36 @@ namespace
                 }
 #endif
 
-                pCppArgs[nPos] = pCppStack;
-                pUnoArgs[nPos] = pCppStack;
+// For armhf we get the floating point arguments from a different area of the stack
+// TODO: deal with functions with more than 8 floating point args that need to overflow
+// to the stack. Find such an UNO API to try on.
+#ifdef __ARM_PCS_VFP
+                if (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT)
+                {
+                    pCppArgs[nPos] =  pUnoArgs[nPos] = pFloatArgs;
+                    pFloatArgs += sizeof(float);
+                } else
+                if (pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE)
+                {
+                    if ((pFloatArgs - pTopStack) % 8) pFloatArgs+=sizeof(float); //align to 8
+                    pCppArgs[nPos] = pUnoArgs[nPos] = pFloatArgs;
+                    pFloatArgs += sizeof(double);
+                    if (++dc == arm::MAX_FPR_REGS) {
+                        if (pCppStack - pTopStack < 16)
+                            pCppStack = pTopStack + 16;
+                        pFloatArgs = pCppStack;
+                    }
+                } else
+#endif
+                    pCppArgs[nPos] = pUnoArgs[nPos] = pCppStack;
+
                 switch (pParamTypeDescr->eTypeClass)
                 {
                     case typelib_TypeClass_HYPER:
                     case typelib_TypeClass_UNSIGNED_HYPER:
+#ifndef __ARM_PCS_VFP
                     case typelib_TypeClass_DOUBLE:
+#endif
                         pCppStack += sizeof(sal_Int32); // extra long
                         break;
                     default:
@@ -176,6 +205,13 @@ namespace
                     TYPELIB_DANGER_RELEASE( pParamTypeDescr );
                 }
             }
+#ifdef __ARM_PCS_VFP
+            // use the stack for output parameters or non floating point values
+                if (rParam.bOut ||
+                        ((pParamTypeDescr->eTypeClass != typelib_TypeClass_DOUBLE)
+                         && (pParamTypeDescr->eTypeClass != typelib_TypeClass_FLOAT))
+                    )
+#endif
             pCppStack += sizeof(sal_Int32); // standard parameter length
         }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/share.hxx b/bridges/source/cpp_uno/gcc3_linux_arm/share.hxx
index f7a85ba..da36c75 100644
--- a/bridges/source/cpp_uno/gcc3_linux_arm/share.hxx
+++ b/bridges/source/cpp_uno/gcc3_linux_arm/share.hxx
@@ -93,7 +93,7 @@ namespace CPPU_CURRENT_NAMESPACE
 
 namespace arm
 {
-    enum armlimits { MAX_GPR_REGS = 4 };
+    enum armlimits { MAX_GPR_REGS = 4, MAX_FPR_REGS = 8 };
     bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef );
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx
index 9502b87..7740dd8 100644
--- a/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx
@@ -131,6 +131,20 @@ namespace arm
         return false;
     }
 
+#ifdef __ARM_PCS_VFP
+    bool is_float_only_struct(const typelib_TypeDescription * type)
+    {
+        const typelib_CompoundTypeDescription * p
+            = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
+        for (sal_Int32 i = 0; i < p->nMembers; ++i)
+        {
+            if (p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_FLOAT &&
+                p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_DOUBLE)
+                return false;
+        }
+        return true;
+    }
+#endif
     bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
     {
         if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
@@ -143,6 +157,13 @@ namespace arm
             //A Composite Type not larger than 4 bytes is returned in r0
             bool bRet = pTypeDescr->nSize > 4 || is_complex_struct(pTypeDescr);
 
+#ifdef __ARM_PCS_VFP
+            // In the VFP ABI, structs with only float/double values that fit in
+            // 16 bytes are returned in registers
+            if( pTypeDescr->nSize <= 16 && is_float_only_struct(pTypeDescr))
+                bRet = false;
+#endif
+
             TYPELIB_DANGER_RELEASE( pTypeDescr );
             return bRet;
         }
@@ -152,11 +173,6 @@ namespace arm
 
 void MapReturn(sal_uInt32 r0, sal_uInt32 r1, typelib_TypeDescriptionReference * pReturnType, sal_uInt32* pRegisterReturn)
 {
-#if !defined(__ARM_EABI__) && !defined(__SOFTFP__)
-    register float fret asm("f0");
-    register double dret asm("f0");
-#endif
-
     switch( pReturnType->eTypeClass )
     {
         case typelib_TypeClass_HYPER:
@@ -176,6 +192,7 @@ void MapReturn(sal_uInt32 r0, sal_uInt32 r1, typelib_TypeDescriptionReference *
 #if !defined(__ARM_PCS_VFP) && (defined(__ARM_EABI__) || defined(__SOFTFP__))
             pRegisterReturn[0] = r0;
 #else
+            register float fret asm("s0");
             *(float*)pRegisterReturn = fret;
 #endif
         break;
@@ -184,6 +201,7 @@ void MapReturn(sal_uInt32 r0, sal_uInt32 r1, typelib_TypeDescriptionReference *
             pRegisterReturn[1] = r1;
             pRegisterReturn[0] = r0;
 #else
+            register double dret asm("d0");
             *(double*)pRegisterReturn = dret;
 #endif
             break;
@@ -211,7 +229,9 @@ void callVirtualMethod(
     sal_uInt32 *pStack,
     sal_uInt32 nStack,
     sal_uInt32 *pGPR,
-    sal_uInt32 nGPR) __attribute__((noinline));
+    sal_uInt32 nGPR,
+    double *pFPR,
+    sal_uInt32 nFPR) __attribute__((noinline));
 
 void callVirtualMethod(
     void * pThis,
@@ -221,7 +241,9 @@ void callVirtualMethod(
     sal_uInt32 *pStack,
     sal_uInt32 nStack,
     sal_uInt32 *pGPR,
-    sal_uInt32 nGPR)
+    sal_uInt32 nGPR,
+    double *pFPR,
+    sal_uInt32 nFPR)
 {
     // never called
     if (! pThis)
@@ -238,39 +260,54 @@ void callVirtualMethod(
     // Should not happen, but...
     if ( nGPR > arm::MAX_GPR_REGS )
         nGPR = arm::MAX_GPR_REGS;
+    if ( nFPR > arm::MAX_FPR_REGS )
+        nFPR = arm::MAX_FPR_REGS;
 
     sal_uInt32 pMethod = *((sal_uInt32*)pThis);
     pMethod += 4 * nVtableIndex;
     pMethod = *((sal_uInt32 *)pMethod);
 
-    typedef void (*FunctionCall )( sal_uInt32, sal_uInt32, sal_uInt32, sal_uInt32);
-    FunctionCall pFunc = (FunctionCall)pMethod;
-
-    (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3]);
-
+    //Return registers
     sal_uInt32 r0;
     sal_uInt32 r1;
 
-    // get return value
     __asm__ __volatile__ (
-        "mov %0, r0\n\t"
-        "mov %1, r1\n\t"
-        : "=r" (r0), "=r" (r1) : );
+        //Fill in general purpose register arguments
+        "ldr r4, %[pgpr]\n\t"
+        "ldmia r4, {r0-r3}\n\t"
+
+#ifdef __ARM_PCS_VFP
+        //Fill in VFP register arguments as double precision values
+        "ldr r4, %[pfpr]\n\t"
+        "vldmia r4, {d0-d7}\n\t"
+#endif
+        //Make the call
+        "ldr r5, %[pmethod]\n\t"
+#ifndef __ARM_ARCH_4T__
+        "blx r5\n\t"
+#else
+        "mov lr, pc ; bx r5\n\t"
+#endif
+
+        //Fill in return values
+        "mov %[r0], r0\n\t"
+        "mov %[r1], r1\n\t"
+        : [r0]"=r" (r0), [r1]"=r" (r1)
+        : [pmethod]"m" (pMethod), [pgpr]"m" (pGPR), [pfpr]"m" (pFPR)
+        : "r4", "r5");
 
     MapReturn(r0, r1, pReturnType, (sal_uInt32*)pRegisterReturn);
 }
 }
 
-#define INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow ) \
+#define INSERT_INT32( pSV, nr, pGPR, pDS ) \
         if ( nr < arm::MAX_GPR_REGS ) \
                 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
         else \
-                bOverFlow = true; \
-        if (bOverFlow) \
                 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
 
 #ifdef __ARM_EABI__
-#define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) \
+#define INSERT_INT64( pSV, nr, pGPR, pDS, pStart ) \
         if ( (nr < arm::MAX_GPR_REGS) && (nr % 2) ) \
         { \
                 ++nr; \
@@ -281,8 +318,6 @@ void callVirtualMethod(
                 pGPR[nr++] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \
         } \
         else \
-                bOverFlow = true; \
-        if (bOverFlow) \
     { \
         if ( (pDS - pStart) % 2) \
                 { \
@@ -292,31 +327,66 @@ void callVirtualMethod(
                 *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \
     }
 #else
-#define INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow ) \
-        INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow) \
-        INSERT_INT32( ((sal_uInt32*)pSV)+1, nr, pGPR, pDS, bOverflow)
+#define INSERT_INT64( pSV, nr, pGPR, pDS, pStart ) \
+        INSERT_INT32( pSV, nr, pGPR, pDS ) \
+        INSERT_INT32( ((sal_uInt32*)pSV)+1, nr, pGPR, pDS )
 #endif
 
-#define INSERT_FLOAT( pSV, nr, pFPR, pDS, bOverflow ) \
-        INSERT_INT32( pSV, nr, pGPR, pDS, bOverflow)
+#ifdef __ARM_PCS_VFP
+// Since single and double arguments share the same register bank the filling of the
+// registers is not always linear. Single values go to the first available single register,
+// while doubles need to have an 8 byte alignment, so only go into double registers starting
+// at every other single register. For ex a float, double, float sequence will fill registers
+// s0, d1, and s1, actually corresponding to the linear order s0,s1, d1.
+//
+// These use the single/double register array and counters and ignore the pGPR argument
+// nSR and nDR are the number of single and double precision registers that are no longer
+// available
+#define INSERT_FLOAT( pSV, nr, pGPR, pDS ) \
+        if (nSR % 2 == 0) {\
+            nSR = 2*nDR; \
+        }\
+        if ( nSR < arm::MAX_FPR_REGS*2 ) {\
+                pSPR[nSR++] = *reinterpret_cast<float *>( pSV ); \
+                if ((nSR % 2 == 1) && (nSR > 2*nDR)) {\
+                    nDR++; \
+                }\
+        }\
+        else \
+        {\
+                *pDS++ = *reinterpret_cast<float *>( pSV );\
+        }
+#define INSERT_DOUBLE( pSV, nr, pGPR, pDS, pStart ) \
+        if ( nDR < arm::MAX_FPR_REGS ) { \
+                pFPR[nDR++] = *reinterpret_cast<double *>( pSV ); \
+        }\
+        else\
+        {\
+            if ( (pDS - pStart) % 2) \
+                { \
+                    ++pDS; \
+                } \
+            *(double *)pDS = *reinterpret_cast<double *>( pSV );\
+            pDS += 2;\
+        }
+#else
+#define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \
+        INSERT_INT32( pSV, nr, pGPR, pDS )
 
-#define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart, bOverflow ) \
-        INSERT_INT64( pSV, nr, pGPR, pDS, pStart, bOverflow )
+#define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart ) \
+        INSERT_INT64( pSV, nr, pGPR, pDS, pStart )
+#endif
 
-#define INSERT_INT16( pSV, nr, pGPR, pDS, bOverflow ) \
+#define INSERT_INT16( pSV, nr, pGPR, pDS ) \
         if ( nr < arm::MAX_GPR_REGS ) \
                 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
         else \
-                bOverFlow = true; \
-        if (bOverFlow) \
                 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
 
-#define INSERT_INT8( pSV, nr, pGPR, pDS, bOverflow ) \
+#define INSERT_INT8( pSV, nr, pGPR, pDS ) \
         if ( nr < arm::MAX_GPR_REGS ) \
                 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
         else \
-                bOverFlow = true; \
-        if (bOverFlow) \
                 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
 
 namespace {
@@ -336,6 +406,11 @@ static void cpp_call(
     sal_uInt32 pGPR[arm::MAX_GPR_REGS];
     sal_uInt32 nGPR = 0;
 
+    double pFPR[arm::MAX_FPR_REGS];
+    float *pSPR = reinterpret_cast< float *>(&pFPR);
+    sal_uInt32 nSR = 0;
+    sal_uInt32 nDR = 0;
+
     // return
     typelib_TypeDescription * pReturnTypeDescr = 0;
     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
@@ -343,7 +418,6 @@ static void cpp_call(
 
     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
 
-    bool bOverFlow = false;
     bool bSimpleReturn = true;
     if (pReturnTypeDescr)
     {
@@ -359,13 +433,13 @@ static void cpp_call(
                     ? __builtin_alloca( pReturnTypeDescr->nSize )
                     : pUnoReturn); // direct way
 
-            INSERT_INT32( &pCppReturn, nGPR, pGPR, pStack, bOverFlow );
+            INSERT_INT32( &pCppReturn, nGPR, pGPR, pStack );
         }
     }
     // push this
     void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
         + aVtableSlot.offset;
-    INSERT_INT32( &pAdjustedThisPtr, nGPR, pGPR, pStack, bOverFlow );
+    INSERT_INT32( &pAdjustedThisPtr, nGPR, pGPR, pStack );
 
     // stack space
     OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
@@ -397,7 +471,7 @@ static void cpp_call(
 #if OSL_DEBUG_LEVEL > 2
                 fprintf(stderr, "hyper is %lx\n", pCppArgs[nPos]);
 #endif
-                INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart, bOverFlow );
+                INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart );
                 break;
             case typelib_TypeClass_LONG:
             case typelib_TypeClass_UNSIGNED_LONG:
@@ -405,22 +479,22 @@ static void cpp_call(
 #if OSL_DEBUG_LEVEL > 2
                 fprintf(stderr, "long is %x\n", pCppArgs[nPos]);
 #endif
-                INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
+                INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
                 break;
             case typelib_TypeClass_SHORT:
             case typelib_TypeClass_CHAR:
             case typelib_TypeClass_UNSIGNED_SHORT:
-                INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
+                INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
                 break;
             case typelib_TypeClass_BOOLEAN:
             case typelib_TypeClass_BYTE:
-                INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
+                INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
                 break;
             case typelib_TypeClass_FLOAT:
-                INSERT_FLOAT( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
+                INSERT_FLOAT( pCppArgs[nPos], nGPR, pGPR, pStack );
                 break;
             case typelib_TypeClass_DOUBLE:
-                INSERT_DOUBLE( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart, bOverFlow );
+                INSERT_DOUBLE( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart );
                 break;
             default:
                 break;
@@ -457,7 +531,7 @@ static void cpp_call(
                 // no longer needed
                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
             }
-            INSERT_INT32( &(pCppArgs[nPos]), nGPR, pGPR, pStack, bOverFlow );
+            INSERT_INT32( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
         }
     }
 
@@ -468,7 +542,8 @@ static void cpp_call(
             pCppReturn, pReturnTypeRef,
             pStackStart,
             (pStack - pStackStart),
-            pGPR, nGPR);
+            pGPR, nGPR,
+            pFPR, nDR);
 
         // NO exception occurred...
         *ppUnoExc = 0;
diff --git a/testtools/com/sun/star/comp/bridge/TestComponent.java b/testtools/com/sun/star/comp/bridge/TestComponent.java
index c63ff7f..757139a 100644
--- a/testtools/com/sun/star/comp/bridge/TestComponent.java
+++ b/testtools/com/sun/star/comp/bridge/TestComponent.java
@@ -511,6 +511,10 @@ public class TestComponent {
             return i2;
         }
 
+        public double testTenDoubles( double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10 ) {
+            return d1 + d2 + d3 + d4 + d5 + d6 + d7 + d8 + d9 + d10;
+        }
+
         // Attributes
         public boolean getBool() throws com.sun.star.uno.RuntimeException {
             return _bool;
diff --git a/testtools/source/bridgetest/bridgetest.cxx b/testtools/source/bridgetest/bridgetest.cxx
index 27af77b..6831eaa 100644
--- a/testtools/source/bridgetest/bridgetest.cxx
+++ b/testtools/source/bridgetest/bridgetest.cxx
@@ -541,6 +541,11 @@ static sal_Bool performTest(
                 sal_Int32 i2 = xLBT->testPPCAlignment(0, 0, 0, 0, 0xBEAF);
                 bRet &= check(i2 == 0xBEAF, "ppc-style alignment test");
             }
+            {
+                double d1 = xLBT->testTenDoubles(0.1, 0.2, 0.3, 0.4, 0.5,
+                    0.6, 0.7, 0.8, 0.9, 1.0);
+                bRet &= check(d1 == 5.5, "armhf doubles test");
+            }
             // Test extended attributes that raise exceptions:
             try {
                 xLBT->getRaiseAttr1();
diff --git a/testtools/source/bridgetest/cli/cli_cs_testobj.cs b/testtools/source/bridgetest/cli/cli_cs_testobj.cs
index 246d3e1..f89241b 100644
--- a/testtools/source/bridgetest/cli/cli_cs_testobj.cs
+++ b/testtools/source/bridgetest/cli/cli_cs_testobj.cs
@@ -264,6 +264,11 @@ public class BridgeTestObject : WeakBase, XRecursiveCall, XBridgeTest2
         return i2;
     }
 
+    double testTenDoubles( double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10 )
+    {
+        return d1 + d2 + d3 + d4 + d5 + d6 + d7 + d8 + d9 + d10;
+    }
+
     // Attributes
     public bool Bool
     {
diff --git a/testtools/source/bridgetest/cppobj.cxx b/testtools/source/bridgetest/cppobj.cxx
index ae22724..b5be1a5 100644
--- a/testtools/source/bridgetest/cppobj.cxx
+++ b/testtools/source/bridgetest/cppobj.cxx
@@ -230,7 +230,8 @@ public:
         { return rStruct; }
     virtual sal_Int32 SAL_CALL testPPCAlignment( sal_Int64, sal_Int64, sal_Int32, sal_Int64, sal_Int32 i2 ) throw(com::sun::star::uno::RuntimeException)
         { return i2; }
-
+    virtual double SAL_CALL testTenDoubles( double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10 ) throw(com::sun::star::uno::RuntimeException)
+        { return d1 + d2 + d3 + d4 + d5 + d6 + d7 + d8 + d9 + d10; }
     virtual sal_Bool SAL_CALL getBool() throw(com::sun::star::uno::RuntimeException)
         { return _aData.Bool; }
     virtual sal_Int8 SAL_CALL getByte() throw(com::sun::star::uno::RuntimeException)
diff --git a/testtools/source/bridgetest/idl/bridgetest.idl b/testtools/source/bridgetest/idl/bridgetest.idl
index 82db320..1e6f6aa 100644
--- a/testtools/source/bridgetest/idl/bridgetest.idl
+++ b/testtools/source/bridgetest/idl/bridgetest.idl
@@ -314,6 +314,11 @@ interface XBridgeTestBase : com::sun::star::uno::XInterface
      */
     long testPPCAlignment( [in] hyper l1, [in] hyper l2, [in] long i1, [in] hyper l3, [in] long i2 );
 
+    /**
+     * VFP ABI (armhf) doubles test
+     */
+    double testTenDoubles( [in] double d1, [in] double d2, [in] double d3, [in] double d4, [in] double d5, [in] double d6, [in] double d7, [in] double d8, [in] double d9, [in] double d10 );
+
     [attribute] boolean                  Bool;
     [attribute] byte                     Byte;
     [attribute] char                     Char;


More information about the Libreoffice-commits mailing list