Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
core
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
LibreOffice
core
Commits
dab11f7f
Kaydet (Commit)
dab11f7f
authored
Şub 10, 2012
tarafından
Jani Monoses
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
ARM bridge: VFP ABI (armhf) support
üst
746e9a7d
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
142 additions
and
17 deletions
+142
-17
armhelper.S
bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S
+16
-2
cpp2uno.cxx
bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx
+32
-2
share.hxx
bridges/source/cpp_uno/gcc3_linux_arm/share.hxx
+1
-1
uno2cpp.cxx
bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx
+93
-12
No files found.
bridges/source/cpp_uno/gcc3_linux_arm/armhelper.S
Dosyayı görüntüle @
dab11f7f
...
...
@@ -8,6 +8,17 @@
# define UNWIND
#else
# 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"
...
...
@@ -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
...
...
bridges/source/cpp_uno/gcc3_linux_arm/cpp2uno.cxx
Dosyayı görüntüle @
dab11f7f
...
...
@@ -69,6 +69,9 @@ namespace
char
*
pTopStack
=
(
char
*
)(
pCallStack
+
0
);
char
*
pCppStack
=
pTopStack
;
#ifdef __ARM_PCS_VFP
char
*
pFloatArgs
=
(
char
*
)(
pCppStack
-
64
);
#endif
// return
typelib_TypeDescription
*
pReturnTypeDescr
=
0
;
if
(
pReturnTypeRef
)
...
...
@@ -125,7 +128,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
:
...
...
@@ -133,13 +138,31 @@ 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
);
}
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
:
...
...
@@ -179,6 +202,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
}
...
...
bridges/source/cpp_uno/gcc3_linux_arm/share.hxx
Dosyayı görüntüle @
dab11f7f
...
...
@@ -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
);
}
...
...
bridges/source/cpp_uno/gcc3_linux_arm/uno2cpp.cxx
Dosyayı görüntüle @
dab11f7f
...
...
@@ -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
;
}
...
...
@@ -208,7 +229,8 @@ void callVirtualMethod(
sal_uInt32
*
pStack
,
sal_uInt32
nStack
,
sal_uInt32
*
pGPR
,
sal_uInt32
nGPR
)
__attribute__
((
noinline
));
sal_uInt32
nGPR
,
double
*
pFPR
)
__attribute__
((
noinline
));
void
callVirtualMethod
(
void
*
pThis
,
...
...
@@ -218,7 +240,8 @@ void callVirtualMethod(
sal_uInt32
*
pStack
,
sal_uInt32
nStack
,
sal_uInt32
*
pGPR
,
sal_uInt32
nGPR
)
sal_uInt32
nGPR
,
double
*
pFPR
)
{
// never called
if
(
!
pThis
)
...
...
@@ -240,19 +263,30 @@ void callVirtualMethod(
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
"
"blx r5
\n\t
"
//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
);
}
...
...
@@ -290,11 +324,49 @@ void callVirtualMethod(
INSERT_INT32( ((sal_uInt32*)pSV)+1, nr, pGPR, pDS )
#endif
#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; \
} \
*pDS++ = *reinterpret_cast<double *>( pSV );\
}
#else
#define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \
INSERT_INT32( pSV, nr, pGPR, pDS )
#define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart ) \
INSERT_INT64( pSV, nr, pGPR, pDS, pStart )
#endif
#define INSERT_INT16( pSV, nr, pGPR, pDS ) \
if ( nr < arm::MAX_GPR_REGS ) \
...
...
@@ -325,6 +397,14 @@ static void cpp_call(
sal_uInt32
pGPR
[
arm
::
MAX_GPR_REGS
];
sal_uInt32
nGPR
=
0
;
// storage and counters for single and double precision VFP registers
double
pFPR
[
arm
::
MAX_FPR_REGS
];
#ifdef __ARM_PCS_VFP
sal_uInt32
nDR
=
0
;
float
*
pSPR
=
reinterpret_cast
<
float
*>
(
&
pFPR
);
sal_uInt32
nSR
=
0
;
#endif
// return
typelib_TypeDescription
*
pReturnTypeDescr
=
0
;
TYPELIB_DANGER_GET
(
&
pReturnTypeDescr
,
pReturnTypeRef
);
...
...
@@ -456,7 +536,8 @@ static void cpp_call(
pCppReturn
,
pReturnTypeRef
,
pStackStart
,
(
pStack
-
pStackStart
),
pGPR
,
nGPR
);
pGPR
,
nGPR
,
pFPR
);
// NO exception occurred...
*
ppUnoExc
=
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment