bridges/Library_cpp_uno.mk                                |    9 
 bridges/source/cpp_uno/gcc3_linux_loongarch64/call.hxx    |   33 
 bridges/source/cpp_uno/gcc3_linux_loongarch64/call.s      |  125 +++
 bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx |  559 ++++++++++++++
 bridges/source/cpp_uno/gcc3_linux_loongarch64/except.cxx  |  251 ++++++
 bridges/source/cpp_uno/gcc3_linux_loongarch64/share.hxx   |   85 ++
 bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx |  546 +++++++++++++
 configure.ac                                              |    7 
 jvmfwk/inc/vendorbase.hxx                                 |    6 
 solenv/gbuild/platform/LINUX_LOONGARCH64_GCC.mk           |   12 
 10 files changed, 1630 insertions(+), 3 deletions(-)

New commits:
commit d3625d968901eb93a9680db8d1165f70de3fd64e
Author:     wjh-la <wujiah...@loongson.cn>
AuthorDate: Wed Jul 27 09:14:16 2022 +0800
Commit:     Stephan Bergmann <sberg...@redhat.com>
CommitDate: Thu Aug 11 10:53:00 2022 +0200

    Add loongarch64 support.
    
    Loongarch is a new RISC ISA , which includes a 32-bit version and a 64-bit 
version, Here are some documents about Loongarch:
    https://github.com/loongson/LoongArch-Documentation.
    
    The loongarch64 bridges implementation refers to mips64 bridges, and the 
code related to abi and asm has been modified
    
    Change-Id: I1d9cd3aadf63046c8cdecc9a64842567bfa1cecc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137486
    Tested-by: Stephan Bergmann <sberg...@redhat.com>
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>

diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk
index a5d2a72c202b..85dd3ec8daf0 100644
--- a/bridges/Library_cpp_uno.mk
+++ b/bridges/Library_cpp_uno.mk
@@ -114,6 +114,15 @@ bridge_noopt_objects := cpp2uno uno2cpp
 bridge_exception_objects := except
 endif
 
+else ifeq ($(CPUNAME),LOONGARCH64)
+
+ifneq ($(filter LINUX,$(OS)),)
+bridges_SELECTED_BRIDGE := gcc3_linux_loongarch64
+bridge_asm_objects := call
+bridge_noopt_objects := cpp2uno uno2cpp
+bridge_exception_objects := except
+endif
+
 else ifeq ($(CPUNAME),POWERPC)
 
 ifneq ($(filter DRAGONFLY FREEBSD LINUX NETBSD OPENBSD,$(OS)),)
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.hxx 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.hxx
new file mode 100644
index 000000000000..51b9772c0f51
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.hxx
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <sal/types.h>
+
+namespace
+{
+extern "C" typelib_TypeClass
+cpp_vtable_call(sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, void** 
gpreg, void** fpreg,
+                void** ovrflw, sal_uInt64* pRegisterReturn /* space for 
register return */);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.s 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.s
new file mode 100644
index 000000000000..b8388508eea1
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/call.s
@@ -0,0 +1,125 @@
+/* -*- tab-width: 4; indent-tabs-mode: nil; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+        .text
+        .globl privateSnippetExecutor
+.LFB0 = .
+        .cfi_startproc
+        .cfi_personality 0x80,DW.ref.__gxx_personality_v0
+        .cfi_lsda 0,.LLSDA0
+        .type  privateSnippetExecutor, @function
+privateSnippetExecutor:
+        addi.d $sp,$sp,-160
+        .cfi_def_cfa_offset 160
+        st.d   $ra,$sp,152
+        .cfi_offset 1, -8
+.LEHB0 = .
+        // Save the float point registers
+        fst.d  $f0,$sp,80
+        fst.d  $f1,$sp,88
+        fst.d  $f2,$sp,96
+        fst.d  $f3,$sp,104
+        fst.d  $f4,$sp,112
+        fst.d  $f5,$sp,120
+        fst.d  $f6,$sp,128
+        fst.d  $f7,$sp,136
+        // Save the general purpose registers
+        st.d   $a0,$sp,16
+        st.d   $a1,$sp,24
+        st.d   $a2,$sp,32
+        st.d   $a3,$sp,40
+        st.d   $a4,$sp,48
+        st.d   $a5,$sp,56
+        st.d   $a6,$sp,64
+        st.d   $a7,$sp,72
+        // Load arguments
+        // a0=index
+        move   $a0,$t6
+        // a1=offset
+        move   $a1,$t7
+        // a2=gpregptr
+        addi.d $a2,$sp,16
+        // a3=fpregptr
+        addi.d $a3,$sp,80
+        // a4=ovrflw
+        addi.d $a4,$sp,160
+        // a5=retregptr
+        move   $a5,$sp
+
+        // Call cpp_vtable_call
+        jirl   $ra,$t5,0
+
+.LEHE0 = .
+        // Perform return value
+        fld.d  $f0,$sp,0
+        fld.d  $f1,$sp,8
+        ld.d   $a0,$sp,0
+        ld.d   $a1,$sp,8
+
+        ld.d   $ra,$sp,152
+        .cfi_restore 1
+        addi.d $sp,$sp,160
+        .cfi_def_cfa_offset 0
+        jr     $ra
+        .cfi_endproc
+
+.LFE0:
+        .globl __gxx_personality_v0
+        .section       .gcc_except_table,"aw",@progbits
+        .align 3
+.LLSDA0:
+        .byte  0xff
+        .byte  0x80
+        .uleb128 .LLSDATT0-.LLSDATTD0
+.LLSDATTD0:
+        .byte  0x1
+        .uleb128 .LLSDACSE0-.LLSDACSB0
+.LLSDACSB0:
+        .uleb128 .LEHB0-.LFB0
+        .uleb128 .LEHE0-.LEHB0
+        .uleb128 0
+        .uleb128 0
+.LLSDACSE0:
+        .byte  0x7f
+        .byte  0
+        .align 3
+        .8byte DW.ref._ZTIi
+.LLSDATT0:
+        .byte  0x1
+        .byte  0
+        .text
+        .size  privateSnippetExecutor, .-privateSnippetExecutor
+        .hidden        DW.ref._ZTIi
+        .weak  DW.ref._ZTIi
+        .section       .data.DW.ref._ZTIi,"awG",@progbits,DW.ref._ZTIi,comdat
+        .align 3
+        .type  DW.ref._ZTIi, @object
+        .size  DW.ref._ZTIi, 8
+DW.ref._ZTIi:
+        .dword _ZTIi
+        .hidden        DW.ref.__gxx_personality_v0
+        .weak  DW.ref.__gxx_personality_v0
+        .section       
.data.DW.ref.__gxx_personality_v0,"awG",@progbits,DW.ref.__gxx_personality_v0,comdat
+        .align 3
+        .type  DW.ref.__gxx_personality_v0, @object
+        .size  DW.ref.__gxx_personality_v0, 8
+DW.ref.__gxx_personality_v0:
+        .dword __gxx_personality_v0
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx
new file mode 100644
index 000000000000..0273b39da4e3
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/cpp2uno.cxx
@@ -0,0 +1,559 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/uno/genfunc.hxx>
+#include <sal/log.hxx>
+#include <typelib/typedescription.hxx>
+#include <uno/data.h>
+#include <osl/endian.h>
+#include "bridge.hxx"
+#include "cppinterfaceproxy.hxx"
+#include "types.hxx"
+#include "vtablefactory.hxx"
+#include "call.hxx"
+#include "share.hxx"
+
+#include <stdio.h>
+#include <string.h>
+
+using namespace com::sun::star::uno;
+
+namespace CPPU_CURRENT_NAMESPACE
+{
+bool is_complex_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_STRUCT
+            || p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
+        {
+            typelib_TypeDescription* t = 0;
+            TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
+            bool b = is_complex_struct(t);
+            TYPELIB_DANGER_RELEASE(t);
+            if (b)
+            {
+                return true;
+            }
+        }
+        else if 
(!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
+            return true;
+    }
+    if (p->pBaseTypeDescription != 0)
+        return is_complex_struct(&p->pBaseTypeDescription->aBase);
+    return false;
+}
+
+bool return_in_hidden_param(typelib_TypeDescriptionReference* pTypeRef)
+{
+    if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
+        return false;
+    else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT
+             || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
+    {
+        typelib_TypeDescription* pTypeDescr = 0;
+        TYPELIB_DANGER_GET(&pTypeDescr, pTypeRef);
+
+        //A Composite Type not larger than 16 bytes is returned in up to two 
GPRs
+        bool bRet = pTypeDescr->nSize > 16 || is_complex_struct(pTypeDescr);
+
+        TYPELIB_DANGER_RELEASE(pTypeDescr);
+        return bRet;
+    }
+    return true;
+}
+}
+
+namespace
+{
+static typelib_TypeClass
+cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* pThis,
+             const typelib_TypeDescription* pMemberTypeDescr,
+             typelib_TypeDescriptionReference* pReturnTypeRef, // 0 indicates 
void return
+             sal_Int32 nParams, typelib_MethodParameter* pParams, void** 
gpreg, void** fpreg,
+             void** ovrflw, sal_uInt64* pRegisterReturn /* space for register 
return */)
+{
+    unsigned int nREG = 0;
+
+    // return
+    typelib_TypeDescription* pReturnTypeDescr = 0;
+    if (pReturnTypeRef)
+        TYPELIB_DANGER_GET(&pReturnTypeDescr, pReturnTypeRef);
+
+    void* pUnoReturn = 0;
+    void* pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, 
reconversion need
+
+    if (pReturnTypeDescr)
+    {
+        if (CPPU_CURRENT_NAMESPACE::return_in_hidden_param(pReturnTypeRef))
+        {
+            pCppReturn = gpreg[nREG]; // complex return via ptr (pCppReturn)
+            nREG++;
+
+            pUnoReturn = 
(bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr)
+                              ? alloca(pReturnTypeDescr->nSize)
+                              : pCppReturn); // direct way
+        }
+        else
+        {
+            pUnoReturn = pRegisterReturn; // direct way for simple types
+        }
+    }
+
+    // pop this
+    nREG++;
+
+    // stack space
+    static_assert(sizeof(void*) == sizeof(sal_Int64), "### unexpected size!");
+    // parameters
+    void** pUnoArgs = (void**)alloca(4 * sizeof(void*) * nParams);
+    void** pCppArgs = pUnoArgs + nParams;
+    // indices of values this have to be converted (interface conversion 
cpp<=>uno)
+    sal_Int32* pTempIndices = (sal_Int32*)(pUnoArgs + (2 * nParams));
+    // type descriptions for reconversions
+    typelib_TypeDescription** ppTempParamTypeDescr
+        = (typelib_TypeDescription**)(pUnoArgs + (3 * nParams));
+
+    sal_Int32 nTempIndices = 0;
+
+    for (sal_Int32 nPos = 0; nPos < nParams; ++nPos)
+    {
+        const typelib_MethodParameter& rParam = pParams[nPos];
+
+        typelib_TypeDescription* pParamTypeDescr = 0;
+        TYPELIB_DANGER_GET(&pParamTypeDescr, rParam.pTypeRef);
+
+        if (!rParam.bOut && 
bridges::cpp_uno::shared::isSimpleType(pParamTypeDescr)) // value
+        {
+            switch (pParamTypeDescr->eTypeClass)
+            {
+                case typelib_TypeClass_FLOAT:
+                case typelib_TypeClass_DOUBLE:
+                    if (nREG < MAX_FP_REGS)
+                    {
+                        pCppArgs[nPos] = &(fpreg[nREG]);
+                        pUnoArgs[nPos] = &(fpreg[nREG]);
+                    }
+                    else
+                    {
+                        pCppArgs[nPos] = &(ovrflw[nREG - MAX_FP_REGS]);
+                        pUnoArgs[nPos] = &(ovrflw[nREG - MAX_FP_REGS]);
+                    }
+                    nREG++;
+                    break;
+
+                default:
+                    if (nREG < MAX_GP_REGS)
+                    {
+                        pCppArgs[nPos] = &(gpreg[nREG]);
+                        pUnoArgs[nPos] = &(gpreg[nREG]);
+                    }
+                    else
+                    {
+                        pCppArgs[nPos] = &(ovrflw[nREG - MAX_GP_REGS]);
+                        pUnoArgs[nPos] = &(ovrflw[nREG - MAX_GP_REGS]);
+                    }
+                    nREG++;
+                    break;
+            }
+            // no longer needed
+            TYPELIB_DANGER_RELEASE(pParamTypeDescr);
+        }
+        else // ptr to complex value | ref
+        {
+            void* pCppStack;
+            if (nREG < MAX_GP_REGS)
+            {
+                pCppArgs[nPos] = pCppStack = gpreg[nREG];
+            }
+            else
+            {
+                pCppArgs[nPos] = pCppStack = ovrflw[nREG - MAX_GP_REGS];
+            }
+            nREG++;
+
+            if (!rParam.bIn) // is pure out
+            {
+                // uno out is unconstructed mem!
+                pUnoArgs[nPos] = alloca(pParamTypeDescr->nSize);
+                pTempIndices[nTempIndices] = nPos;
+                // will be released at reconversion
+                ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+            }
+            // is in/inout
+            else if 
(bridges::cpp_uno::shared::relatesToInterfaceType(pParamTypeDescr))
+            {
+                uno_copyAndConvertData(pUnoArgs[nPos] = 
alloca(pParamTypeDescr->nSize), pCppStack,
+                                       pParamTypeDescr, 
pThis->getBridge()->getCpp2Uno());
+                pTempIndices[nTempIndices] = nPos; // has to be reconverted
+                // will be released at reconversion
+                ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+            }
+            else // direct way
+            {
+                pUnoArgs[nPos] = pCppStack;
+                // no longer needed
+                TYPELIB_DANGER_RELEASE(pParamTypeDescr);
+            }
+        }
+    }
+    // ExceptionHolder
+    uno_Any aUnoExc; // Any will be constructed by callee
+    uno_Any* pUnoExc = &aUnoExc;
+
+    // invoke uno dispatch call
+    (*pThis->getUnoI()->pDispatcher)(pThis->getUnoI(), pMemberTypeDescr, 
pUnoReturn, pUnoArgs,
+                                     &pUnoExc);
+    // in case an exception occurred...
+    if (pUnoExc)
+    {
+        // destruct temporary in/inout params
+        for (; nTempIndices--;)
+        {
+            sal_Int32 nIndex = pTempIndices[nTempIndices];
+
+            if (pParams[nIndex].bIn) // is in/inout => was constructed
+                uno_destructData(pUnoArgs[nIndex], 
ppTempParamTypeDescr[nTempIndices], 0);
+            TYPELIB_DANGER_RELEASE(ppTempParamTypeDescr[nTempIndices]);
+        }
+        if (pReturnTypeDescr)
+            TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
+
+        CPPU_CURRENT_NAMESPACE::raiseException(&aUnoExc, 
pThis->getBridge()->getUno2Cpp());
+        // has to destruct the any
+        // is here for dummy
+        return typelib_TypeClass_VOID;
+    }
+    else // else no exception occurred...
+    {
+        // temporary params
+        for (; nTempIndices--;)
+        {
+            sal_Int32 nIndex = pTempIndices[nTempIndices];
+            typelib_TypeDescription* pParamTypeDescr = 
ppTempParamTypeDescr[nTempIndices];
+
+            if (pParams[nIndex].bOut) // inout/out
+            {
+                // convert and assign
+                uno_destructData(pCppArgs[nIndex], pParamTypeDescr, 
cpp_release);
+                uno_copyAndConvertData(pCppArgs[nIndex], pUnoArgs[nIndex], 
pParamTypeDescr,
+                                       pThis->getBridge()->getUno2Cpp());
+            }
+            // destroy temp uno param
+            uno_destructData(pUnoArgs[nIndex], pParamTypeDescr, 0);
+
+            TYPELIB_DANGER_RELEASE(pParamTypeDescr);
+        }
+        // return
+        if (pCppReturn) // has complex return
+        {
+            if (pUnoReturn != pCppReturn) // needs reconversion
+            {
+                uno_copyAndConvertData(pCppReturn, pUnoReturn, 
pReturnTypeDescr,
+                                       pThis->getBridge()->getUno2Cpp());
+                // destroy temp uno return
+                uno_destructData(pUnoReturn, pReturnTypeDescr, 0);
+            }
+            // complex return ptr is set to return reg
+            *(void**)pRegisterReturn = pCppReturn;
+        }
+        if (pReturnTypeDescr)
+        {
+            typelib_TypeClass eRet = 
(typelib_TypeClass)pReturnTypeDescr->eTypeClass;
+            TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
+            return eRet;
+        }
+        else
+            return typelib_TypeClass_VOID;
+    }
+}
+
+/**
+   * is called on incoming vtable calls
+   * (called by asm snippets)
+   */
+typelib_TypeClass cpp_vtable_call(sal_Int32 nFunctionIndex, sal_Int32 
nVtableOffset, void** gpreg,
+                                  void** fpreg, void** ovrflw,
+                                  sal_uInt64* pRegisterReturn /* space for 
register return */)
+{
+    static_assert(sizeof(sal_Int64) == sizeof(void*), "### unexpected!");
+
+    // gpreg:  [ret *], this, [other gpr params]
+    // fpreg:  [fpr params]
+    // ovrflw: [gpr or fpr params (properly aligned)]
+    void* pThis;
+    if (nFunctionIndex & 0x80000000)
+    {
+        nFunctionIndex &= 0x7fffffff;
+        pThis = gpreg[1];
+    }
+    else
+    {
+        pThis = gpreg[0];
+    }
+    pThis = static_cast<char*>(pThis) - nVtableOffset;
+    bridges::cpp_uno::shared::CppInterfaceProxy* pCppI
+        = 
bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(pThis);
+    typelib_InterfaceTypeDescription* pTypeDescr = pCppI->getTypeDescr();
+
+    if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
+    {
+        SAL_WARN("bridges", "illegal " << 
OUString::unacquired(&pTypeDescr->aBase.pTypeName)
+                                       << " vtable index " << nFunctionIndex 
<< "/"
+                                       << 
pTypeDescr->nMapFunctionIndexToMemberIndex);
+        throw RuntimeException(("illegal " + 
OUString::unacquired(&pTypeDescr->aBase.pTypeName)
+                                + " vtable index " + 
OUString::number(nFunctionIndex) + "/"
+                                + 
OUString::number(pTypeDescr->nMapFunctionIndexToMemberIndex)),
+                               (XInterface*)pThis);
+    }
+
+    // determine called method
+    sal_Int32 nMemberPos = 
pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
+    assert(nMemberPos < pTypeDescr->nAllMembers);
+
+    TypeDescription aMemberDescr(pTypeDescr->ppAllMembers[nMemberPos]);
+
+    typelib_TypeClass eRet;
+    switch (aMemberDescr.get()->eTypeClass)
+    {
+        case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+        {
+            typelib_TypeDescriptionReference* pAttrTypeRef
+                = 
reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(aMemberDescr.get())
+                      ->pAttributeTypeRef;
+
+            if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == 
nFunctionIndex)
+            {
+                // is GET method
+                eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pAttrTypeRef, 
0, 0, // no params
+                                    gpreg, fpreg, ovrflw, pRegisterReturn);
+            }
+            else
+            {
+                // is SET method
+                typelib_MethodParameter aParam;
+                aParam.pTypeRef = pAttrTypeRef;
+                aParam.bIn = sal_True;
+                aParam.bOut = sal_False;
+
+                eRet = cpp2uno_call(pCppI, aMemberDescr.get(),
+                                    0, // indicates void return
+                                    1, &aParam, gpreg, fpreg, ovrflw, 
pRegisterReturn);
+            }
+            break;
+        }
+        case typelib_TypeClass_INTERFACE_METHOD:
+        {
+            // is METHOD
+            switch (nFunctionIndex)
+            {
+                case 1: // acquire()
+                    pCppI->acquireProxy(); // non virtual call!
+                    eRet = typelib_TypeClass_VOID;
+                    break;
+                case 2: // release()
+                    pCppI->releaseProxy(); // non virtual call!
+                    eRet = typelib_TypeClass_VOID;
+                    break;
+                case 0: // queryInterface() opt
+                {
+                    typelib_TypeDescription* pTD = 0;
+                    TYPELIB_DANGER_GET(&pTD, 
reinterpret_cast<Type*>(gpreg[2])->getTypeLibType());
+                    if (pTD)
+                    {
+                        XInterface* pInterface = 0;
+                        
(*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
+                            pCppI->getBridge()->getCppEnv(), 
(void**)&pInterface,
+                            pCppI->getOid().pData,
+                            
reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD));
+
+                        if (pInterface)
+                        {
+                            
::uno_any_construct(reinterpret_cast<uno_Any*>(gpreg[0]), &pInterface,
+                                                pTD, cpp_acquire);
+
+                            pInterface->release();
+                            TYPELIB_DANGER_RELEASE(pTD);
+
+                            reinterpret_cast<void**>(pRegisterReturn)[0] = 
gpreg[0];
+                            eRet = typelib_TypeClass_ANY;
+                            break;
+                        }
+                        TYPELIB_DANGER_RELEASE(pTD);
+                    }
+                } // else perform queryInterface()
+                default:
+                    typelib_InterfaceMethodTypeDescription* pMethodTD
+                        = 
reinterpret_cast<typelib_InterfaceMethodTypeDescription*>(
+                            aMemberDescr.get());
+
+                    eRet = cpp2uno_call(pCppI, aMemberDescr.get(), 
pMethodTD->pReturnTypeRef,
+                                        pMethodTD->nParams, 
pMethodTD->pParams, gpreg, fpreg,
+                                        ovrflw, pRegisterReturn);
+            }
+            break;
+        }
+        default:
+        {
+            throw RuntimeException("no member description found!", 
(XInterface*)pThis);
+        }
+    }
+
+    return eRet;
+}
+
+extern "C" void privateSnippetExecutor(...);
+
+int const codeSnippetSize = 0x34;
+
+unsigned char* codeSnippet(unsigned char* code, sal_Int32 functionIndex, 
sal_Int32 vtableOffset,
+                           bool bHasHiddenParam)
+{
+    if (bHasHiddenParam)
+        functionIndex |= 0x80000000;
+
+    unsigned int* p = (unsigned int*)code;
+
+    assert((((unsigned long)code) & 0x3) == 0); //aligned to 4 otherwise a 
mistake
+
+    /* generate this code */
+    /*
+       # index
+        0:   14000012        lu12i.w $t6,0x0
+        4:   34420000        ori     $t6,$t6,0x0
+       # privateSnippetExecutor
+        8:   14000014        lu12i.w $t8,0x0
+        c:   03800294        ori     $t8,$t8,0x0
+       10:   16000014        lu32i.d $t8,0x0
+       14:   03000294        lu52i.d $t8,$t8,0x0
+       # cpp_vtable_call
+       18:   14000011        lu12i.w $t5,0x0
+       1c:   03800231        ori     $t5,$t5,0x0
+       20:   16000011        lu32i.d $t5,0x0
+       24:   03000231        lu52i.d $t5,$t5,0x0
+       # offset
+       28:   14000013        lu12i.w $t7,0x0
+       2c:   03800273        ori     $t7,$t7,0x0
+       30:   4c000280        jr      $t8
+     */
+
+    *p++ = 0x14000012 | (((functionIndex >> 12) & 0x000fffff) << 5);
+    *p++ = 0x03800252 | ((functionIndex & 0x00000fff) << 10);
+    *p++ = 0x14000014 | (((((unsigned long)privateSnippetExecutor) >> 12) & 
0x000fffff) << 5);
+    *p++ = 0x03800294 | ((((unsigned long)privateSnippetExecutor) & 
0x00000fff) << 10);
+    *p++ = 0x16000014 | (((((unsigned long)privateSnippetExecutor) >> 32) & 
0x000fffff) << 5);
+    *p++ = 0x03000294 | (((((unsigned long)privateSnippetExecutor) >> 52) & 
0x00000fff) << 10);
+    *p++ = 0x14000011 | (((((unsigned long)cpp_vtable_call) >> 12) & 
0x000fffff) << 5);
+    *p++ = 0x03800231 | ((((unsigned long)cpp_vtable_call) & 0x00000fff) << 
10);
+    *p++ = 0x16000011 | (((((unsigned long)cpp_vtable_call) >> 32) & 
0x000fffff) << 5);
+    *p++ = 0x03000231 | (((((unsigned long)cpp_vtable_call) >> 52) & 
0x00000fff) << 10);
+    *p++ = 0x14000013 | (((vtableOffset >> 12) & 0x000fffff) << 5);
+    *p++ = 0x03800273 | ((vtableOffset & 0x00000fff) << 10);
+    *p++ = 0x4c000280;
+    return (code + codeSnippetSize);
+}
+}
+
+void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const* 
bptr,
+                                                        unsigned char const* 
eptr)
+{
+    asm volatile("ibar 0" :::);
+}
+
+struct bridges::cpp_uno::shared::VtableFactory::Slot
+{
+    void* fn;
+};
+
+bridges::cpp_uno::shared::VtableFactory::Slot*
+bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void* block)
+{
+    return static_cast<Slot*>(block) + 2;
+}
+
+std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize(sal_Int32 
slotCount)
+{
+    return (slotCount + 2) * sizeof(Slot) + slotCount * codeSnippetSize;
+}
+
+bridges::cpp_uno::shared::VtableFactory::Slot*
+bridges::cpp_uno::shared::VtableFactory::initializeBlock(void* block, 
sal_Int32 slotCount,
+                                                         sal_Int32,
+                                                         
typelib_InterfaceTypeDescription*)
+{
+    Slot* slots = mapBlockToVtable(block);
+    slots[-2].fn = 0; //null
+    slots[-1].fn = 0; //destructor
+    return slots + slotCount;
+}
+
+unsigned char* bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
+    Slot** slots, unsigned char* code, sal_PtrDiff writetoexecdiff,
+    typelib_InterfaceTypeDescription const* type, sal_Int32 functionOffset, 
sal_Int32 functionCount,
+    sal_Int32 vtableOffset)
+{
+    (*slots) -= functionCount;
+    Slot* s = *slots;
+
+    for (sal_Int32 i = 0; i < type->nMembers; ++i)
+    {
+        typelib_TypeDescription* member = 0;
+        TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
+        assert(member != 0);
+        switch (member->eTypeClass)
+        {
+            case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+                // Getter:
+                (s++)->fn = code + writetoexecdiff;
+                code = codeSnippet(
+                    code, functionOffset++, vtableOffset,
+                    CPPU_CURRENT_NAMESPACE::return_in_hidden_param(
+                        
reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(member)
+                            ->pAttributeTypeRef));
+
+                // Setter:
+                if 
(!reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(member)
+                         ->bReadOnly)
+                {
+                    (s++)->fn = code + writetoexecdiff;
+                    code = codeSnippet(code, functionOffset++, vtableOffset, 
false);
+                }
+                break;
+
+            case typelib_TypeClass_INTERFACE_METHOD:
+                (s++)->fn = code + writetoexecdiff;
+                code = codeSnippet(
+                    code, functionOffset++, vtableOffset,
+                    CPPU_CURRENT_NAMESPACE::return_in_hidden_param(
+                        
reinterpret_cast<typelib_InterfaceMethodTypeDescription*>(member)
+                            ->pReturnTypeRef));
+                break;
+
+            default:
+                assert(false);
+                break;
+        }
+        TYPELIB_DANGER_RELEASE(member);
+    }
+    return code;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/except.cxx 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/except.cxx
new file mode 100644
index 000000000000..b69c52b1f4b4
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/except.cxx
@@ -0,0 +1,251 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#include <stdio.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <cxxabi.h>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <osl/mutex.hxx>
+
+#include <com/sun/star/uno/genfunc.hxx>
+#include <typelib/typedescription.hxx>
+#include <uno/any2.h>
+
+#include <unordered_map>
+#include "share.hxx"
+
+using namespace ::std;
+using namespace ::osl;
+using namespace ::com::sun::star::uno;
+using namespace ::__cxxabiv1;
+
+namespace CPPU_CURRENT_NAMESPACE
+{
+void dummy_can_throw_anything(char const*) {}
+
+static OUString toUNOname(char const* p)
+{
+    // example: N3com3sun4star4lang24IllegalArgumentExceptionE
+
+    OUStringBuffer buf(64);
+    assert('N' == *p);
+    ++p; // skip N
+
+    while ('E' != *p)
+    {
+        // read chars count
+        long n = (*p++ - '0');
+        while ('0' <= *p && '9' >= *p)
+        {
+            n *= 10;
+            n += (*p++ - '0');
+        }
+        buf.appendAscii(p, n);
+        p += n;
+        if ('E' != *p)
+            buf.append('.');
+    }
+
+    return buf.makeStringAndClear();
+}
+
+class RTTI
+{
+    typedef std::unordered_map<OUString, type_info*> t_rtti_map;
+
+    Mutex m_mutex;
+    t_rtti_map m_rttis;
+    t_rtti_map m_generatedRttis;
+
+    void* m_hApp;
+
+public:
+    RTTI();
+    ~RTTI();
+
+    type_info* getRTTI(typelib_CompoundTypeDescription*);
+};
+
+RTTI::RTTI()
+    : m_hApp(dlopen(0, RTLD_LAZY))
+{
+}
+
+RTTI::~RTTI() { dlclose(m_hApp); }
+
+type_info* RTTI::getRTTI(typelib_CompoundTypeDescription* pTypeDescr)
+{
+    type_info* rtti;
+
+    OUString const& unoName = *(OUString const*)&pTypeDescr->aBase.pTypeName;
+
+    MutexGuard guard(m_mutex);
+    t_rtti_map::const_iterator iRttiFind(m_rttis.find(unoName));
+    if (iRttiFind == m_rttis.end())
+    {
+        // RTTI symbol
+        OStringBuffer buf(64);
+        buf.append("_ZTIN");
+        sal_Int32 index = 0;
+        do
+        {
+            OUString token(unoName.getToken(0, '.', index));
+            buf.append(token.getLength());
+            OString c_token(OUStringToOString(token, 
RTL_TEXTENCODING_ASCII_US));
+            buf.append(c_token);
+        } while (index >= 0);
+        buf.append('E');
+
+        OString symName(buf.makeStringAndClear());
+        rtti = (type_info*)dlsym(m_hApp, symName.getStr());
+
+        if (rtti)
+        {
+            pair<t_rtti_map::iterator, bool> insertion(
+                m_rttis.insert(t_rtti_map::value_type(unoName, rtti)));
+            assert(insertion.second && "### inserting new rtti failed?!");
+        }
+        else
+        {
+            // try to lookup the symbol in the generated rtti map
+            t_rtti_map::const_iterator iFind(m_generatedRttis.find(unoName));
+            if (iFind == m_generatedRttis.end())
+            {
+                // we must generate it !
+                // symbol and rtti-name is nearly identical,
+                // the symbol is prefixed with _ZTI
+                char const* rttiName = symName.getStr() + 4;
+                if (pTypeDescr->pBaseTypeDescription)
+                {
+                    // ensure availability of base
+                    type_info* base_rtti = getRTTI(
+                        
(typelib_CompoundTypeDescription*)pTypeDescr->pBaseTypeDescription);
+                    rtti
+                        = new __si_class_type_info(strdup(rttiName), 
(__class_type_info*)base_rtti);
+                }
+                else
+                {
+                    // this class has no base class
+                    rtti = new __class_type_info(strdup(rttiName));
+                }
+
+                pair<t_rtti_map::iterator, bool> insertion(
+                    m_generatedRttis.insert(t_rtti_map::value_type(unoName, 
rtti)));
+                assert(insertion.second && "### inserting new generated rtti 
failed?!");
+            }
+            else // taking already generated rtti
+            {
+                rtti = iFind->second;
+            }
+        }
+    }
+    else
+    {
+        rtti = iRttiFind->second;
+    }
+
+    return rtti;
+}
+
+static void deleteException(void* pExc)
+{
+    __cxa_exception const* header = ((__cxa_exception const*)pExc - 1);
+    typelib_TypeDescription* pTD = 0;
+    OUString unoName(toUNOname(header->exceptionType->name()));
+    ::typelib_typedescription_getByName(&pTD, unoName.pData);
+    assert(pTD && "### unknown exception type! leaving out destruction => 
leaking!!!");
+    if (pTD)
+    {
+        ::uno_destructData(pExc, pTD, cpp_release);
+        ::typelib_typedescription_release(pTD);
+    }
+}
+
+void raiseException(uno_Any* pUnoExc, uno_Mapping* pUno2Cpp)
+{
+    void* pCppExc;
+    type_info* rtti;
+
+    {
+        // construct cpp exception object
+        typelib_TypeDescription* pTypeDescr = 0;
+        TYPELIB_DANGER_GET(&pTypeDescr, pUnoExc->pType);
+        assert(pTypeDescr);
+        if (!pTypeDescr)
+        {
+            throw RuntimeException(OUString("cannot get typedescription for 
type ")
+                                   + 
OUString::unacquired(&pUnoExc->pType->pTypeName));
+        }
+
+        pCppExc = __cxa_allocate_exception(pTypeDescr->nSize);
+        ::uno_copyAndConvertData(pCppExc, pUnoExc->pData, pTypeDescr, 
pUno2Cpp);
+
+        // destruct uno exception
+        ::uno_any_destruct(pUnoExc, 0);
+        // avoiding locked counts
+        static RTTI rtti_data;
+        rtti = 
(type_info*)rtti_data.getRTTI((typelib_CompoundTypeDescription*)pTypeDescr);
+        TYPELIB_DANGER_RELEASE(pTypeDescr);
+        assert(rtti && "### no rtti for throwing exception!");
+        if (!rtti)
+        {
+            throw RuntimeException(OUString("no rtti for type ")
+                                   + 
OUString::unacquired(&pUnoExc->pType->pTypeName));
+        }
+    }
+
+    __cxa_throw(pCppExc, rtti, deleteException);
+}
+
+void fillUnoException(uno_Any* pUnoExc, uno_Mapping* pCpp2Uno)
+{
+    __cxa_exception* header = __cxa_get_globals()->caughtExceptions;
+    if (!header)
+    {
+        RuntimeException aRE("no exception header!");
+        Type const& rType = cppu::UnoType<decltype(aRE)>::get();
+        uno_type_any_constructAndConvert(pUnoExc, &aRE, 
rType.getTypeLibType(), pCpp2Uno);
+        SAL_WARN("bridges", aRE.Message);
+        return;
+    }
+
+    std::type_info* exceptionType = __cxa_current_exception_type();
+
+    typelib_TypeDescription* pExcTypeDescr = 0;
+    OUString unoName(toUNOname(exceptionType->name()));
+    typelib_typedescription_getByName(&pExcTypeDescr, unoName.pData);
+    if (0 == pExcTypeDescr)
+    {
+        RuntimeException aRE(OUString("exception type not found: ") + unoName);
+        Type const& rType = cppu::UnoType<decltype(aRE)>::get();
+        uno_type_any_constructAndConvert(pUnoExc, &aRE, 
rType.getTypeLibType(), pCpp2Uno);
+        SAL_WARN("bridges", aRE.Message);
+    }
+    else
+    {
+        // construct uno exception any
+        uno_any_constructAndConvert(pUnoExc, header->adjustedPtr, 
pExcTypeDescr, pCpp2Uno);
+        typelib_typedescription_release(pExcTypeDescr);
+    }
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/share.hxx 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/share.hxx
new file mode 100644
index 000000000000..331ed789e39f
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/share.hxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "uno/mapping.h"
+
+#include <typeinfo>
+#include <exception>
+#include <cstddef>
+
+#define MAX_GP_REGS (8)
+#define MAX_FP_REGS (8)
+
+namespace CPPU_CURRENT_NAMESPACE
+{
+void dummy_can_throw_anything(char const*);
+
+// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h
+
+struct _Unwind_Exception
+{
+    unsigned exception_class __attribute__((__mode__(__DI__)));
+    void* exception_cleanup;
+    unsigned private_1 __attribute__((__mode__(__word__)));
+    unsigned private_2 __attribute__((__mode__(__word__)));
+} __attribute__((__aligned__));
+
+struct __cxa_exception
+{
+    std::type_info* exceptionType;
+    void (*exceptionDestructor)(void*);
+
+    void (*unexpectedHandler)(); // std::unexpected_handler dropped from C++17
+    std::terminate_handler terminateHandler;
+
+    __cxa_exception* nextException;
+
+    int handlerCount;
+
+    int handlerSwitchValue;
+    const unsigned char* actionRecord;
+    const unsigned char* languageSpecificData;
+    void* catchTemp;
+    void* adjustedPtr;
+
+    _Unwind_Exception unwindHeader;
+};
+
+extern "C" void* __cxa_allocate_exception(std::size_t thrown_size) throw();
+extern "C" void __cxa_throw(void* thrown_exception, std::type_info* tinfo, 
void (*dest)(void*))
+    __attribute__((noreturn));
+
+struct __cxa_eh_globals
+{
+    __cxa_exception* caughtExceptions;
+    unsigned int uncaughtExceptions;
+};
+
+extern "C" __cxa_eh_globals* __cxa_get_globals() throw();
+extern "C" std::type_info* __cxa_current_exception_type() throw();
+
+void raiseException(uno_Any* pUnoExc, uno_Mapping* pUno2Cpp);
+
+void fillUnoException(uno_Any*, uno_Mapping* pCpp2Uno);
+
+bool return_in_hidden_param(typelib_TypeDescriptionReference* pTypeRef);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx 
b/bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx
new file mode 100644
index 000000000000..0004794ce55d
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_linux_loongarch64/uno2cpp.cxx
@@ -0,0 +1,546 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <exception>
+#include <malloc.h>
+#include <cstring>
+#include <typeinfo>
+
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/genfunc.hxx>
+#include <o3tl/runtimetooustring.hxx>
+#include <uno/data.h>
+
+#include "bridge.hxx"
+#include "types.hxx"
+#include "unointerfaceproxy.hxx"
+#include "vtables.hxx"
+
+#include "share.hxx"
+
+#define INSERT_FLOAT_DOUBLE(pSV, nr, pFPR, pDS)                                
                    \
+    if (nr < MAX_FP_REGS)                                                      
                    \
+        pFPR[nr++] = *reinterpret_cast<double*>(pSV);                          
                    \
+    else                                                                       
                    \
+        *pDS++ = *reinterpret_cast<sal_uInt64*>(pSV); // verbatim!
+
+#define INSERT_INT64(pSV, nr, pGPR, pDS)                                       
                    \
+    if (nr < MAX_GP_REGS)                                                      
                    \
+        pGPR[nr++] = *reinterpret_cast<sal_Int64*>(pSV);                       
                    \
+    else                                                                       
                    \
+        *pDS++ = *reinterpret_cast<sal_Int64*>(pSV);
+
+#define INSERT_INT32(pSV, nr, pGPR, pDS)                                       
                    \
+    if (nr < MAX_GP_REGS)                                                      
                    \
+        pGPR[nr++] = *reinterpret_cast<sal_Int32*>(pSV);                       
                    \
+    else                                                                       
                    \
+        *pDS++ = *reinterpret_cast<sal_Int32*>(pSV);
+
+#define INSERT_INT16(pSV, nr, pGPR, pDS)                                       
                    \
+    if (nr < MAX_GP_REGS)                                                      
                    \
+        pGPR[nr++] = *reinterpret_cast<sal_Int16*>(pSV);                       
                    \
+    else                                                                       
                    \
+        *pDS++ = *reinterpret_cast<sal_Int16*>(pSV);
+
+#define INSERT_UINT16(pSV, nr, pGPR, pDS)                                      
                    \
+    if (nr < MAX_GP_REGS)                                                      
                    \
+        pGPR[nr++] = *reinterpret_cast<sal_uInt16*>(pSV);                      
                    \
+    else                                                                       
                    \
+        *pDS++ = *reinterpret_cast<sal_uInt16*>(pSV);
+
+#define INSERT_INT8(pSV, nr, pGPR, pDS)                                        
                    \
+    if (nr < MAX_GP_REGS)                                                      
                    \
+        pGPR[nr++] = *reinterpret_cast<sal_Int8*>(pSV);                        
                    \
+    else                                                                       
                    \
+        *pDS++ = *reinterpret_cast<sal_Int8*>(pSV);
+
+using namespace ::com::sun::star::uno;
+
+namespace
+{
+bool isReturnInFPR(const typelib_TypeDescription* pTypeDescr, sal_uInt32& 
nSize)
+{
+    const typelib_CompoundTypeDescription* p
+        = reinterpret_cast<const typelib_CompoundTypeDescription*>(pTypeDescr);
+
+    for (sal_Int32 i = 0; i < p->nMembers; ++i)
+    {
+        typelib_TypeDescriptionReference* pTypeInStruct = p->ppTypeRefs[i];
+
+        switch (pTypeInStruct->eTypeClass)
+        {
+            case typelib_TypeClass_STRUCT:
+            case typelib_TypeClass_EXCEPTION:
+            {
+                typelib_TypeDescription* t = 0;
+                TYPELIB_DANGER_GET(&t, pTypeInStruct);
+                bool isFPR = isReturnInFPR(t, nSize);
+                TYPELIB_DANGER_RELEASE(t);
+                if (!isFPR)
+                    return false;
+            }
+            break;
+            case typelib_TypeClass_FLOAT:
+            case typelib_TypeClass_DOUBLE:
+                if (nSize >= 16)
+                    return false;
+                nSize += 8;
+                break;
+            default:
+                return false;
+        }
+    }
+    return true;
+}
+
+void fillReturn(const typelib_TypeDescription* pTypeDescr, sal_Int64* gret, 
double* fret,
+                void* pRegisterReturn)
+{
+    sal_uInt32 nSize = 0;
+    if (isReturnInFPR(pTypeDescr, nSize))
+    {
+        reinterpret_cast<double*>(pRegisterReturn)[0] = fret[0];
+        reinterpret_cast<double*>(pRegisterReturn)[1] = fret[1];
+    }
+    else
+    {
+        reinterpret_cast<sal_Int64*>(pRegisterReturn)[0] = gret[0];
+        reinterpret_cast<sal_Int64*>(pRegisterReturn)[1] = gret[1];
+    }
+}
+
+static void callVirtualMethod(void* pAdjustedThisPtr, sal_Int32 nVtableIndex, 
void* pRegisterReturn,
+                              typelib_TypeDescriptionReference* 
pReturnTypeRef, bool bSimpleReturn,
+                              sal_uInt64* pStack, sal_uInt32 nStack, 
sal_uInt64* pGPR, double* pFPR,
+                              sal_uInt32 nREG)
+{
+    // Should not happen, but...
+    static_assert(MAX_GP_REGS == MAX_FP_REGS, "must be the same size");
+    if (nREG > MAX_GP_REGS)
+        nREG = MAX_GP_REGS;
+
+    // Get pointer to method
+    sal_uInt64 pMethod = *((sal_uInt64*)pAdjustedThisPtr);
+    pMethod += 8 * nVtableIndex;
+    void* mfunc = (void*)*((sal_uInt64*)pMethod);
+    // Load parameters to stack, if necessary
+    sal_uInt64* pCallStack = NULL;
+    if (nStack)
+    {
+        // 16-bytes aligned
+        sal_uInt32 nStackBytes = ((nStack + 1) >> 1) * 16;
+        pCallStack = (sal_uInt64*)__builtin_alloca(nStackBytes);
+        std::memcpy(pCallStack, pStack, nStackBytes);
+    }
+
+    sal_Int64 gret[2];
+    double fret[2];
+    asm volatile(
+        // Fill the general purpose registers
+        "ld.d $r4,%[gpr],0 \n\t"
+        "ld.d $r5,%[gpr],8 \n\t"
+        "ld.d $r6,%[gpr],16 \n\t"
+        "ld.d $r7,%[gpr],24 \n\t"
+        "ld.d $r8,%[gpr],32 \n\t"
+        "ld.d $r9,%[gpr],40 \n\t"
+        "ld.d $r10,%[gpr],48 \n\t"
+        "ld.d $r11,%[gpr],56 \n\t"
+        // Fill the floating pointer registers
+        "fld.d $f0,%[fpr],0 \n\t"
+        "fld.d $f1,%[fpr],8 \n\t"
+        "fld.d $f2,%[fpr],16 \n\t"
+        "fld.d $f3,%[fpr],24 \n\t"
+        "fld.d $f4,%[fpr],32 \n\t"
+        "fld.d $f5,%[fpr],40 \n\t"
+        "fld.d $f6,%[fpr],48 \n\t"
+        "fld.d $f7,%[fpr],56 \n\t"
+        // Perform the call
+        "jirl $ra,%[mfunc],0 \n\t"
+        // Fill the return values
+        "move %[gret1], $a0 \n\t"
+        "move %[gret2], $a1 \n\t"
+        "fmov.d %[fret1], $f0 \n\t"
+        "fmov.d %[fret2], $f1 \n\t"
+        : [gret1] "=r"(gret[0]), [gret2] "=r"(gret[1]), [fret1] "=f"(fret[0]), 
[fret2] "=f"(fret[1])
+        : [gpr] "r"(pGPR), [fpr] "r"(pFPR), [mfunc] "r"(mfunc),
+          [stack] "m"(
+              pCallStack) // dummy input to prevent the compiler from 
optimizing the alloca out
+        : "$r4", "$r5", "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r1", 
"$f0", "$f1", "$f2",
+          "$f3", "$f4", "$f5", "$f6", "$f7", "memory");
+
+    switch (pReturnTypeRef->eTypeClass)
+    {
+        case typelib_TypeClass_HYPER:
+        case typelib_TypeClass_UNSIGNED_HYPER:
+        case typelib_TypeClass_LONG:
+        case typelib_TypeClass_UNSIGNED_LONG:
+        case typelib_TypeClass_ENUM:
+        case typelib_TypeClass_CHAR:
+        case typelib_TypeClass_SHORT:
+        case typelib_TypeClass_UNSIGNED_SHORT:
+        case typelib_TypeClass_BOOLEAN:
+        case typelib_TypeClass_BYTE:
+            *reinterpret_cast<sal_Int64*>(pRegisterReturn) = gret[0];
+            break;
+        case typelib_TypeClass_FLOAT:
+        case typelib_TypeClass_DOUBLE:
+            *reinterpret_cast<double*>(pRegisterReturn) = fret[0];
+            break;
+        case typelib_TypeClass_STRUCT:
+        case typelib_TypeClass_EXCEPTION:
+        {
+            sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
+            if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
+            {
+                typelib_TypeDescription* pTypeDescr = 0;
+                TYPELIB_DANGER_GET(&pTypeDescr, pReturnTypeRef);
+                fillReturn(pTypeDescr, gret, fret, pRegisterReturn);
+                TYPELIB_DANGER_RELEASE(pTypeDescr);
+            }
+            break;
+        }
+        default:
+            break;
+    }
+}
+
+static void cpp_call(bridges::cpp_uno::shared::UnoInterfaceProxy* pThis,
+                     bridges::cpp_uno::shared::VtableSlot aVtableSlot,
+                     typelib_TypeDescriptionReference* pReturnTypeRef, 
sal_Int32 nParams,
+                     typelib_MethodParameter* pParams, void* pUnoReturn, void* 
pUnoArgs[],
+                     uno_Any** ppUnoExc)
+{
+    // max space for: [complex ret ptr], values|ptr ...
+    sal_uInt64* pStack = (sal_uInt64*)__builtin_alloca(((nParams + 3) * 
sizeof(sal_Int64)));
+    sal_uInt64* pStackStart = pStack;
+
+    sal_uInt64 pGPR[MAX_GP_REGS];
+    double pFPR[MAX_FP_REGS];
+    sal_uInt32 nREG = 0;
+
+    // return
+    typelib_TypeDescription* pReturnTypeDescr = 0;
+    TYPELIB_DANGER_GET(&pReturnTypeDescr, pReturnTypeRef);
+    assert(pReturnTypeDescr);
+
+    void* pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
+
+    bool bSimpleReturn = true;
+    if (pReturnTypeDescr)
+    {
+        if (CPPU_CURRENT_NAMESPACE::return_in_hidden_param(pReturnTypeRef))
+        {
+            bSimpleReturn = false;
+            // complex return via ptr
+            pCppReturn = 
bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr)
+                             ? __builtin_alloca(pReturnTypeDescr->nSize)
+                             : pUnoReturn;
+            INSERT_INT64(&pCppReturn, nREG, pGPR, pStack);
+        }
+        else
+        {
+            pCppReturn = pUnoReturn; // direct way for simple types
+        }
+    }
+
+    // push this
+    void* pAdjustedThisPtr = reinterpret_cast<void**>(pThis->getCppI()) + 
aVtableSlot.offset;
+    INSERT_INT64(&pAdjustedThisPtr, nREG, pGPR, pStack);
+
+    // args
+    void** pCppArgs = (void**)alloca(3 * sizeof(void*) * nParams);
+    // indices of values this have to be converted (interface conversion 
cpp<=>uno)
+    sal_Int32* pTempIndices = (sal_Int32*)(pCppArgs + nParams);
+    // type descriptions for reconversions
+    typelib_TypeDescription** ppTempParamTypeDescr
+        = (typelib_TypeDescription**)(pCppArgs + (2 * nParams));
+
+    sal_Int32 nTempIndices = 0;
+
+    for (sal_Int32 nPos = 0; nPos < nParams; ++nPos)
+    {
+        const typelib_MethodParameter& rParam = pParams[nPos];
+        typelib_TypeDescription* pParamTypeDescr = 0;
+        TYPELIB_DANGER_GET(&pParamTypeDescr, rParam.pTypeRef);
+
+        if (!rParam.bOut && 
bridges::cpp_uno::shared::isSimpleType(pParamTypeDescr))
+        {
+            uno_copyAndConvertData(pCppArgs[nPos] = alloca(8), pUnoArgs[nPos], 
pParamTypeDescr,
+                                   pThis->getBridge()->getUno2Cpp());
+
+            switch (pParamTypeDescr->eTypeClass)
+            {
+                case typelib_TypeClass_LONG:
+                case typelib_TypeClass_UNSIGNED_LONG:
+                    INSERT_INT64(pCppArgs[nPos], nREG, pGPR, pStack);
+                    break;
+                case typelib_TypeClass_ENUM:
+                    INSERT_INT32(pCppArgs[nPos], nREG, pGPR, pStack);
+                    break;
+                case typelib_TypeClass_CHAR:
+                case typelib_TypeClass_SHORT:
+                    INSERT_INT16(pCppArgs[nPos], nREG, pGPR, pStack);
+                    break;
+                case typelib_TypeClass_UNSIGNED_SHORT:
+                    INSERT_UINT16(pCppArgs[nPos], nREG, pGPR, pStack);
+                    break;
+                case typelib_TypeClass_BOOLEAN:
+                case typelib_TypeClass_BYTE:
+                    INSERT_INT8(pCppArgs[nPos], nREG, pGPR, pStack);
+                    break;
+                case typelib_TypeClass_FLOAT:
+                case typelib_TypeClass_DOUBLE:
+                    INSERT_FLOAT_DOUBLE(pCppArgs[nPos], nREG, pFPR, pStack);
+                    break;
+                case typelib_TypeClass_HYPER:
+                case typelib_TypeClass_UNSIGNED_HYPER:
+                    INSERT_INT64(pCppArgs[nPos], nREG, pGPR, pStack);
+                    break;
+                default:
+                    break;
+            }
+
+            // no longer needed
+            TYPELIB_DANGER_RELEASE(pParamTypeDescr);
+        }
+        else // ptr to complex value | ref
+        {
+            if (!rParam.bIn) // is pure out
+            {
+                // cpp out is constructed mem, uno out is not!
+                uno_constructData(pCppArgs[nPos] = 
alloca(pParamTypeDescr->nSize), pParamTypeDescr);
+                pTempIndices[nTempIndices] = nPos; // default constructed for 
cpp call
+                // will be released at reconversion
+                ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+            }
+            // is in/inout
+            else if 
(bridges::cpp_uno::shared::relatesToInterfaceType(pParamTypeDescr))
+            {
+                uno_copyAndConvertData(pCppArgs[nPos] = 
alloca(pParamTypeDescr->nSize),
+                                       pUnoArgs[nPos], pParamTypeDescr,
+                                       pThis->getBridge()->getUno2Cpp());
+
+                pTempIndices[nTempIndices] = nPos; // has to be reconverted
+                // will be released at reconversion
+                ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+            }
+            else // direct way
+            {
+                pCppArgs[nPos] = pUnoArgs[nPos];
+                // no longer needed
+                TYPELIB_DANGER_RELEASE(pParamTypeDescr);
+            }
+            INSERT_INT64(&(pCppArgs[nPos]), nREG, pGPR, pStack);
+        }
+    }
+
+    try
+    {
+        try
+        {
+            callVirtualMethod(pAdjustedThisPtr, aVtableSlot.index, pCppReturn, 
pReturnTypeRef,
+                              bSimpleReturn, pStackStart, (pStack - 
pStackStart), pGPR, pFPR, nREG);
+        }
+        catch (css::uno::Exception&)
+        {
+            throw;
+        }
+        catch (std::exception& e)
+        {
+            throw css::uno::RuntimeException("C++ code threw "
+                                             + 
o3tl::runtimeToOUString(typeid(e).name()) + ": "
+                                             + 
o3tl::runtimeToOUString(e.what()));
+        }
+        catch (...)
+        {
+            throw css::uno::RuntimeException("C++ code threw unknown 
exception");
+        }
+        // NO exception occurred...
+        *ppUnoExc = 0;
+
+        // reconvert temporary params
+        for (; nTempIndices--;)
+        {
+            sal_Int32 nIndex = pTempIndices[nTempIndices];
+            typelib_TypeDescription* pParamTypeDescr = 
ppTempParamTypeDescr[nTempIndices];
+
+            if (pParams[nIndex].bIn)
+            {
+                if (pParams[nIndex].bOut) // inout
+                {
+                    uno_destructData(pUnoArgs[nIndex], pParamTypeDescr, 0); // 
destroy uno value
+                    uno_copyAndConvertData(pUnoArgs[nIndex], pCppArgs[nIndex], 
pParamTypeDescr,
+                                           pThis->getBridge()->getCpp2Uno());
+                }
+            }
+            else // pure out
+            {
+                uno_copyAndConvertData(pUnoArgs[nIndex], pCppArgs[nIndex], 
pParamTypeDescr,
+                                       pThis->getBridge()->getCpp2Uno());
+            }
+            // destroy temp cpp param => cpp: every param was constructed
+            uno_destructData(pCppArgs[nIndex], pParamTypeDescr, cpp_release);
+
+            TYPELIB_DANGER_RELEASE(pParamTypeDescr);
+        }
+        // return value
+        if (pCppReturn && pUnoReturn != pCppReturn)
+        {
+            uno_copyAndConvertData(pUnoReturn, pCppReturn, pReturnTypeDescr,
+                                   pThis->getBridge()->getCpp2Uno());
+            uno_destructData(pCppReturn, pReturnTypeDescr, cpp_release);
+        }
+    }
+    catch (...)
+    {
+        // fill uno exception
+        CPPU_CURRENT_NAMESPACE::fillUnoException(*ppUnoExc, 
pThis->getBridge()->getCpp2Uno());
+
+        // temporary params
+        for (; nTempIndices--;)
+        {
+            sal_Int32 nIndex = pTempIndices[nTempIndices];
+            // destroy temp cpp param => cpp: every param was constructed
+            uno_destructData(pCppArgs[nIndex], 
ppTempParamTypeDescr[nTempIndices], cpp_release);
+            TYPELIB_DANGER_RELEASE(ppTempParamTypeDescr[nTempIndices]);
+        }
+        // return type
+        if (pReturnTypeDescr)
+            TYPELIB_DANGER_RELEASE(pReturnTypeDescr);
+    }
+}
+}
+
+namespace bridges::cpp_uno::shared
+{
+void unoInterfaceProxyDispatch(uno_Interface* pUnoI, const 
typelib_TypeDescription* pMemberDescr,
+                               void* pReturn, void* pArgs[], uno_Any** 
ppException)
+{
+    // is my surrogate
+    bridges::cpp_uno::shared::UnoInterfaceProxy* pThis
+        = static_cast<bridges::cpp_uno::shared::UnoInterfaceProxy*>(pUnoI);
+    //typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
+
+    switch (pMemberDescr->eTypeClass)
+    {
+        case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+        {
+            VtableSlot aVtableSlot(getVtableSlot(
+                reinterpret_cast<typelib_InterfaceAttributeTypeDescription 
const*>(pMemberDescr)));
+
+            if (pReturn)
+            {
+                // dependent dispatch
+                cpp_call(
+                    pThis, aVtableSlot,
+                    
((typelib_InterfaceAttributeTypeDescription*)pMemberDescr)->pAttributeTypeRef,
+                    0, 0, // no params
+                    pReturn, pArgs, ppException);
+            }
+            else
+            {
+                // is SET
+                typelib_MethodParameter aParam;
+                aParam.pTypeRef
+                    = 
((typelib_InterfaceAttributeTypeDescription*)pMemberDescr)->pAttributeTypeRef;
+                aParam.bIn = sal_True;
+                aParam.bOut = sal_False;
+
+                typelib_TypeDescriptionReference* pReturnTypeRef = 0;
+                OUString aVoidName("void");
+                typelib_typedescriptionreference_new(&pReturnTypeRef, 
typelib_TypeClass_VOID,
+                                                     aVoidName.pData);
+
+                // dependent dispatch
+                aVtableSlot.index += 1; //get then set method
+                cpp_call(pThis, aVtableSlot, pReturnTypeRef, 1, &aParam, 
pReturn, pArgs,
+                         ppException);
+
+                typelib_typedescriptionreference_release(pReturnTypeRef);
+            }
+
+            break;
+        }
+        case typelib_TypeClass_INTERFACE_METHOD:
+        {
+            VtableSlot aVtableSlot(getVtableSlot(
+                reinterpret_cast<typelib_InterfaceMethodTypeDescription 
const*>(pMemberDescr)));
+            switch (aVtableSlot.index)
+            {
+                // standard calls
+                case 1: // acquire uno interface
+                    (*pUnoI->acquire)(pUnoI);
+                    *ppException = 0;
+                    break;
+                case 2: // release uno interface
+                    (*pUnoI->release)(pUnoI);
+                    *ppException = 0;
+                    break;
+                case 0: // queryInterface() opt
+                {
+                    typelib_TypeDescription* pTD = 0;
+                    TYPELIB_DANGER_GET(&pTD, 
reinterpret_cast<Type*>(pArgs[0])->getTypeLibType());
+                    if (pTD)
+                    {
+                        uno_Interface* pInterface = 0;
+                        (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
+                            pThis->pBridge->getUnoEnv(), (void**)&pInterface, 
pThis->oid.pData,
+                            (typelib_InterfaceTypeDescription*)pTD);
+
+                        if (pInterface)
+                        {
+                            
::uno_any_construct(reinterpret_cast<uno_Any*>(pReturn), &pInterface,
+                                                pTD, 0);
+                            (*pInterface->release)(pInterface);
+                            TYPELIB_DANGER_RELEASE(pTD);
+                            *ppException = 0;
+                            break;
+                        }
+                        TYPELIB_DANGER_RELEASE(pTD);
+                    }
+                } // else perform queryInterface()
+                default:
+                    // dependent dispatch
+                    cpp_call(
+                        pThis, aVtableSlot,
+                        
((typelib_InterfaceMethodTypeDescription*)pMemberDescr)->pReturnTypeRef,
+                        
((typelib_InterfaceMethodTypeDescription*)pMemberDescr)->nParams,
+                        
((typelib_InterfaceMethodTypeDescription*)pMemberDescr)->pParams, pReturn,
+                        pArgs, ppException);
+            }
+            break;
+        }
+        default:
+        {
+            ::com::sun::star::uno::RuntimeException aExc(
+                "illegal member type description!",
+                
::com::sun::star::uno::Reference<::com::sun::star::uno::XInterface>());
+
+            Type const& rExcType = cppu::UnoType<decltype(aExc)>::get();
+            // binary identical null reference
+            ::uno_type_any_construct(*ppException, &aExc, 
rExcType.getTypeLibType(), 0);
+        }
+    }
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/configure.ac b/configure.ac
index 851c2afe9b94..c639bda264fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5263,6 +5263,11 @@ linux-gnu*|linux-musl*)
         RTL_ARCH=X86_64
         PLATFORMID=linux_x86_64
         ;;
+    loongarch64)
+       CPUNAME=LOONGARCH64
+       RTL_ARCH=LOONGARCH64
+       PLATFORMID=linux_loongarch64
+       ;;
     *)
         AC_MSG_ERROR([Unsupported host_cpu $host_cpu for host_os $host_os])
         ;;
@@ -12879,7 +12884,7 @@ AC_SUBST(RHINO_JAR)
 # platforms there.
 supports_multilib=
 case "$host_cpu" in
-x86_64 | powerpc64 | powerpc64le | s390x | aarch64 | mips64 | mips64el)
+x86_64 | powerpc64 | powerpc64le | s390x | aarch64 | mips64 | mips64el | 
loongarch64)
     if test "$SAL_TYPES_SIZEOFLONG" = "8"; then
         supports_multilib="yes"
     fi
diff --git a/jvmfwk/inc/vendorbase.hxx b/jvmfwk/inc/vendorbase.hxx
index 779fc8f7a46f..2bbf656c6e32 100644
--- a/jvmfwk/inc/vendorbase.hxx
+++ b/jvmfwk/inc/vendorbase.hxx
@@ -75,9 +75,11 @@ OpenJDK at least, but probably not true for Lemotes JDK */
 #define JFW_PLUGIN_ARCH "alpha"
 #elif defined AARCH64
 #define JFW_PLUGIN_ARCH "aarch64"
-#else // SPARC, INTEL, POWERPC, MIPS, MIPS64, ARM, IA64, M68K, HPPA, ALPHA
+#elif defined LOONGARCH64
+#define JFW_PLUGIN_ARCH "loongarch64"
+#else // SPARC, INTEL, POWERPC, MIPS, MIPS64, ARM, IA64, M68K, HPPA, ALPHA, 
LOONGARCH64
 #error unknown platform
-#endif // SPARC, INTEL, POWERPC, MIPS, MIPS64, ARM, IA64, M68K, HPPA, ALPHA
+#endif // SPARC, INTEL, POWERPC, MIPS, MIPS64, ARM, IA64, M68K, HPPA, ALPHA, 
LOONGARCH64
 
 class MalformedVersionException final : public std::exception
 {
diff --git a/solenv/gbuild/platform/LINUX_LOONGARCH64_GCC.mk 
b/solenv/gbuild/platform/LINUX_LOONGARCH64_GCC.mk
new file mode 100644
index 000000000000..15cb0bb6fea5
--- /dev/null
+++ b/solenv/gbuild/platform/LINUX_LOONGARCH64_GCC.mk
@@ -0,0 +1,12 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 
100 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+include $(GBUILDDIR)/platform/linux.mk
+
+# vim: set noet sw=4 ts=4:

Reply via email to