diff -r cef565f1c325 -r 6cb1ac7cd223 mozilla-aarch64-bmo-963024.patch --- a/mozilla-aarch64-bmo-963024.patch Mon Apr 14 09:09:11 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,517 +0,0 @@ - -# HG changeset patch -# User Marcin Juszkiewicz -# Date 1393440196 18000 -# Node ID d56b5c1a557348d4ac14a4d1ea7a5b5d240e3647 -# Parent 6a46f53ad944b44385398822d7bcf7621a785d91 -Bug 963024 - AArch64 support for XPCOM. r=froydnj - -diff --git a/xpcom/reflect/xptcall/src/md/unix/moz.build b/xpcom/reflect/xptcall/src/md/unix/moz.build ---- a/xpcom/reflect/xptcall/src/md/unix/moz.build -+++ b/xpcom/reflect/xptcall/src/md/unix/moz.build -@@ -144,16 +144,23 @@ if CONFIG['OS_ARCH'] == 'NetBSD': - if CONFIG['OS_TEST'] in ('amiga', 'atari', 'hp300', 'mac68k', 'mvme68k', - 'next68k', 'sun3', 'sun3x', 'x68k'): - SOURCES += [ - 'xptcinvoke_netbsd_m68k.cpp', - 'xptcstubs_netbsd_m68k.cpp' - ] - - if CONFIG['OS_ARCH'] == 'Linux': -+ if CONFIG['OS_TEST'] == 'aarch64': -+ SOURCES += [ -+ 'xptcinvoke_aarch64.cpp', -+ 'xptcinvoke_asm_aarch64.s', -+ 'xptcstubs_aarch64.cpp', -+ 'xptcstubs_asm_aarch64.s', -+ ] - if CONFIG['OS_TEST'] == 'm68k': - SOURCES += [ - 'xptcinvoke_linux_m68k.cpp', - 'xptcstubs_linux_m68k.cpp', - ] - if CONFIG['OS_TEST'].find('mips') != -1: - if CONFIG['OS_TEST'].find('mips64') != -1: - SOURCES += [ -diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_aarch64.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_aarch64.cpp -new file mode 100644 ---- /dev/null -+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_aarch64.cpp -@@ -0,0 +1,136 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -+/* 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" -+ -+#if !defined(__aarch64__) -+#error "This code is for Linux AArch64 only." -+#endif -+ -+ -+/* "Procedure Call Standard for the ARM 64-bit Architecture" document, sections -+ * "5.4 Parameter Passing" and "6.1.2 Procedure Calling" contain all the -+ * needed information. -+ * -+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf -+ */ -+ -+#ifndef __AARCH64EL__ -+#error "Only little endian compatibility was tested" -+#endif -+ -+/* -+ * Allocation of integer function arguments initially to registers r1-r7 -+ * and then to stack. Handling of 'that' argument which goes to register r0 -+ * is handled separately and does not belong here. -+ * -+ * 'ireg_args' - pointer to the current position in the buffer, -+ * corresponding to the register arguments -+ * 'stack_args' - pointer to the current position in the buffer, -+ * corresponding to the arguments on stack -+ * 'end' - pointer to the end of the registers argument -+ * buffer. -+ */ -+static inline void alloc_word(uint64_t* &ireg_args, -+ uint64_t* &stack_args, -+ uint64_t* end, -+ uint64_t data) -+{ -+ if (ireg_args < end) { -+ *ireg_args = data; -+ ireg_args++; -+ } else { -+ *stack_args = data; -+ stack_args++; -+ } -+} -+ -+static inline void alloc_double(double* &freg_args, -+ uint64_t* &stack_args, -+ double* end, -+ double data) -+{ -+ if (freg_args < end) { -+ *freg_args = data; -+ freg_args++; -+ } else { -+ memcpy(stack_args, &data, sizeof(data)); -+ stack_args++; -+ } -+} -+ -+static inline void alloc_float(double* &freg_args, -+ uint64_t* &stack_args, -+ double* end, -+ float data) -+{ -+ if (freg_args < end) { -+ memcpy(freg_args, &data, sizeof(data)); -+ freg_args++; -+ } else { -+ memcpy(stack_args, &data, sizeof(data)); -+ stack_args++; -+ } -+} -+ -+ -+extern "C" void -+invoke_copy_to_stack(uint64_t* stk, uint64_t *end, -+ uint32_t paramCount, nsXPTCVariant* s) -+{ -+ uint64_t *ireg_args = stk; -+ uint64_t *ireg_end = ireg_args + 8; -+ double *freg_args = (double *)ireg_end; -+ double *freg_end = freg_args + 8; -+ uint64_t *stack_args = (uint64_t *)freg_end; -+ -+ // leave room for 'that' argument in x0 -+ ++ireg_args; -+ -+ for (uint32_t i = 0; i < paramCount; i++, s++) { -+ if (s->IsPtrData()) { -+ alloc_word(ireg_args, stack_args, ireg_end, (uint64_t)s->ptr); -+ continue; -+ } -+ // According to the ABI, integral types that are smaller than 8 bytes -+ // are to be passed in 8-byte registers or 8-byte stack slots. -+ switch (s->type) { -+ case nsXPTType::T_FLOAT: -+ alloc_float(freg_args, stack_args, freg_end, s->val.f); -+ break; -+ case nsXPTType::T_DOUBLE: -+ alloc_double(freg_args, stack_args, freg_end, s->val.d); -+ break; -+ case nsXPTType::T_I8: alloc_word(ireg_args, stk, end, s->val.i8); break; -+ case nsXPTType::T_I16: alloc_word(ireg_args, stk, end, s->val.i16); break; -+ case nsXPTType::T_I32: alloc_word(ireg_args, stk, end, s->val.i32); break; -+ case nsXPTType::T_I64: alloc_word(ireg_args, stk, end, s->val.i64); break; -+ case nsXPTType::T_U8: alloc_word(ireg_args, stk, end, s->val.u8); break; -+ case nsXPTType::T_U16: alloc_word(ireg_args, stk, end, s->val.u16); break; -+ case nsXPTType::T_U32: alloc_word(ireg_args, stk, end, s->val.u32); break; -+ case nsXPTType::T_U64: alloc_word(ireg_args, stk, end, s->val.u64); break; -+ case nsXPTType::T_BOOL: alloc_word(ireg_args, stk, end, s->val.b); break; -+ case nsXPTType::T_CHAR: alloc_word(ireg_args, stk, end, s->val.c); break; -+ case nsXPTType::T_WCHAR: alloc_word(ireg_args, stk, end, s->val.wc); break; -+ default: -+ // all the others are plain pointer types -+ alloc_word(ireg_args, stack_args, ireg_end, -+ reinterpret_cast(s->val.p)); -+ break; -+ } -+ } -+} -+ -+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/src/md/unix/xptcinvoke_asm_aarch64.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_aarch64.s -new file mode 100644 ---- /dev/null -+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_aarch64.s -@@ -0,0 +1,67 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -+/* 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/. */ -+ -+ .section ".text" -+ .globl _NS_InvokeByIndex -+ .type _NS_InvokeByIndex,@function -+ -+/* -+ * _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex, -+ * uint32_t paramCount, nsXPTCVariant* params) -+ */ -+ -+_NS_InvokeByIndex: -+ # set up frame -+ stp x29, x30, [sp,#-32]! -+ mov x29, sp -+ stp x19, x20, [sp,#16] -+ -+ # save methodIndex across function calls -+ mov w20, w1 -+ -+ # end of stack area passed to invoke_copy_to_stack -+ mov x1, sp -+ -+ # assume 8 bytes of stack for each argument with 16-byte alignment -+ add w19, w2, #1 -+ and w19, w19, #0xfffffffe -+ sub sp, sp, w19, uxth #3 -+ -+ # temporary place to store args passed in r0-r7,v0-v7 -+ sub sp, sp, #128 -+ -+ # save 'that' on stack -+ str x0, [sp] -+ -+ # start of stack area passed to invoke_copy_to_stack -+ mov x0, sp -+ bl invoke_copy_to_stack -+ -+ # load arguments passed in r0-r7 -+ ldp x6, x7, [sp, #48] -+ ldp x4, x5, [sp, #32] -+ ldp x2, x3, [sp, #16] -+ ldp x0, x1, [sp],#64 -+ -+ # load arguments passed in v0-v7 -+ ldp d6, d7, [sp, #48] -+ ldp d4, d5, [sp, #32] -+ ldp d2, d3, [sp, #16] -+ ldp d0, d1, [sp],#64 -+ -+ # call the method -+ ldr x16, [x0] -+ add x16, x16, w20, uxth #3 -+ ldr x16, [x16] -+ blr x16 -+ -+ add sp, sp, w19, uxth #3 -+ ldp x19, x20, [sp,#16] -+ ldp x29, x30, [sp],#32 -+ ret -+ -+ .size _NS_InvokeByIndex, . - _NS_InvokeByIndex -+ -+ -diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcstubs_aarch64.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcstubs_aarch64.cpp -new file mode 100644 ---- /dev/null -+++ b/xpcom/reflect/xptcall/src/md/unix/xptcstubs_aarch64.cpp -@@ -0,0 +1,219 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -+/* 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" -+#include "xptiprivate.h" -+ -+#ifndef __AARCH64EL__ -+#error "Only little endian compatibility was tested" -+#endif -+ -+/* -+ * This is for AArch64 ABI -+ * -+ * When we're called, the "gp" registers are stored in gprData and -+ * the "fp" registers are stored in fprData. Each array has 8 regs -+ * but first reg in gprData is a placeholder for 'self'. -+ */ -+extern "C" nsresult -+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args, -+ uint64_t *gprData, double *fprData) -+{ -+#define PARAM_BUFFER_COUNT 16 -+#define PARAM_GPR_COUNT 8 -+#define PARAM_FPR_COUNT 8 -+ -+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; -+ nsXPTCMiniVariant* dispatchParams = NULL; -+ const nsXPTMethodInfo* info; -+ nsresult result = NS_ERROR_FAILURE; -+ -+ NS_ASSERTION(self,"no self"); -+ -+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); -+ NS_ASSERTION(info,"no method info"); -+ -+ uint32_t paramCount = info->GetParamCount(); -+ -+ // setup variant array pointer -+ if (paramCount > PARAM_BUFFER_COUNT) { -+ dispatchParams = new nsXPTCMiniVariant[paramCount]; -+ } else { -+ dispatchParams = paramBuffer; -+ } -+ NS_ASSERTION(dispatchParams,"no place for params"); -+ -+ uint64_t* ap = args; -+ uint32_t next_gpr = 1; // skip first arg which is 'self' -+ uint32_t next_fpr = 0; -+ for (uint32_t i = 0; i < paramCount; i++) { -+ const nsXPTParamInfo& param = info->GetParam(i); -+ const nsXPTType& type = param.GetType(); -+ nsXPTCMiniVariant* dp = &dispatchParams[i]; -+ -+ if (param.IsOut() || !type.IsArithmetic()) { -+ if (next_gpr < PARAM_GPR_COUNT) { -+ dp->val.p = (void*)gprData[next_gpr++]; -+ } else { -+ dp->val.p = (void*)*ap++; -+ } -+ continue; -+ } -+ -+ switch (type) { -+ case nsXPTType::T_I8: -+ if (next_gpr < PARAM_GPR_COUNT) { -+ dp->val.i8 = (int8_t)gprData[next_gpr++]; -+ } else { -+ dp->val.i8 = (int8_t)*ap++; -+ } -+ break; -+ -+ case nsXPTType::T_I16: -+ if (next_gpr < PARAM_GPR_COUNT) { -+ dp->val.i16 = (int16_t)gprData[next_gpr++]; -+ } else { -+ dp->val.i16 = (int16_t)*ap++; -+ } -+ break; -+ -+ case nsXPTType::T_I32: -+ if (next_gpr < PARAM_GPR_COUNT) { -+ dp->val.i32 = (int32_t)gprData[next_gpr++]; -+ } else { -+ dp->val.i32 = (int32_t)*ap++; -+ } -+ break; -+ -+ case nsXPTType::T_I64: -+ if (next_gpr < PARAM_GPR_COUNT) { -+ dp->val.i64 = (int64_t)gprData[next_gpr++]; -+ } else { -+ dp->val.i64 = (int64_t)*ap++; -+ } -+ break; -+ -+ case nsXPTType::T_U8: -+ if (next_gpr < PARAM_GPR_COUNT) { -+ dp->val.u8 = (uint8_t)gprData[next_gpr++]; -+ } else { -+ dp->val.u8 = (uint8_t)*ap++; -+ } -+ break; -+ -+ case nsXPTType::T_U16: -+ if (next_gpr < PARAM_GPR_COUNT) { -+ dp->val.u16 = (uint16_t)gprData[next_gpr++]; -+ } else { -+ dp->val.u16 = (uint16_t)*ap++; -+ } -+ break; -+ -+ case nsXPTType::T_U32: -+ if (next_gpr < PARAM_GPR_COUNT) { -+ dp->val.u32 = (uint32_t)gprData[next_gpr++]; -+ } else { -+ dp->val.u32 = (uint32_t)*ap++; -+ } -+ break; -+ -+ case nsXPTType::T_U64: -+ if (next_gpr < PARAM_GPR_COUNT) { -+ dp->val.u64 = (uint64_t)gprData[next_gpr++]; -+ } else { -+ dp->val.u64 = (uint64_t)*ap++; -+ } -+ break; -+ -+ case nsXPTType::T_FLOAT: -+ if (next_fpr < PARAM_FPR_COUNT) { -+ memcpy(&dp->val.f, &fprData[next_fpr++], sizeof(dp->val.f)); -+ } else { -+ memcpy(&dp->val.f, ap++, sizeof(dp->val.f)); -+ } -+ break; -+ -+ case nsXPTType::T_DOUBLE: -+ if (next_fpr < PARAM_FPR_COUNT) { -+ memcpy(&dp->val.d, &fprData[next_fpr++], sizeof(dp->val.d)); -+ } else { -+ memcpy(&dp->val.d, ap++, sizeof(dp->val.d)); -+ } -+ break; -+ -+ case nsXPTType::T_BOOL: -+ if (next_gpr < PARAM_GPR_COUNT) { -+ dp->val.b = (bool)gprData[next_gpr++]; -+ } else { -+ dp->val.b = (bool)*ap++; -+ } -+ break; -+ -+ case nsXPTType::T_CHAR: -+ if (next_gpr < PARAM_GPR_COUNT) { -+ dp->val.c = (char)gprData[next_gpr++]; -+ } else { -+ dp->val.c = (char)*ap++; -+ } -+ break; -+ -+ case nsXPTType::T_WCHAR: -+ if (next_gpr < PARAM_GPR_COUNT) { -+ dp->val.wc = (wchar_t)gprData[next_gpr++]; -+ } else { -+ dp->val.wc = (wchar_t)*ap++; -+ } -+ break; -+ -+ default: -+ NS_ASSERTION(0, "bad type"); -+ break; -+ } -+ } -+ -+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); -+ -+ if (dispatchParams != paramBuffer) { -+ delete [] dispatchParams; -+ } -+ -+ return result; -+} -+ -+// Load w17 with the constant 'n' and branch to SharedStub(). -+# define STUB_ENTRY(n) \ -+ __asm__ ( \ -+ ".section \".text\" \n\t" \ -+ ".align 2\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" \ -+ "mov w17,#"#n" \n\t" \ -+ "b SharedStub \n" \ -+); -+ -+#define SENTINEL_ENTRY(n) \ -+ nsresult nsXPTCStubBase::Sentinel##n() \ -+{ \ -+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \ -+ return NS_ERROR_NOT_IMPLEMENTED; \ -+} -+ -+#include "xptcstubsdef.inc" -diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_aarch64.s b/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_aarch64.s -new file mode 100644 ---- /dev/null -+++ b/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_aarch64.s -@@ -0,0 +1,39 @@ -+# 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/. -+ -+ .set NGPREGS,8 -+ .set NFPREGS,8 -+ -+ .section ".text" -+ .globl SharedStub -+ .hidden SharedStub -+ .type SharedStub,@function -+SharedStub: -+ stp x29, x30, [sp,#-16]! -+ mov x29, sp -+ -+ sub sp, sp, #8*(NGPREGS+NFPREGS) -+ stp x0, x1, [sp, #64+(0*8)] -+ stp x2, x3, [sp, #64+(2*8)] -+ stp x4, x5, [sp, #64+(4*8)] -+ stp x6, x7, [sp, #64+(6*8)] -+ stp d0, d1, [sp, #(0*8)] -+ stp d2, d3, [sp, #(2*8)] -+ stp d4, d5, [sp, #(4*8)] -+ stp d6, d7, [sp, #(6*8)] -+ -+ # methodIndex passed from stub -+ mov w1, w17 -+ -+ add x2, sp, #16+(8*(NGPREGS+NFPREGS)) -+ add x3, sp, #8*NFPREGS -+ add x4, sp, #0 -+ -+ bl PrepareAndDispatch -+ -+ add sp, sp, #8*(NGPREGS+NFPREGS) -+ ldp x29, x30, [sp],#16 -+ ret -+ -+ .size SharedStub, . - SharedStub -