From ea29ccd951f9ea53e9218c435fc75a4a78250131 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 13 Jun 2023 00:42:26 +0800 Subject: [PATCH 5/5] xpcom add loongarch64 support diff --git a/xpcom/reflect/xptcall/md/unix/moz.build b/xpcom/reflect/xptcall/md/unix/moz.build index 1779c148cb..e74c936c38 100644 --- a/xpcom/reflect/xptcall/md/unix/moz.build +++ b/xpcom/reflect/xptcall/md/unix/moz.build @@ -271,6 +271,14 @@ if CONFIG["OS_ARCH"] == "Linux" and CONFIG["CPU_ARCH"] == "riscv64": "xptcstubs_riscv64.cpp", ] +if CONFIG["OS_ARCH"] == "Linux" and CONFIG["CPU_ARCH"] == "loongarch64": + SOURCES += [ + "xptcinvoke_asm_loongarch64.S", + "xptcinvoke_loongarch64.cpp", + "xptcstubs_asm_loongarch64.S", + "xptcstubs_loongarch64.cpp", + ] + FINAL_LIBRARY = "xul" LOCAL_INCLUDES += [ diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_loongarch64.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_loongarch64.S new file mode 100644 index 0000000000..f0a6662986 --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_loongarch64.S @@ -0,0 +1,92 @@ +/* This Source Code Form subject to the terms of 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/. + */ + + .set NGPREGS, 8 + .set NFPREGS, 8 + + .text + .globl _NS_InvokeByIndex + .type _NS_InvokeByIndex, @function +/* + * _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + * uint32_t paramCount, nsXPTCVariant* params) + */ +_NS_InvokeByIndex: + .cfi_startproc + addi.d $sp, $sp, -32 + .cfi_def_cfa_offset 32 + st.d $s0, $sp, 16 + .cfi_offset 23, -16 + st.d $s1, $sp, 8 + .cfi_offset 24, -24 + st.d $s2, $sp, 0 + .cfi_offset 25, -32 + st.d $ra, $sp, 24 + .cfi_offset 1, -8 + + move $s2, $a0 + move $s1, $a1 + move $s0, $sp + .cfi_def_cfa_register 23 + + /* 16-bytes alignment */ + addi.d $a0, $a2, 1 + li.d $t4, 0xfffffffffffffffe + and $a0, $a0, $t4 + slli.d $a0, $a0, 3 + sub.d $sp, $sp, $a0 + move $a4, $sp + + addi.d $sp, $sp, -8*(NFPREGS+NGPREGS) + move $a0, $sp + addi.d $a1, $sp, 8*NGPREGS + + bl invoke_copy_to_stack + + /* 1st argument is this */ + move $a0, $s2 + + ld.d $a1, $sp, 8 + ld.d $a2, $sp, 16 + ld.d $a3, $sp, 24 + ld.d $a4, $sp, 32 + ld.d $a5, $sp, 40 + ld.d $a6, $sp, 48 + ld.d $a7, $sp, 56 + + fld.d $fa0, $sp, 64 + fld.d $fa1, $sp, 72 + fld.d $fa2, $sp, 80 + fld.d $fa3, $sp, 88 + fld.d $fa4, $sp, 96 + fld.d $fa5, $sp, 104 + fld.d $fa6, $sp, 112 + fld.d $fa7, $sp, 120 + + addi.d $sp, $sp, 8*(NGPREGS+NFPREGS) + + ld.d $s2, $s2, 0 + slli.w $s1, $s1, 3 + add.d $s2, $s2, $s1 + ld.d $t3, $s2, 0 + jirl $ra, $t3, 0 + + move $sp, $s0 + .cfi_def_cfa_register 3 + ld.d $s0, $sp, 16 + .cfi_restore 23 + ld.d $s1, $sp, 8 + .cfi_restore 24 + ld.d $s2, $sp, 0 + .cfi_restore 25 + ld.d $ra, $sp, 24 + .cfi_restore 1 + addi.d $sp, $sp, 32 + .cfi_def_cfa_offset -32 + jirl $zero, $ra, 0 + .cfi_endproc + .size _NS_InvokeByIndex, .-_NS_InvokeByIndex + .section .note.GNU-stack, "", @progbits + diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp new file mode 100644 index 0000000000..7238c72fab --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp @@ -0,0 +1,100 @@ +/* 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/. */ + +// Platform specific code to invoke XPCOM methods on native objects + +#include "xptcprivate.h" + +extern "C" void invoke_copy_to_stack(uint64_t* gpregs, double* fpregs, + uint32_t paramCount, nsXPTCVariant* s, + uint64_t* d) { + static const uint32_t GPR_COUNT = 8; + static const uint32_t FPR_COUNT = 8; + + uint32_t nr_gpr = 1; // skip one GPR register for "this" + uint32_t nr_fpr = 0; + uint64_t value = 0; + + for (uint32_t i = 0; i < paramCount; i++, s++) { + if (s->IsIndirect()) { + value = (uint64_t)&s->val; + } else { + switch (s->type) { + case nsXPTType::T_FLOAT: + break; + case nsXPTType::T_DOUBLE: + break; + case nsXPTType::T_I8: + value = s->val.i8; + break; + case nsXPTType::T_I16: + value = s->val.i16; + break; + case nsXPTType::T_I32: + value = s->val.i32; + break; + case nsXPTType::T_I64: + value = s->val.i64; + break; + case nsXPTType::T_U8: + value = s->val.u8; + break; + case nsXPTType::T_U16: + value = s->val.u16; + break; + case nsXPTType::T_U32: + value = s->val.u32; + break; + case nsXPTType::T_U64: + value = s->val.u64; + break; + case nsXPTType::T_BOOL: + value = s->val.b; + break; + case nsXPTType::T_CHAR: + value = s->val.c; + break; + case nsXPTType::T_WCHAR: + value = s->val.wc; + break; + default: + value = (uint64_t)s->val.p; + break; + } + } + + if (!s->IsIndirect() && s->type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) { + fpregs[nr_fpr++] = s->val.d; + } else if (nr_gpr < GPR_COUNT) { + memcpy(&gpregs[nr_gpr++], &(s->val.d), sizeof(s->val.d)); + } else { + memcpy(d++, &(s->val.d), sizeof(s->val.d)); + } + } else if (!s->IsIndirect() && s->type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) { + memcpy(&fpregs[nr_fpr++], &(s->val.f), sizeof(s->val.f)); + } else if (nr_gpr < GPR_COUNT) { + memcpy(&gpregs[nr_gpr++], &(s->val.f), sizeof(s->val.f)); + } else { + memcpy(d++, &(s->val.f), sizeof(s->val.f)); + } + } else { + if (nr_gpr < GPR_COUNT) { + gpregs[nr_gpr++] = value; + } else { + *d++ = value; + } + } + } +} + +extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, + uint32_t paramCount, + nsXPTCVariant* params); +EXPORT_XPCOM_API(nsresult) +NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, uint32_t paramCount, + nsXPTCVariant* params) { + return _NS_InvokeByIndex(that, methodIndex, paramCount, params); +} diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_loongarch64.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_loongarch64.S new file mode 100644 index 0000000000..ae4e0cf73f --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_loongarch64.S @@ -0,0 +1,52 @@ +# 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/. + + .set NGPRGES, 8 + .set NFPREGS, 8 + + .text + .globl SharedStub + .hidden SharedStub + .type SharedStub,@function + +SharedStub: + .cfi_startproc + move $t0, $sp + addi.d $sp, $sp, -8*(NGPRGES+NFPREGS)-16 + .cfi_def_cfa_offset 8*(NGPRGES+NFPREGS)+16 + st.d $a0, $sp, 0 + st.d $a1, $sp, 8 + st.d $a2, $sp, 16 + st.d $a3, $sp, 24 + st.d $a4, $sp, 32 + st.d $a5, $sp, 40 + st.d $a6, $sp, 48 + st.d $a7, $sp, 56 + fst.d $fa0, $sp, 64 + fst.d $fa1, $sp, 72 + fst.d $fa2, $sp, 80 + fst.d $fa3, $sp, 88 + fst.d $fa4, $sp, 96 + fst.d $fa5, $sp, 104 + fst.d $fa6, $sp, 112 + fst.d $fa7, $sp, 120 + st.d $ra, $sp, 136 + .cfi_offset 1, 136 + + /* methodIndex is passed from stub */ + move $a1, $t6 + move $a2, $t0 + move $a3, $sp + addi.d $a4, $sp, 8*NGPRGES + + bl PrepareAndDispatch + + ld.d $ra, $sp, 136 + .cfi_restore 1 + addi.d $sp, $sp, 8*(NGPRGES+NFPREGS)+16 + .cfi_def_cfa_offset -8*(NGPRGES+NFPREGS)-16 + jirl $zero, $ra, 0 + .cfi_endproc + + .size SharedStub, .-SharedStub + .section .note.GNU-stack, "", @progbits diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_loongarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_loongarch64.cpp new file mode 100644 index 0000000000..5c4cd6d95e --- /dev/null +++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_loongarch64.cpp @@ -0,0 +1,159 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "xptcprivate.h" + +extern "C" nsresult ATTRIBUTE_USED PrepareAndDispatch(nsXPTCStubBase* self, + uint32_t methodIndex, + uint64_t* args, + uint64_t* gpregs, + double* fpregs) { + static const uint32_t GPR_COUNT = 8; + static const uint32_t FPR_COUNT = 8; + nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; + const nsXPTMethodInfo* info; + + self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + + uint32_t paramCount = info->GetParamCount(); + const uint8_t indexOfJSContext = info->IndexOfJSContext(); + + uint64_t* ap = args; + uint32_t nr_gpr = 1; // skip the arg which is 'self' + uint32_t nr_fpr = 0; + uint64_t value; + + for (uint32_t i = 0; i < paramCount; i++) { + const nsXPTParamInfo& param = info->GetParam(i); + const nsXPTType& type = param.GetType(); + nsXPTCMiniVariant* dp = ¶mBuffer[i]; + + if (i == indexOfJSContext) { + if (nr_gpr < GPR_COUNT) + nr_gpr++; + else + ap++; + } + + if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { + if (nr_fpr < FPR_COUNT) { + dp->val.d = fpregs[nr_fpr++]; + } else if (nr_gpr < GPR_COUNT) { + memcpy(&dp->val.d, &gpregs[nr_gpr++], sizeof(dp->val.d)); + } else { + memcpy(&dp->val.d, ap++, sizeof(dp->val.d)); + } + continue; + } + + if (!param.IsOut() && type == nsXPTType::T_FLOAT) { + if (nr_fpr < FPR_COUNT) { + memcpy(&dp->val.f, &fpregs[nr_fpr++], sizeof(dp->val.f)); + } else if (nr_gpr < GPR_COUNT) { + memcpy(&dp->val.f, &gpregs[nr_gpr++], sizeof(dp->val.f)); + } else { + memcpy(&dp->val.f, ap++, sizeof(dp->val.f)); + } + continue; + } + + if (nr_gpr < GPR_COUNT) { + value = gpregs[nr_gpr++]; + } else { + value = *ap++; + } + + if (param.IsOut() || !type.IsArithmetic()) { + dp->val.p = (void*)value; + continue; + } + + switch (type) { + case nsXPTType::T_I8: + dp->val.i8 = (int8_t)value; + break; + case nsXPTType::T_I16: + dp->val.i16 = (int16_t)value; + break; + case nsXPTType::T_I32: + dp->val.i32 = (int32_t)value; + break; + case nsXPTType::T_I64: + dp->val.i64 = (int64_t)value; + break; + case nsXPTType::T_U8: + dp->val.u8 = (uint8_t)value; + break; + case nsXPTType::T_U16: + dp->val.u16 = (uint16_t)value; + break; + case nsXPTType::T_U32: + dp->val.u32 = (uint32_t)value; + break; + case nsXPTType::T_U64: + dp->val.u64 = (uint64_t)value; + break; + case nsXPTType::T_BOOL: + dp->val.b = (bool)(uint8_t)value; + break; + case nsXPTType::T_CHAR: + dp->val.c = (char)value; + break; + case nsXPTType::T_WCHAR: + dp->val.wc = (wchar_t)value; + break; + default: + NS_ERROR("bad type"); + break; + } + } + + nsresult result = self->mOuter->CallMethod((uint16_t)methodIndex, info, + paramBuffer); + return result; +} + +// Load $t6 with the constant 'n' and branch to SharedStub(). +// clang-format off +#define STUB_ENTRY(n) \ + __asm__( \ + ".text\n\t" \ + ".if "#n" < 10 \n\t" \ + ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".hidden _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ + "_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ + ".elseif "#n" < 100 \n\t" \ + ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".hidden _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ + "_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ + ".elseif "#n" < 1000 \n\t" \ + ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".hidden _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ + ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ + "_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ + ".else \n\t" \ + ".err \"stub number "#n" >= 1000 not yet supported\"\n" \ + ".endif \n\t" \ + "li.d $t6, "#n" \n\t" \ + "b SharedStub \n" \ + ".if "#n" < 10 \n\t" \ + ".size _ZN14nsXPTCStubBase5Stub"#n"Ev,.-_ZN14nsXPTCStubBase5Stub"#n"Ev\n\t" \ + ".elseif "#n" < 100 \n\t" \ + ".size _ZN14nsXPTCStubBase6Stub"#n"Ev,.-_ZN14nsXPTCStubBase6Stub"#n"Ev\n\t" \ + ".else \n\t" \ + ".size _ZN14nsXPTCStubBase7Stub"#n"Ev,.-_ZN14nsXPTCStubBase7Stub"#n"Ev\n\t" \ + ".endif" \ +); +// clang-format on + +#define SENTINEL_ENTRY(n) \ + nsresult nsXPTCStubBase::Sentinel##n() { \ + NS_ERROR("nsXPTCStubBase::Sentinel called"); \ + return NS_ERROR_NOT_IMPLEMENTED; \ + } + +#include "xptcstubsdef.inc" -- 2.39.1