summaryrefslogtreecommitdiff
path: root/xpcom/reflect/xptcall/md
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/reflect/xptcall/md')
-rw-r--r--xpcom/reflect/xptcall/md/moz.build12
-rw-r--r--xpcom/reflect/xptcall/md/test/README6
-rwxr-xr-xxpcom/reflect/xptcall/md/test/clean.bat5
-rw-r--r--xpcom/reflect/xptcall/md/test/invoke_test.cpp207
-rwxr-xr-xxpcom/reflect/xptcall/md/test/mk_invoke.bat9
-rwxr-xr-xxpcom/reflect/xptcall/md/test/mk_stub.bat9
-rw-r--r--xpcom/reflect/xptcall/md/test/moz.build9
-rw-r--r--xpcom/reflect/xptcall/md/test/stub_test.cpp213
-rw-r--r--xpcom/reflect/xptcall/md/unix/Makefile.in79
-rw-r--r--xpcom/reflect/xptcall/md/unix/moz.build327
-rw-r--r--xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp66
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h17
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp140
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp144
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp417
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp181
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp183
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.s67
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s145
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s146
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S134
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S122
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s131
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s108
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S167
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s129
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s128
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s124
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S98
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_netbsd.s95
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S94
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s142
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s86
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s53
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s55
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s55
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s52
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s56
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s85
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s55
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp16
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp97
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp132
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp100
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp144
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_m68k.cpp130
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp195
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp190
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp99
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp142
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_netbsd_m68k.cpp143
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp149
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp97
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp74
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp63
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp128
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_netbsd.cpp115
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp109
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp113
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp69
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp131
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp128
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp131
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparcv9_solaris.cpp73
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp149
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp188
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp67
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp219
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp189
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp238
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp113
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp205
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.s39
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s123
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s124
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S116
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m475
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S111
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s68
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s73
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S112
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4119
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m497
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4114
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S77
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_netbsd.s70
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S72
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s50
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s49
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s49
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s49
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparcv9_solaris.s50
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_64_solaris_SUNW.s63
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_solaris_SUNW.s78
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp16
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp139
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp151
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp154
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp187
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_linux_m68k.cpp98
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp183
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp187
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp112
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp185
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_netbsd_m68k.cpp115
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp143
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp246
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp185
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp172
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp220
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_netbsd.cpp185
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp202
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp165
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp104
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp117
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp120
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp112
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparcv9_solaris.cpp101
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp190
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp204
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_solaris.cpp139
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_x86_solaris.cpp77
-rw-r--r--xpcom/reflect/xptcall/md/win32/moz.build45
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp45
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm107
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s110
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm63
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp59
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp106
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs.cpp227
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm335
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp197
-rw-r--r--xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp297
133 files changed, 16065 insertions, 0 deletions
diff --git a/xpcom/reflect/xptcall/md/moz.build b/xpcom/reflect/xptcall/md/moz.build
new file mode 100644
index 0000000000..a4b59aaf00
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/moz.build
@@ -0,0 +1,12 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+arch = CONFIG['OS_ARCH']
+
+if arch == 'WINNT':
+ DIRS += ['win32']
+else:
+ DIRS += ['unix']
diff --git a/xpcom/reflect/xptcall/md/test/README b/xpcom/reflect/xptcall/md/test/README
new file mode 100644
index 0000000000..04850b2e01
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/README
@@ -0,0 +1,6 @@
+These are just simple test programs in which stripped down versions of the
+XPConnect invoke and stubs code can be built and tested as the code is brought
+up on various platforms. These probrams do not test the param sizing and copying
+functionality of the routines. However, they do supply a place where the lowest
+level assembly language code can be developed and debugged in the simplest of
+contexts before it is moved into the real routines. \ No newline at end of file
diff --git a/xpcom/reflect/xptcall/md/test/clean.bat b/xpcom/reflect/xptcall/md/test/clean.bat
new file mode 100755
index 0000000000..f320e222c9
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/clean.bat
@@ -0,0 +1,5 @@
+@echo off
+echo deleting intermediate files
+if exist *.obj del *.obj > NUL
+if exist *.ilk del *.ilk > NUL
+if exist *.pdb del *.pdb > NUL \ No newline at end of file
diff --git a/xpcom/reflect/xptcall/md/test/invoke_test.cpp b/xpcom/reflect/xptcall/md/test/invoke_test.cpp
new file mode 100644
index 0000000000..068db8b2fd
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/invoke_test.cpp
@@ -0,0 +1,207 @@
+/* -*- Mode: C; tab-width: 4; 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 <stdio.h>
+
+typedef unsigned nsresult;
+typedef unsigned uint32_t;
+typedef unsigned nsXPCVariant;
+
+
+#if defined(WIN32)
+#define NS_IMETHOD virtual nsresult __stdcall
+#define NS_IMETHODIMP nsresult __stdcall
+#else
+#define NS_IMETHOD virtual nsresult
+#define NS_IMETHODIMP nsresult
+#endif
+
+
+class base{
+public:
+ NS_IMETHOD ignored() = 0;
+};
+
+class foo : public base {
+public:
+ NS_IMETHOD callme1(int i, int j) = 0;
+ NS_IMETHOD callme2(int i, int j) = 0;
+ NS_IMETHOD callme3(int i, int j) = 0;
+};
+
+class bar : public foo{
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1(int i, int j);
+ NS_IMETHOD callme2(int i, int j);
+ NS_IMETHOD callme3(int i, int j);
+};
+
+/*
+class baz : public base {
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1();
+ NS_IMETHOD callme2();
+ NS_IMETHOD callme3();
+ void setfoo(foo* f) {other = f;}
+
+ foo* other;
+};
+NS_IMETHODIMP baz::ignored(){return 0;}
+*/
+
+NS_IMETHODIMP bar::ignored(){return 0;}
+
+NS_IMETHODIMP bar::callme1(int i, int j)
+{
+ printf("called bar::callme1 with: %d %d\n", i, j);
+ return 5;
+}
+
+NS_IMETHODIMP bar::callme2(int i, int j)
+{
+ printf("called bar::callme2 with: %d %d\n", i, j);
+ return 5;
+}
+
+NS_IMETHODIMP bar::callme3(int i, int j)
+{
+ printf("called bar::callme3 with: %d %d\n", i, j);
+ return 5;
+}
+
+void docall(foo* f, int i, int j){
+ f->callme1(i, j);
+}
+
+/***************************************************************************/
+#if defined(WIN32)
+
+static uint32_t __stdcall
+invoke_count_words(uint32_t paramCount, nsXPCVariant* s)
+{
+ return paramCount;
+}
+
+static void __stdcall
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPCVariant* s)
+{
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ *((uint32_t*)d) = *((uint32_t*)s);
+ }
+}
+
+static nsresult __stdcall
+DoInvoke(void* that, uint32_t index,
+ uint32_t paramCount, nsXPCVariant* params)
+{
+ __asm {
+ push params
+ push paramCount
+ call invoke_count_words // stdcall, result in eax
+ shl eax,2 // *= 4
+ sub esp,eax // make space for params
+ mov edx,esp
+ push params
+ push paramCount
+ push edx
+ call invoke_copy_to_stack // stdcall
+ mov ecx,that // instance in ecx
+ push ecx // push this
+ mov edx,[ecx] // vtable in edx
+ mov eax,index
+ shl eax,2 // *= 4
+ add edx,eax
+ call [edx] // stdcall, i.e. callee cleans up stack.
+ }
+}
+
+#else
+/***************************************************************************/
+// just Linux_x86 now. Add other later...
+
+static uint32_t
+invoke_count_words(uint32_t paramCount, nsXPCVariant* s)
+{
+ return paramCount;
+}
+
+static void
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPCVariant* s)
+{
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ *((uint32_t*)d) = *((uint32_t*)s);
+ }
+}
+
+static nsresult
+DoInvoke(void* that, uint32_t index,
+ uint32_t paramCount, nsXPCVariant* params)
+{
+ uint32_t result;
+ void* fn_count = invoke_count_words;
+ void* fn_copy = invoke_copy_to_stack;
+
+ __asm__ __volatile__(
+ "pushl %4\n\t"
+ "pushl %3\n\t"
+ "movl %5, %%eax\n\t"
+ "call *%%eax\n\t" /* count words */
+ "addl $0x8, %%esp\n\t"
+ "shl $2, %%eax\n\t" /* *= 4 */
+ "subl %%eax, %%esp\n\t" /* make room for params */
+ "movl %%esp, %%edx\n\t"
+ "pushl %4\n\t"
+ "pushl %3\n\t"
+ "pushl %%edx\n\t"
+ "movl %6, %%eax\n\t"
+ "call *%%eax\n\t" /* copy params */
+ "addl $0xc, %%esp\n\t"
+ "movl %1, %%ecx\n\t"
+ "pushl %%ecx\n\t"
+ "movl (%%ecx), %%edx\n\t"
+ "movl %2, %%eax\n\t" /* function index */
+ "shl $2, %%eax\n\t" /* *= 4 */
+ "addl $8, %%eax\n\t" /* += 8 */
+ "addl %%eax, %%edx\n\t"
+ "call *(%%edx)\n\t" /* safe to not cleanup esp */
+ "movl %%eax, %0"
+ : "=g" (result) /* %0 */
+ : "g" (that), /* %1 */
+ "g" (index), /* %2 */
+ "g" (paramCount), /* %3 */
+ "g" (params), /* %4 */
+ "g" (fn_count), /* %5 */
+ "g" (fn_copy) /* %6 */
+ : "ax", "cx", "dx", "memory"
+ );
+
+ return result;
+}
+
+#endif
+/***************************************************************************/
+
+int main()
+{
+ nsXPCVariant params1[2] = {1,2};
+ nsXPCVariant params2[2] = {2,4};
+ nsXPCVariant params3[2] = {3,6};
+
+ foo* a = new bar();
+
+// printf("calling via C++...\n");
+// docall(a, 12, 24);
+
+ printf("calling via ASM...\n");
+ DoInvoke(a, 1, 2, params1);
+ DoInvoke(a, 2, 2, params2);
+ DoInvoke(a, 3, 2, params3);
+
+ return 0;
+}
diff --git a/xpcom/reflect/xptcall/md/test/mk_invoke.bat b/xpcom/reflect/xptcall/md/test/mk_invoke.bat
new file mode 100755
index 0000000000..10a9be51de
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/mk_invoke.bat
@@ -0,0 +1,9 @@
+@echo off
+@echo deleing old output
+if exist invoke_test.obj del invoke_test.obj > NUL
+if exist invoke_test.ilk del invoke_test.ilk > NUL
+if exist *.pdb del *.pdb > NUL
+if exist invoke_test.exe del invoke_test.exe > NUL
+
+@echo building...
+cl /nologo -Zi -DWIN32 invoke_test.cpp \ No newline at end of file
diff --git a/xpcom/reflect/xptcall/md/test/mk_stub.bat b/xpcom/reflect/xptcall/md/test/mk_stub.bat
new file mode 100755
index 0000000000..f9af17affe
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/mk_stub.bat
@@ -0,0 +1,9 @@
+@echo off
+@echo deleing old output
+if exist stub_test.obj del stub_test.obj > NUL
+if exist stub_test.ilk del stub_test.ilk > NUL
+if exist *.pdb del *.pdb > NUL
+if exist stub_test.exe del stub_test.exe > NUL
+
+@echo building...
+cl /nologo -Zi -DWIN32 stub_test.cpp \ No newline at end of file
diff --git a/xpcom/reflect/xptcall/md/test/moz.build b/xpcom/reflect/xptcall/md/test/moz.build
new file mode 100644
index 0000000000..2261c3ce61
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/moz.build
@@ -0,0 +1,9 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+SimplePrograms([
+ 'stub_test',
+])
diff --git a/xpcom/reflect/xptcall/md/test/stub_test.cpp b/xpcom/reflect/xptcall/md/test/stub_test.cpp
new file mode 100644
index 0000000000..6c9559c656
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/test/stub_test.cpp
@@ -0,0 +1,213 @@
+/* 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 <stdio.h>
+
+typedef unsigned nsresult;
+typedef unsigned uint32_t;
+typedef unsigned nsXPCVariant;
+
+
+#if defined(WIN32)
+#define NS_IMETHOD virtual nsresult __stdcall
+#define NS_IMETHODIMP nsresult __stdcall
+#else
+#define NS_IMETHOD virtual nsresult
+#define NS_IMETHODIMP nsresult
+#endif
+
+
+class base{
+public:
+ NS_IMETHOD ignored() = 0;
+};
+
+class foo : public base {
+public:
+ NS_IMETHOD callme1(int i, int j) = 0;
+ NS_IMETHOD callme2(int i, int j) = 0;
+ NS_IMETHOD callme3(int i, int j) = 0;
+};
+
+class bar : public foo{
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1(int i, int j);
+ NS_IMETHOD callme2(int i, int j);
+ NS_IMETHOD callme3(int i, int j);
+};
+
+class baz : public base {
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1();
+ NS_IMETHOD callme2();
+ NS_IMETHOD callme3();
+ void setfoo(foo* f) {other = f;}
+
+ foo* other;
+};
+NS_IMETHODIMP baz::ignored(){return 0;}
+
+NS_IMETHODIMP bar::ignored(){return 0;}
+
+NS_IMETHODIMP bar::callme1(int i, int j)
+{
+ printf("called bar::callme1 with: %d %d\n", i, j);
+ return 15;
+}
+
+NS_IMETHODIMP bar::callme2(int i, int j)
+{
+ printf("called bar::callme2 with: %d %d\n", i, j);
+ return 25;
+}
+
+NS_IMETHODIMP bar::callme3(int i, int j)
+{
+ printf("called bar::callme3 with: %d %d\n", i, j);
+ return 35;
+}
+
+void docall(foo* f, int i, int j){
+ f->callme1(i, j);
+}
+
+/***************************************************************************/
+#if defined(WIN32)
+
+static int __stdcall
+PrepareAndDispatch(baz* self, uint32_t methodIndex,
+ uint32_t* args, uint32_t* stackBytesToPop)
+{
+ fprintf(stdout, "PrepareAndDispatch (%p, %d, %p)\n",
+ (void*)self, methodIndex, (void*)args);
+ foo* a = self->other;
+ int p1 = (int) *args;
+ int p2 = (int) *(args+1);
+ int out = 0;
+ switch(methodIndex)
+ {
+ case 1: out = a->callme1(p1, p2); break;
+ case 2: out = a->callme2(p1, p2); break;
+ case 3: out = a->callme3(p1, p2); break;
+ }
+ *stackBytesToPop = 2*4;
+ return out;
+}
+
+#ifndef __GNUC__
+static __declspec(naked) void SharedStub(void)
+{
+ __asm {
+ push ebp // set up simple stack frame
+ mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args
+ push ecx // make room for a ptr
+ lea eax, [ebp-4] // pointer to stackBytesToPop
+ push eax
+ lea ecx, [ebp+16] // pointer to args
+ push ecx
+ mov edx, [ebp+4] // vtbl_index
+ push edx
+ mov eax, [ebp+12] // this
+ push eax
+ call PrepareAndDispatch
+ mov edx, [ebp+8] // return address
+ mov ecx, [ebp-4] // stackBytesToPop
+ add ecx, 12 // for this, the index, and ret address
+ mov esp, ebp
+ pop ebp
+ add esp, ecx // fix up stack pointer
+ jmp edx // simulate __stdcall return
+ }
+}
+
+// these macros get expanded (many times) in the file #included below
+#define STUB_ENTRY(n) \
+__declspec(naked) nsresult __stdcall baz::callme##n() \
+{ __asm push n __asm jmp SharedStub }
+
+#else /* __GNUC__ */
+
+#define STUB_ENTRY(n) \
+nsresult __stdcall baz::callme##n() \
+{ \
+ uint32_t *args, stackBytesToPop; \
+ int result = 0; \
+ baz *obj; \
+ __asm__ __volatile__ ( \
+ "leal 0x0c(%%ebp), %0\n\t" /* args */ \
+ "movl 0x08(%%ebp), %1\n\t" /* this */ \
+ : "=r" (args), \
+ "=r" (obj)); \
+ result = PrepareAndDispatch(obj, n, args,&stackBytesToPop); \
+ fprintf(stdout, "stub returning: %d\n", result); \
+ fprintf(stdout, "bytes to pop: %d\n", stackBytesToPop); \
+ return result; \
+}
+
+#endif /* ! __GNUC__ */
+
+#else
+/***************************************************************************/
+// just Linux_x86 now. Add other later...
+
+static int
+PrepareAndDispatch(baz* self, uint32_t methodIndex, uint32_t* args)
+{
+ foo* a = self->other;
+ int p1 = (int) *args;
+ int p2 = (int) *(args+1);
+ switch(methodIndex)
+ {
+ case 1: a->callme1(p1, p2); break;
+ case 2: a->callme2(p1, p2); break;
+ case 3: a->callme3(p1, p2); break;
+ }
+ return 1;
+}
+
+#define STUB_ENTRY(n) \
+nsresult baz::callme##n() \
+{ \
+ void* method = PrepareAndDispatch; \
+ nsresult result; \
+ __asm__ __volatile__( \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "pushl %%ecx\n\t" \
+ "pushl $"#n"\n\t" /* method index */ \
+ "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \
+ "pushl %%ecx\n\t" \
+ "call *%%edx" /* PrepareAndDispatch */ \
+ : "=a" (result) /* %0 */ \
+ : "d" (method) /* %1 */ \
+ : "memory" ); \
+ return result; \
+}
+
+#endif
+/***************************************************************************/
+
+STUB_ENTRY(1)
+STUB_ENTRY(2)
+STUB_ENTRY(3)
+
+int main()
+{
+ foo* a = new bar();
+ baz* b = new baz();
+
+ /* here we make the global 'check for alloc failure' checker happy */
+ if(!a || !b)
+ return 1;
+
+ foo* c = (foo*)b;
+
+ b->setfoo(a);
+ c->callme1(1,2);
+ c->callme2(2,4);
+ c->callme3(3,6);
+
+ return 0;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/Makefile.in b/xpcom/reflect/xptcall/md/unix/Makefile.in
new file mode 100644
index 0000000000..e4cdc389bb
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/Makefile.in
@@ -0,0 +1,79 @@
+#
+# 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/.
+
+######################################################################
+# HPPA
+######################################################################
+#
+# HP-UX/PA32
+#
+# for gas and gcc, check comment in xptcinvoke_asm_pa32.s
+ifeq ($(OS_ARCH),HP-UX)
+ifneq ($(CC),gcc)
+# #18875 Building the CPP's (CXX) optimized causes a crash
+CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS))
+endif
+endif
+
+#
+# Linux/HPPA/gcc
+#
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(filter hppa hppa2.0 hppa1.1,$(OS_TEST)))
+ifndef GNU_CXX
+else
+# #434190 optimized builds crash
+CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS))
+endif
+endif
+endif
+
+
+######################################################################
+# PowerPC
+######################################################################
+#
+# AIX/PPC
+#
+ifeq ($(OS_ARCH),AIX)
+# #24617 Building the CPP's (CXX) optimized causes a crash
+CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS))
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(findstring mips, $(OS_TEST)))
+xptcstubs_asm_mips.o: $(DIST)/include/xptcstubsdef.inc
+endif
+endif
+
+ifeq ($(OS_ARCH),Darwin)
+xptcstubs_asm_ppc_darwin.s: xptcstubs_asm_ppc_darwin.s.m4 $(DIST)/include/xptcstubsdef.inc Makefile
+ gm4 $(INCLUDES) $< > $@
+endif
+
+ifeq ($(OS_ARCH),AIX)
+ifdef HAVE_64BIT_BUILD
+xptcstubs_asm_ppc_aix64.s: xptcstubs_asm_ppc_aix64.s.m4 $(DIST)/include/xptcstubsdef.inc Makefile
+ m4 -DAIX_OBJMODEL=$(AIX_OBJMODEL) $(INCLUDES) -I. $< > $@
+else
+xptcstubs_asm_ppc_aix.s: xptcstubs_asm_ppc_aix.s.m4 $(DIST)/include/xptcstubsdef.inc Makefile
+ m4 -DAIX_OBJMODEL=$(AIX_OBJMODEL) $(INCLUDES) -I. $< > $@
+endif
+endif
+
+ifeq ($(OS_ARCH),SunOS)
+ifeq (86,$(findstring 86,$(OS_TEST)))
+ifndef GNU_CC
+xptcstubsdef_asm.solx86: $(DIST)/include/xptcstubsdef.inc
+ sed \
+ -e 's/^\(STUB_ENTRY\)(\([0-9]\))/\11\(\2\)/' \
+ -e 's/^\(STUB_ENTRY\)(\([0-9][0-9]\))/\12\(\2\)/' \
+ -e 's/^\(STUB_ENTRY\)(\([0-9][0-9][0-9]\))/\13\(\2\)/' \
+ $(DIST)/include/xptcstubsdef.inc > $@
+endif
+endif
+endif
diff --git a/xpcom/reflect/xptcall/md/unix/moz.build b/xpcom/reflect/xptcall/md/unix/moz.build
new file mode 100644
index 0000000000..1d182bbd6f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/moz.build
@@ -0,0 +1,327 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+if CONFIG['OS_ARCH'] == 'Darwin':
+ SOURCES += [
+ 'xptcinvoke_darwin.cpp',
+ 'xptcstubs_darwin.cpp',
+ ]
+ if CONFIG['OS_TEST'] == 'powerpc':
+ SOURCES += [
+ '!xptcstubs_asm_ppc_darwin.s',
+ 'xptcinvoke_asm_ppc_rhapsody.s',
+ ]
+ if '86' in CONFIG['OS_TEST'] and CONFIG['OS_TEST'] != 'x86_64':
+ DEFINES['MOZ_NEED_LEADING_UNDERSCORE'] = True
+
+if CONFIG['OS_ARCH'] == 'GNU':
+ if CONFIG['CPU_ARCH'] == 'x86':
+ SOURCES += [
+ 'xptcinvoke_gcc_x86_unix.cpp',
+ 'xptcstubs_gcc_x86_unix.cpp'
+ ]
+
+if CONFIG['OS_ARCH'] in ('Linux', 'Bitrig', 'DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD') or \
+ CONFIG['OS_ARCH'].startswith('GNU_'):
+ if CONFIG['OS_TEST'] == 'x86_64':
+ SOURCES += [
+ 'xptcinvoke_x86_64_unix.cpp',
+ 'xptcstubs_x86_64_linux.cpp',
+ ]
+ elif '86' in CONFIG['OS_TEST']:
+ SOURCES += [
+ 'xptcinvoke_gcc_x86_unix.cpp',
+ 'xptcstubs_gcc_x86_unix.cpp'
+ ]
+
+if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'):
+ if 'ia64' in CONFIG['OS_TEST']:
+ SOURCES += [
+ 'xptcinvoke_asm_ipf64.s',
+ 'xptcinvoke_ipf64.cpp',
+ 'xptcstubs_asm_ipf64.s',
+ 'xptcstubs_ipf64.cpp'
+ ]
+
+if CONFIG['OS_ARCH'] == 'SunOS' and '86' in CONFIG['OS_TEST']:
+ GENERATED_FILES = [
+ 'xptcstubsdef_asm.solx86',
+ ]
+ if CONFIG['OS_TEST'] == 'x86_64':
+ if CONFIG['GNU_CC']:
+ SOURCES += [
+ 'xptcinvoke_x86_64_unix.cpp',
+ 'xptcstubs_x86_64_linux.cpp'
+ ]
+ else:
+ ASFLAGS += ['-xarch=amd64']
+ SOURCES += [
+ 'xptcinvoke_x86_64_solaris.cpp',
+ 'xptcstubs_asm_x86_64_solaris_SUNW.s',
+ 'xptcstubs_x86_64_solaris.cpp',
+ ]
+ else:
+ if CONFIG['GNU_CC']:
+ SOURCES += [
+ 'xptcinvoke_gcc_x86_unix.cpp',
+ 'xptcstubs_gcc_x86_unix.cpp'
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke_asm_x86_solaris_SUNW.s',
+ 'xptcinvoke_x86_solaris.cpp',
+ 'xptcstubs_asm_x86_solaris_SUNW.s',
+ 'xptcstubs_x86_solaris.cpp'
+ ]
+
+if CONFIG['OS_TEST'] == 'alpha':
+ if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD', 'NetBSD'):
+ SOURCES += [
+ 'xptcinvoke_linux_alpha.cpp',
+ 'xptcstubs_linux_alpha.cpp',
+ ]
+ elif CONFIG['OS_ARCH'] == 'OpenBSD':
+ SOURCES += [
+ 'xptcinvoke_alpha_openbsd.cpp',
+ 'xptcstubs_alpha_openbsd.cpp',
+ ]
+
+if CONFIG['CPU_ARCH'] == 'arm' or CONFIG['OS_TEST'] == 'sa110':
+ if CONFIG['OS_ARCH'] == 'Linux':
+ SOURCES += [
+ 'xptcinvoke_arm.cpp',
+ 'xptcstubs_arm.cpp'
+ ]
+ CXXFLAGS += ['-O2']
+ elif CONFIG['OS_ARCH'] == 'NetBSD':
+ SOURCES += [
+ 'xptcinvoke_arm_netbsd.cpp',
+ 'xptcstubs_arm_netbsd.cpp',
+ ]
+
+if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['OS_ARCH'] in ('Bitrig', 'OpenBSD'):
+ SOURCES += [
+ 'xptcinvoke_arm_openbsd.cpp',
+ 'xptcstubs_arm_openbsd.cpp',
+ ]
+
+if CONFIG['OS_ARCH'] == 'HP-UX':
+ if CONFIG['CC'] != 'gcc':
+ if CONFIG['OS_TEST'] == 'ia64':
+ SOURCES += [
+ 'xptcinvoke_asm_ipf32.s',
+ 'xptcinvoke_ipf32.cpp',
+ 'xptcstubs_asm_ipf32.s',
+ 'xptcstubs_ipf32.cpp',
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke_asm_pa32.s',
+ 'xptcinvoke_pa32.cpp',
+ 'xptcstubs_asm_pa32.s',
+ 'xptcstubs_pa32.cpp'
+ ]
+
+if CONFIG['OS_ARCH'] == 'Linux':
+ if CONFIG['OS_TEST'] in ('hppa', 'hppa2.0', 'hppa1.1'):
+ if CONFIG['GNU_CXX']:
+ SOURCES += [
+ 'xptcinvoke_asm_parisc_linux.s',
+ 'xptcinvoke_pa32.cpp',
+ 'xptcstubs_asm_parisc_linux.s',
+ 'xptcstubs_pa32.cpp',
+ ]
+ elif CONFIG['COMPILE_ENVIRONMENT']:
+ error('Unknown C++ compiler, xptcall assembly will probably be incorrect.')
+
+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'] in ('Linux', 'FreeBSD', 'NetBSD', 'OpenBSD'):
+ 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 'mips' in CONFIG['OS_TEST']:
+ if 'mips64' in CONFIG['OS_TEST']:
+ SOURCES += [
+ 'xptcinvoke_asm_mips64.S',
+ 'xptcinvoke_mips64.cpp',
+ 'xptcstubs_asm_mips64.S',
+ 'xptcstubs_mips64.cpp',
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke_asm_mips.S',
+ 'xptcinvoke_mips.cpp',
+ 'xptcstubs_asm_mips.S',
+ 'xptcstubs_mips.cpp',
+ ]
+
+if CONFIG['OS_ARCH'] == 'AIX':
+ if CONFIG['HAVE_64BIT_BUILD']:
+ SOURCES += [
+ '!xptcstubs_asm_ppc_aix64.s',
+ 'xptcinvoke_asm_ppc_aix64.s',
+ 'xptcinvoke_ppc_aix64.cpp',
+ 'xptcstubs_ppc_aix64.cpp',
+ ]
+ else:
+ SOURCES += [
+ '!xptcstubs_asm_ppc_aix.s',
+ 'xptcinvoke_ppc_aix.cpp',
+ 'xptcstubs_ppc_aix.cpp',
+ ]
+ if CONFIG['AIX_OBJMODEL'] == 'ibm':
+ SOURCES += [
+ 'xptcinvoke_asm_ppc_ibmobj_aix.s',
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke_asm_ppc_aix.s',
+ ]
+
+if CONFIG['OS_TEST'] == 'powerpc':
+ if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'):
+ SOURCES += [
+ 'xptcinvoke_asm_ppc_linux.S',
+ 'xptcinvoke_ppc_linux.cpp',
+ 'xptcstubs_asm_ppc_linux.S',
+ 'xptcstubs_ppc_linux.cpp',
+ ]
+
+if CONFIG['OS_TEST'] in ('powerpc64', 'powerpc64le'):
+ if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'):
+ SOURCES += [
+ 'xptcinvoke_asm_ppc64_linux.S',
+ 'xptcinvoke_ppc64_linux.cpp',
+ 'xptcstubs_asm_ppc64_linux.S',
+ 'xptcstubs_ppc64_linux.cpp',
+ ]
+
+if CONFIG['OS_TEST'] in ('macppc', 'bebox', 'ofppc', 'prep', 'amigappc'):
+ if CONFIG['OS_ARCH'] == 'NetBSD':
+ SOURCES += [
+ 'xptcinvoke_asm_ppc_netbsd.s',
+ 'xptcinvoke_ppc_netbsd.cpp',
+ 'xptcstubs_asm_ppc_netbsd.s',
+ 'xptcstubs_ppc_netbsd.cpp',
+ ]
+
+if CONFIG['OS_ARCH'] == 'OpenBSD' and CONFIG['OS_TEST'] == 'powerpc':
+ SOURCES += [
+ 'xptcinvoke_asm_ppc_openbsd.S',
+ 'xptcinvoke_ppc_openbsd.cpp',
+ 'xptcstubs_asm_ppc_openbsd.S',
+ 'xptcstubs_ppc_openbsd.cpp',
+ ]
+
+if CONFIG['OS_ARCH'] == 'Linux' and 'sparc' in CONFIG['OS_TEST']:
+ SOURCES += [
+ 'xptcinvoke_asm_sparc_linux_GCC3.s',
+ 'xptcinvoke_sparc_solaris.cpp',
+ 'xptcstubs_asm_sparc_solaris.s',
+ 'xptcstubs_sparc_solaris.cpp',
+ ]
+
+if CONFIG['OS_ARCH'] == 'NetBSD' and CONFIG['OS_TEST'] == 'sparc':
+ SOURCES += [
+ 'xptcinvoke_asm_sparc_netbsd.s',
+ 'xptcinvoke_sparc_netbsd.cpp',
+ 'xptcstubs_asm_sparc_netbsd.s',
+ 'xptcstubs_sparc_netbsd.cpp',
+ ]
+
+if CONFIG['OS_ARCH'] == 'OpenBSD' and CONFIG['OS_TEST'] == 'sparc':
+ SOURCES += [
+ 'xptcinvoke_asm_sparc_openbsd.s',
+ 'xptcinvoke_sparc_openbsd.cpp',
+ 'xptcstubs_asm_sparc_openbsd.s',
+ 'xptcstubs_sparc_openbsd.cpp',
+ ]
+
+if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD') and CONFIG['OS_TEST'] == 'sparc64':
+ SOURCES += [
+ 'xptcinvoke_asm_sparc64_openbsd.s',
+ 'xptcinvoke_sparc64_openbsd.cpp',
+ 'xptcstubs_asm_sparc64_openbsd.s',
+ 'xptcstubs_sparc64_openbsd.cpp',
+ ]
+
+if CONFIG['OS_ARCH'] == 'SunOS' and '86' not in CONFIG['OS_TEST']:
+ if CONFIG['HAVE_64BIT_BUILD']:
+ ASFLAGS += ['-xarch=v9']
+ SOURCES += [
+ 'xptcinvoke_sparcv9_solaris.cpp',
+ 'xptcstubs_sparcv9_solaris.cpp',
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke_sparc_solaris.cpp',
+ 'xptcstubs_sparc_solaris.cpp',
+ ]
+ if CONFIG['GNU_CC']:
+ SOURCES += [
+ 'xptcinvoke_asm_sparc_solaris_GCC3.s',
+ 'xptcstubs_asm_sparc_solaris.s',
+ ]
+ else:
+ if CONFIG['HAVE_64BIT_BUILD']:
+ SOURCES += [
+ 'xptcinvoke_asm_sparcv9_solaris_SUNW.s',
+ 'xptcstubs_asm_sparcv9_solaris.s',
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke_asm_sparc_solaris_SUNW.s',
+ 'xptcstubs_asm_sparc_solaris.s',
+ ]
+
+if CONFIG['OS_ARCH'] == 'Linux':
+ if CONFIG['OS_TEST'] == 's390':
+ SOURCES += [
+ 'xptcinvoke_linux_s390.cpp',
+ 'xptcstubs_linux_s390.cpp',
+ ]
+ CXXFLAGS += [
+ '-fno-strict-aliasing',
+ '-fno-inline',
+ '-fomit-frame-pointer',
+ '-mbackchain',
+ ]
+ elif CONFIG['OS_TEST'] == 's390x':
+ SOURCES += [
+ 'xptcinvoke_linux_s390x.cpp',
+ 'xptcstubs_linux_s390x.cpp',
+ ]
+ CXXFLAGS += [
+ '-fno-strict-aliasing',
+ '-fno-inline',
+ '-fomit-frame-pointer',
+ '-mbackchain',
+ ]
+
+FINAL_LIBRARY = 'xul'
+
+LOCAL_INCLUDES += [
+ '../..',
+ '/xpcom/reflect/xptinfo',
+]
+
+NO_PGO = True
diff --git a/xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp b/xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp
new file mode 100644
index 0000000000..0cb327a3dc
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp
@@ -0,0 +1,66 @@
+/* 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 code contributed by Bert Driehuis <bert_driehuis@nl.compuware.com> */
+
+#include <stdio.h>
+
+// Try to determine the vtable layout generated by G++
+// Produces the offset at which the first vtable entry can be
+// found, and the factor to apply for subsequent entries on stdout.
+// Example output:
+// #define GCC_VTABLE_START 0xc
+// #define GCC_VTABLE_FACTOR 0x8
+
+class test {
+public:
+ virtual int t1(void);
+ virtual int t2(void);
+ int x;
+};
+
+test::test() { this->x = 0x12121212; };
+
+int test::t1(void) { return 1; }
+int test::t2(void) { return 2; }
+
+void die(char *x) {
+ fprintf(stderr, "%s\n", x);
+ exit(1);
+}
+
+int
+main()
+{
+ int i;
+ test *t = new test();
+ int *tp = (int *) t;
+ int off1 = -1;
+ int off2 = -1;
+ int factor;
+ int factorshift;
+
+ if (*tp++ != 0x12121212)
+ die("Integer element test::x not found!");
+ tp = (int *) *tp;
+ for (i = 0; i < 10; i++) {
+ if (tp[i] == (int) t->t1)
+ off1 = i;
+ if (tp[i] == (int) t->t2)
+ off2 = i;
+ }
+ if (off1 == -1 || off2 == -1)
+ die("Could not determine offset into vtable!");
+ factor = (off2 - off1) * 4;
+ factorshift = -1;
+ while (factor) {
+ factorshift++;
+ factor >>= 1;
+ }
+ printf("/* Automatically generated by vtable_layout_x86.cpp */\n");
+ printf("#define GCC_VTABLE_START\t0x%x\n", off1 * 4);
+ printf("#define GCC_VTABLE_FACTOR\t0x%x\n", (off2 - off1) * 4);
+ printf("#define GCC_VTABLE_SHIFT\t0x%x\n", factorshift);
+ exit(0);
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h b/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h
new file mode 100644
index 0000000000..733646c497
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h
@@ -0,0 +1,17 @@
+/* -*- 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/. */
+
+/* Special include file for xptc*_gcc_x86_unix.cpp */
+
+//
+// this may improve the static function calls, but may not.
+//
+
+#ifdef MOZ_NEED_LEADING_UNDERSCORE
+#define SYMBOL_UNDERSCORE "_"
+#else
+#define SYMBOL_UNDERSCORE
+#endif
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp
new file mode 100644
index 0000000000..e5807dbcde
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp
@@ -0,0 +1,140 @@
+/* -*- 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++) {
+ uint64_t word;
+
+ if (s->IsPtrData()) {
+ word = (uint64_t)s->ptr;
+ } else {
+ // 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);
+ continue;
+ case nsXPTType::T_DOUBLE:
+ alloc_double(freg_args, stack_args, freg_end, s->val.d);
+ continue;
+ case nsXPTType::T_I8: word = s->val.i8; break;
+ case nsXPTType::T_I16: word = s->val.i16; break;
+ case nsXPTType::T_I32: word = s->val.i32; break;
+ case nsXPTType::T_I64: word = s->val.i64; break;
+ case nsXPTType::T_U8: word = s->val.u8; break;
+ case nsXPTType::T_U16: word = s->val.u16; break;
+ case nsXPTType::T_U32: word = s->val.u32; break;
+ case nsXPTType::T_U64: word = s->val.u64; break;
+ case nsXPTType::T_BOOL: word = s->val.b; break;
+ case nsXPTType::T_CHAR: word = s->val.c; break;
+ case nsXPTType::T_WCHAR: word = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ word = reinterpret_cast<uint64_t>(s->val.p);
+ break;
+ }
+ }
+
+ alloc_word(ireg_args, stack_args, ireg_end, word);
+ }
+}
+
+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/xptcinvoke_alpha_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp
new file mode 100644
index 0000000000..dc111e4358
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp
@@ -0,0 +1,144 @@
+/* -*- 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"
+
+/* Prototype specifies unmangled function name and disables unused warning */
+static void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+__asm__("invoke_copy_to_stack") __attribute__((used));
+
+static void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *d = (uint64_t)s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *d = (uint64_t)s->val.i8; break;
+ case nsXPTType::T_I16 : *d = (uint64_t)s->val.i16; break;
+ case nsXPTType::T_I32 : *d = (uint64_t)s->val.i32; break;
+ case nsXPTType::T_I64 : *d = (uint64_t)s->val.i64; break;
+ case nsXPTType::T_U8 : *d = (uint64_t)s->val.u8; break;
+ case nsXPTType::T_U16 : *d = (uint64_t)s->val.u16; break;
+ case nsXPTType::T_U32 : *d = (uint64_t)s->val.u32; break;
+ case nsXPTType::T_U64 : *d = (uint64_t)s->val.u64; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // convert floats to doubles if they are to be passed
+ // via registers so we can just deal with doubles later
+ union { uint64_t u64; double d; } t;
+ t.d = (double)s->val.f;
+ *d = t.u64;
+ }
+ else
+ // otherwise copy to stack normally
+ *d = (uint64_t)s->val.u32;
+ break;
+ case nsXPTType::T_DOUBLE : *d = (uint64_t)s->val.u64; break;
+ case nsXPTType::T_BOOL : *d = (uint64_t)s->val.b; break;
+ case nsXPTType::T_CHAR : *d = (uint64_t)s->val.c; break;
+ case nsXPTType::T_WCHAR : *d = (uint64_t)s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *d = (uint64_t)s->val.p;
+ break;
+ }
+ }
+}
+
+/*
+ * EXPORT_XPCOM_API(nsresult)
+ * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ * uint32_t paramCount, nsXPTCVariant* params)
+ */
+__asm__(
+ "#### NS_InvokeByIndex ####\n"
+".text\n\t"
+ ".align 5\n\t"
+ ".globl NS_InvokeByIndex\n\t"
+ ".ent NS_InvokeByIndex\n"
+"NS_InvokeByIndex:\n\t"
+ ".frame $15,32,$26,0\n\t"
+ ".mask 0x4008000,-32\n\t"
+ "ldgp $29,0($27)\n"
+"$NS_InvokeByIndex..ng:\n\t"
+ "subq $30,32,$30\n\t"
+ "stq $26,0($30)\n\t"
+ "stq $15,8($30)\n\t"
+ "bis $30,$30,$15\n\t"
+ ".prologue 1\n\t"
+
+ /*
+ * Allocate enough stack space to hold the greater of 6 or "paramCount"+1
+ * parameters. (+1 for "this" pointer) Room for at least 6 parameters
+ * is required for storage of those passed via registers.
+ */
+
+ "bis $31,5,$2\n\t" /* count = MAX(5, "paramCount") */
+ "cmplt $2,$18,$1\n\t"
+ "cmovne $1,$18,$2\n\t"
+ "s8addq $2,16,$1\n\t" /* room for count+1 params (8 bytes each) */
+ "bic $1,15,$1\n\t" /* stack space is rounded up to 0 % 16 */
+ "subq $30,$1,$30\n\t"
+
+ "stq $16,0($30)\n\t" /* save "that" (as "this" pointer) */
+ "stq $17,16($15)\n\t" /* save "methodIndex" */
+
+ "addq $30,8,$16\n\t" /* pass stack pointer */
+ "bis $18,$18,$17\n\t" /* pass "paramCount" */
+ "bis $19,$19,$18\n\t" /* pass "params" */
+ "bsr $26,$invoke_copy_to_stack..ng\n\t" /* call invoke_copy_to_stack */
+
+ /*
+ * Copy the first 6 parameters to registers and remove from stack frame.
+ * Both the integer and floating point registers are set for each parameter
+ * except the first which is the "this" pointer. (integer only)
+ * The floating point registers are all set as doubles since the
+ * invoke_copy_to_stack function should have converted the floats.
+ */
+ "ldq $16,0($30)\n\t" /* integer registers */
+ "ldq $17,8($30)\n\t"
+ "ldq $18,16($30)\n\t"
+ "ldq $19,24($30)\n\t"
+ "ldq $20,32($30)\n\t"
+ "ldq $21,40($30)\n\t"
+ "ldt $f17,8($30)\n\t" /* floating point registers */
+ "ldt $f18,16($30)\n\t"
+ "ldt $f19,24($30)\n\t"
+ "ldt $f20,32($30)\n\t"
+ "ldt $f21,40($30)\n\t"
+
+ "addq $30,48,$30\n\t" /* remove params from stack */
+
+ /*
+ * Call the virtual function with the constructed stack frame.
+ */
+ "bis $16,$16,$1\n\t" /* load "this" */
+ "ldq $2,16($15)\n\t" /* load "methodIndex" */
+ "ldq $1,0($1)\n\t" /* load vtable */
+ "s8addq $2,$31,$2\n\t" /* vtable index = "methodIndex" * 8 */
+ "addq $1,$2,$1\n\t"
+ "ldq $27,0($1)\n\t" /* load address of function */
+ "jsr $26,($27),0\n\t" /* call virtual function */
+ "ldgp $29,0($26)\n\t"
+
+ "bis $15,$15,$30\n\t"
+ "ldq $26,0($30)\n\t"
+ "ldq $15,8($30)\n\t"
+ "addq $30,32,$30\n\t"
+ "ret $31,($26),1\n\t"
+ ".end NS_InvokeByIndex"
+ );
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp
new file mode 100644
index 0000000000..4cd5eb47d8
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp
@@ -0,0 +1,417 @@
+/* -*- 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"
+
+#include "mozilla/Compiler.h"
+
+#if !defined(__arm__) && !(defined(LINUX) || defined(ANDROID) || defined(XP_IOS))
+#error "This code is for Linux/iOS ARM only. Check that it works on your system, too.\nBeware that this code is highly compiler dependent."
+#endif
+
+#if MOZ_IS_GCC
+#if defined(__ARM_EABI__) && !defined(__ARM_PCS_VFP) && !defined(__ARM_PCS)
+#error "Can't identify floating point calling conventions.\nPlease ensure that your toolchain defines __ARM_PCS or __ARM_PCS_VFP."
+#endif
+#endif
+
+#ifndef __ARM_PCS_VFP
+
+/* This function copies a 64-bits word from dw to the given pointer in
+ * a buffer delimited by start and end, possibly wrapping around the
+ * buffer boundaries, and/or properly aligning the data at 64-bits word
+ * boundaries (for EABI).
+ * start and end are both assumed to be 64-bits aligned.
+ * Returns a pointer to the second 32-bits word copied (to accomodate
+ * the invoke_copy_to_stack loop).
+ */
+static uint32_t *
+copy_double_word(uint32_t *start, uint32_t *current, uint32_t *end, uint64_t *dw)
+{
+#ifdef __ARM_EABI__
+ /* Aligning the pointer for EABI */
+ current = (uint32_t *)(((uint32_t)current + 7) & ~7);
+ /* Wrap when reaching the end of the buffer */
+ if (current == end) current = start;
+#else
+ /* On non-EABI, 64-bits values are not aligned and when we reach the end
+ * of the buffer, we need to write half of the data at the end, and the
+ * other half at the beginning. */
+ if (current == end - 1) {
+ *current = ((uint32_t*)dw)[0];
+ *start = ((uint32_t*)dw)[1];
+ return start;
+ }
+#endif
+
+ *((uint64_t*) current) = *dw;
+ return current + 1;
+}
+
+/* See stack_space comment in NS_InvokeByIndex to see why this needs not to
+ * be static on DEBUG builds. */
+#ifndef DEBUG
+static
+#endif
+void
+invoke_copy_to_stack(uint32_t* stk, uint32_t *end,
+ uint32_t paramCount, nsXPTCVariant* s)
+{
+ /* The stack buffer is 64-bits aligned. The end argument points to its end.
+ * The caller is assumed to create a stack buffer of at least four 32-bits
+ * words.
+ * We use the last three 32-bit words to store the values for r1, r2 and r3
+ * for the method call, i.e. the first words for arguments passing.
+ */
+ uint32_t *d = end - 3;
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ /* Wrap when reaching the end of the stack buffer */
+ if (d == end) d = stk;
+ NS_ASSERTION(d >= stk && d < end,
+ "invoke_copy_to_stack is copying outside its given buffer");
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ // According to the ARM EABI, integral types that are smaller than a word
+ // are to be sign/zero-extended to a full word and treated as 4-byte values.
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 :
+ d = copy_double_word(stk, d, end, (uint64_t *)&s->val.i64);
+ break;
+ case nsXPTType::T_U8 : *((uint32_t*)d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 :
+ d = copy_double_word(stk, d, end, (uint64_t *)&s->val.u64);
+ break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE :
+ d = copy_double_word(stk, d, end, (uint64_t *)&s->val.d);
+ break;
+ case nsXPTType::T_BOOL : *((int32_t*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((int32_t*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t);
+
+// Avoid AddressSanitizer instrumentation for the next function because it
+// depends on __builtin_alloca behavior and alignment that cannot be relied on
+// once the function is compiled with a version of ASan that has dynamic-alloca
+// instrumentation enabled.
+
+MOZ_ASAN_BLACKLIST
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+
+/* This is to call a given method of class that.
+ * The parameters are in params, the number is in paramCount.
+ * The routine will issue calls to count the number of words
+ * required for argument passing and to copy the arguments to
+ * the stack.
+ * ACPS passes the first 3 params in r1-r3 (with exceptions for 64-bits
+ * arguments), and the remaining goes onto the stack.
+ * We allocate a buffer on the stack for a "worst case" estimate of how much
+ * stack might be needed for EABI, i.e. twice the number of parameters.
+ * The end of this buffer will be used to store r1 to r3, so that the start
+ * of the stack is the remaining parameters.
+ * The magic here is to call the method with "that" and three 32-bits
+ * arguments corresponding to r1-r3, so that the compiler generates the
+ * proper function call. The stack will also contain the remaining arguments.
+ *
+ * !!! IMPORTANT !!!
+ * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented
+ * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])!
+ *
+ */
+
+ vtable_func *vtable, func;
+ int base_size = (paramCount > 1) ? paramCount : 2;
+
+/* !!! IMPORTANT !!!
+ * On DEBUG builds, the NS_ASSERTION used in invoke_copy_to_stack needs to use
+ * the stack to pass the 5th argument to NS_DebugBreak. When invoke_copy_to_stack
+ * is inlined, this can result, depending on the compiler and flags, in the
+ * stack pointer not pointing at stack_space when the method is called at the
+ * end of this function. More generally, any function call requiring stack
+ * allocation of arguments is unsafe to be inlined in this function.
+ */
+ uint32_t *stack_space = (uint32_t *) __builtin_alloca(base_size * 8);
+
+ invoke_copy_to_stack(stack_space, &stack_space[base_size * 2],
+ paramCount, params);
+
+ vtable = *reinterpret_cast<vtable_func **>(that);
+ func = vtable[methodIndex];
+
+ return func(that, stack_space[base_size * 2 - 3],
+ stack_space[base_size * 2 - 2],
+ stack_space[base_size * 2 - 1]);
+}
+
+#else /* __ARM_PCS_VFP */
+
+/* "Procedure Call Standard for the ARM Architecture" document, sections
+ * "5.5 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
+ */
+
+#if defined(__thumb__) && !defined(__thumb2__)
+#error "Thumb1 is not supported"
+#endif
+
+#ifndef __ARMEL__
+#error "Only little endian compatibility was tested"
+#endif
+
+/*
+ * Allocation of integer function arguments initially to registers r1-r3
+ * and then to stack. Handling of 'this' argument which goes to r0 registers
+ * is handled separately and does not belong to these two inline functions.
+ *
+ * The doubleword arguments are allocated to even:odd
+ * register pairs or get aligned at 8-byte boundary on stack. The "holes"
+ * which may appear as a result of this realignment remain unused.
+ *
+ * '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 (it is guaranteed to be 8-bytes aligned)
+ */
+
+static inline void copy_word(uint32_t* &ireg_args,
+ uint32_t* &stack_args,
+ uint32_t* end,
+ uint32_t data)
+{
+ if (ireg_args < end) {
+ *ireg_args = data;
+ ireg_args++;
+ } else {
+ *stack_args = data;
+ stack_args++;
+ }
+}
+
+static inline void copy_dword(uint32_t* &ireg_args,
+ uint32_t* &stack_args,
+ uint32_t* end,
+ uint64_t data)
+{
+ if (ireg_args + 1 < end) {
+ if ((uint32_t)ireg_args & 4) {
+ ireg_args++;
+ }
+ *(uint64_t *)ireg_args = data;
+ ireg_args += 2;
+ } else {
+ ireg_args = end;
+ if ((uint32_t)stack_args & 4) {
+ stack_args++;
+ }
+ *(uint64_t *)stack_args = data;
+ stack_args += 2;
+ }
+}
+
+/*
+ * Allocation of floating point arguments to VFP registers (s0-s15, d0-d7).
+ *
+ * Unlike integer registers allocation, "back-filling" needs to be
+ * supported. For example, the third floating point argument in the
+ * following function is going to be allocated to s1 register, back-filling
+ * the "hole":
+ * void f(float s0, double d1, float s1)
+ *
+ * Refer to the "Procedure Call Standard for the ARM Architecture" document
+ * for more details.
+ *
+ * 'vfp_s_args' - pointer to the current position in the buffer with
+ * the next unallocated single precision register
+ * 'vfp_d_args' - pointer to the current position in the buffer with
+ * the next unallocated double precision register,
+ * it has the same value as 'vfp_s_args' when back-filling
+ * is not used
+ * 'end' - pointer to the end of the vfp registers argument
+ * buffer (it is guaranteed to be 8-bytes aligned)
+ *
+ * Mozilla bugtracker has a test program attached which be used for
+ * experimenting with VFP registers allocation code and testing its
+ * correctness:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=601914#c19
+ */
+
+static inline bool copy_vfp_single(float* &vfp_s_args, double* &vfp_d_args,
+ float* end, float data)
+{
+ if (vfp_s_args >= end)
+ return false;
+
+ *vfp_s_args = data;
+ vfp_s_args++;
+ if (vfp_s_args < (float *)vfp_d_args) {
+ // It was the case of back-filling, now the next free single precision
+ // register should overlap with the next free double precision register
+ vfp_s_args = (float *)vfp_d_args;
+ } else if (vfp_s_args > (float *)vfp_d_args) {
+ // also update the pointer to the next free double precision register
+ vfp_d_args++;
+ }
+ return true;
+}
+
+static inline bool copy_vfp_double(float* &vfp_s_args, double* &vfp_d_args,
+ float* end, double data)
+{
+ if (vfp_d_args >= (double *)end) {
+ // The back-filling continues only so long as no VFP CPRC has been
+ // allocated to a slot on the stack. Basically no VFP registers can
+ // be allocated after this point.
+ vfp_s_args = end;
+ return false;
+ }
+
+ if (vfp_s_args == (float *)vfp_d_args) {
+ // also update the pointer to the next free single precision register
+ vfp_s_args += 2;
+ }
+ *vfp_d_args = data;
+ vfp_d_args++;
+ return true;
+}
+
+static void
+invoke_copy_to_stack(uint32_t* stk, uint32_t *end,
+ uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t *ireg_args = end - 3;
+ float *vfp_s_args = (float *)end;
+ double *vfp_d_args = (double *)end;
+ float *vfp_end = vfp_s_args + 16;
+
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (s->IsPtrData()) {
+ copy_word(ireg_args, stk, end, (uint32_t)s->ptr);
+ continue;
+ }
+ // According to the ARM EABI, integral types that are smaller than a word
+ // are to be sign/zero-extended to a full word and treated as 4-byte values
+ switch (s->type)
+ {
+ case nsXPTType::T_FLOAT:
+ if (!copy_vfp_single(vfp_s_args, vfp_d_args, vfp_end, s->val.f)) {
+ copy_word(end, stk, end, reinterpret_cast<uint32_t&>(s->val.f));
+ }
+ break;
+ case nsXPTType::T_DOUBLE:
+ if (!copy_vfp_double(vfp_s_args, vfp_d_args, vfp_end, s->val.d)) {
+ copy_dword(end, stk, end, reinterpret_cast<uint64_t&>(s->val.d));
+ }
+ break;
+ case nsXPTType::T_I8: copy_word(ireg_args, stk, end, s->val.i8); break;
+ case nsXPTType::T_I16: copy_word(ireg_args, stk, end, s->val.i16); break;
+ case nsXPTType::T_I32: copy_word(ireg_args, stk, end, s->val.i32); break;
+ case nsXPTType::T_I64: copy_dword(ireg_args, stk, end, s->val.i64); break;
+ case nsXPTType::T_U8: copy_word(ireg_args, stk, end, s->val.u8); break;
+ case nsXPTType::T_U16: copy_word(ireg_args, stk, end, s->val.u16); break;
+ case nsXPTType::T_U32: copy_word(ireg_args, stk, end, s->val.u32); break;
+ case nsXPTType::T_U64: copy_dword(ireg_args, stk, end, s->val.u64); break;
+ case nsXPTType::T_BOOL: copy_word(ireg_args, stk, end, s->val.b); break;
+ case nsXPTType::T_CHAR: copy_word(ireg_args, stk, end, s->val.c); break;
+ case nsXPTType::T_WCHAR: copy_word(ireg_args, stk, end, s->val.wc); break;
+ default:
+ // all the others are plain pointer types
+ copy_word(ireg_args, stk, end, reinterpret_cast<uint32_t>(s->val.p));
+ break;
+ }
+ }
+}
+
+typedef uint32_t (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t);
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ vtable_func *vtable = *reinterpret_cast<vtable_func **>(that);
+ vtable_func func = vtable[methodIndex];
+ // 'register uint32_t result asm("r0")' could be used here, but it does not
+ // seem to be reliable in all cases: http://gcc.gnu.org/PR46164
+ nsresult result;
+ asm (
+ "mov r3, sp\n"
+ "mov %[stack_space_size], %[param_count_plus_2], lsl #3\n"
+ "tst r3, #4\n" /* check stack alignment */
+
+ "add %[stack_space_size], #(4 * 16)\n" /* space for VFP registers */
+ "mov r3, %[params]\n"
+
+ "it ne\n"
+ "addne %[stack_space_size], %[stack_space_size], #4\n"
+ "sub r0, sp, %[stack_space_size]\n" /* allocate space on stack */
+
+ "sub r2, %[param_count_plus_2], #2\n"
+ "mov sp, r0\n"
+
+ "add r1, r0, %[param_count_plus_2], lsl #3\n"
+ "blx %[invoke_copy_to_stack]\n"
+
+ "add ip, sp, %[param_count_plus_2], lsl #3\n"
+ "mov r0, %[that]\n"
+ "ldmdb ip, {r1, r2, r3}\n"
+ "vldm ip, {d0, d1, d2, d3, d4, d5, d6, d7}\n"
+ "blx %[func]\n"
+
+ "add sp, sp, %[stack_space_size]\n" /* cleanup stack */
+ "mov %[stack_space_size], r0\n" /* it's actually 'result' variable */
+ : [stack_space_size] "=&r" (result)
+ : [func] "r" (func),
+ [that] "r" (that),
+ [params] "r" (params),
+ [param_count_plus_2] "r" (paramCount + 2),
+ [invoke_copy_to_stack] "r" (invoke_copy_to_stack)
+ : "cc", "memory",
+ // Mark all the scratch registers as clobbered because they may be
+ // modified by the functions, called from this inline assembly block
+ "r0", "r1", "r2", "r3", "ip", "lr",
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ // Also unconditionally mark d16-d31 registers as clobbered even though
+ // they actually don't exist in vfpv2 and vfpv3-d16 variants. There is
+ // no way to identify VFP variant using preprocessor at the momemnt
+ // (see http://gcc.gnu.org/PR46128 for more details), but fortunately
+ // current versions of gcc do not seem to complain about these registers
+ // even when this code is compiled with '-mfpu=vfpv3-d16' option.
+ // If gcc becomes more strict in the future and/or provides a way to
+ // identify VFP variant, the following d16-d31 registers list needs
+ // to be wrapped into some #ifdef
+ "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+ "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"
+ );
+ return result;
+}
+
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp
new file mode 100644
index 0000000000..1b0c214ea8
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp
@@ -0,0 +1,181 @@
+/* -*- 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"
+
+// Remember that these 'words' are 32bit DWORDS
+
+static uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+static void
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C"
+struct my_params_struct {
+ nsISupports* that;
+ uint32_t Index;
+ uint32_t Count;
+ nsXPTCVariant* params;
+ uint32_t fn_count;
+ uint32_t fn_copy;
+};
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ uint32_t result;
+ struct my_params_struct my_params;
+ my_params.that = that;
+ my_params.Index = methodIndex;
+ my_params.Count = paramCount;
+ my_params.params = params;
+ my_params.fn_copy = (uint32_t) &invoke_copy_to_stack;
+ my_params.fn_count = (uint32_t) &invoke_count_words;
+
+/* This is to call a given method of class that.
+ * The parameters are in params, the number is in paramCount.
+ * The routine will issue calls to count the number of words
+ * required for argument passing and to copy the arguments to
+ * the stack.
+ * Since APCS passes the first 3 params in r1-r3, we need to
+ * load the first three words from the stack and correct the stack
+ * pointer (sp) in the appropriate way. This means:
+ *
+ * 1.) more than 3 arguments: load r1-r3, correct sp and remember No.
+ * of bytes left on the stack in r4
+ *
+ * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope),
+ * restore sp as if nothing had happened and set the marker r4 to zero.
+ *
+ * Afterwards sp will be restored using the value in r4 (which is not a temporary register
+ * and will be preserved by the function/method called according to APCS [ARM Procedure
+ * Calling Standard]).
+ *
+ * !!! IMPORTANT !!!
+ * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented
+ * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])!
+ *
+ */
+
+ __asm__ __volatile__(
+ "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */
+ "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */
+ "ldr r0, [%1, #8] \n\t"
+ "mov lr, pc \n\t" /* call it... */
+ "mov pc, ip \n\t"
+ "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */
+ "sub sp, sp, r4 \n\t" /* use stack space for the args... */
+ "mov r0, sp \n\t" /* prepare a pointer an the stack */
+ "ldr r1, [%1, #8] \n\t" /* =paramCount */
+ "ldr r2, [%1, #12] \n\t" /* =params */
+ "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */
+ "mov lr, pc \n\t" /* copy args to the stack like the */
+ "mov pc, ip \n\t" /* compiler would. */
+ "ldr r0, [%1] \n\t" /* =that */
+ "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */
+ "ldr r2, [%1, #4] \n\t"
+ "add r2, r1, r2, lsl #3\n\t" /* a vtable_entry(x)=8 + (8 bytes * x) */
+ "add r2, r2, #8 \n\t" /* with this compilers */
+ "ldr r3, [r2] \n\t" /* get virtual offset from vtable */
+ "mov r3, r3, lsl #16 \n\t"
+ "add r0, r0, r3, asr #16\n\t"
+ "ldr ip, [r2, #4] \n\t" /* get method address from vtable */
+ "cmp r4, #12 \n\t" /* more than 3 arguments??? */
+ "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */
+ "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */
+ "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */
+ "addle sp, sp, r4 \n\t" /* and restore stack pointer */
+ "movle r4, #0 \n\t" /* a mark for restoring sp */
+ "mov lr, pc \n\t" /* call mathod */
+ "mov pc, ip \n\t"
+ "add sp, sp, r4 \n\t" /* restore stack pointer */
+ "mov %0, r0 \n\t" /* the result... */
+ : "=r" (result)
+ : "r" (&my_params)
+ : "r0", "r1", "r2", "r3", "r4", "ip", "lr"
+ );
+
+ return result;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp
new file mode 100644
index 0000000000..4ec7dd20fb
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp
@@ -0,0 +1,183 @@
+/* -*- 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"
+
+// Remember that these 'words' are 32bit DWORDS
+
+static uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+static void
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" {
+ struct my_params_struct {
+ nsISupports* that;
+ uint32_t Index;
+ uint32_t Count;
+ nsXPTCVariant* params;
+ uint32_t fn_count;
+ uint32_t fn_copy;
+ };
+}
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ uint32_t result;
+ struct my_params_struct my_params;
+ my_params.that = that;
+ my_params.Index = methodIndex;
+ my_params.Count = paramCount;
+ my_params.params = params;
+ my_params.fn_copy = (uint32_t) &invoke_copy_to_stack;
+ my_params.fn_count = (uint32_t) &invoke_count_words;
+
+/* This is to call a given method of class that.
+ * The parameters are in params, the number is in paramCount.
+ * The routine will issue calls to count the number of words
+ * required for argument passing and to copy the arguments to
+ * the stack.
+ * Since APCS passes the first 3 params in r1-r3, we need to
+ * load the first three words from the stack and correct the stack
+ * pointer (sp) in the appropriate way. This means:
+ *
+ * 1.) more than 3 arguments: load r1-r3, correct sp and remember No.
+ * of bytes left on the stack in r4
+ *
+ * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope),
+ * restore sp as if nothing had happened and set the marker r4 to zero.
+ *
+ * Afterwards sp will be restored using the value in r4 (which is not a temporary register
+ * and will be preserved by the function/method called according to APCS [ARM Procedure
+ * Calling Standard]).
+ *
+ * !!! IMPORTANT !!!
+ * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented
+ * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])!
+ *
+ */
+
+#ifdef __GNUC__
+ __asm__ __volatile__(
+ "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */
+ "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */
+ "ldr r0, [%1, #8] \n\t"
+ "mov lr, pc \n\t" /* call it... */
+ "mov pc, ip \n\t"
+ "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */
+ "sub sp, sp, r4 \n\t" /* use stack space for the args... */
+ "mov r0, sp \n\t" /* prepare a pointer an the stack */
+ "ldr r1, [%1, #8] \n\t" /* =paramCount */
+ "ldr r2, [%1, #12] \n\t" /* =params */
+ "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */
+ "mov lr, pc \n\t" /* copy args to the stack like the */
+ "mov pc, ip \n\t" /* compiler would. */
+ "ldr r0, [%1] \n\t" /* =that */
+ "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */
+ "ldr r2, [%1, #4] \n\t"
+ "mov r2, r2, lsl #2 \n\t" /* a vtable_entry(x)=8 + (4 bytes * x) */
+ "ldr ip, [r1, r2] \n\t" /* get method adress from vtable */
+ "cmp r4, #12 \n\t" /* more than 3 arguments??? */
+ "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */
+ "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */
+ "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */
+ "addle sp, sp, r4 \n\t" /* and restore stack pointer */
+ "movle r4, #0 \n\t" /* a mark for restoring sp */
+ "ldr r0, [%1, #0] \n\t" /* get (self) */
+ "mov lr, pc \n\t" /* call mathod */
+ "mov pc, ip \n\t"
+ "add sp, sp, r4 \n\t" /* restore stack pointer */
+ "mov %0, r0 \n\t" /* the result... */
+ : "=r" (result)
+ : "r" (&my_params), "m" (my_params)
+ : "r0", "r1", "r2", "r3", "r4", "ip", "lr", "sp"
+ );
+#else
+#error "Unsupported compiler. Use g++ >= 2.8 for OpenBSD/arm."
+#endif /* G++ >= 2.8 */
+
+ return result;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.s
new file mode 100644
index 0000000000..efe691a683
--- /dev/null
+++ b/xpcom/reflect/xptcall/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/md/unix/xptcinvoke_asm_ipf32.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s
new file mode 100644
index 0000000000..794c4f5c17
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s
@@ -0,0 +1,145 @@
+
+// Select C numeric constant
+ .radix C
+// for 64 bit mode, use .psr abi64
+ .psr abi32
+// big endian
+ .psr msb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'NS_InvokeByIndex'
+ .proc NS_InvokeByIndex
+// manual bundling
+ .explicit
+
+// extern "C" uint32_t
+// invoke_copy_to_stack(uint64_t* d,
+// const uint32_t paramCount, nsXPTCVariant* s)
+ .global invoke_copy_to_stack
+// .exclass invoke_copy_to_stack, @fullyvisible
+ .type invoke_copy_to_stack,@function
+
+// .exclass NS_InvokeByIndex, @fullyvisible
+ .type NS_InvokeByIndex,@function
+
+// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+// uint32_t paramCount, nsXPTCVariant* params);
+NS_InvokeByIndex::
+ .prologue
+ .save ar.pfs, r37
+// allocate 4 input args, 6 local args, and 8 output args
+ alloc r37 = ar.pfs, 4, 6, 8, 0 // M
+ nop.i 0 ;; // I
+
+// unwind table already knows gp, no need to specify anything
+ add r39 = 0, gp // A
+ .save rp, r36
+ mov r36 = rp // I
+ .vframe r38
+ add r38 = 0, sp ;; // A
+
+// We first calculate the amount of extra memory stack space required
+// for the arguments, and register storage.
+// We then call invoke_copy_to_stack() to write the argument contents
+// to the specified memory regions.
+// We then copy the integer arguments to integer registers, and floating
+// arguments to float registers.
+// Lastly we load the virtual table jump pointer, and call the target
+// subroutine.
+
+// in0 : that
+// in1 : methodIndex
+// in2 : paramCount
+// in3 : params
+
+// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64
+// 16 byte frame header
+// 8 * even(paramCount) memory argument area
+// 64 bytes integer register area
+// 64 bytes float register area
+// This scheme makes sure stack fram size is a multiple of 16
+
+ .body
+ add r10 = 8, r0 // A
+// r41 points to float register area
+ add r41 = -64, sp // A
+// r40 points to int register area
+ add r40 = -128, sp ;; // A
+
+ add out1 = 0, r40 // A
+ add out2 = 0, r41 // A
+ tbit.z p14,p15 = in2,0 ;; // I
+
+// compute 8 * even(paramCount)
+(p14) shladd r11 = in2, 3, r0 ;; // A
+(p15) shladd r11 = in2, 3, r10 ;; // A
+ sub out0 = r40, r11 ;; // A
+
+// advance the stack frame
+ add sp = -16, out0 // A
+ add out3 = 0, in2 // A
+ add out4 = 0, in3 // A
+
+// branch to invoke_copy_to_stack
+ br.call.sptk.few rp = invoke_copy_to_stack ;; // B
+
+// restore gp
+ add gp = 0, r39 // A
+ add out0 = 0, in0 // A
+
+// load the integer and float registers
+ ld8 out1 = [r40], 8 // M
+ ldfd f8 = [r41], 8 ;; // M
+
+ ld8 out2 = [r40], 8 // M
+ ldfd f9 = [r41], 8 ;; // M
+
+ ld8 out3 = [r40], 8 // M
+ ldfd f10 = [r41], 8 ;; // M
+
+ ld8 out4 = [r40], 8 // M
+ ldfd f11 = [r41], 8 ;; // M
+
+ ld8 out5 = [r40], 8 // M
+ ldfd f12 = [r41], 8 ;; // M
+// 16 * methodIndex
+ shladd r11 = in1, 4, r0 // A
+
+ ld8 out6 = [r40], 8 // M
+ ldfd f13 = [r41], 8 ;; // M
+
+ ld8 out7 = [r40], 8 // M
+ ldfd f14 = [r41], 8 // M
+ addp4 r8 = 0, in0 ;; // A
+
+// look up virtual base table and dispatch to target subroutine
+// This section assumes 32 bit pointer mode, and virtual base table
+// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html
+
+// load base table
+ ld4 r8 = [r8] ;; // M
+ addp4 r8 = r11, r8 ;; // A
+
+ // first entry is jump pointer, second entry is gp
+ addp4 r9 = 8, r8 ;; // A
+// load jump pointer
+ ld8 r8 = [r8]
+
+// load gp
+ ld8 gp = [r9] ;; // M
+ mov b6 = r8 ;; // I
+
+// branch to target virtual function
+ br.call.sptk.few rp = b6 ;; // B
+
+// epilog
+ mov ar.pfs = r37 // I
+ mov rp = r36 ;; // I
+
+ add sp = 0, r38 // A
+ add gp = 0, r39 // A
+ br.ret.sptk.few rp ;; // B
+
+ .endp
+
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s
new file mode 100644
index 0000000000..140c441177
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s
@@ -0,0 +1,146 @@
+
+// Select C numeric constant
+ .radix C
+// for 64 bit mode, use .psr abi64
+ .psr abi64
+// little endian
+ .psr lsb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'NS_InvokeByIndex'
+ .proc NS_InvokeByIndex
+// manual bundling
+ .explicit
+
+// extern "C" uint32_t
+// invoke_copy_to_stack(uint64_t* d,
+// const uint32_t paramCount, nsXPTCVariant* s)
+ .global invoke_copy_to_stack
+// .exclass invoke_copy_to_stack, @fullyvisible
+ .type invoke_copy_to_stack,@function
+
+// .exclass NS_InvokeByIndex, @fullyvisible
+ .type NS_InvokeByIndex,@function
+
+// XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+// uint32_t paramCount, nsXPTCVariant* params);
+NS_InvokeByIndex::
+ .prologue
+ .save ar.pfs, r37
+// allocate 4 input args, 6 local args, and 8 output args
+ alloc r37 = ar.pfs, 4, 6, 8, 0 // M
+ nop.i 0 ;; // I
+
+// unwind table already knows gp, no need to specify anything
+ add r39 = 0, gp // A
+ .save rp, r36
+ mov r36 = rp // I
+ .vframe r38
+ add r38 = 0, sp ;; // A
+
+// We first calculate the amount of extra memory stack space required
+// for the arguments, and register storage.
+// We then call invoke_copy_to_stack() to write the argument contents
+// to the specified memory regions.
+// We then copy the integer arguments to integer registers, and floating
+// arguments to float registers.
+// Lastly we load the virtual table jump pointer, and call the target
+// subroutine.
+
+// in0 : that
+// in1 : methodIndex
+// in2 : paramCount
+// in3 : params
+
+// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64
+// 16 byte frame header
+// 8 * even(paramCount) memory argument area
+// 64 bytes integer register area
+// 64 bytes float register area
+// This scheme makes sure stack fram size is a multiple of 16
+
+ .body
+ add r10 = 8, r0 // A
+// r41 points to float register area
+ add r41 = -64, sp // A
+// r40 points to int register area
+ add r40 = -128, sp ;; // A
+
+ add out1 = 0, r40 // A
+ add out2 = 0, r41 // A
+ tbit.z p14,p15 = in2,0 ;; // I
+
+// compute 8 * even(paramCount)
+(p14) shladd r11 = in2, 3, r0 ;; // A
+(p15) shladd r11 = in2, 3, r10 ;; // A
+ sub out0 = r40, r11 ;; // A
+
+// advance the stack frame
+ add sp = -16, out0 // A
+ add out3 = 0, in2 // A
+ add out4 = 0, in3 // A
+
+// branch to invoke_copy_to_stack
+ br.call.sptk.few rp = invoke_copy_to_stack ;; // B
+
+// restore gp
+ add gp = 0, r39 // A
+ add out0 = 0, in0 // A
+
+// load the integer and float registers
+ ld8 out1 = [r40], 8 // M
+ ldfd f8 = [r41], 8 ;; // M
+
+ ld8 out2 = [r40], 8 // M
+ ldfd f9 = [r41], 8 ;; // M
+
+ ld8 out3 = [r40], 8 // M
+ ldfd f10 = [r41], 8 ;; // M
+
+ ld8 out4 = [r40], 8 // M
+ ldfd f11 = [r41], 8 ;; // M
+
+ ld8 out5 = [r40], 8 // M
+ ldfd f12 = [r41], 8 ;; // M
+// 16 * methodIndex
+ shladd r11 = in1, 4, r0 // A
+
+ ld8 out6 = [r40], 8 // M
+ ldfd f13 = [r41], 8 ;; // M
+
+ ld8 out7 = [r40], 8 // M
+ ldfd f14 = [r41], 8 // M
+ add r8 = 0, in0 ;; // A
+
+// look up virtual base table and dispatch to target subroutine
+// This section assumes 64 bit pointer mode, and virtual base table
+// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html
+
+// load base table
+ ld8 r8 = [r8] ;; // M
+ add r8 = r11, r8 ;; // A
+
+ // first entry is jump pointer, second entry is gp
+ add r9 = 8, r8 ;; // A
+// load jump pointer
+ ld8 r8 = [r8]
+
+// load gp
+ ld8 gp = [r9] ;; // M
+ mov b6 = r8 ;; // I
+
+// branch to target virtual function
+ br.call.sptk.few rp = b6 ;; // B
+
+// epilog
+ mov ar.pfs = r37 // I
+ mov rp = r36 ;; // I
+
+ add sp = 0, r38 // A
+ add gp = 0, r39 // A
+ br.ret.sptk.few rp ;; // B
+
+ .endp
+
+/* Magic indicating no need for an executable stack */
+.section .note.GNU-stack, "", @progbits ; .previous
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S
new file mode 100644
index 0000000000..32ff3b3565
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S
@@ -0,0 +1,134 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * 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 code is for MIPS using the O32 ABI. */
+
+#ifdef ANDROID
+#include <asm/regdef.h>
+#include <asm/asm.h>
+#include <machine/asm.h>
+#else
+#include <sys/regdef.h>
+#include <sys/asm.h>
+#endif
+
+# NARGSAVE is the argument space in the callers frame, including extra
+# 'shadowed' space for the argument registers. The minimum of 4
+# argument slots is sometimes predefined in the header files.
+#ifndef NARGSAVE
+#define NARGSAVE 4
+#endif
+
+#define LOCALSZ 3 /* gp, fp, ra */
+#define FRAMESZ ((((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK)
+
+#define RAOFF (FRAMESZ - (1*SZREG))
+#define FPOFF (FRAMESZ - (2*SZREG))
+#define GPOFF (FRAMESZ - (3*SZREG))
+
+#define A0OFF (FRAMESZ + (0*SZREG))
+#define A1OFF (FRAMESZ + (1*SZREG))
+#define A2OFF (FRAMESZ + (2*SZREG))
+#define A3OFF (FRAMESZ + (3*SZREG))
+
+ .text
+
+#
+# _NS_InvokeByIndex(that, methodIndex, paramCount, params)
+# a0 a1 a2 a3
+
+ .globl _NS_InvokeByIndex
+ .align 2
+ .type _NS_InvokeByIndex,@function
+ .ent _NS_InvokeByIndex,0
+ .frame fp, FRAMESZ, ra
+_NS_InvokeByIndex:
+ SETUP_GP
+ subu sp, FRAMESZ
+
+ # specify the save register mask for gp, fp, ra, a3 - a0
+ .mask 0xD00000F0, RAOFF-FRAMESZ
+
+ sw ra, RAOFF(sp)
+ sw fp, FPOFF(sp)
+
+ # we can't use .cprestore in a variable stack frame
+ sw gp, GPOFF(sp)
+
+ sw a0, A0OFF(sp)
+ sw a1, A1OFF(sp)
+ sw a2, A2OFF(sp)
+ sw a3, A3OFF(sp)
+
+ # save bottom of fixed frame
+ move fp, sp
+
+ # extern "C" uint32
+ # invoke_count_words(uint32_t paramCount, nsXPTCVariant* s);
+ la t9, invoke_count_words
+ move a0, a2
+ move a1, a3
+ jalr t9
+ lw gp, GPOFF(fp)
+
+ # allocate variable stack, with a size of:
+ # wordsize (of 4 bytes) * result (already aligned to dword)
+ # but a minimum of 16 byte
+ sll v0, 2
+ slt t0, v0, 16
+ beqz t0, 1f
+ li v0, 16
+1: subu sp, v0
+
+ # let a0 point to the bottom of the variable stack, allocate
+ # another fixed stack for:
+ # extern "C" void
+ # invoke_copy_to_stack(uint32_t* d, uint32_t paramCount,
+ # nsXPTCVariant* s);
+ la t9, invoke_copy_to_stack
+ move a0, sp
+ lw a1, A2OFF(fp)
+ lw a2, A3OFF(fp)
+ subu sp, 16
+ jalr t9
+ lw gp, GPOFF(fp)
+
+ # back to the variable stack frame
+ addu sp, 16
+
+ # calculate the function we need to jump to, which must then be
+ # stored in t9
+ lw a0, A0OFF(fp) # a0 = set "that" to be "this"
+ lw t0, A1OFF(fp) # a1 = methodIndex
+ lw t9, 0(a0)
+ # t0 = methodIndex << PTRLOG
+ sll t0, t0, PTRLOG
+ addu t9, t0
+ lw t9, (t9)
+
+ # Set a1-a3 to what invoke_copy_to_stack told us. a0 is already
+ # the "this" pointer. We don't have to care about floating
+ # point arguments, the non-FP "this" pointer as first argument
+ # means they'll never be used.
+ lw a1, 1*SZREG(sp)
+ lw a2, 2*SZREG(sp)
+ lw a3, 3*SZREG(sp)
+
+ jalr t9
+ # Micro-optimization: There's no gp usage below this point, so
+ # we don't reload.
+ # lw gp, GPOFF(fp)
+
+ # leave variable stack frame
+ move sp, fp
+
+ lw ra, RAOFF(sp)
+ lw fp, FPOFF(sp)
+
+ addiu sp, FRAMESZ
+ j ra
+END(_NS_InvokeByIndex)
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S
new file mode 100644
index 0000000000..eef34de7f2
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S
@@ -0,0 +1,122 @@
+/* -*- 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 <sys/regdef.h>
+#include <sys/asm.h>
+
+.text
+.globl invoke_count_words
+.globl invoke_copy_to_stack
+
+LOCALSZ=7 # a0, a1, a2, a3, s0, ra, gp
+FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+
+RAOFF=FRAMESZ-(1*SZREG)
+A0OFF=FRAMESZ-(2*SZREG)
+A1OFF=FRAMESZ-(3*SZREG)
+A2OFF=FRAMESZ-(4*SZREG)
+A3OFF=FRAMESZ-(5*SZREG)
+S0OFF=FRAMESZ-(6*SZREG)
+GPOFF=FRAMESZ-(7*SZREG)
+
+#
+# _NS_InvokeByIndex(that, methodIndex, paramCount, params)
+# a0 a1 a2 a3
+
+NESTED(_NS_InvokeByIndex, FRAMESZ, ra)
+ PTR_SUBU sp, FRAMESZ
+ SETUP_GP64(GPOFF, _NS_InvokeByIndex)
+
+ REG_S ra, RAOFF(sp)
+ REG_S a0, A0OFF(sp)
+ REG_S a1, A1OFF(sp)
+ REG_S a2, A2OFF(sp)
+ REG_S a3, A3OFF(sp)
+ REG_S s0, S0OFF(sp)
+
+ # invoke_count_words(paramCount, params)
+ move a0, a2
+ move a1, a3
+ jal invoke_count_words
+
+ # invoke_copy_to_stack(uint32_t* d, uint32_t paramCount,
+ # nsXPTCVariant* s, uint32_t *reg)
+
+ REG_L a1, A2OFF(sp) # a1 - paramCount
+ REG_L a2, A3OFF(sp) # a2 - params
+
+ # save sp before we copy the params to the stack
+ move t0, sp
+
+ # assume full size of 16 bytes per param to be safe
+ sll v0, 4 # 16 bytes * num params
+ PTR_SUBU sp, sp, v0 # make room
+ move a0, sp # a0 - param stack address
+
+ # create temporary stack space to write int and fp regs
+ PTR_SUBU sp, 64 # 64 = 8 regs of 8 bytes
+ move a3, sp
+
+ # save the old sp and save the arg stack
+ PTR_SUBU sp, sp, 16
+ REG_S t0, 0(sp)
+ REG_S a0, 8(sp)
+
+ # copy the param into the stack areas
+ jal invoke_copy_to_stack
+
+ REG_L t3, 8(sp) # get previous a0
+ REG_L sp, 0(sp) # get orig sp back
+
+ REG_L a0, A0OFF(sp) # a0 - that
+ REG_L a1, A1OFF(sp) # a1 - methodIndex
+
+ # t1 = methodIndex * pow(2, PTRLOG)
+ # (use shift instead of mult)
+ sll t1, a1, PTRLOG
+
+ # calculate the function we need to jump to,
+ # which must then be saved in t9
+ PTR_L t9, 0(a0)
+ PTR_ADDU t9, t9, t1
+ PTR_L t9, (t9)
+
+ # get register save area from invoke_copy_to_stack
+ PTR_SUBU t1, t3, 64
+
+ # a1..a7 and f13..f19 should now be set to what
+ # invoke_copy_to_stack told us. skip a0 and f12
+ # because that's the "this" pointer
+
+ REG_L a1, 0(t1)
+ REG_L a2, 8(t1)
+ REG_L a3, 16(t1)
+ REG_L a4, 24(t1)
+ REG_L a5, 32(t1)
+ REG_L a6, 40(t1)
+ REG_L a7, 48(t1)
+
+ l.d $f13, 0(t1)
+ l.d $f14, 8(t1)
+ l.d $f15, 16(t1)
+ l.d $f16, 24(t1)
+ l.d $f17, 32(t1)
+ l.d $f18, 40(t1)
+ l.d $f19, 48(t1)
+
+ # save away our stack pointer and create
+ # the stack pointer for the function
+ move s0, sp
+ move sp, t3
+
+ jalr t9
+
+ move sp, s0
+
+ RESTORE_GP64
+ REG_L ra, RAOFF(sp)
+ REG_L s0, S0OFF(sp)
+ PTR_ADDU sp, FRAMESZ
+ j ra
+.end _NS_InvokeByIndex
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s
new file mode 100644
index 0000000000..6fa9a86ba8
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s
@@ -0,0 +1,131 @@
+ .LEVEL 1.1
+framesz .EQU 128
+
+; XPTC_InvokeByIndex(nsISuppots* that, uint32_t methodIndex,
+; uint32_t paramCount, nsXPTCVariant* params);
+
+; g++ need to compile everything with -fvtable-thunks !
+
+ .SPACE $TEXT$,SORT=8
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
+XPTC_InvokeByIndex
+ .PROC
+ .CALLINFO CALLER,FRAME=72,ENTRY_GR=%r3,SAVE_RP,SAVE_SP,ARGS_SAVED,ALLOCA_FRAME
+
+ ; frame marker takes 48 bytes,
+ ; register spill area takes 8 bytes,
+ ; local stack area takes 72 bytes result in 128 bytes total
+
+ .ENTRY
+ STW %rp,-20(%sp)
+ STW,MA %r3,128(%sp)
+
+ LDO -framesz(%r30),%r28
+ STW %r28,-4(%r30) ; save previous sp
+ STW %r19,-32(%r30)
+
+ STW %r26,-36-framesz(%r30) ; save argument registers in
+ STW %r25,-40-framesz(%r30) ; in PREVIOUS frame
+ STW %r24,-44-framesz(%r30) ;
+ STW %r23,-48-framesz(%r30) ;
+
+ B,L .+8,%r2
+ ADDIL L'invoke_count_bytes-$PIC_pcrel$1+4,%r2,%r1
+ LDO R'invoke_count_bytes-$PIC_pcrel$2+8(%r1),%r1
+$PIC_pcrel$1
+ LDSID (%r1),%r31
+$PIC_pcrel$2
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26;out=28
+ BE,L 0(%sr0,%r1),%r31
+ COPY %r31,%r2
+
+ CMPIB,>= 0,%r28, .+76
+ COPY %r30,%r3 ; copy stack ptr to saved stack ptr
+ ADD %r30,%r28,%r30 ; extend stack frame
+ LDW -4(%r3),%r28 ; move frame
+ STW %r28,-4(%r30)
+ LDW -8(%r3),%r28
+ STW %r28,-8(%r30)
+ LDW -12(%r3),%r28
+ STW %r28,-12(%r30)
+ LDW -16(%r3),%r28
+ STW %r28,-16(%r30)
+ LDW -20(%r3),%r28
+ STW %r28,-20(%r30)
+ LDW -24(%r3),%r28
+ STW %r28,-24(%r30)
+ LDW -28(%r3),%r28
+ STW %r28,-28(%r30)
+ LDW -32(%r3),%r28
+ STW %r28,-32(%r30)
+
+ LDO -40(%r30),%r26 ; load copy address
+ LDW -44-framesz(%r3),%r25 ; load rest of 2 arguments
+ LDW -48-framesz(%r3),%r24 ;
+
+ LDW -32(%r30),%r19 ; shared lib call destroys r19; reload
+ B,L .+8,%r2
+ ADDIL L'invoke_copy_to_stack-$PIC_pcrel$3+4,%r2,%r1
+ LDO R'invoke_copy_to_stack-$PIC_pcrel$4+8(%r1),%r1
+$PIC_pcrel$3
+ LDSID (%r1),%r31
+$PIC_pcrel$4
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26
+ BE,L 0(%sr0,%r1),%r31
+ COPY %r31,%r2
+
+ LDO -48(%r30),%r20
+ EXTRW,U,= %r28,31,1,%r22
+ FLDD 0(%r20),%fr7 ; load double arg 1
+ EXTRW,U,= %r28,30,1,%r22
+ FLDW 8(%r20),%fr5L ; load float arg 1
+ EXTRW,U,= %r28,29,1,%r22
+ FLDW 4(%r20),%fr6L ; load float arg 2
+ EXTRW,U,= %r28,28,1,%r22
+ FLDW 0(%r20),%fr7L ; load float arg 3
+
+ LDW -36-framesz(%r3),%r26 ; load ptr to 'that'
+ LDW -40(%r30),%r25 ; load the rest of dispatch argument registers
+ LDW -44(%r30),%r24
+ LDW -48(%r30),%r23
+
+ LDW -36-framesz(%r3),%r20 ; load vtable addr
+ LDW -40-framesz(%r3),%r28 ; load index
+ LDW 0(%r20),%r20 ; follow vtable
+ LDO 16(%r20),%r20 ; offset vtable by 16 bytes (g++: 8, aCC: 16)
+ SH2ADDL %r28,%r20,%r28 ; add 4*index to vtable entry
+ LDW 0(%r28),%r22 ; load vtable entry
+
+ B,L .+8,%r2
+ ADDIL L'$$dyncall_external-$PIC_pcrel$5+4,%r2,%r1
+ LDO R'$$dyncall_external-$PIC_pcrel$6+8(%r1),%r1
+$PIC_pcrel$5
+ LDSID (%r1),%r31
+$PIC_pcrel$6
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+;in=22-26;out=28;
+ BE,L 0(%sr0,%r1),%r31
+ COPY %r31,%r2
+
+ LDW -32(%r30),%r19
+ COPY %r3,%r30 ; restore saved stack ptr
+
+ LDW -148(%sp),%rp
+ BVE (%rp)
+ .EXIT
+ LDW,MB -128(%sp),%r3
+
+ .PROCEND ;in=23,24,25,26;
+
+ .ALIGN 8
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+ .IMPORT $$dyncall_external,MILLICODE
+ .IMPORT invoke_count_bytes,CODE
+ .IMPORT invoke_copy_to_stack,CODE
+ .EXPORT XPTC_InvokeByIndex,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR,LONG_RETURN
+ .END
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s
new file mode 100644
index 0000000000..7a207addfd
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s
@@ -0,0 +1,108 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * 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/. */
+
+ .LEVEL 1.1
+ .text
+ .align 4
+
+framesz:
+ .equ 128
+
+.globl NS_InvokeByIndex
+ .type NS_InvokeByIndex, @function
+
+
+NS_InvokeByIndex:
+ .PROC
+ .CALLINFO FRAME=72, CALLER,SAVE_RP, SAVE_SP, ENTRY_GR=3
+ .ENTRY
+
+; frame marker takes 48 bytes,
+; register spill area takes 8 bytes,
+; local stack area takes 72 bytes result in 128 bytes total
+
+ STW %rp,-20(%sp)
+ STW,MA %r3,128(%sp)
+
+ LDO -framesz(%r30),%r28
+ STW %r28,-4(%r30) ; save previous sp
+ STW %r19,-32(%r30)
+
+ STW %r26,-36-framesz(%r30) ; save argument registers in
+ STW %r25,-40-framesz(%r30) ; in PREVIOUS frame
+ STW %r24,-44-framesz(%r30) ;
+ STW %r23,-48-framesz(%r30) ;
+
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26;out=28
+ BL invoke_count_bytes,%r31
+ COPY %r31,%r2
+
+ CMPIB,>= 0,%r28, .+76
+ COPY %r30,%r3 ; copy stack ptr to saved stack ptr
+ ADD %r30,%r28,%r30 ; extend stack frame
+ LDW -4(%r3),%r28 ; move frame
+ STW %r28,-4(%r30)
+ LDW -8(%r3),%r28
+ STW %r28,-8(%r30)
+ LDW -12(%r3),%r28
+ STW %r28,-12(%r30)
+ LDW -16(%r3),%r28
+ STW %r28,-16(%r30)
+ LDW -20(%r3),%r28
+ STW %r28,-20(%r30)
+ LDW -24(%r3),%r28
+ STW %r28,-24(%r30)
+ LDW -28(%r3),%r28
+ STW %r28,-28(%r30)
+ LDW -32(%r3),%r28
+ STW %r28,-32(%r30)
+
+ LDO -40(%r30),%r26 ; load copy address
+ LDW -44-framesz(%r3),%r25 ; load rest of 2 arguments
+ LDW -48-framesz(%r3),%r24 ;
+
+ LDW -32(%r30),%r19 ; shared lib call destroys r19; reload
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26
+ BL invoke_copy_to_stack,%r31
+ COPY %r31,%r2
+
+ LDO -48(%r30),%r20
+ EXTRW,U,= %r28,31,1,%r22
+ FLDD 0(%r20),%fr7 ; load double arg 1
+ EXTRW,U,= %r28,30,1,%r22
+ FLDW 8(%r20),%fr5L ; load float arg 1
+ EXTRW,U,= %r28,29,1,%r22
+ FLDW 4(%r20),%fr6L ; load float arg 2
+ EXTRW,U,= %r28,28,1,%r22
+ FLDW 0(%r20),%fr7L ; load float arg 3
+
+ LDW -36-framesz(%r3),%r26 ; load ptr to 'that'
+ LDW -40(%r30),%r25 ; load the rest of dispatch argument registers
+ LDW -44(%r30),%r24
+ LDW -48(%r30),%r23
+
+ LDW -36-framesz(%r3),%r20 ; load vtable addr
+ LDW -40-framesz(%r3),%r28 ; load index
+ LDW 0(%r20),%r20 ; follow vtable
+ SH2ADDL %r28,%r20,%r28 ; add 4*index to vtable entry
+ LDW 0(%r28),%r22 ; load vtable entry
+
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR ;in=22-26;out=28;
+ BL $$dyncall,%r31
+ COPY %r31,%r2
+
+ LDW -32(%r30),%r19
+ COPY %r3,%r30 ; restore saved stack ptr
+
+ LDW -148(%sp),%rp
+ LDWM -128(%sp),%r3
+ BV,N (%rp)
+ NOP
+ .EXIT
+ .PROCEND ;in=23,24,25,26;
+ .SIZE NS_InvokeByIndex, .-NS_InvokeByIndex
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S
new file mode 100644
index 0000000000..37211c8853
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S
@@ -0,0 +1,167 @@
+# 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 r0,0; .set r1,1; .set r2,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+# The ABI defines a fixed stack frame area of 4 doublewords (ELFv2)
+# or 6 doublewords (ELFv1); the last of these doublewords is used
+# as TOC pointer save area. The fixed area is followed by a parameter
+# save area of 8 doublewords (used for vararg routines), followed
+# by space for parameters passed on the stack.
+#
+# We set STACK_TOC to the offset of the TOC pointer save area, and
+# STACK_PARAMS to the offset of the first on-stack parameter.
+
+#if _CALL_ELF == 2
+#define STACK_TOC 24
+#define STACK_PARAMS 96
+#else
+#define STACK_TOC 40
+#define STACK_PARAMS 112
+#endif
+
+#
+# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+#if _CALL_ELF == 2
+ .section ".text"
+ .type NS_InvokeByIndex,@function
+ .globl NS_InvokeByIndex
+ .align 2
+NS_InvokeByIndex:
+0: addis 2,12,(.TOC.-0b)@ha
+ addi 2,2,(.TOC.-0b)@l
+ .localentry NS_InvokeByIndex,.-NS_InvokeByIndex
+#else
+ .section ".toc","aw"
+ .section ".text"
+ .align 2
+ .globl NS_InvokeByIndex
+ .section ".opd","aw"
+ .align 3
+NS_InvokeByIndex:
+ .quad .NS_InvokeByIndex,.TOC.@tocbase
+ .previous
+ .type NS_InvokeByIndex,@function
+.NS_InvokeByIndex:
+#endif
+ mflr 0
+ std 0,16(r1)
+
+ std r29,-24(r1)
+ std r30,-16(r1)
+ std r31,-8(r1)
+
+ mr r29,r3 # Save 'that' in r29
+ mr r30,r4 # Save 'methodIndex' in r30
+ mr r31,r1 # Save old frame
+
+ # Allocate stack frame with space for params. Since at least the
+ # first 7 parameters (not including 'that') will be in registers,
+ # we don't actually need stack space for those. We must ensure
+ # that the stack remains 16-byte aligned.
+ #
+ # | (fixed area + | | 7 GP | 13 FP | 3 NV |
+ # | param. save) |(params)........| regs | regs | regs |
+ # (r1)......(+STACK_PARAMS)... (-23*8).(-16*8).(-3*8)..(r31)
+
+ # +stack frame, -unused stack params, +regs storage, +1 for alignment
+ addi r7,r5,((STACK_PARAMS/8)-7+7+13+3+1)
+ rldicr r7,r7,3,59 # multiply by 8 and mask with ~15
+ neg r7,r7
+ stdux r1,r1,r7
+
+
+ # Call invoke_copy_to_stack(uint64_t* gpregs, double* fpregs,
+ # uint32_t paramCount, nsXPTCVariant* s,
+ # uint64_t* d))
+
+ # r5, r6 are passed through intact (paramCount, params)
+ # r7 (d) has to be r1+STACK_PARAMS
+ # -- where parameters are passed on the stack.
+ # r3, r4 are above that, easier to address from r31 than from r1
+
+ subi r3,r31,(23*8) # r3 --> GPRS
+ subi r4,r31,(16*8) # r4 --> FPRS
+ addi r7,r1,STACK_PARAMS # r7 --> params
+ bl invoke_copy_to_stack
+ nop
+
+ # Set up to invoke function
+
+ ld r9,0(r29) # vtable (r29 is 'that')
+ mr r3,r29 # self is first arg, obviously
+
+ sldi r30,r30,3 # Find function descriptor
+ add r9,r9,r30
+ ld r12,0(r9)
+
+ std r2,STACK_TOC(r1) # Save r2 (TOC pointer)
+
+#if _CALL_ELF == 2
+ mtctr r12
+#else
+ ld r0,0(r12) # Actual address from fd.
+ mtctr 0
+ ld r11,16(r12) # Environment pointer from fd.
+ ld r2,8(r12) # TOC pointer from fd.
+#endif
+
+ # Load FP and GP registers as required
+ ld r4, -(23*8)(r31)
+ ld r5, -(22*8)(r31)
+ ld r6, -(21*8)(r31)
+ ld r7, -(20*8)(r31)
+ ld r8, -(19*8)(r31)
+ ld r9, -(18*8)(r31)
+ ld r10, -(17*8)(r31)
+
+ lfd f1, -(16*8)(r31)
+ lfd f2, -(15*8)(r31)
+ lfd f3, -(14*8)(r31)
+ lfd f4, -(13*8)(r31)
+ lfd f5, -(12*8)(r31)
+ lfd f6, -(11*8)(r31)
+ lfd f7, -(10*8)(r31)
+ lfd f8, -(9*8)(r31)
+ lfd f9, -(8*8)(r31)
+ lfd f10, -(7*8)(r31)
+ lfd f11, -(6*8)(r31)
+ lfd f12, -(5*8)(r31)
+ lfd f13, -(4*8)(r31)
+
+ bctrl # Do it
+
+ ld r2,STACK_TOC(r1) # Load our own TOC pointer
+ ld r1,0(r1) # Revert stack frame
+ ld 0,16(r1) # Reload lr
+ ld 29,-24(r1) # Restore NVGPRS
+ ld 30,-16(r1)
+ ld 31,-8(r1)
+ mtlr 0
+ blr
+
+#if _CALL_ELF == 2
+ .size NS_InvokeByIndex,.-NS_InvokeByIndex
+#else
+ .size NS_InvokeByIndex,.-.NS_InvokeByIndex
+#endif
+
+ # Magic indicating no need for an executable stack
+ .section .note.GNU-stack, "", @progbits ; .previous
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s
new file mode 100644
index 0000000000..eb6b6661d3
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s
@@ -0,0 +1,129 @@
+#
+# -*- 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/.
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+.set BO_IF,12
+.set CR0_EQ,2
+
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .NS_InvokeByIndex
+ .globl NS_InvokeByIndex{DS}
+ .extern .invoke_copy_to_stack
+ .extern ._ptrgl{PR}
+
+
+#
+# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+.NS_InvokeByIndex:
+ mflr r0
+ stw r31,-4(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ stw r3,24(sp) # that
+ stw r4,28(sp) # methodIndex
+ stw r5,32(sp) # paramCount
+ stw r6,36(sp) # params
+ stw r0,8(sp)
+ stwu sp,-136(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,168(sp) # paramCount
+ lwz r5,172(sp) # params
+ mr r6,sp # fprData
+ slwi r3,r4,3 # number of bytes of stack required
+ # at most 8*paramCount
+ addi r3,r3,28 # linkage area
+ mr r31,sp # save original stack top
+ subfc sp,r3,sp # bump the stack
+ addi r3,sp,28 # parameter pointer excludes linkage area size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31) # Restore floating point registers
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,160(r31) # that
+ lwz r4,0(r3) # get vTable from 'that'
+ lwz r5,164(r31) # methodIndex
+ slwi r5,r5,3 # methodIndex * 8
+ addi r5,r5,8 # step over junk at start of vTable !
+ lwzx r11,r5,r4 # get function pointer
+
+ addi r5,r5,4 # We need to manually adjust the 'that' pointer, this is CFRONT based
+ lwzx r5,r4,r5 # offset = r4(vtable) + r5(methodIndex offset) - 4
+ add r3,r5,r3 # adjust 'that' r3 = r3 + r5
+
+ lwz r4,28(sp)
+ lwz r5,32(sp)
+ lwz r6,36(sp)
+ lwz r7,40(sp)
+ lwz r8,44(sp)
+ lwz r9,48(sp)
+ lwz r10,52(sp)
+
+ bl ._ptrgl{PR}
+ nop
+
+ mr sp,r31
+ lwz r0,144(sp)
+ addi sp,sp,136
+ mtlr r0
+ lwz r31,-4(sp)
+ blr
+
+
+# .data section
+
+ .toc # 0x00000038
+T.18.NS_InvokeByIndex:
+ .tc H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS}
+
+ .csect NS_InvokeByIndex{DS}
+ .long .NS_InvokeByIndex # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect NS_InvokeByIndex{DS}
+
+# .bss section
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s
new file mode 100644
index 0000000000..722583de5b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s
@@ -0,0 +1,128 @@
+# 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 r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+.set BO_IF,12
+.set CR0_EQ,2
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .NS_InvokeByIndex
+ .globl NS_InvokeByIndex{DS}
+ .extern .invoke_copy_to_stack
+ .extern ._ptrgl{PR}
+
+#
+# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+.NS_InvokeByIndex:
+ mflr r0
+ std r31,-8(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ std r3,48(sp) # that
+ std r4,56(sp) # methodIndex
+ std r5,64(sp) # paramCount
+ std r6,72(sp) # params
+ std r0,16(sp)
+ stdu sp,-168(sp) # 2*24=48 for linkage area,
+ # 8*13=104 for fprData area
+ # 16 for saved registers
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ ld r4,232(sp) # paramCount (168+8+56)
+ ld r5,240(sp) # params
+ mr r6,sp # fprData
+ sldi r3,r4,3 # number of bytes of stack required
+ # is at most numParams*8
+ addi r3,r3,56 # linkage area (48) + this (8)
+ mr r31,sp # save original stack top
+ subfc sp,r3,sp # bump the stack
+ addi r3,sp,56 # parameter pointer excludes linkage area
+ # size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31) # Restore floating point registers
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ ld r3,216(r31) # that (168+48)
+ ld r4,0(r3) # get vTable from 'that'
+ ld r5,224(r31) # methodIndex (168+56)
+ sldi r5,r5,3 # methodIndex * 8
+ # No junk at the start of 64bit vtable !!!
+ ldx r11,r5,r4 # get function pointer (this jumps
+ # either to the function if no adjustment
+ # is needed (displacement = 0), or it
+ # jumps to the thunk code, which will jump
+ # to the function at the end)
+
+ # No adjustment of the that pointer in 64bit mode, this is done
+ # by the thunk code
+
+ ld r4,56(sp)
+ ld r5,64(sp)
+ ld r6,72(sp)
+ ld r7,80(sp)
+ ld r8,88(sp)
+ ld r9,96(sp)
+ ld r10,104(sp)
+
+ bl ._ptrgl{PR}
+ nop
+
+ mr sp,r31
+ ld r0,184(sp) # 168+16
+ addi sp,sp,168
+ mtlr r0
+ ld r31,-8(sp)
+ blr
+
+# .data section
+
+ .toc # 0x00000038
+T.18.NS_InvokeByIndex:
+ .tc H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS}
+
+ .csect NS_InvokeByIndex{DS}
+ .llong .NS_InvokeByIndex # "\0\0\0\0"
+ .llong TOC{TC0} # "\0\0\0008"
+ .llong 0x00000000 # "\0\0\0\0"
+# End csect NS_InvokeByIndex{DS}
+
+# .bss section
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
new file mode 100644
index 0000000000..414a6536fa
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
@@ -0,0 +1,124 @@
+#
+# -*- 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/.
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+.set BO_IF,12
+.set CR0_EQ,2
+
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .NS_InvokeByIndex
+ .globl NS_InvokeByIndex{DS}
+ .extern .invoke_copy_to_stack
+ .extern ._ptrgl{PR}
+
+
+#
+# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+.NS_InvokeByIndex:
+ mflr r0
+ stw r31,-4(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ stw r3,24(sp) # that
+ stw r4,28(sp) # methodIndex
+ stw r5,32(sp) # paramCount
+ stw r6,36(sp) # params
+ stw r0,8(sp)
+ stwu sp,-136(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,168(sp) # paramCount
+ lwz r5,172(sp) # params
+ mr r6,sp # fprData
+ slwi r3,r4,3 # number of bytes of stack required
+ # at most 8*paramCount
+ addi r3,r3,28 # linkage area
+ mr r31,sp # save original stack top
+ subfc sp,r3,sp # bump the stack
+ addi r3,sp,28 # parameter pointer excludes linkage area size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31) # Restore floating point registers
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,160(r31) # that
+ lwz r4,0(r3) # get vTable from 'that'
+ lwz r5,164(r31) # methodIndex
+ slwi r5,r5,2 # methodIndex * 4
+ lwzx r11,r5,r4 # get function pointer
+
+ lwz r4,28(sp)
+ lwz r5,32(sp)
+ lwz r6,36(sp)
+ lwz r7,40(sp)
+ lwz r8,44(sp)
+ lwz r9,48(sp)
+ lwz r10,52(sp)
+
+ bl ._ptrgl{PR}
+ nop
+
+ mr sp,r31
+ lwz r0,144(sp)
+ addi sp,sp,136
+ mtlr r0
+ lwz r31,-4(sp)
+ blr
+
+
+# .data section
+
+ .toc # 0x00000038
+T.18.NS_InvokeByIndex:
+ .tc H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS}
+
+ .csect NS_InvokeByIndex{DS}
+ .long .NS_InvokeByIndex # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect NS_InvokeByIndex{DS}
+
+# .bss section
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S
new file mode 100644
index 0000000000..e87382286c
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S
@@ -0,0 +1,98 @@
+// -*- Mode: Asm -*-
+//
+// 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 r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl NS_InvokeByIndex
+ .type NS_InvokeByIndex,@function
+
+//
+// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+// uint32_t paramCount, nsXPTCVariant* params)
+//
+
+NS_InvokeByIndex:
+ stwu sp,-32(sp) // setup standard stack frame
+ mflr r0 // save LR
+ stw r3,8(sp) // r3 <= that
+ stw r4,12(sp) // r4 <= methodIndex
+ stw r30,16(sp)
+ stw r31,20(sp)
+
+ stw r0,36(sp) // store LR backchain
+ mr r31,sp
+
+ rlwinm r10,r5,3,0,27 // r10 = (ParamCount * 2 * 4) & ~0x0f
+ addi r0,r10,96 // reserve stack for GPR and FPR register save area r0 = r10 + 96
+ lwz r9,0(sp) // r9 = backchain
+ neg r0,r0
+ stwux r9,sp,r0 // reserve stack space and save SP backchain
+
+ addi r3,sp,8 // r3 <= args
+ mr r4,r5 // r4 <= paramCount
+ mr r5,r6 // r5 <= params
+ add r6,r3,r10 // r6 <= gpregs ( == args + r10 )
+ mr r30,r6 // store in r30 for use later...
+#ifndef __NO_FPRS__
+ addi r7,r6,32 // r7 <= fpregs ( == gpregs + 32 )
+#else
+ li r7, 0
+#endif
+
+ bl invoke_copy_to_stack@local // (args, paramCount, params, gpregs, fpregs)
+#ifndef __NO_FPRS__
+ lfd f1,32(r30) // load FP registers with method parameters
+ lfd f2,40(r30)
+ lfd f3,48(r30)
+ lfd f4,56(r30)
+ lfd f5,64(r30)
+ lfd f6,72(r30)
+ lfd f7,80(r30)
+ lfd f8,88(r30)
+#endif
+ lwz r3,8(r31) // r3 <= that
+ lwz r4,12(r31) // r4 <= methodIndex
+ lwz r5,0(r3) // r5 <= vtable ( == *that )
+ slwi r4,r4,2 // convert to offset ( *= 4 )
+ lwzx r0,r5,r4 // r0 <= methodpointer ( == vtable + offset )
+
+ lwz r4,4(r30) // load GP regs with method parameters
+ lwz r5,8(r30)
+ lwz r6,12(r30)
+ lwz r7,16(r30)
+ lwz r8,20(r30)
+ lwz r9,24(r30)
+ lwz r10,28(r30)
+
+ mtlr r0 // copy methodpointer to LR
+ blrl // call method
+
+ lwz r30,16(r31) // restore r30 & r31
+ lwz r31,20(r31)
+
+ lwz r11,0(sp) // clean up the stack
+ lwz r0,4(r11)
+ mtlr r0
+ mr sp,r11
+ blr
+
+/* Magic indicating no need for an executable stack */
+.section .note.GNU-stack, "", @progbits ; .previous
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_netbsd.s
new file mode 100644
index 0000000000..33650f399d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_netbsd.s
@@ -0,0 +1,95 @@
+# -*- Mode: Asm -*-
+#
+# 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 r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl XPTC_InvokeByIndex
+ .type XPTC_InvokeByIndex,@function
+
+#
+# XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+XPTC_InvokeByIndex:
+ stwu sp,-32(sp) # setup standard stack frame
+ mflr r0 # save LR
+ stw r3,8(sp) # r3 <= that
+ stw r4,12(sp) # r4 <= methodIndex
+ stw r30,16(sp)
+ stw r31,20(sp)
+
+ stw r0,36(sp) # store LR backchain
+ mr r31,sp
+
+ rlwinm r10,r5,3,0,27 # r10 = (ParamCount * 2 * 4) & ~0x0f
+ addi r0,r10,96 # reserve stack for GPR and FPR register save area r0 = r10 + 96
+ lwz r9,0(sp) # r9 = backchain
+ neg r0,r0
+ stwux r9,sp,r0 # reserve stack sapce and save SP backchain
+
+ addi r3,sp,8 # r3 <= args
+ mr r4,r5 # r4 <= paramCount
+ mr r5,r6 # r5 <= params
+ add r6,r3,r10 # r6 <= gpregs ( == args + r10 )
+ mr r30,r6 # store in r30 for use later...
+ addi r7,r6,32 # r7 <= fpregs ( == gpregs + 32 )
+
+ bl invoke_copy_to_stack@local # (args, paramCount, params, gpregs, fpregs)
+
+ lfd f1,32(r30) # load FP registers with method parameters
+ lfd f2,40(r30)
+ lfd f3,48(r30)
+ lfd f4,56(r30)
+ lfd f5,64(r30)
+ lfd f6,72(r30)
+ lfd f7,80(r30)
+ lfd f8,88(r30)
+
+ lwz r3,8(r31) # r3 <= that
+ lwz r4,12(r31) # r4 <= methodIndex
+ lwz r5,0(r3) # r5 <= vtable ( == *that )
+ slwi r4,r4,3 # convert to offset ( *= 8 )
+ addi r4,r4,8 # skip first two vtable entries
+ add r4,r4,r5
+ lhz r0,0(r4) # virtual base offset
+ extsh r0,r0
+ add r3,r3,r0
+ lwz r0,4(r4) # r0 <= methodpointer ( == vtable + offset )
+
+ lwz r4,4(r30) # load GP regs with method parameters
+ lwz r5,8(r30)
+ lwz r6,12(r30)
+ lwz r7,16(r30)
+ lwz r8,20(r30)
+ lwz r9,24(r30)
+ lwz r10,28(r30)
+
+ mtlr r0 # copy methodpointer to LR
+ blrl # call method
+
+ lwz r30,16(r31) # restore r30 & r31
+ lwz r31,20(r31)
+
+ lwz r11,0(sp) # clean up the stack
+ lwz r0,4(r11)
+ mtlr r0
+ mr sp,r11
+ blr
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S
new file mode 100644
index 0000000000..f02c0b2204
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S
@@ -0,0 +1,94 @@
+// -*- Mode: Asm -*-
+//
+// 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 r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl NS_InvokeByIndex
+ .type NS_InvokeByIndex,@function
+
+//
+// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+// uint32_t paramCount, nsXPTCVariant* params)
+//
+
+NS_InvokeByIndex:
+ stwu sp,-32(sp) // setup standard stack frame
+ mflr r0 // save LR
+ stw r3,8(sp) // r3 <= that
+ stw r4,12(sp) // r4 <= methodIndex
+ stw r30,16(sp)
+ stw r31,20(sp)
+
+ stw r0,36(sp) // store LR backchain
+ mr r31,sp
+
+ rlwinm r10,r5,3,0,27 // r10 = (ParamCount * 2 * 4) & ~0x0f
+ addi r0,r10,96 // reserve stack for GPR and FPR register save area r0 = r10 + 96
+ lwz r9,0(sp) // r9 = backchain
+ neg r0,r0
+ stwux r9,sp,r0 // reserve stack space and save SP backchain
+
+ addi r3,sp,8 // r3 <= args
+ mr r4,r5 // r4 <= paramCount
+ mr r5,r6 // r5 <= params
+ add r6,r3,r10 // r6 <= gpregs ( == args + r10 )
+ mr r30,r6 // store in r30 for use later...
+ addi r7,r6,32 // r7 <= fpregs ( == gpregs + 32 )
+
+ bl invoke_copy_to_stack@local // (args, paramCount, params, gpregs, fpregs)
+
+ lfd f1,32(r30) // load FP registers with method parameters
+ lfd f2,40(r30)
+ lfd f3,48(r30)
+ lfd f4,56(r30)
+ lfd f5,64(r30)
+ lfd f6,72(r30)
+ lfd f7,80(r30)
+ lfd f8,88(r30)
+
+ lwz r3,8(r31) // r3 <= that
+ lwz r4,12(r31) // r4 <= methodIndex
+ lwz r5,0(r3) // r5 <= vtable ( == *that )
+ slwi r4,r4,2 // convert to offset ( *= 4 )
+ lwzx r0,r5,r4 // r0 <= methodpointer ( == vtable + offset )
+
+ lwz r4,4(r30) // load GP regs with method parameters
+ lwz r5,8(r30)
+ lwz r6,12(r30)
+ lwz r7,16(r30)
+ lwz r8,20(r30)
+ lwz r9,24(r30)
+ lwz r10,28(r30)
+
+ mtlr r0 // copy methodpointer to LR
+ blrl // call method
+
+ lwz r30,16(r31) // restore r30 & r31
+ lwz r31,20(r31)
+
+ lwz r11,0(sp) // clean up the stack
+ lwz r0,4(r11)
+ mtlr r0
+ mr sp,r11
+ blr
+
+// Magic indicating no need for an executable stack
+.section .note.GNU-stack, "", @progbits ; .previous
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s
new file mode 100644
index 0000000000..1dc12b2b30
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s
@@ -0,0 +1,142 @@
+#
+# -*- Mode: Asm -*-
+#
+# 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/.
+
+#
+# ** Assumed vtable layout (obtained by disassembling with gdb):
+# ** 4 bytes per vtable entry, skip 0th and 1st entries, so the mapping
+# ** from index to entry is (4 * index) + 8.
+#
+
+.text
+ .align 2
+#
+# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+.globl __NS_InvokeByIndex
+__NS_InvokeByIndex:
+ mflr r0
+ stw r31,-4(r1)
+#
+# save off the incoming values in the callers parameter area
+#
+ stw r3,24(r1) ; that
+ stw r4,28(r1) ; methodIndex
+ stw r5,32(r1) ; paramCount
+ stw r6,36(r1) ; params
+ stw r0,8(r1)
+ stwu r1,-144(r1) ; 24 for linkage area,
+ ; 8*13 for fprData area,
+ ; 8 for saved registers,
+ ; 8 to keep stack 16-byte aligned
+
+# set up for and call 'invoke_count_words' to get new stack size
+#
+ mr r3,r5
+ mr r4,r6
+
+ stwu r1,-24(r1)
+ bl L_invoke_count_words$stub
+ lwz r1,0(r1)
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,176(r1) ; paramCount
+ lwz r5,180(r1) ; params
+ mr r6,r1 ; fprData
+ slwi r3,r3,2 ; number of stack bytes required
+ addi r3,r3,28 ; linkage area
+ mr r31,r1 ; save original stack top
+ sub r1,r1,r3 ; bump the stack
+ clrrwi r1,r1,4 ; keep the stack 16-byte aligned
+ addi r3,r31,144 ; act like real alloca, so 0(sp) always
+ stw r3,0(r1) ; points back to previous stack frame
+ addi r3,r1,28 ; parameter pointer excludes linkage area size + 'this'
+
+# create "temporary" stack frame for _invoke_copy_to_stack to operate in.
+ stwu r1,-40(r1)
+ bl L_invoke_copy_to_stack$stub
+# remove temporary stack frame.
+ lwz r1,0(r1)
+
+ lfd f1,0(r31)
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,168(r31) ; that
+ lwz r4,0(r3) ; get vTable from 'that'
+ lwz r5,172(r31) ; methodIndex
+ slwi r5,r5,2 ; methodIndex * 4
+ lwzx r12,r5,r4 ; get function pointer
+
+ lwz r4,28(r1)
+ lwz r5,32(r1)
+ lwz r6,36(r1)
+ lwz r7,40(r1)
+ lwz r8,44(r1)
+ lwz r9,48(r1)
+ lwz r10,52(r1)
+
+ mtlr r12
+ blrl
+
+ mr r1,r31
+ lwz r0,152(r1)
+ addi r1,r1,144
+ mtlr r0
+ lwz r31,-4(r1)
+
+ blr
+
+.picsymbol_stub
+L_invoke_count_words$stub:
+ .indirect_symbol _invoke_count_words
+ mflr r0
+ bcl 20,31,L1$pb
+L1$pb:
+ mflr r11
+ addis r11,r11,ha16(L1$lz-L1$pb)
+ mtlr r0
+ lwz r12,lo16(L1$lz-L1$pb)(r11)
+ mtctr r12
+ addi r11,r11,lo16(L1$lz-L1$pb)
+ bctr
+.lazy_symbol_pointer
+L1$lz:
+ .indirect_symbol _invoke_count_words
+ .long dyld_stub_binding_helper
+
+
+.picsymbol_stub
+L_invoke_copy_to_stack$stub:
+ .indirect_symbol _invoke_copy_to_stack
+ mflr r0
+ bcl 20,31,L2$pb
+L2$pb:
+ mflr r11
+ addis r11,r11,ha16(L2$lz-L2$pb)
+ mtlr r0
+ lwz r12,lo16(L2$lz-L2$pb)(r11)
+ mtctr r12
+ addi r11,r11,lo16(L2$lz-L2$pb)
+ bctr
+.lazy_symbol_pointer
+L2$lz:
+ .indirect_symbol _invoke_copy_to_stack
+ .long dyld_stub_binding_helper
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s
new file mode 100644
index 0000000000..dfd6189f83
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc64_openbsd.s
@@ -0,0 +1,86 @@
+/* -*- Mode: asm; tab-width: 2; 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/. */
+
+/*
+ Platform specific code to invoke XPCOM methods on native objects
+ for sparcv9 Solaris.
+
+ See the SPARC Compliance Definition (SCD) Chapter 3
+ for more information about what is going on here, including
+ the use of BIAS (0x7ff).
+ The SCD is available from http://www.sparc.com/.
+*/
+
+ .global NS_InvokeByIndex
+ .type NS_InvokeByIndex, #function
+
+/*
+ NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+*/
+NS_InvokeByIndex:
+ save %sp,-(128 + 64),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 64
+ sll %i2,4,%l0 ! assume the worst case
+ ! paramCount * 2 * 8 bytes
+ cmp %l0, 0 ! are there any args? If not,
+ be .invoke ! no need to copy args to stack
+ nop
+
+ sub %sp,%l0,%sp ! create the additional stack space
+ add %sp,0x7ff+136,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+
+!
+! load arguments from stack into the outgoing registers
+! BIAS is 0x7ff (2047)
+!
+
+! load the %o1..5 64bit (extended word) output registers registers
+ ldx [%sp + 0x7ff + 136],%o1 ! %i1
+ ldx [%sp + 0x7ff + 144],%o2 ! %i2
+ ldx [%sp + 0x7ff + 152],%o3 ! %i3
+ ldx [%sp + 0x7ff + 160],%o4 ! %i4
+ ldx [%sp + 0x7ff + 168],%o5 ! %i5
+
+! load the even number double registers starting with %f2
+ ldd [%sp + 0x7ff + 136],%f2
+ ldd [%sp + 0x7ff + 144],%f4
+ ldd [%sp + 0x7ff + 152],%f6
+ ldd [%sp + 0x7ff + 160],%f8
+ ldd [%sp + 0x7ff + 168],%f10
+ ldd [%sp + 0x7ff + 176],%f12
+ ldd [%sp + 0x7ff + 184],%f14
+ ldd [%sp + 0x7ff + 192],%f16
+ ldd [%sp + 0x7ff + 200],%f18
+ ldd [%sp + 0x7ff + 208],%f20
+ ldd [%sp + 0x7ff + 216],%f22
+ ldd [%sp + 0x7ff + 224],%f24
+ ldd [%sp + 0x7ff + 232],%f26
+ ldd [%sp + 0x7ff + 240],%f28
+ ldd [%sp + 0x7ff + 248],%f30
+
+!
+! calculate the target address from the vtable
+!
+.invoke:
+ sll %i1,3,%l0 ! index *= 8
+! add %l0,16,%l0 ! there are 2 extra entries in the vTable (16bytes)
+ ldx [%i0],%l1 ! *that --> address of vtable
+ ldx [%l0 + %l1],%l0 ! that->vtable[index * 8 + 16] --> address
+
+ jmpl %l0,%o7 ! call the routine
+ mov %i0,%o0 ! move 'this' pointer to out register
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
+
+ .size NS_InvokeByIndex, .-NS_InvokeByIndex
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s
new file mode 100644
index 0000000000..36196805e8
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s
@@ -0,0 +1,53 @@
+/* -*- 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 for
+ * Linux/Sparc with gcc 3 ABI.
+ */
+ .global NS_InvokeByIndex
+/*
+ * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ * uint32_t paramCount, nsXPTCVariant* params);
+ *
+ */
+NS_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,2,%i1 ! multiply index by 4
+ add %i1,%l1,%l1 ! l1 now points to vTable entry
+ ld [%l1],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s
new file mode 100644
index 0000000000..893432a5e8
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s
@@ -0,0 +1,55 @@
+/* -*- 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 */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?)
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,3,%i1
+ add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry
+ lduh [%l1],%l0 ! this adjustor
+ sll %l0,16,%l0 ! sign extend to 32 bits
+ sra %l0,16,%l0
+ add %l0,%i0,%i0 ! adjust this
+ ld [%l1 + 4],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s
new file mode 100644
index 0000000000..1ef6953703
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s
@@ -0,0 +1,55 @@
+/* -*- 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 */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?)
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,3,%i1
+ add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry
+ lduh [%l1],%l0 ! this adjustor
+ sll %l0,16,%l0 ! sign extend to 32 bits
+ sra %l0,16,%l0
+ add %l0,%i0,%i0 ! adjust this
+ ld [%l1 + 4],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s
new file mode 100644
index 0000000000..54adcd1474
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s
@@ -0,0 +1,52 @@
+/* -*- 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 for
+ * solaris/sparc with gcc 3 ABI.
+ */
+ .global NS_InvokeByIndex
+/*
+ * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ * uint32_t paramCount, nsXPTCVariant* params);
+ */
+NS_InvokeByIndex:
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,2,%i1 ! multiply index by 4
+ add %i1,%l1,%l1 ! l1 now points to vTable entry
+ ld [%l1],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s
new file mode 100644
index 0000000000..0137703924
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s
@@ -0,0 +1,56 @@
+/* -*- 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 */
+
+ .global NS_InvokeByIndex
+ .type NS_InvokeByIndex, #function
+/*
+ NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+*/
+NS_InvokeByIndex:
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+ sll %i2,3,%l0 ! assume the worst case
+ ! paramCount * 2 * 4 bytes
+ cmp %l0, 0 ! are there any args? If not,
+ be .invoke ! no need to copy args to stack
+
+ sub %sp,%l0,%sp ! create the additional stack space
+ add %sp,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+
+!
+! load arguments from stack into the outgoing registers
+!
+ ld [%sp + 72],%o1
+ ld [%sp + 76],%o2
+ ld [%sp + 80],%o3
+ ld [%sp + 84],%o4
+ ld [%sp + 88],%o5
+
+!
+! calculate the target address from the vtable
+!
+.invoke:
+ sll %i1,2,%l0 ! index *= 4
+ add %l0,8,%l0 ! there are 2 extra entries in the vTable
+ ld [%i0],%l1 ! *that --> address of vtable
+ ld [%l0 + %l1],%l0 ! that->vtable[index * 4 + 8] --> address
+
+ jmpl %l0,%o7 ! call the routine
+ mov %i0,%o0 ! move 'this' pointer to out register
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
+
+ .size NS_InvokeByIndex, .-NS_InvokeByIndex
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s
new file mode 100644
index 0000000000..34861abc0e
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s
@@ -0,0 +1,85 @@
+/* -*- Mode: asm; tab-width: 2; 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/. */
+
+/*
+ Platform specific code to invoke XPCOM methods on native objects
+ for sparcv9 Solaris.
+
+ See the SPARC Compliance Definition (SCD) Chapter 3
+ for more information about what is going on here, including
+ the use of BIAS (0x7ff).
+ The SCD is available from http://www.sparc.com/.
+*/
+
+ .global NS_InvokeByIndex
+ .type NS_InvokeByIndex, #function
+
+/*
+ NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+*/
+NS_InvokeByIndex:
+ save %sp,-(128 + 64),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 64
+ sll %i2,4,%l0 ! assume the worst case
+ ! paramCount * 2 * 8 bytes
+ cmp %l0, 0 ! are there any args? If not,
+ be .invoke ! no need to copy args to stack
+
+ sub %sp,%l0,%sp ! create the additional stack space
+ add %sp,0x7ff+136,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+
+!
+! load arguments from stack into the outgoing registers
+! BIAS is 0x7ff (2047)
+!
+
+! load the %o1..5 64bit (extended word) output registers registers
+ ldx [%sp + 0x7ff + 136],%o1 ! %i1
+ ldx [%sp + 0x7ff + 144],%o2 ! %i2
+ ldx [%sp + 0x7ff + 152],%o3 ! %i3
+ ldx [%sp + 0x7ff + 160],%o4 ! %i4
+ ldx [%sp + 0x7ff + 168],%o5 ! %i5
+
+! load the even number double registers starting with %d2
+ ldd [%sp + 0x7ff + 136],%d2
+ ldd [%sp + 0x7ff + 144],%d4
+ ldd [%sp + 0x7ff + 152],%d6
+ ldd [%sp + 0x7ff + 160],%d8
+ ldd [%sp + 0x7ff + 168],%d10
+ ldd [%sp + 0x7ff + 176],%d12
+ ldd [%sp + 0x7ff + 184],%d14
+ ldd [%sp + 0x7ff + 192],%d16
+ ldd [%sp + 0x7ff + 200],%d18
+ ldd [%sp + 0x7ff + 208],%d20
+ ldd [%sp + 0x7ff + 216],%d22
+ ldd [%sp + 0x7ff + 224],%d24
+ ldd [%sp + 0x7ff + 232],%d26
+ ldd [%sp + 0x7ff + 240],%d28
+ ldd [%sp + 0x7ff + 248],%d30
+
+!
+! calculate the target address from the vtable
+!
+.invoke:
+ sll %i1,3,%l0 ! index *= 8
+ add %l0,16,%l0 ! there are 2 extra entries in the vTable (16bytes)
+ ldx [%i0],%l1 ! *that --> address of vtable
+ ldx [%l0 + %l1],%l0 ! that->vtable[index * 8 + 16] --> address
+
+ jmpl %l0,%o7 ! call the routine
+ mov %i0,%o0 ! move 'this' pointer to out register
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
+
+ .size NS_InvokeByIndex, .-NS_InvokeByIndex
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s
new file mode 100644
index 0000000000..af665a1628
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s
@@ -0,0 +1,55 @@
+ .globl NS_InvokeByIndex
+ .type NS_InvokeByIndex, @function
+NS_InvokeByIndex:
+ push %ebp
+ movl %esp,%ebp
+ push %ebx
+ call .CG0.66
+.CG0.66:
+ pop %ebx
+ addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx
+ push 20(%ebp)
+ push 16(%ebp)
+ push 12(%ebp)
+ push 8(%ebp)
+ / INLINE: invoke_by_index
+
+
+
+ pushl %ebx
+ pushl %esi
+ movl %esp, %ebx
+
+ pushl 0x14(%ebp)
+ pushl 0x10(%ebp)
+ call invoke_count_words
+ mov %ebx, %esp
+
+ sall $0x2 , %eax
+ subl %eax, %esp
+ movl %esp, %esi
+
+ pushl %esp
+ pushl 0x14(%ebp)
+ pushl 0x10(%ebp)
+ call invoke_copy_to_stack
+ movl %esi, %esp
+
+ movl 0x8(%ebp), %ecx
+ pushl %ecx
+ movl (%ecx), %edx
+ movl 0xc(%ebp), %eax
+ movl 0x8(%edx, %eax, 4), %edx
+
+ call *%edx
+ mov %ebx, %esp
+ popl %esi
+ popl %ebx
+ / INLINE_END
+ addl $16,%esp
+ pop %ebx
+ movl %ebp,%esp
+ pop %ebp
+ ret
+ .size NS_InvokeByIndex, . - NS_InvokeByIndex
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp
new file mode 100644
index 0000000000..04407db396
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp
@@ -0,0 +1,16 @@
+/* -*- Mode: C -*- */
+/* 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/. */
+
+#if defined(__i386__)
+#include "xptcinvoke_gcc_x86_unix.cpp"
+#elif defined(__x86_64__)
+#include "xptcinvoke_x86_64_unix.cpp"
+#elif defined(__ppc__)
+#include "xptcinvoke_ppc_rhapsody.cpp"
+#elif defined(__arm__)
+#include "xptcinvoke_arm.cpp"
+#else
+#error unknown cpu architecture
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp
new file mode 100644
index 0000000000..d4a8a12fbc
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp
@@ -0,0 +1,97 @@
+/* -*- 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"
+#include "xptc_gcc_x86_unix.h"
+
+extern "C" {
+static void ATTRIBUTE_USED __attribute__ ((regparm(3)))
+invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d)
+{
+ for(uint32_t i = paramCount; i >0; i--, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ default : *((void**)d) = s->val.p; break;
+ }
+ }
+}
+} // extern "C"
+
+/*
+ EXPORT_XPCOM_API(nsresult)
+ NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+ Each param takes at most two 4-byte words.
+ It doesn't matter if we push too many words, and calculating the exact
+ amount takes time.
+
+ that = ebp + 0x08
+ methodIndex = ebp + 0x0c
+ paramCount = ebp + 0x10
+ params = ebp + 0x14
+
+*/
+
+__asm__ (
+ ".text\n\t"
+/* alignment here seems unimportant here; this was 16, now it's 2 which
+ is what xptcstubs uses. */
+ ".align 2\n\t"
+ ".globl " SYMBOL_UNDERSCORE "NS_InvokeByIndex\n\t"
+#ifndef XP_MACOSX
+ ".type " SYMBOL_UNDERSCORE "NS_InvokeByIndex,@function\n"
+#endif
+ SYMBOL_UNDERSCORE "NS_InvokeByIndex:\n\t"
+ "pushl %ebp\n\t"
+ "movl %esp, %ebp\n\t"
+ "movl 0x10(%ebp), %eax\n\t"
+ "leal 0(,%eax,8),%edx\n\t"
+
+ /* set up call frame for method. */
+ "subl %edx, %esp\n\t" /* make room for params. */
+/* Align to maximum x86 data size: 128 bits == 16 bytes == XMM register size.
+ * This is to avoid protection faults where SSE+ alignment of stack pointer
+ * is assumed and required, e.g. by GCC4's -ftree-vectorize option.
+ */
+ "andl $0xfffffff0, %esp\n\t" /* drop(?) stack ptr to 128-bit align */
+/* $esp should be aligned to a 16-byte boundary here (note we include an
+ * additional 4 bytes in a later push instruction). This will ensure $ebp
+ * in the function called below is aligned to a 0x8 boundary. SSE instructions
+ * like movapd/movdqa expect memory operand to be aligned on a 16-byte
+ * boundary. The GCC compiler will generate the memory operand using $ebp
+ * with an 8-byte offset.
+ */
+ "subl $0xc, %esp\n\t" /* lower again; push/call below will re-align */
+ "movl %esp, %ecx\n\t" /* ecx = d */
+ "movl 8(%ebp), %edx\n\t" /* edx = this */
+ "pushl %edx\n\t" /* push this. esp % 16 == 0 */
+
+ "movl 0x14(%ebp), %edx\n\t"
+ "call " SYMBOL_UNDERSCORE "invoke_copy_to_stack\n\t"
+ "movl 0x08(%ebp), %ecx\n\t" /* 'that' */
+ "movl (%ecx), %edx\n\t"
+ "movl 0x0c(%ebp), %eax\n\t" /* function index */
+ "leal (%edx,%eax,4), %edx\n\t"
+ "call *(%edx)\n\t"
+ "movl %ebp, %esp\n\t"
+ "popl %ebp\n\t"
+ "ret\n"
+#ifndef XP_MACOSX
+ ".size " SYMBOL_UNDERSCORE "NS_InvokeByIndex, . -" SYMBOL_UNDERSCORE "NS_InvokeByIndex\n\t"
+#endif
+);
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp
new file mode 100644
index 0000000000..1500f31757
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp
@@ -0,0 +1,132 @@
+
+/* -*- 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 <iostream.h>
+
+// "This code is for IA64 only"
+
+
+/* invoke_copy_to_stack() will copy from variant array 's' to
+ * the stack argument area 'mloc', the integer register area 'iloc', and
+ * the float register area 'floc'.
+ *
+ */
+extern "C" void
+invoke_copy_to_stack(uint64_t* mloc, uint64_t* iloc, uint64_t* floc,
+ const uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint64_t* dest = mloc;
+ uint32_t len = paramCount;
+ nsXPTCVariant* source = s;
+
+ uint32_t indx;
+ uint32_t endlen;
+ endlen = (len > 7) ? 7 : len;
+ /* handle the memory arguments */
+ for (indx = 7; indx < len; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].ptr;
+#endif
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_DOUBLE: *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+#else
+ {
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].val.p;
+ }
+#endif
+ }
+ ++dest;
+ }
+ /* process register arguments */
+ dest = iloc;
+ for (indx = 0; indx < endlen; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].ptr;
+#endif
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT :
+ *((double*) (floc++)) = (double) source[indx].val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ *((double*) (floc++)) = source[indx].val.d;
+ break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+#else
+ {
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].val.p;
+ }
+#endif
+ }
+ ++dest;
+ }
+
+}
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp
new file mode 100644
index 0000000000..c2a4dd0886
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp
@@ -0,0 +1,100 @@
+
+/* -*- 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 <stdint.h>
+
+// "This code is for IA64 only"
+
+
+/* invoke_copy_to_stack() will copy from variant array 's' to
+ * the stack argument area 'mloc', the integer register area 'iloc', and
+ * the float register area 'floc'.
+ *
+ */
+extern "C" void
+invoke_copy_to_stack(uint64_t* mloc, uint64_t* iloc, uint64_t* floc,
+ const uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint64_t* dest = mloc;
+ uint32_t len = paramCount;
+ nsXPTCVariant* source = s;
+
+ uint32_t indx;
+ uint32_t endlen;
+ endlen = (len > 7) ? 7 : len;
+ /* handle the memory arguments */
+ for (indx = 7; indx < len; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_DOUBLE: *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+ }
+ ++dest;
+ }
+ /* process register arguments */
+ dest = iloc;
+ for (indx = 0; indx < endlen; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT :
+ *((double*) (floc++)) = (double) source[indx].val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ *((double*) (floc++)) = source[indx].val.d;
+ break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+ }
+ ++dest;
+ }
+
+}
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp
new file mode 100644
index 0000000000..dc111e4358
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp
@@ -0,0 +1,144 @@
+/* -*- 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"
+
+/* Prototype specifies unmangled function name and disables unused warning */
+static void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+__asm__("invoke_copy_to_stack") __attribute__((used));
+
+static void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *d = (uint64_t)s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *d = (uint64_t)s->val.i8; break;
+ case nsXPTType::T_I16 : *d = (uint64_t)s->val.i16; break;
+ case nsXPTType::T_I32 : *d = (uint64_t)s->val.i32; break;
+ case nsXPTType::T_I64 : *d = (uint64_t)s->val.i64; break;
+ case nsXPTType::T_U8 : *d = (uint64_t)s->val.u8; break;
+ case nsXPTType::T_U16 : *d = (uint64_t)s->val.u16; break;
+ case nsXPTType::T_U32 : *d = (uint64_t)s->val.u32; break;
+ case nsXPTType::T_U64 : *d = (uint64_t)s->val.u64; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // convert floats to doubles if they are to be passed
+ // via registers so we can just deal with doubles later
+ union { uint64_t u64; double d; } t;
+ t.d = (double)s->val.f;
+ *d = t.u64;
+ }
+ else
+ // otherwise copy to stack normally
+ *d = (uint64_t)s->val.u32;
+ break;
+ case nsXPTType::T_DOUBLE : *d = (uint64_t)s->val.u64; break;
+ case nsXPTType::T_BOOL : *d = (uint64_t)s->val.b; break;
+ case nsXPTType::T_CHAR : *d = (uint64_t)s->val.c; break;
+ case nsXPTType::T_WCHAR : *d = (uint64_t)s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *d = (uint64_t)s->val.p;
+ break;
+ }
+ }
+}
+
+/*
+ * EXPORT_XPCOM_API(nsresult)
+ * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ * uint32_t paramCount, nsXPTCVariant* params)
+ */
+__asm__(
+ "#### NS_InvokeByIndex ####\n"
+".text\n\t"
+ ".align 5\n\t"
+ ".globl NS_InvokeByIndex\n\t"
+ ".ent NS_InvokeByIndex\n"
+"NS_InvokeByIndex:\n\t"
+ ".frame $15,32,$26,0\n\t"
+ ".mask 0x4008000,-32\n\t"
+ "ldgp $29,0($27)\n"
+"$NS_InvokeByIndex..ng:\n\t"
+ "subq $30,32,$30\n\t"
+ "stq $26,0($30)\n\t"
+ "stq $15,8($30)\n\t"
+ "bis $30,$30,$15\n\t"
+ ".prologue 1\n\t"
+
+ /*
+ * Allocate enough stack space to hold the greater of 6 or "paramCount"+1
+ * parameters. (+1 for "this" pointer) Room for at least 6 parameters
+ * is required for storage of those passed via registers.
+ */
+
+ "bis $31,5,$2\n\t" /* count = MAX(5, "paramCount") */
+ "cmplt $2,$18,$1\n\t"
+ "cmovne $1,$18,$2\n\t"
+ "s8addq $2,16,$1\n\t" /* room for count+1 params (8 bytes each) */
+ "bic $1,15,$1\n\t" /* stack space is rounded up to 0 % 16 */
+ "subq $30,$1,$30\n\t"
+
+ "stq $16,0($30)\n\t" /* save "that" (as "this" pointer) */
+ "stq $17,16($15)\n\t" /* save "methodIndex" */
+
+ "addq $30,8,$16\n\t" /* pass stack pointer */
+ "bis $18,$18,$17\n\t" /* pass "paramCount" */
+ "bis $19,$19,$18\n\t" /* pass "params" */
+ "bsr $26,$invoke_copy_to_stack..ng\n\t" /* call invoke_copy_to_stack */
+
+ /*
+ * Copy the first 6 parameters to registers and remove from stack frame.
+ * Both the integer and floating point registers are set for each parameter
+ * except the first which is the "this" pointer. (integer only)
+ * The floating point registers are all set as doubles since the
+ * invoke_copy_to_stack function should have converted the floats.
+ */
+ "ldq $16,0($30)\n\t" /* integer registers */
+ "ldq $17,8($30)\n\t"
+ "ldq $18,16($30)\n\t"
+ "ldq $19,24($30)\n\t"
+ "ldq $20,32($30)\n\t"
+ "ldq $21,40($30)\n\t"
+ "ldt $f17,8($30)\n\t" /* floating point registers */
+ "ldt $f18,16($30)\n\t"
+ "ldt $f19,24($30)\n\t"
+ "ldt $f20,32($30)\n\t"
+ "ldt $f21,40($30)\n\t"
+
+ "addq $30,48,$30\n\t" /* remove params from stack */
+
+ /*
+ * Call the virtual function with the constructed stack frame.
+ */
+ "bis $16,$16,$1\n\t" /* load "this" */
+ "ldq $2,16($15)\n\t" /* load "methodIndex" */
+ "ldq $1,0($1)\n\t" /* load vtable */
+ "s8addq $2,$31,$2\n\t" /* vtable index = "methodIndex" * 8 */
+ "addq $1,$2,$1\n\t"
+ "ldq $27,0($1)\n\t" /* load address of function */
+ "jsr $26,($27),0\n\t" /* call virtual function */
+ "ldgp $29,0($26)\n\t"
+
+ "bis $15,$15,$30\n\t"
+ "ldq $26,0($30)\n\t"
+ "ldq $15,8($30)\n\t"
+ "addq $30,32,$30\n\t"
+ "ret $31,($26),1\n\t"
+ ".end NS_InvokeByIndex"
+ );
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_m68k.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_m68k.cpp
new file mode 100644
index 0000000000..6f2934cbc8
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_m68k.cpp
@@ -0,0 +1,130 @@
+/* -*- 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"
+
+// Remember that these 'words' are 32bit DWORDS
+
+extern "C" {
+ static uint32_t
+ invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+ {
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+ }
+
+ void
+ invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+ {
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ // 8 and 16 bit types should be promoted to 32 bits when copying
+ // onto the stack.
+ case nsXPTType::T_I8 : *((uint32_t*)d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((uint32_t*)d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint32_t*)d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((uint32_t*)d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*)d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+ }
+}
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ uint32_t result, n;
+
+ n = invoke_count_words(paramCount, params) * 4;
+
+ __asm__ __volatile__(
+ "subl %5, %%sp\n\t" /* make room for params */
+ "movel %4, %%sp@-\n\t"
+ "movel %3, %%sp@-\n\t"
+ "pea %%sp@(8)\n\t"
+ "jbsr invoke_copy_to_stack\n\t" /* copy params */
+ "addw #12, %%sp\n\t"
+ "movel %1, %%sp@-\n\t"
+ "movel %1@, %%a0\n\t"
+ "movel %%a0@(%2:l:4), %%a0\n\t"
+ "jbsr %%a0@\n\t" /* safe to not cleanup sp */
+ "lea %%sp@(4,%5:l), %%sp\n\t"
+ "movel %%d0, %0"
+ : "=d" (result) /* %0 */
+ : "a" (that), /* %1 */
+ "d" (methodIndex), /* %2 */
+ "g" (paramCount), /* %3 */
+ "g" (params), /* %4 */
+ "d" (n) /* %5 */
+ : "a0", "a1", "d0", "d1", "memory"
+ );
+
+ return result;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp
new file mode 100644
index 0000000000..573dfb00c2
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp
@@ -0,0 +1,195 @@
+/* -*- 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"
+
+
+static uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t overflow = 0, gpr = 1 /*this*/, fpr = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5) gpr++; else overflow++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 4) gpr+=2; else gpr=5, overflow+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 4) gpr+=2; else gpr=5, overflow+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 2) fpr++; else overflow++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 2) fpr++; else overflow+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ }
+ }
+ /* Round up number of overflow words to ensure stack
+ stays aligned to 8 bytes. */
+ return (overflow + 1) & ~1;
+}
+
+static void
+invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d_ov, uint32_t overflow)
+{
+ uint32_t *d_gpr = d_ov + overflow;
+ uint64_t *d_fpr = (uint64_t *)(d_gpr + 4);
+ uint32_t gpr = 1 /*this*/, fpr = 0;
+
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5)
+ *((void**)d_gpr) = s->ptr, d_gpr++, gpr++;
+ else
+ *((void**)d_ov ) = s->ptr, d_ov++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ *((int32_t*) d_gpr) = s->val.i8, d_gpr++, gpr++;
+ else
+ *((int32_t*) d_ov ) = s->val.i8, d_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ *((int32_t*) d_gpr) = s->val.i16, d_gpr++, gpr++;
+ else
+ *((int32_t*) d_ov ) = s->val.i16, d_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ *((int32_t*) d_gpr) = s->val.i32, d_gpr++, gpr++;
+ else
+ *((int32_t*) d_ov ) = s->val.i32, d_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 4)
+ *((int64_t*) d_gpr) = s->val.i64, d_gpr+=2, gpr+=2;
+ else
+ *((int64_t*) d_ov ) = s->val.i64, d_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ *((uint32_t*) d_gpr) = s->val.u8, d_gpr++, gpr++;
+ else
+ *((uint32_t*) d_ov ) = s->val.u8, d_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ *((uint32_t*)d_gpr) = s->val.u16, d_gpr++, gpr++;
+ else
+ *((uint32_t*)d_ov ) = s->val.u16, d_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ *((uint32_t*)d_gpr) = s->val.u32, d_gpr++, gpr++;
+ else
+ *((uint32_t*)d_ov ) = s->val.u32, d_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 4)
+ *((uint64_t*)d_gpr) = s->val.u64, d_gpr+=2, gpr+=2;
+ else
+ *((uint64_t*)d_ov ) = s->val.u64, d_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 2)
+ *((float*) d_fpr) = s->val.f, d_fpr++, fpr++;
+ else
+ *((float*) d_ov ) = s->val.f, d_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 2)
+ *((double*) d_fpr) = s->val.d, d_fpr++, fpr++;
+ else
+ *((double*) d_ov ) = s->val.d, d_ov+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ *((uint32_t*)d_gpr) = s->val.b, d_gpr++, gpr++;
+ else
+ *((uint32_t*)d_ov ) = s->val.b, d_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ *((uint32_t*)d_gpr) = s->val.c, d_gpr++, gpr++;
+ else
+ *((uint32_t*)d_ov ) = s->val.c, d_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ *((uint32_t*)d_gpr) = s->val.wc, d_gpr++, gpr++;
+ else
+ *((uint32_t*)d_ov ) = s->val.wc, d_ov++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5)
+ *((void**) d_gpr) = s->val.p, d_gpr++, gpr++;
+ else
+ *((void**) d_ov ) = s->val.p, d_ov++;
+ break;
+ }
+ }
+}
+
+typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t, uint32_t, double, double);
+
+// Avoid AddressSanitizer instrumentation for the next function because it
+// depends on __builtin_alloca behavior and alignment that cannot be relied on
+// once the function is compiled with a version of ASan that has dynamic-alloca
+// instrumentation enabled.
+
+MOZ_ASAN_BLACKLIST
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ vtable_func *vtable = *reinterpret_cast<vtable_func **>(that);
+ vtable_func method = vtable[methodIndex];
+ uint32_t overflow = invoke_count_words (paramCount, params);
+ uint32_t *stack_space = reinterpret_cast<uint32_t *>(__builtin_alloca((overflow + 8 /* 4 32-bits gpr + 2 64-bits fpr */) * 4));
+
+ invoke_copy_to_stack(paramCount, params, stack_space, overflow);
+
+ uint32_t *d_gpr = stack_space + overflow;
+ double *d_fpr = reinterpret_cast<double *>(d_gpr + 4);
+
+ return method(that, d_gpr[0], d_gpr[1], d_gpr[2], d_gpr[3], d_fpr[0], d_fpr[1]);
+}
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp
new file mode 100644
index 0000000000..86478a8502
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp
@@ -0,0 +1,190 @@
+/* -*- 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"
+
+
+static uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t overflow = 0, gpr = 1 /*this*/, fpr = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5) gpr++; else overflow++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ case nsXPTType::T_I64 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ case nsXPTType::T_U64 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_FLOAT :
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 4) fpr++; else overflow++;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ }
+ }
+ /* Round up number of overflow words to ensure stack
+ stays aligned to 8 bytes. */
+ return (overflow + 1) & ~1;
+}
+
+static void
+invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint64_t* d_ov, uint32_t overflow)
+{
+ uint64_t *d_gpr = d_ov + overflow;
+ uint64_t *d_fpr = (uint64_t *)(d_gpr + 4);
+ uint32_t gpr = 1 /*this*/, fpr = 0;
+
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5)
+ *((void**)d_gpr) = s->ptr, d_gpr++, gpr++;
+ else
+ *((void**)d_ov ) = s->ptr, d_ov++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ *((int64_t*) d_gpr) = s->val.i8, d_gpr++, gpr++;
+ else
+ *((int64_t*) d_ov ) = s->val.i8, d_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ *((int64_t*) d_gpr) = s->val.i16, d_gpr++, gpr++;
+ else
+ *((int64_t*) d_ov ) = s->val.i16, d_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ *((int64_t*) d_gpr) = s->val.i32, d_gpr++, gpr++;
+ else
+ *((int64_t*) d_ov ) = s->val.i32, d_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 5)
+ *((int64_t*) d_gpr) = s->val.i64, d_gpr++, gpr++;
+ else
+ *((int64_t*) d_ov ) = s->val.i64, d_ov++;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ *((uint64_t*) d_gpr) = s->val.u8, d_gpr++, gpr++;
+ else
+ *((uint64_t*) d_ov ) = s->val.u8, d_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ *((uint64_t*)d_gpr) = s->val.u16, d_gpr++, gpr++;
+ else
+ *((uint64_t*)d_ov ) = s->val.u16, d_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ *((uint64_t*)d_gpr) = s->val.u32, d_gpr++, gpr++;
+ else
+ *((uint64_t*)d_ov ) = s->val.u32, d_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 5)
+ *((uint64_t*)d_gpr) = s->val.u64, d_gpr++, gpr++;
+ else
+ *((uint64_t*)d_ov ) = s->val.u64, d_ov++;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 4)
+ *((float*) d_fpr) = s->val.f, d_fpr++, fpr++;
+ else
+ *(((float*) d_ov )+1) = s->val.f, d_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 4)
+ *((double*) d_fpr) = s->val.d, d_fpr++, fpr++;
+ else
+ *((double*) d_ov ) = s->val.d, d_ov++;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ *((uint64_t*)d_gpr) = s->val.b, d_gpr++, gpr++;
+ else
+ *((uint64_t*)d_ov ) = s->val.b, d_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ *((uint64_t*)d_gpr) = s->val.c, d_gpr++, gpr++;
+ else
+ *((uint64_t*)d_ov ) = s->val.c, d_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ *((uint64_t*)d_gpr) = s->val.wc, d_gpr++, gpr++;
+ else
+ *((uint64_t*)d_ov ) = s->val.wc, d_ov++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5)
+ *((void**) d_gpr) = s->val.p, d_gpr++, gpr++;
+ else
+ *((void**) d_ov ) = s->val.p, d_ov++;
+ break;
+ }
+ }
+}
+
+typedef nsresult (*vtable_func)(nsISupports *, uint64_t, uint64_t, uint64_t, uint64_t, double, double, double, double);
+
+// Avoid AddressSanitizer instrumentation for the next function because it
+// depends on __builtin_alloca behavior and alignment that cannot be relied on
+// once the function is compiled with a version of ASan that has dynamic-alloca
+// instrumentation enabled.
+
+MOZ_ASAN_BLACKLIST
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ vtable_func *vtable = *reinterpret_cast<vtable_func **>(that);
+ vtable_func method = vtable[methodIndex];
+ uint64_t overflow = invoke_count_words (paramCount, params);
+ uint64_t *stack_space = reinterpret_cast<uint64_t *>(__builtin_alloca((overflow + 8 /* 4 64-bits gpr + 4 64-bits fpr */) * 8));
+ uint64_t result;
+
+ invoke_copy_to_stack(paramCount, params, stack_space, overflow);
+
+ uint64_t *d_gpr = stack_space + overflow;
+ double *d_fpr = reinterpret_cast<double *>(d_gpr + 4);
+
+ return method(that, d_gpr[0], d_gpr[1], d_gpr[2], d_gpr[3], d_fpr[0], d_fpr[1], d_fpr[2], d_fpr[3]);
+}
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp
new file mode 100644
index 0000000000..f6585e7f05
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp
@@ -0,0 +1,99 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * 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 code is for MIPS using the O32 ABI. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#include <stdint.h>
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ // Count a word for a0 even though it's never stored or loaded
+ // We do this only for alignment of register pairs.
+ uint32_t result = 1;
+ for (uint32_t i = 0; i < paramCount; i++, result++, s++)
+ {
+ if (s->IsPtrData())
+ continue;
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE :
+ if (result & 1)
+ result++;
+ result++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return (result + 1) & ~(uint32_t)1;
+}
+
+extern "C" void
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount,
+ nsXPTCVariant* s)
+{
+ // Skip the unused a0 slot, which we keep only for register pair alignment.
+ d++;
+
+ for (uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if (s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *d = (uint32_t) s->val.i8; break;
+ case nsXPTType::T_I16 : *d = (uint32_t) s->val.i16; break;
+ case nsXPTType::T_I32 : *d = (uint32_t) s->val.i32; break;
+ case nsXPTType::T_I64 :
+ if ((intptr_t)d & 4) d++;
+ *((int64_t*) d) = s->val.i64; d++;
+ break;
+ case nsXPTType::T_U8 : *d = (uint32_t) s->val.u8; break;
+ case nsXPTType::T_U16 : *d = (uint32_t) s->val.u16; break;
+ case nsXPTType::T_U32 : *d = (uint32_t) s->val.u32; break;
+ case nsXPTType::T_U64 :
+ if ((intptr_t)d & 4) d++;
+ *((uint64_t*) d) = s->val.u64; d++;
+ break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE :
+ if ((intptr_t)d & 4) d++;
+ *((double*) d) = s->val.d; d++;
+ break;
+ case nsXPTType::T_BOOL : *d = (bool) s->val.b; break;
+ case nsXPTType::T_CHAR : *d = (char) s->val.c; break;
+ case nsXPTType::T_WCHAR : *d = (wchar_t) s->val.wc; break;
+ default:
+ *((void**)d) = 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/md/unix/xptcinvoke_mips64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp
new file mode 100644
index 0000000000..1dd54f96f5
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp
@@ -0,0 +1,142 @@
+/* -*- 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 (_MIPS_SIM != _ABIN32) && (_MIPS_SIM != _ABI64)
+#error "This code is for MIPS n32/n64 only"
+#endif
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ return paramCount;
+}
+
+extern "C" void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount,
+ nsXPTCVariant* s, uint64_t *regs)
+{
+#define N_ARG_REGS 7 /* 8 regs minus 1 for "this" ptr */
+
+ for (uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if (s->IsPtrData()) {
+ if (i < N_ARG_REGS)
+ regs[i] = (uint64_t)s->ptr;
+ else
+ *d++ = (uint64_t)s->ptr;
+ continue;
+ }
+ switch (s->type) {
+ //
+ // signed types first
+ //
+ case nsXPTType::T_I8:
+ if (i < N_ARG_REGS)
+ ((int64_t*)regs)[i] = s->val.i8;
+ else
+ *d++ = s->val.i8;
+ break;
+ case nsXPTType::T_I16:
+ if (i < N_ARG_REGS)
+ ((int64_t*)regs)[i] = s->val.i16;
+ else
+ *d++ = s->val.i16;
+ break;
+ case nsXPTType::T_I32:
+ if (i < N_ARG_REGS)
+ ((int64_t*)regs)[i] = s->val.i32;
+ else
+ *d++ = s->val.i32;
+ break;
+ case nsXPTType::T_I64:
+ if (i < N_ARG_REGS)
+ ((int64_t*)regs)[i] = s->val.i64;
+ else
+ *d++ = s->val.i64;
+ break;
+ //
+ // unsigned types next
+ //
+ case nsXPTType::T_U8:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u8;
+ else
+ *d++ = s->val.u8;
+ break;
+ case nsXPTType::T_U16:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u16;
+ else
+ *d++ = s->val.u16;
+ break;
+ case nsXPTType::T_U32:
+ if (i < N_ARG_REGS)
+ // 32-bit values need to be sign-extended
+ // in register, so use the signed value.
+ regs[i] = s->val.i32;
+ else
+ *d++ = s->val.u32;
+ break;
+ case nsXPTType::T_U64:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u64;
+ else
+ *d++ = s->val.u64;
+ break;
+ case nsXPTType::T_FLOAT:
+ if (i < N_ARG_REGS)
+ *(float*)&regs[i] = s->val.f;
+ else
+ *(float*)d++ = s->val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ if (i < N_ARG_REGS)
+ *(double*)&regs[i] = s->val.d;
+ else
+ *(double*)d++ = s->val.d;
+ break;
+ case nsXPTType::T_BOOL:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.b;
+ else
+ *d++ = s->val.b;
+ break;
+ case nsXPTType::T_CHAR:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.c;
+ else
+ *d++ = s->val.c;
+ break;
+ case nsXPTType::T_WCHAR:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.wc;
+ else
+ *d++ = s->val.wc;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (i < N_ARG_REGS)
+ regs[i] = (uint64_t)s->val.p;
+ else
+ *d++ = (uint64_t)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/md/unix/xptcinvoke_netbsd_m68k.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_netbsd_m68k.cpp
new file mode 100644
index 0000000000..47e0e76667
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_netbsd_m68k.cpp
@@ -0,0 +1,143 @@
+/* -*- 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"
+
+// Remember that these 'words' are 32bit DWORDS
+
+#if !defined(__NetBSD__) || !defined(__m68k__)
+#error This code is for NetBSD/m68k only
+#endif
+
+extern "C" {
+ static uint32_t
+ invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+ {
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+ }
+
+ static void
+ invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+ {
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ // 8 and 16 bit types should be promoted to 32 bits when copying
+ // onto the stack.
+ case nsXPTType::T_I8 : *((uint32_t*)d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((uint32_t*)d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint32_t*)d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((uint32_t*)d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*)d) = s->val.c; break;
+ // wchar_t is an int (32 bits) on NetBSD
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+ }
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ uint32_t result;
+
+ __asm__ __volatile__(
+ "movl %4, sp@-\n\t"
+ "movl %3, sp@-\n\t"
+ "jbsr _invoke_count_words\n\t" /* count words */
+ "addql #8, sp\n\t"
+ "lsll #2, d0\n\t" /* *= 4 */
+ "movl sp, a2\n\t" /* save original sp */
+ "subl d0, sp\n\t" /* make room for params */
+ "movl sp, a0\n\t"
+ "movl %4, sp@-\n\t"
+ "movl %3, sp@-\n\t"
+ "movl a0, sp@-\n\t"
+ "jbsr _invoke_copy_to_stack\n\t" /* copy params */
+ "addl #12, sp\n\t"
+ "movl %1, a0\n\t"
+ "movl a0@, a1\n\t"
+ "movl %2, d0\n\t" /* function index */
+ "movl a0, d1\n\t"
+ "movw a1@(8,d0:l:8), a0\n\t"
+ "addl a0, d1\n\t"
+ "movl a1@(12,d0:l:8), a1\n\t"
+ "movl d1, sp@-\n\t"
+ "jbsr a1@\n\t"
+ "movl a2, sp\n\t" /* restore original sp */
+ "movl d0, %0\n\t"
+ : "=g" (result) /* %0 */
+ : "g" (that), /* %1 */
+ "g" (methodIndex), /* %2 */
+ "g" (paramCount), /* %3 */
+ "g" (params) /* %4 */
+ : "a0", "a1", "a2", "d0", "d1", "memory"
+ );
+
+ return result;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp
new file mode 100644
index 0000000000..0e6d28fbda
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp
@@ -0,0 +1,149 @@
+
+/* -*- 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"
+
+#if _HPUX
+#error "This code is for HP-PA RISC 32 bit mode only"
+#endif
+
+#include <alloca.h>
+
+typedef unsigned nsXPCVariant;
+
+extern "C" int32_t
+invoke_count_bytes(nsISupports* that, const uint32_t methodIndex,
+ const uint32_t paramCount, const nsXPTCVariant* s)
+{
+ int32_t result = 4; /* variant records do not include self pointer */
+
+ /* counts the number of bytes required by the argument stack,
+ 64 bit integer, and double requires 8 bytes. All else requires
+ 4 bytes.
+ */
+
+ {
+ uint32_t indx;
+ for (indx = paramCount; indx > 0; --indx, ++s)
+ {
+ if (! s->IsPtrData())
+ {
+ if (s->type == nsXPTType::T_I64 || s->type == nsXPTType::T_U64 ||
+ s->type == nsXPTType::T_DOUBLE)
+ {
+ /* 64 bit integer and double aligned on 8 byte boundaries */
+ result += (result & 4) + 8;
+ continue;
+ }
+ }
+ result += 4; /* all other cases use 4 bytes */
+ }
+ }
+ result -= 72; /* existing stack buffer is 72 bytes */
+ if (result < 0)
+ return 0;
+ {
+ /* round up to 64 bytes boundary */
+ int32_t remainder = result & 63;
+ return (remainder == 0) ? result : (result + 64 - remainder);
+ }
+}
+
+extern "C" uint32_t
+invoke_copy_to_stack(uint32_t* d,
+ const uint32_t paramCount, nsXPTCVariant* s)
+{
+
+ typedef struct
+ {
+ uint32_t hi;
+ uint32_t lo;
+ } DU;
+
+ uint32_t* dest = d;
+ nsXPTCVariant* source = s;
+ /* we clobber param vars by copying stuff on stack, have to use local var */
+
+ uint32_t floatflags = 0;
+ /* flag indicating which floating point registers to load */
+
+ uint32_t regwords = 1; /* register 26 is reserved for ptr to 'that' */
+ uint32_t indx;
+
+ for (indx = paramCount; indx > 0; --indx, --dest, ++source)
+ {
+ if (source->IsPtrData())
+ {
+ *((void**) dest) = source->ptr;
+ ++regwords;
+ continue;
+ }
+ switch (source->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) dest) = source->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) dest) = source->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) dest) = source->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ if (regwords & 1)
+ {
+ /* align on double word boundary */
+ --dest;
+ ++regwords;
+ }
+ *((uint32_t*) dest) = ((DU *) source)->lo;
+ *((uint32_t*) --dest) = ((DU *) source)->hi;
+ /* big endian - hi word in low addr */
+ regwords += 2;
+ continue;
+ case nsXPTType::T_DOUBLE :
+ if (regwords & 1)
+ {
+ /* align on double word boundary */
+ --dest;
+ ++regwords;
+ }
+ switch (regwords) /* load double precision float register */
+ {
+ case 2:
+ floatflags |= 1;
+ }
+ *((uint32_t*) dest) = ((DU *) source)->lo;
+ *((uint32_t*) --dest) = ((DU *) source)->hi;
+ /* big endian - hi word in low addr */
+ regwords += 2;
+ continue;
+ case nsXPTType::T_FLOAT :
+ switch (regwords) /* load single precision float register */
+ {
+ case 1:
+ floatflags |= 2;
+ break;
+ case 2:
+ floatflags |= 4;
+ break;
+ case 3:
+ floatflags |= 8;
+ }
+ *((float*) dest) = source->val.f;
+ break;
+ case nsXPTType::T_U8 : *((uint32_t*) (dest)) = source->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*) (dest)) = source->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*) (dest)) = source->val.u32; break;
+ case nsXPTType::T_BOOL : *((uint32_t*) (dest)) = source->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*) (dest)) = source->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32_t*) (dest)) = source->val.wc; break;
+
+ default:
+ // all the others are plain pointer types
+ *((void**) dest) = source->val.p;
+ }
+ ++regwords;
+ }
+ return floatflags;
+}
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp
new file mode 100644
index 0000000000..c93dc46212
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp
@@ -0,0 +1,97 @@
+/* -*- 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
+
+// The purpose of NS_InvokeByIndex() is to map a platform
+// independent call to the platform ABI. To do that,
+// NS_InvokeByIndex() has to determine the method to call via vtable
+// access. The parameters for the method are read from the
+// nsXPTCVariant* and prepared for the native ABI.
+
+// The PowerPC64 platform ABI can be found here:
+// http://www.freestandards.org/spec/ELF/ppc64/
+// and in particular:
+// http://www.freestandards.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-CALL
+
+#include <stdio.h>
+#include "xptcprivate.h"
+
+// 8 integral parameters are passed in registers, not including 'that'
+#define GPR_COUNT 7
+
+// 8 floating point parameters are passed in registers, floats are
+// promoted to doubles when passed in registers
+#define FPR_COUNT 13
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ return uint32_t(((paramCount * 2) + 3) & ~3);
+}
+
+extern "C" void
+invoke_copy_to_stack(uint64_t* gpregs,
+ double* fpregs,
+ uint32_t paramCount,
+ nsXPTCVariant* s,
+ uint64_t* d)
+{
+ uint64_t tempu64;
+
+ for(uint32_t i = 0; i < paramCount; i++, s++) {
+ if(s->IsPtrData())
+ tempu64 = (uint64_t) s->ptr;
+ else {
+ switch(s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: tempu64 = s->val.i8; break;
+ case nsXPTType::T_I16: tempu64 = s->val.i16; break;
+ case nsXPTType::T_I32: tempu64 = s->val.i32; break;
+ case nsXPTType::T_I64: tempu64 = s->val.i64; break;
+ case nsXPTType::T_U8: tempu64 = s->val.u8; break;
+ case nsXPTType::T_U16: tempu64 = s->val.u16; break;
+ case nsXPTType::T_U32: tempu64 = s->val.u32; break;
+ case nsXPTType::T_U64: tempu64 = s->val.u64; break;
+ case nsXPTType::T_BOOL: tempu64 = s->val.b; break;
+ case nsXPTType::T_CHAR: tempu64 = s->val.c; break;
+ case nsXPTType::T_WCHAR: tempu64 = s->val.wc; break;
+ default: tempu64 = (uint64_t) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (i < FPR_COUNT)
+ fpregs[i] = s->val.d;
+ else
+ *(double *)d = s->val.d;
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (i < FPR_COUNT) {
+ fpregs[i] = s->val.f; // if passed in registers, floats are promoted to doubles
+ } else {
+ float *p = (float *)d;
+#ifndef __LITTLE_ENDIAN__
+ p++;
+#endif
+ *p = s->val.f;
+ }
+ }
+ else {
+ if (i < GPR_COUNT)
+ gpregs[i] = tempu64;
+ else
+ *d = tempu64;
+ }
+ if (i >= 7)
+ d++;
+ }
+}
+
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp
new file mode 100644
index 0000000000..ba2a5dab08
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp
@@ -0,0 +1,74 @@
+/* -*- 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"
+
+#ifndef AIX
+#error "This code is for PowerPC only"
+#endif
+
+extern "C" void
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s, double *fprData)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint32_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32_t l_paramCount = paramCount, fpCount = 0;
+ double *l_fprData = fprData;
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if(l_s->IsPtrData())
+ {
+ *((void**)l_d) = l_s->ptr;
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ *((uint32_t*) l_d++) = ((DU *)l_s)->hi;
+ *((uint32_t*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_DOUBLE :
+ *((uint32_t*) l_d++) = ((DU *)l_s)->hi;
+ *((uint32_t*) l_d) = ((DU *)l_s)->lo;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.d;
+ break;
+ case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT :
+ *((float*) l_d) = l_s->val.f;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.f;
+ break;
+ case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+}
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp
new file mode 100644
index 0000000000..616c2f687e
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp
@@ -0,0 +1,63 @@
+/* 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"
+
+#ifdef _AIX
+
+extern "C" void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s, double *fprData)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint64_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32_t l_paramCount = paramCount, fpCount = 0;
+ double *l_fprData = fprData;
+
+ for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if(l_s->IsPtrData())
+ {
+ *l_d = (uint64_t)l_s->ptr;
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8: *l_d = (uint64_t)l_s->val.i8; break;
+ case nsXPTType::T_I16: *l_d = (uint64_t)l_s->val.i16; break;
+ case nsXPTType::T_I32: *l_d = (uint64_t)l_s->val.i32; break;
+ case nsXPTType::T_I64: *l_d = (uint64_t)l_s->val.i64; break;
+ case nsXPTType::T_U8: *l_d = (uint64_t)l_s->val.u8; break;
+ case nsXPTType::T_U16: *l_d = (uint64_t)l_s->val.u16; break;
+ case nsXPTType::T_U32: *l_d = (uint64_t)l_s->val.u32; break;
+ case nsXPTType::T_U64: *l_d = (uint64_t)l_s->val.u64; break;
+ case nsXPTType::T_BOOL: *l_d = (uint64_t)l_s->val.b; break;
+ case nsXPTType::T_CHAR: *l_d = (uint64_t)l_s->val.c; break;
+ case nsXPTType::T_WCHAR: *l_d = (uint64_t)l_s->val.wc; break;
+
+ case nsXPTType::T_DOUBLE:
+ *((double*)l_d) = l_s->val.d;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.d;
+ break;
+ case nsXPTType::T_FLOAT:
+ *((float*)l_d) = l_s->val.f;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.f;
+ break;
+ default:
+ // all the others are plain pointer types
+ *l_d = (uint64_t)l_s->val.p;
+ break;
+ }
+ }
+}
+#endif
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp
new file mode 100644
index 0000000000..deb72db8f5
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp
@@ -0,0 +1,128 @@
+/* -*- 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
+
+// The purpose of NS_InvokeByIndex() is to map a platform
+// indepenpent call to the platform ABI. To do that,
+// NS_InvokeByIndex() has to determine the method to call via vtable
+// access. The parameters for the method are read from the
+// nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC
+// ABI this means that the first 8 integral and floating point
+// parameters are passed in registers.
+
+#include "xptcprivate.h"
+
+// 8 integral parameters are passed in registers
+#define GPR_COUNT 8
+
+// With hardfloat support 8 floating point parameters are passed in registers,
+// floats are promoted to doubles when passed in registers
+// In Softfloat mode, everything is handled via gprs
+#ifndef __NO_FPRS__
+#define FPR_COUNT 8
+#endif
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ return uint32_t(((paramCount * 2) + 3) & ~3);
+}
+
+extern "C" void
+invoke_copy_to_stack(uint32_t* d,
+ uint32_t paramCount,
+ nsXPTCVariant* s,
+ uint32_t* gpregs,
+ double* fpregs)
+{
+ uint32_t gpr = 1; // skip one GP reg for 'that'
+#ifndef __NO_FPRS__
+ uint32_t fpr = 0;
+#endif
+ uint32_t tempu32;
+ uint64_t tempu64;
+
+ for(uint32_t i = 0; i < paramCount; i++, s++) {
+ if(s->IsPtrData()) {
+ if(s->type == nsXPTType::T_JSVAL)
+ tempu32 = (uint32_t) &s->ptr;
+ else
+ tempu32 = (uint32_t) s->ptr;
+ }
+ else {
+ switch(s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: tempu32 = s->val.i8; break;
+ case nsXPTType::T_I16: tempu32 = s->val.i16; break;
+ case nsXPTType::T_I32: tempu32 = s->val.i32; break;
+ case nsXPTType::T_I64: tempu64 = s->val.i64; break;
+ case nsXPTType::T_U8: tempu32 = s->val.u8; break;
+ case nsXPTType::T_U16: tempu32 = s->val.u16; break;
+ case nsXPTType::T_U32: tempu32 = s->val.u32; break;
+ case nsXPTType::T_U64: tempu64 = s->val.u64; break;
+ case nsXPTType::T_BOOL: tempu32 = s->val.b; break;
+ case nsXPTType::T_CHAR: tempu32 = s->val.c; break;
+ case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break;
+ default: tempu32 = (uint32_t) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+#ifndef __NO_FPRS__
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.d;
+#else
+ if (gpr & 1)
+ gpr++;
+ if ((gpr + 1) < GPR_COUNT) {
+ *((double*) &gpregs[gpr]) = s->val.d;
+ gpr += 2;
+ }
+#endif
+ else {
+ if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack
+ *((double*) d) = s->val.d;
+ d += 2;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+#ifndef __NO_FPRS__
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles
+#else
+ if (gpr < GPR_COUNT)
+ *((float*) &gpregs[gpr++]) = s->val.f;
+#endif
+ else
+ *((float*) d++) = s->val.f;
+ }
+ else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64
+ || s->type == nsXPTType::T_U64)) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((gpr + 1) < GPR_COUNT) {
+ *((uint64_t*) &gpregs[gpr]) = tempu64;
+ gpr += 2;
+ }
+ else {
+ if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack
+ *((uint64_t*) d) = tempu64;
+ d += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ gpregs[gpr++] = tempu32;
+ else
+ *d++ = tempu32;
+ }
+
+ }
+}
+
+extern "C"
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_netbsd.cpp
new file mode 100644
index 0000000000..515e8c50bd
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_netbsd.cpp
@@ -0,0 +1,115 @@
+/* -*- 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
+
+// The purpose of XPTC_InvokeByIndex() is to map a platform
+// indepenpent call to the platform ABI. To do that,
+// XPTC_InvokeByIndex() has to determine the method to call via vtable
+// access. The parameters for the method are read from the
+// nsXPTCVariant* and prepared for the native ABI. For the Linux/PPC
+// ABI this means that the first 8 integral and floating point
+// parameters are passed in registers.
+
+#include "xptcprivate.h"
+
+// 8 integral parameters are passed in registers
+#define GPR_COUNT 8
+
+// 8 floating point parameters are passed in registers, floats are
+// promoted to doubles when passed in registers
+#define FPR_COUNT 8
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ return uint32_t(((paramCount * 2) + 3) & ~3);
+}
+
+extern "C" void
+invoke_copy_to_stack(uint32_t* d,
+ uint32_t paramCount,
+ nsXPTCVariant* s,
+ uint32_t* gpregs,
+ double* fpregs)
+{
+ uint32_t gpr = 1; // skip one GP reg for 'that'
+ uint32_t fpr = 0;
+ uint32_t tempu32;
+ uint64_t tempu64;
+
+ for(uint32_t i = 0; i < paramCount; i++, s++) {
+ if(s->IsPtrData()) {
+ if(s->type == nsXPTType::T_JSVAL)
+ tempu32 = (uint32_t) &(s->ptr);
+ else
+ tempu32 = (uint32_t) s->ptr;
+ } else {
+ switch(s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: tempu32 = s->val.i8; break;
+ case nsXPTType::T_I16: tempu32 = s->val.i16; break;
+ case nsXPTType::T_I32: tempu32 = s->val.i32; break;
+ case nsXPTType::T_I64: tempu64 = s->val.i64; break;
+ case nsXPTType::T_U8: tempu32 = s->val.u8; break;
+ case nsXPTType::T_U16: tempu32 = s->val.u16; break;
+ case nsXPTType::T_U32: tempu32 = s->val.u32; break;
+ case nsXPTType::T_U64: tempu64 = s->val.u64; break;
+ case nsXPTType::T_BOOL: tempu32 = s->val.b; break;
+ case nsXPTType::T_CHAR: tempu32 = s->val.c; break;
+ case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break;
+ default: tempu32 = (uint32_t) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.d;
+ else {
+ if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack
+ *((double*) d) = s->val.d;
+ d += 2;
+ if (gpr < GPR_COUNT)
+ gpr += 2;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles
+ else {
+ *((float*) d) = s->val.f;
+ d += 1;
+ if (gpr < GPR_COUNT)
+ gpr += 1;
+ }
+ }
+ else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64
+ || s->type == nsXPTType::T_U64)) {
+ if ((gpr + 1) < GPR_COUNT) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ *((uint64_t*) &gpregs[gpr]) = tempu64;
+ gpr += 2;
+ }
+ else {
+ if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack
+ *((uint64_t*) d) = tempu64;
+ d += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ gpregs[gpr++] = tempu32;
+ else
+ *d++ = tempu32;
+ }
+
+ }
+}
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp
new file mode 100644
index 0000000000..5353220fef
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp
@@ -0,0 +1,109 @@
+/* -*- 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
+
+// The purpose of NS_InvokeByIndex() is to map a platform
+// indepenpent call to the platform ABI. To do that,
+// NS_InvokeByIndex() has to determine the method to call via vtable
+// access. The parameters for the method are read from the
+// nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC
+// ABI this means that the first 8 integral and floating point
+// parameters are passed in registers.
+
+#include "xptcprivate.h"
+
+// 8 integral parameters are passed in registers
+#define GPR_COUNT 8
+
+// 8 floating point parameters are passed in registers, floats are
+// promoted to doubles when passed in registers
+#define FPR_COUNT 8
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ return uint32_t(((paramCount * 2) + 3) & ~3);
+}
+
+extern "C" void
+invoke_copy_to_stack(uint32_t* d,
+ uint32_t paramCount,
+ nsXPTCVariant* s,
+ uint32_t* gpregs,
+ double* fpregs)
+{
+ uint32_t gpr = 1; // skip one GP reg for 'that'
+ uint32_t fpr = 0;
+ uint32_t tempu32;
+ uint64_t tempu64;
+
+ for(uint32_t i = 0; i < paramCount; i++, s++) {
+ if(s->IsPtrData()) {
+ if(s->type == nsXPTType::T_JSVAL)
+ tempu32 = (uint32_t) &(s->ptr);
+ else
+ tempu32 = (uint32_t) s->ptr;
+ } else {
+ switch(s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: tempu32 = s->val.i8; break;
+ case nsXPTType::T_I16: tempu32 = s->val.i16; break;
+ case nsXPTType::T_I32: tempu32 = s->val.i32; break;
+ case nsXPTType::T_I64: tempu64 = s->val.i64; break;
+ case nsXPTType::T_U8: tempu32 = s->val.u8; break;
+ case nsXPTType::T_U16: tempu32 = s->val.u16; break;
+ case nsXPTType::T_U32: tempu32 = s->val.u32; break;
+ case nsXPTType::T_U64: tempu64 = s->val.u64; break;
+ case nsXPTType::T_BOOL: tempu32 = s->val.b; break;
+ case nsXPTType::T_CHAR: tempu32 = s->val.c; break;
+ case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break;
+ default: tempu32 = (uint32_t) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.d;
+ else {
+ if ((uint32_t) d & 4) d++; // doubles are 8-byte aligned on stack
+ *((double*) d) = s->val.d;
+ d += 2;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles
+ else
+ *((float*) d++) = s->val.f;
+ }
+ else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64
+ || s->type == nsXPTType::T_U64)) {
+ if ((gpr + 1) < GPR_COUNT) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ *((uint64_t*) &gpregs[gpr]) = tempu64;
+ gpr += 2;
+ }
+ else {
+ if ((uint32_t) d & 4) d++; // longlongs are 8-byte aligned on stack
+ *((uint64_t*) d) = tempu64;
+ d += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ gpregs[gpr++] = tempu32;
+ else
+ *d++ = tempu32;
+ }
+
+ }
+}
+
+extern "C"
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp
new file mode 100644
index 0000000000..1a40cfeea7
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp
@@ -0,0 +1,113 @@
+/* -*- Mode: C; tab-width: 4; 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"
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ /* fprintf(stderr,"invoke_count_words(%d,%p)\n",paramCount, s);*/
+
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+extern "C" void
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s, double *fprData)
+{
+ uint32_t fpCount = 0;
+
+ /* fprintf(stderr,"invoke_copy_to_stack(%p, %d, %p, %p)\n", d, paramCount, s, fprData);*/
+
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint32_t*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f;
+ if (fpCount < 13)
+ fprData[fpCount++] = s->val.f;
+ break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++;
+ if (fpCount < 13)
+ fprData[fpCount++] = s->val.d;
+ break;
+ case nsXPTType::T_BOOL : *((uint32_t*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((int32_t*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((uint32_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = 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/md/unix/xptcinvoke_sparc64_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp
new file mode 100644
index 0000000000..050f9414de
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; 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/. */
+
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+extern "C" uint64_t
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ /*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+ */
+ uint64_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint64_t l_paramCount = paramCount;
+ uint64_t regCount = 0; // return the number of registers to load from the stack
+
+ for(uint64_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+
+ if (l_s->IsPtrData())
+ {
+ *l_d = (uint64_t)l_s->ptr;
+ continue;
+ }
+ switch (l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int64_t*)l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int64_t*)l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int64_t*)l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*)l_d) = l_s->val.i64; break;
+
+ case nsXPTType::T_U8 : *((uint64_t*)l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint64_t*)l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint64_t*)l_d) = l_s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)l_d) = l_s->val.u64; break;
+
+ /* in the case of floats, we want to put the bits in to the
+ 64bit space right justified... floats in the parameter array on
+ sparcv9 use odd numbered registers.. %f1, %f3, so we have to skip
+ the space that would be occupied by %f0, %f2, etc.
+ */
+ case nsXPTType::T_FLOAT : *(((float*)l_d) + 1) = l_s->val.f; break;
+ case nsXPTType::T_DOUBLE: *((double*)l_d) = l_s->val.d; break;
+ case nsXPTType::T_BOOL : *((int64_t*)l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint64_t*)l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int64_t*)l_d) = l_s->val.wc; break;
+
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+
+ return regCount;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp
new file mode 100644
index 0000000000..126ef1dad2
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp
@@ -0,0 +1,131 @@
+/* -*- 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"
+
+/* solaris defines __sparc for workshop compilers and
+ linux defines __sparc__ */
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+typedef unsigned nsXPCVariant;
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ // nuts, I know there's a cooler way of doing this, but it's late
+ // now and it'll probably come to me in the morning.
+ if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment
+ return result;
+}
+
+extern "C" uint32_t
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint32_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32_t l_paramCount = paramCount;
+ uint32_t regCount = 0; // return the number of registers to load from the stack
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+ if(l_s->IsPtrData())
+ {
+ if(l_s->type == nsXPTType::T_JSVAL)
+ {
+ // On SPARC, we need to pass a pointer to HandleValue
+ *((void**)l_d) = &l_s->ptr;
+ } else
+ {
+ *((void**)l_d) = l_s->ptr;
+ }
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE : *((uint32_t*) l_d++) = ((DU *)l_s)->hi;
+ if (regCount < 5) regCount++;
+ *((uint32_t*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break;
+ case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+ return regCount;
+}
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp
new file mode 100644
index 0000000000..9b2e4f858f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp
@@ -0,0 +1,128 @@
+/* -*- 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(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+typedef unsigned nsXPCVariant;
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ // nuts, I know there's a cooler way of doing this, but it's late
+ // now and it'll probably come to me in the morning.
+ if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment
+ return result;
+}
+
+extern "C" uint32_t
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint32_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32_t l_paramCount = paramCount;
+ uint32_t regCount = 0; // return the number of registers to load from the stack
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+ if(l_s->IsPtrData())
+ {
+ if(l_s->type == nsXPTType::T_JSVAL)
+ {
+ // On SPARC, we need to pass a pointer to HandleValue
+ *((void**)l_d) = &l_s->ptr;
+ } else
+ {
+ *((void**)l_d) = l_s->ptr;
+ }
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE : *((uint32_t*) l_d++) = ((DU *)l_s)->hi;
+ if (regCount < 5) regCount++;
+ *((uint32_t*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break;
+ case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+ return regCount;
+}
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp
new file mode 100644
index 0000000000..126ef1dad2
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp
@@ -0,0 +1,131 @@
+/* -*- 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"
+
+/* solaris defines __sparc for workshop compilers and
+ linux defines __sparc__ */
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+typedef unsigned nsXPCVariant;
+
+extern "C" uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ // nuts, I know there's a cooler way of doing this, but it's late
+ // now and it'll probably come to me in the morning.
+ if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment
+ return result;
+}
+
+extern "C" uint32_t
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint32_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32_t l_paramCount = paramCount;
+ uint32_t regCount = 0; // return the number of registers to load from the stack
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+ if(l_s->IsPtrData())
+ {
+ if(l_s->type == nsXPTType::T_JSVAL)
+ {
+ // On SPARC, we need to pass a pointer to HandleValue
+ *((void**)l_d) = &l_s->ptr;
+ } else
+ {
+ *((void**)l_d) = l_s->ptr;
+ }
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32_t*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32_t*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE : *((uint32_t*) l_d++) = ((DU *)l_s)->hi;
+ if (regCount < 5) regCount++;
+ *((uint32_t*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_U8 : *((uint32_t*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32_t*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break;
+ case nsXPTType::T_BOOL : *((uint32_t*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32_t*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32_t*) l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+ return regCount;
+}
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparcv9_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparcv9_solaris.cpp
new file mode 100644
index 0000000000..0d2d6b0a8f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparcv9_solaris.cpp
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 2; 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/. */
+
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+/* Prototype specifies unmangled function name */
+extern "C" uint64_t
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s);
+
+extern "C" uint64_t
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ /*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+ */
+ uint64_t *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint64_t l_paramCount = paramCount;
+ uint64_t regCount = 0; // return the number of registers to load from the stack
+
+ for(uint64_t i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+
+ if (l_s->IsPtrData())
+ {
+ *l_d = (uint64_t)l_s->ptr;
+ continue;
+ }
+ switch (l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int64_t*)l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int64_t*)l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int64_t*)l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*)l_d) = l_s->val.i64; break;
+
+ case nsXPTType::T_U8 : *((uint64_t*)l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint64_t*)l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint64_t*)l_d) = l_s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)l_d) = l_s->val.u64; break;
+
+ /* in the case of floats, we want to put the bits in to the
+ 64bit space right justified... floats in the parameter array on
+ sparcv9 use odd numbered registers.. %f1, %f3, so we have to skip
+ the space that would be occupied by %f0, %f2, etc.
+ */
+ case nsXPTType::T_FLOAT : *(((float*)l_d) + 1) = l_s->val.f; break;
+ case nsXPTType::T_DOUBLE: *((double*)l_d) = l_s->val.d; break;
+ case nsXPTType::T_BOOL : *((uint64_t*)l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint64_t*)l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int64_t*)l_d) = l_s->val.wc; break;
+
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+
+ return regCount;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp
new file mode 100644
index 0000000000..0d34243663
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp
@@ -0,0 +1,149 @@
+/* -*- 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"
+#include "alloca.h"
+
+// 6 integral parameters are passed in registers
+const uint32_t GPR_COUNT = 6;
+
+// 8 floating point parameters are passed in SSE registers
+const uint32_t FPR_COUNT = 8;
+
+// Remember that these 'words' are 64-bit long
+static inline void
+invoke_count_words(uint32_t paramCount, nsXPTCVariant * s,
+ uint32_t & nr_gpr, uint32_t & nr_fpr, uint32_t & nr_stack)
+{
+ nr_gpr = 1; // skip one GP register for 'that'
+ nr_fpr = 0;
+ nr_stack = 0;
+
+ /* Compute number of eightbytes of class MEMORY. */
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (!s->IsPtrData()
+ && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) {
+ if (nr_fpr < FPR_COUNT)
+ nr_fpr++;
+ else
+ nr_stack++;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ nr_stack++;
+ }
+ }
+}
+
+static void
+invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s,
+ uint64_t * gpregs, double * fpregs)
+{
+ uint32_t nr_gpr = 1; // skip one GP register for 'that'
+ uint32_t nr_fpr = 0;
+ uint64_t value;
+
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (s->IsPtrData())
+ value = (uint64_t) s->ptr;
+ 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->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((double *)d) = s->val.d;
+ d++;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((float *)d) = s->val.f;
+ d++;
+ }
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ gpregs[nr_gpr++] = value;
+ else
+ *d++ = value;
+ }
+ }
+}
+
+// Avoid AddressSanitizer instrumentation for the next function because it
+// depends on __builtin_alloca behavior and alignment that cannot be relied on
+// once the function is compiled with a version of ASan that has dynamic-alloca
+// instrumentation enabled.
+
+MOZ_ASAN_BLACKLIST
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant * params)
+{
+ uint32_t nr_gpr, nr_fpr, nr_stack;
+ invoke_count_words(paramCount, params, nr_gpr, nr_fpr, nr_stack);
+
+ // Stack, if used, must be 16-bytes aligned
+ if (nr_stack)
+ nr_stack = (nr_stack + 1) & ~1;
+
+ // Load parameters to stack, if necessary
+ uint64_t *stack = (uint64_t *) __builtin_alloca(nr_stack * 8);
+ uint64_t gpregs[GPR_COUNT];
+ double fpregs[FPR_COUNT];
+ invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs);
+
+ switch (nr_fpr) {
+ case 8: asm("movupd %0, %xmm7" : : "xmm7" (fpregs[7]));
+ case 7: asm("movupd %0, %xmm6" : : "xmm6" (fpregs[6]));
+ case 6: asm("movupd %0, %xmm5" : : "xmm5" (fpregs[5]));
+ case 5: asm("movupd %0, %xmm4" : : "xmm4" (fpregs[4]));
+ case 4: asm("movupd %0, %xmm3" : : "xmm3" (fpregs[3]));
+ case 3: asm("movupd %0, %xmm2" : : "xmm2" (fpregs[2]));
+ case 2: asm("movupd %0, %xmm1" : : "xmm1" (fpregs[1]));
+ case 1: asm("movupd %0, %xmm0" : : "xmm0" (fpregs[0]));
+ case 0:;
+ }
+
+ // Ensure that assignments to SSE registers won't be optimized away
+ asm("" ::: "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7");
+
+ // Get pointer to method
+ uint64_t methodAddress = *((uint64_t *)that);
+ methodAddress += 16 + 8 * methodIndex;
+ methodAddress = *((uint64_t *)methodAddress);
+
+ typedef uint32_t (*Method)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
+ uint32_t result = ((Method)methodAddress)((uint64_t)that, gpregs[1], gpregs[2], gpregs[3], gpregs[4], gpregs[5]);
+ return result;
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp
new file mode 100644
index 0000000000..08e5198897
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp
@@ -0,0 +1,188 @@
+/* -*- 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"
+
+// 6 integral parameters are passed in registers
+const uint32_t GPR_COUNT = 6;
+
+// 8 floating point parameters are passed in SSE registers
+const uint32_t FPR_COUNT = 8;
+
+// Remember that these 'words' are 64-bit long
+static inline void
+invoke_count_words(uint32_t paramCount, nsXPTCVariant * s,
+ uint32_t & nr_stack)
+{
+ uint32_t nr_gpr;
+ uint32_t nr_fpr;
+ nr_gpr = 1; // skip one GP register for 'that'
+ nr_fpr = 0;
+ nr_stack = 0;
+
+ /* Compute number of eightbytes of class MEMORY. */
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (!s->IsPtrData()
+ && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) {
+ if (nr_fpr < FPR_COUNT)
+ nr_fpr++;
+ else
+ nr_stack++;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ nr_stack++;
+ }
+ }
+}
+
+static void
+invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s,
+ uint64_t * gpregs, double * fpregs)
+{
+ uint32_t nr_gpr = 1u; // skip one GP register for 'that'
+ uint32_t nr_fpr = 0u;
+ uint64_t value = 0u;
+
+ for (uint32_t i = 0; i < paramCount; i++, s++) {
+ if (s->IsPtrData())
+ value = (uint64_t) s->ptr;
+ 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->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((double *)d) = s->val.d;
+ d++;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((float *)d) = s->val.f;
+ d++;
+ }
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ gpregs[nr_gpr++] = value;
+ else
+ *d++ = value;
+ }
+ }
+}
+
+// Disable avx for the next function to allow compilation with
+// -march=native on new machines, or similar hardcoded -march options.
+// Having avx enabled appears to change the alignment behavior of alloca
+// (apparently adding an extra 16 bytes) of padding/alignment (and using
+// 32-byte alignment instead of 16-byte). This seems to be the best
+// available workaround, given that this code, which should perhaps
+// better be written in assembly, is written in C++.
+#ifndef __clang__
+#pragma GCC push_options
+#pragma GCC target ("no-avx")
+#endif
+
+// Avoid AddressSanitizer instrumentation for the next function because it
+// depends on __builtin_alloca behavior and alignment that cannot be relied on
+// once the function is compiled with a version of ASan that has dynamic-alloca
+// instrumentation enabled.
+
+MOZ_ASAN_BLACKLIST
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant * params)
+{
+ uint32_t nr_stack;
+ invoke_count_words(paramCount, params, nr_stack);
+
+ // Stack, if used, must be 16-bytes aligned
+ if (nr_stack)
+ nr_stack = (nr_stack + 1) & ~1;
+
+ // Load parameters to stack, if necessary
+ uint64_t *stack = (uint64_t *) __builtin_alloca(nr_stack * 8);
+ uint64_t gpregs[GPR_COUNT];
+ double fpregs[FPR_COUNT];
+ invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs);
+
+ // We used to have switches to make sure we would only load the registers
+ // that are needed for this call. That produced larger code that was
+ // not faster in practice. It also caused compiler warnings about the
+ // variables being used uninitialized.
+ // We now just load every every register. There could still be a warning
+ // from a memory analysis tools that we are loading uninitialized stack
+ // positions.
+
+ // FIXME: this function depends on the above __builtin_alloca placing
+ // the array in the correct spot for the ABI.
+
+ // Load FPR registers from fpregs[]
+ double d0, d1, d2, d3, d4, d5, d6, d7;
+
+ d7 = fpregs[7];
+ d6 = fpregs[6];
+ d5 = fpregs[5];
+ d4 = fpregs[4];
+ d3 = fpregs[3];
+ d2 = fpregs[2];
+ d1 = fpregs[1];
+ d0 = fpregs[0];
+
+ // Load GPR registers from gpregs[]
+ uint64_t a0, a1, a2, a3, a4, a5;
+
+ a5 = gpregs[5];
+ a4 = gpregs[4];
+ a3 = gpregs[3];
+ a2 = gpregs[2];
+ a1 = gpregs[1];
+ a0 = (uint64_t) that;
+
+ // Get pointer to method
+ uint64_t methodAddress = *((uint64_t *)that);
+ methodAddress += 8 * methodIndex;
+ methodAddress = *((uint64_t *)methodAddress);
+
+ typedef nsresult (*Method)(uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t, uint64_t, double, double, double,
+ double, double, double, double, double);
+ nsresult result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5,
+ d0, d1, d2, d3, d4, d5,
+ d6, d7);
+ return result;
+}
+
+#ifndef __clang__
+#pragma GCC pop_options
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp
new file mode 100644
index 0000000000..f545fcc996
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp
@@ -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/. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+extern "C" {
+
+// Remember that these 'words' are 32bit DWORDS
+
+uint32_t
+invoke_count_words(uint32_t paramCount, nsXPTCVariant* s)
+{
+ uint32_t result = 0;
+ for(uint32_t i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ result++;
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE :
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+void
+invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d)
+{
+ for(uint32_t i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+/* XXX: the following line is here (rather than as the default clause in
+ * the following switch statement) so that the Sun native compiler
+ * will generate the correct assembly code on the Solaris Intel
+ * platform. See the comments in bug #28817 for more details.
+ */
+
+ *((void**)d) = s->val.p;
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ }
+ }
+}
+
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp
new file mode 100644
index 0000000000..571fb42a2f
--- /dev/null
+++ b/xpcom/reflect/xptcall/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/md/unix/xptcstubs_alpha_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp
new file mode 100644
index 0000000000..d538767e1d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp
@@ -0,0 +1,189 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+/* Prototype specifies unmangled function name and disables unused warning */
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args)
+__asm__("PrepareAndDispatch") ATTRIBUTE_USED;
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args)
+{
+ const uint8_t PARAM_BUFFER_COUNT = 16;
+ const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+
+ 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");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // args[0] to args[NUM_ARG_REGS] hold floating point register values
+ uint64_t* ap = args + NUM_ARG_REGS;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break;
+ case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break;
+ case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break;
+ case nsXPTType::T_I64 : dp->val.i64 = (int64_t) *ap; break;
+ case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break;
+ case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break;
+ case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break;
+ case nsXPTType::T_U64 : dp->val.u64 = (uint64_t) *ap; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // floats passed via registers are stored as doubles
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (uint64_t) args[i];
+ dp->val.f = (float) dp->val.d; // convert double to float
+ }
+ else
+ dp->val.u32 = (uint32_t) *ap;
+ break;
+ case nsXPTType::T_DOUBLE :
+ // doubles passed via registers are also stored
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap;
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break;
+ case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break;
+ case nsXPTType::T_WCHAR : dp->val.wc = (char16_t) *ap; break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * SharedStub()
+ * Collects arguments and calls PrepareAndDispatch. The "methodIndex" is
+ * passed to this function via $1 to preserve the argument registers.
+ */
+__asm__(
+ "#### SharedStub ####\n"
+".text\n\t"
+ ".align 5\n\t"
+ ".ent SharedStub\n"
+"SharedStub:\n\t"
+ ".frame $30,96,$26,0\n\t"
+ ".mask 0x4000000,-96\n\t"
+ "ldgp $29,0($27)\n"
+"$SharedStub..ng:\n\t"
+ "subq $30,96,$30\n\t"
+ "stq $26,0($30)\n\t"
+ ".prologue 1\n\t"
+
+ /*
+ * Store arguments passed via registers to the stack.
+ * Floating point registers are stored as doubles and converted
+ * to floats in PrepareAndDispatch if necessary.
+ */
+ "stt $f17,16($30)\n\t" /* floating point registers */
+ "stt $f18,24($30)\n\t"
+ "stt $f19,32($30)\n\t"
+ "stt $f20,40($30)\n\t"
+ "stt $f21,48($30)\n\t"
+ "stq $17,56($30)\n\t" /* integer registers */
+ "stq $18,64($30)\n\t"
+ "stq $19,72($30)\n\t"
+ "stq $20,80($30)\n\t"
+ "stq $21,88($30)\n\t"
+
+ /*
+ * Call PrepareAndDispatch function.
+ */
+ "bis $1,$1,$17\n\t" /* pass "methodIndex" */
+ "addq $30,16,$18\n\t" /* pass "args" */
+ "bsr $26,$PrepareAndDispatch..ng\n\t"
+
+ "ldq $26,0($30)\n\t"
+ "addq $30,96,$30\n\t"
+ "ret $31,($26),1\n\t"
+ ".end SharedStub"
+ );
+
+/*
+ * nsresult nsXPTCStubBase::Stub##n()
+ * Sets register $1 to "methodIndex" and jumps to SharedStub.
+ */
+#define STUB_MANGLED_ENTRY(n, symbol) \
+ "#### Stub"#n" ####" "\n\t" \
+ ".text" "\n\t" \
+ ".align 5" "\n\t" \
+ ".globl " symbol "\n\t" \
+ ".ent " symbol "\n" \
+symbol ":" "\n\t" \
+ ".frame $30,0,$26,0" "\n\t" \
+ "ldgp $29,0($27)" "\n" \
+"$" symbol "..ng:" "\n\t" \
+ ".prologue 1" "\n\t" \
+ "lda $1,"#n "\n\t" \
+ "br $31,$SharedStub..ng" "\n\t" \
+ ".end " symbol
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".if "#n" < 10" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase5Stub"#n"Ev") "\n\t" \
+ ".elseif "#n" < 100" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase6Stub"#n"Ev") "\n\t" \
+ ".elseif "#n" < 1000" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase7Stub"#n"Ev") "\n\t" \
+ ".else" "\n\t" \
+ ".err \"Stub"#n" >= 1000 not yet supported.\"" "\n\t" \
+ ".endif" \
+ );
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp
new file mode 100644
index 0000000000..ef4f8514d9
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp
@@ -0,0 +1,238 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+#if !defined(__arm__) && !(defined(LINUX) || defined(ANDROID) || defined(XP_DARWIN))
+#error "This code is for Linux/iOS ARM only. Please check if it works for you, too.\nDepends strongly on gcc behaviour."
+#endif
+
+/* Specify explicitly a symbol for this function, don't try to guess the c++ mangled symbol. */
+static nsresult PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) asm("_PrepareAndDispatch")
+ATTRIBUTE_USED;
+
+#ifdef __ARM_EABI__
+#define DOUBLEWORD_ALIGN(p) ((uint32_t *)((((uint32_t)(p)) + 7) & 0xfffffff8))
+#else
+#define DOUBLEWORD_ALIGN(p) (p)
+#endif
+
+// Apple's iOS toolchain is lame.
+#ifdef __APPLE__
+#define GNU(str)
+#define APPLE(str) str
+#define UNDERSCORE "__"
+#else
+#define GNU(str) str
+#define APPLE(str)
+#define UNDERSCORE "_"
+#endif
+
+#ifdef __thumb__
+#define THUMB_FUNC ".thumb_func\n"
+#else
+#define THUMB_FUNC
+#endif
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ 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");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_I64 : ap = DOUBLEWORD_ALIGN(ap);
+ dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U64 : ap = DOUBLEWORD_ALIGN(ap);
+ dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : ap = DOUBLEWORD_ALIGN(ap);
+ dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * This is our shared stub.
+ *
+ * r0 = Self.
+ *
+ * The Rules:
+ * We pass an (undefined) number of arguments into this function.
+ * The first 3 C++ arguments are in r1 - r3, the rest are built
+ * by the calling function on the stack.
+ *
+ * We are allowed to corrupt r0 - r3, ip, and lr.
+ *
+ * Other Info:
+ * We pass the stub number in using `ip'.
+ *
+ * Implementation:
+ * - We save r1 to r3 inclusive onto the stack, which will be
+ * immediately below the caller saved arguments.
+ * - setup r2 (PrepareAndDispatch's args pointer) to point at
+ * the base of all these arguments
+ * - Save LR (for the return address)
+ * - Set r1 (PrepareAndDispatch's methodindex argument) from ip
+ * - r0 is passed through (self)
+ * - Call PrepareAndDispatch
+ * - When the call returns, we return by loading the PC off the
+ * stack, and undoing the stack (one instruction)!
+ *
+ */
+__asm__ ("\n"
+ GNU(".text\n")
+ APPLE(".section __TEXT,__text\n")
+ THUMB_FUNC
+ ".align 2\n"
+ "SharedStub:\n"
+ GNU(".fnstart\n")
+ GNU(".cfi_startproc\n")
+ "stmfd sp!, {r1, r2, r3}\n"
+ GNU(".save {r1, r2, r3}\n")
+ GNU(".cfi_def_cfa_offset 12\n")
+ GNU(".cfi_offset r3, -4\n")
+ GNU(".cfi_offset r2, -8\n")
+ GNU(".cfi_offset r1, -12\n")
+ "mov r2, sp\n"
+ "str lr, [sp, #-4]!\n"
+ GNU(".save {lr}\n")
+ GNU(".cfi_def_cfa_offset 16\n")
+ GNU(".cfi_offset lr, -16\n")
+ "mov r1, ip\n"
+ "bl _PrepareAndDispatch\n"
+ "ldr pc, [sp], #16\n"
+ GNU(".cfi_endproc\n")
+ GNU(".fnend"));
+
+/*
+ * Create sets of stubs to call the SharedStub.
+ * We don't touch the stack here, nor any registers, other than IP.
+ * IP is defined to be corruptable by a called function, so we are
+ * safe to use it.
+ *
+ * This will work with or without optimisation.
+ */
+
+/*
+ * Note : As G++3 ABI contains the length of the functionname in the
+ * mangled name, it is difficult to get a generic assembler mechanism like
+ * in the G++ 2.95 case.
+ * Create names would be like :
+ * _ZN14nsXPTCStubBase5Stub9Ev
+ * _ZN14nsXPTCStubBase6Stub13Ev
+ * _ZN14nsXPTCStubBase7Stub144Ev
+ * Use the assembler directives to get the names right...
+ */
+
+#define STUB_ENTRY(n) \
+ __asm__( \
+ GNU(".section \".text\"\n") \
+ APPLE(".section __TEXT,__text\n") \
+" .align 2\n" \
+" .if ("#n" - 10) < 0\n" \
+" .globl " UNDERSCORE "ZN14nsXPTCStubBase5Stub"#n"Ev\n" \
+ THUMB_FUNC \
+ GNU(".type _ZN14nsXPTCStubBase5Stub"#n"Ev,#function\n") \
+UNDERSCORE "ZN14nsXPTCStubBase5Stub"#n"Ev:\n" \
+" .else\n" \
+" .if ("#n" - 100) < 0\n" \
+" .globl " UNDERSCORE "ZN14nsXPTCStubBase6Stub"#n"Ev\n" \
+ THUMB_FUNC \
+ GNU(".type _ZN14nsXPTCStubBase6Stub"#n"Ev,#function\n") \
+UNDERSCORE "ZN14nsXPTCStubBase6Stub"#n"Ev:\n" \
+" .else\n" \
+" .if ("#n" - 1000) < 0\n" \
+" .globl " UNDERSCORE "ZN14nsXPTCStubBase7Stub"#n"Ev\n" \
+ THUMB_FUNC \
+ GNU(".type _ZN14nsXPTCStubBase7Stub"#n"Ev,#function\n") \
+UNDERSCORE "ZN14nsXPTCStubBase7Stub"#n"Ev:\n" \
+" .else\n" \
+" .err \"stub number "#n"> 1000 not yet supported\"\n" \
+" .endif\n" \
+" .endif\n" \
+" .endif\n" \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t");
+
+#if 0
+/*
+ * This part is left in as comment : this is how the method definition
+ * should look like.
+ */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n () \
+{ \
+ __asm__ ( \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t"); \
+ return 0; /* avoid warnings */ \
+}
+#endif
+
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp
new file mode 100644
index 0000000000..27c2b3d027
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp
@@ -0,0 +1,113 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ nsIInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ 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");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * These stubs move just move the values passed in registers onto the stack,
+ * so they are contiguous with values passed on the stack, and then calls
+ * PrepareAndDispatch() to do the dirty work.
+ */
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".global _Stub"#n"__14nsXPTCStubBase\n\t" \
+"_Stub"#n"__14nsXPTCStubBase:\n\t" \
+ "stmfd sp!, {r1, r2, r3} \n\t" \
+ "mov ip, sp \n\t" \
+ "stmfd sp!, {fp, ip, lr, pc} \n\t" \
+ "sub fp, ip, #4 \n\t" \
+ "mov r1, #"#n" \n\t" /* = methodIndex */ \
+ "add r2, sp, #16 \n\t" \
+ "bl _PrepareAndDispatch__FP14nsXPTCStubBaseUiPUi \n\t" \
+ "ldmea fp, {fp, sp, lr} \n\t" \
+ "add sp, sp, #12 \n\t" \
+ "mov pc, lr \n\t" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp
new file mode 100644
index 0000000000..f63d0c1e28
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp
@@ -0,0 +1,205 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+#ifdef __GNUC__
+/* This tells gcc3.4+ not to optimize away symbols.
+ * @see http://gcc.gnu.org/gcc-3.4/changes.html
+ */
+#define DONT_DROP_OR_WARN __attribute__((used))
+#else
+/* This tells older gccs not to warn about unused vairables.
+ * @see http://docs.freebsd.org/info/gcc/gcc.info.Variable_Attributes.html
+ */
+#define DONT_DROP_OR_WARN __attribute__((unused))
+#endif
+
+/* Specify explicitly a symbol for this function, don't try to guess the c++ mangled symbol. */
+static nsresult PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args) asm("_PrepareAndDispatch")
+DONT_DROP_OR_WARN;
+
+static nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ 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");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * This is our shared stub.
+ *
+ * r0 = Self.
+ *
+ * The Rules:
+ * We pass an (undefined) number of arguments into this function.
+ * The first 3 C++ arguments are in r1 - r3, the rest are built
+ * by the calling function on the stack.
+ *
+ * We are allowed to corrupt r0 - r3, ip, and lr.
+ *
+ * Other Info:
+ * We pass the stub number in using `ip'.
+ *
+ * Implementation:
+ * - We save r1 to r3 inclusive onto the stack, which will be
+ * immediately below the caller saved arguments.
+ * - setup r2 (PrepareAndDispatch's args pointer) to point at
+ * the base of all these arguments
+ * - Save LR (for the return address)
+ * - Set r1 (PrepareAndDispatch's methodindex argument) from ip
+ * - r0 is passed through (self)
+ * - Call PrepareAndDispatch
+ * - When the call returns, we return by loading the PC off the
+ * stack, and undoing the stack (one instruction)!
+ *
+ */
+__asm__ ("\n\
+ .text \n\
+ .align 2 \n\
+SharedStub: \n\
+ stmfd sp!, {r1, r2, r3} \n\
+ mov r2, sp \n\
+ str lr, [sp, #-4]! \n\
+ mov r1, ip \n\
+ bl _PrepareAndDispatch \n\
+ ldr pc, [sp], #16");
+
+/*
+ * Create sets of stubs to call the SharedStub.
+ * We don't touch the stack here, nor any registers, other than IP.
+ * IP is defined to be corruptable by a called function, so we are
+ * safe to use it.
+ *
+ * This will work with or without optimisation.
+ */
+
+/*
+ * Note : As G++3 ABI contains the length of the functionname in the
+ * mangled name, it is difficult to get a generic assembler mechanism like
+ * in the G++ 2.95 case.
+ * Create names would be like :
+ * _ZN14nsXPTCStubBase5Stub9Ev
+ * _ZN14nsXPTCStubBase6Stub13Ev
+ * _ZN14nsXPTCStubBase7Stub144Ev
+ * Use the assembler directives to get the names right...
+ */
+
+#define STUB_ENTRY(n) \
+ __asm__( \
+ ".section \".text\"\n" \
+" .align 2\n" \
+" .iflt ("#n" - 10)\n" \
+" .globl _ZN14nsXPTCStubBase5Stub"#n"Ev\n" \
+" .type _ZN14nsXPTCStubBase5Stub"#n"Ev,#function\n" \
+"_ZN14nsXPTCStubBase5Stub"#n"Ev:\n" \
+" .else\n" \
+" .iflt ("#n" - 100)\n" \
+" .globl _ZN14nsXPTCStubBase6Stub"#n"Ev\n" \
+" .type _ZN14nsXPTCStubBase6Stub"#n"Ev,#function\n" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev:\n" \
+" .else\n" \
+" .iflt ("#n" - 1000)\n" \
+" .globl _ZN14nsXPTCStubBase7Stub"#n"Ev\n" \
+" .type _ZN14nsXPTCStubBase7Stub"#n"Ev,#function\n" \
+"_ZN14nsXPTCStubBase7Stub"#n"Ev:\n" \
+" .else\n" \
+" .err \"stub number "#n"> 1000 not yet supported\"\n" \
+" .endif\n" \
+" .endif\n" \
+" .endif\n" \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t");
+
+#if 0
+/*
+ * This part is left in as comment : this is how the method definition
+ * should look like.
+ */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n () \
+{ \
+ __asm__ ( \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t"); \
+ return 0; /* avoid warnings */ \
+}
+#endif
+
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.s
new file mode 100644
index 0000000000..6603a4f25b
--- /dev/null
+++ b/xpcom/reflect/xptcall/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
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s
new file mode 100644
index 0000000000..720dd6cc71
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s
@@ -0,0 +1,123 @@
+
+// Select C numeric constant
+ .radix C
+ .psr abi32
+ .psr msb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'SharedStub'
+ .proc SharedStub
+// manual bundling
+ .explicit
+
+ .global PrepareAndDispatch
+// .exclass PrepareAndDispatch, @fullyvisible
+ .type PrepareAndDispatch,@function
+
+SharedStub::
+// 10 arguments, first 8 are the input arguments of previous
+// function call. The 9th one is methodIndex and the 10th is the
+// pointer to the remaining input arguments. The last two arguments
+// are passed in memory.
+ .prologue
+ .save ar.pfs , r41
+// allocate 8 input args, 4 local args, and 5 output args
+ alloc r41 = ar.pfs, 8, 4, 5, 0 // M
+ .save rp, r40
+ mov r40 = rp // I
+ addp4 out4 = 28, sp ;; // I
+
+ .save ar.unat, r42
+ mov r42 = ar.unat // M
+ .fframe 144
+ add sp = -144, sp // A
+// unwind table already knows gp, don't need to specify anything
+ add r43 = 0, gp ;; // A
+
+// We have possible 8 integer registers and 8 float registers that could
+// be arguments. We also have a stack region from the previous
+// stack frame that may hold some stack arguments.
+// We need to write the integer registers to a memory region, write
+// the float registers to a memory region (making sure we don't step
+// on NAT while touching the registers). We also mark the memory
+// address of the stack arguments.
+// We then call PrepareAndDispatch() specifying the three memory
+// region pointers.
+
+
+ .body
+ add out0 = 0, in0 // A move self ptr
+// 144 bytes = 16 byte stack header + 64 byte int space + 64 byte float space
+// methodIndex is at 144 + 16 bytes away from current sp
+// (current frame + previous frame header)
+ ld4 out4 = [out4] // A restarg address
+ add r11 = 160, sp ;; // A address of methodIndex
+
+ ld8 out1 = [r11] // M load methodIndex
+// sp + 16 is the start of intargs
+ add out2 = 16, sp // A address of intargs
+// the intargs take up 64 bytes, so sp + 16 + 64 is the start of floatargs
+ add out3 = 80, sp ;; // A address of floatargs
+
+ add r11 = 0, out2 ;; // A
+ st8.spill [r11] = in1, 8 // M
+ add r10 = 0, out3 ;; // A
+
+ st8.spill [r11] = in2, 8 ;; // M
+ st8.spill [r11] = in3, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in4, 8 ;; // M
+ st8.spill [r11] = in5, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in6, 8 ;; // M
+ st8.spill [r11] = in7 // M
+ fclass.nm p14,p15 = f8,@nat ;; // F
+
+(p14) stfd [r10] = f8, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 = f9,@nat ;; // F
+
+(p12) stfd [r10] = f9, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f10,@nat ;; // F
+
+(p14) stfd [r10] = f10, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f11,@nat ;; // F
+
+(p12) stfd [r10] = f11, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f12,@nat ;; // F
+
+(p14) stfd [r10] = f12, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f13,@nat ;; // F
+
+(p12) stfd [r10] = f13, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f14,@nat ;; // F
+
+(p14) stfd [r10] = f14, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f15,@nat ;; // F
+
+(p12) stfd [r10] = f15, 8 // M
+(p13) add r10 = 8, r10 // A
+
+// branch to PrepareAndDispatch
+ br.call.dptk.few rp = PrepareAndDispatch ;; // B
+
+// epilog
+ mov ar.unat = r42 // M
+ mov ar.pfs = r41 // I
+ mov rp = r40 ;; // I
+
+ add gp = 0, r43 // A
+ add sp = 144, sp // A
+ br.ret.dptk.few rp ;; // B
+
+ .endp
+
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s
new file mode 100644
index 0000000000..4c07836d72
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s
@@ -0,0 +1,124 @@
+
+// Select C numeric constant
+ .radix C
+ .psr abi64
+ .psr lsb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'SharedStub'
+ .proc SharedStub
+// manual bundling
+ .explicit
+
+ .global PrepareAndDispatch
+// .exclass PrepareAndDispatch, @fullyvisible
+ .type PrepareAndDispatch,@function
+
+SharedStub::
+// 10 arguments, first 8 are the input arguments of previous
+// function call. The 9th one is methodIndex and the 10th is the
+// pointer to the remaining input arguments. The last two arguments
+// are passed in memory.
+ .prologue
+ .save ar.pfs , r41
+// allocate 8 input args, 4 local args, and 5 output args
+ alloc r41 = ar.pfs, 8, 4, 5, 0 // M
+ .save rp, r40
+ mov r40 = rp // I
+ add out4 = 24, sp ;; // I
+
+ .save ar.unat, r42
+ mov r42 = ar.unat // M
+ .fframe 144
+ add sp = -144, sp // A
+// unwind table already knows gp, don't need to specify anything
+ add r43 = 0, gp ;; // A
+
+// We have possible 8 integer registers and 8 float registers that could
+// be arguments. We also have a stack region from the previous
+// stack frame that may hold some stack arguments.
+// We need to write the integer registers to a memory region, write
+// the float registers to a memory region (making sure we don't step
+// on NAT while touching the registers). We also mark the memory
+// address of the stack arguments.
+// We then call PrepareAndDispatch() specifying the three memory
+// region pointers.
+
+
+ .body
+ add out0 = 0, in0 // A move self ptr
+// 144 bytes = 16 byte stack header + 64 byte int space + 64 byte float space
+// methodIndex is at 144 + 16 bytes away from current sp
+// (current frame + previous frame header)
+ ld8 out4 = [out4] // M restarg address
+ add r11 = 160, sp ;; // A address of methodIndex
+
+ ld8 out1 = [r11] // M load methodIndex
+// sp + 16 is the start of intargs
+ add out2 = 16, sp // A address of intargs
+// the intargs take up 64 bytes, so sp + 16 + 64 is the start of floatargs
+ add out3 = 80, sp ;; // A address of floatargs
+
+ add r11 = 0, out2 ;; // A
+ st8.spill [r11] = in1, 8 // M
+ add r10 = 0, out3 ;; // A
+
+ st8.spill [r11] = in2, 8 ;; // M
+ st8.spill [r11] = in3, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in4, 8 ;; // M
+ st8.spill [r11] = in5, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in6, 8 ;; // M
+ st8.spill [r11] = in7 // M
+ fclass.nm p14,p15 = f8,@nat ;; // F
+
+(p14) stfd [r10] = f8, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 = f9,@nat ;; // F
+
+(p12) stfd [r10] = f9, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f10,@nat ;; // F
+
+(p14) stfd [r10] = f10, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f11,@nat ;; // F
+
+(p12) stfd [r10] = f11, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f12,@nat ;; // F
+
+(p14) stfd [r10] = f12, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f13,@nat ;; // F
+
+(p12) stfd [r10] = f13, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f14,@nat ;; // F
+
+(p14) stfd [r10] = f14, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f15,@nat ;; // F
+
+(p12) stfd [r10] = f15, 8 // M
+(p13) add r10 = 8, r10 // A
+
+// branch to PrepareAndDispatch
+ br.call.dptk.few rp = PrepareAndDispatch ;; // B
+
+// epilog
+ mov ar.unat = r42 // M
+ mov ar.pfs = r41 // I
+ mov rp = r40 ;; // I
+
+ add gp = 0, r43 // A
+ add sp = 144, sp // A
+ br.ret.dptk.few rp ;; // B
+
+ .endp
+
+/* Magic indicating no need for an executable stack */
+.section .note.GNU-stack, "", @progbits ; .previous
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S
new file mode 100644
index 0000000000..d17301634e
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S
@@ -0,0 +1,116 @@
+/* -*- Mode: asm; tab-width: 4; 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/. */
+
+/* This code is for MIPS using the O32 ABI. */
+
+#ifdef ANDROID
+#include <asm/regdef.h>
+#include <asm/asm.h>
+#include <machine/asm.h>
+#else
+#include <sys/regdef.h>
+#include <sys/asm.h>
+#endif
+
+# NARGSAVE is the argument space in the callers frame, including extra
+# 'shadowed' space for the argument registers. The minimum of 4
+# argument slots is sometimes predefined in the header files.
+#ifndef NARGSAVE
+#define NARGSAVE 4
+#endif
+
+#define LOCALSZ 2 /* gp, ra */
+#define FRAMESZ ((((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK)
+
+#define RAOFF (FRAMESZ - (1*SZREG))
+#define GPOFF (FRAMESZ - (2*SZREG))
+
+#define A0OFF (FRAMESZ + (0*SZREG))
+#define A1OFF (FRAMESZ + (1*SZREG))
+#define A2OFF (FRAMESZ + (2*SZREG))
+#define A3OFF (FRAMESZ + (3*SZREG))
+
+ .text
+
+#define STUB_ENTRY(x) \
+ .if x < 10; \
+ .globl _ZN14nsXPTCStubBase5Stub ##x ##Ev; \
+ .type _ZN14nsXPTCStubBase5Stub ##x ##Ev,@function; \
+ .aent _ZN14nsXPTCStubBase5Stub ##x ##Ev,0; \
+_ZN14nsXPTCStubBase5Stub ##x ##Ev:; \
+ SETUP_GP; \
+ li t0,x; \
+ b sharedstub; \
+ .elseif x < 100; \
+ .globl _ZN14nsXPTCStubBase6Stub ##x ##Ev; \
+ .type _ZN14nsXPTCStubBase6Stub ##x ##Ev,@function; \
+ .aent _ZN14nsXPTCStubBase6Stub ##x ##Ev,0; \
+_ZN14nsXPTCStubBase6Stub ##x ##Ev:; \
+ SETUP_GP; \
+ li t0,x; \
+ b sharedstub; \
+ .elseif x < 1000; \
+ .globl _ZN14nsXPTCStubBase7Stub ##x ##Ev; \
+ .type _ZN14nsXPTCStubBase7Stub ##x ##Ev,@function; \
+ .aent _ZN14nsXPTCStubBase7Stub ##x ##Ev,0; \
+_ZN14nsXPTCStubBase7Stub ##x ##Ev:; \
+ SETUP_GP; \
+ li t0,x; \
+ b sharedstub; \
+ .else; \
+ .err; \
+ .endif
+
+# SENTINEL_ENTRY is handled in the cpp file.
+#define SENTINEL_ENTRY(x)
+
+#
+# open a dummy frame for the function entries
+#
+ .align 2
+ .type dummy,@function
+ .ent dummy, 0
+ .frame sp, FRAMESZ, ra
+dummy:
+ SETUP_GP
+
+#include "xptcstubsdef.inc"
+
+sharedstub:
+ subu sp, FRAMESZ
+
+ # specify the save register mask for gp, ra, a0-a3
+ .mask 0x900000F0, RAOFF-FRAMESZ
+
+ sw ra, RAOFF(sp)
+ SAVE_GP(GPOFF)
+
+ # Micro-optimization: a0 is already loaded, and its slot gets
+ # ignored by PrepareAndDispatch, so no need to save it here.
+ # sw a0, A0OFF(sp)
+ sw a1, A1OFF(sp)
+ sw a2, A2OFF(sp)
+ sw a3, A3OFF(sp)
+
+ la t9, PrepareAndDispatch
+
+ # t0 is methodIndex
+ move a1, t0
+ # have a2 point to the begin of the argument space on stack
+ addiu a2, sp, FRAMESZ
+
+ # PrepareAndDispatch(that, methodIndex, args)
+ jalr t9
+
+ # Micro-optimization: Using jalr explicitly has the side-effect
+ # of not triggering .cprestore. This is ok because we have no
+ # gp reference below this point. It also allows better
+ # instruction sscheduling.
+ # lw gp, GPOFF(fp)
+
+ lw ra, RAOFF(sp)
+ addiu sp, FRAMESZ
+ j ra
+ END(dummy)
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4
new file mode 100644
index 0000000000..33c7b1492c
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4
@@ -0,0 +1,75 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * 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 code is for MIPS using the O32 ABI. */
+
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+ .text
+ .globl PrepareAndDispatch
+
+NARGSAVE=4 # extra space for the callee to use. gccism
+ # we can put our a0-a3 in our callers space.
+LOCALSZ=2 # gp, ra
+FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+
+define(STUB_NAME, `Stub'$1`__14nsXPTCStubBase')
+
+define(STUB_ENTRY,
+` .globl 'STUB_NAME($1)`
+ .align 2
+ .type 'STUB_NAME($1)`,@function
+ .ent 'STUB_NAME($1)`, 0
+'STUB_NAME($1)`:
+ .frame sp, FRAMESZ, ra
+ .set noreorder
+ .cpload t9
+ .set reorder
+ subu sp, FRAMESZ
+ .cprestore 16
+ li t0, '$1`
+ b sharedstub
+.end 'STUB_NAME($1)`
+
+')
+
+define(SENTINEL_ENTRY, `')
+
+include(xptcstubsdef.inc)
+
+ .globl sharedstub
+ .ent sharedstub
+sharedstub:
+
+ REG_S ra, 20(sp)
+
+ REG_S a0, 24(sp)
+ REG_S a1, 28(sp)
+ REG_S a2, 32(sp)
+ REG_S a3, 36(sp)
+
+ # t0 is methodIndex
+ move a1, t0
+
+ # put the start of a1, a2, a3, and stack
+ move a2, sp
+ addi a2, 24 # have a2 point to sp + 24 (where a0 is)
+
+ # PrepareAndDispatch(that, methodIndex, args)
+ # a0 a1 a2
+ #
+ jal PrepareAndDispatch
+
+ REG_L ra, 20(sp)
+ REG_L a1, 28(sp)
+ REG_L a2, 32(sp)
+
+ addu sp, FRAMESZ
+ j ra
+
+.end sharedstub
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S
new file mode 100644
index 0000000000..11d851536e
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S
@@ -0,0 +1,111 @@
+/* -*- 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 <sys/regdef.h>
+#include <sys/asm.h>
+
+LOCALSZ=16
+FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+
+A1OFF=FRAMESZ-(9*SZREG)
+A2OFF=FRAMESZ-(8*SZREG)
+A3OFF=FRAMESZ-(7*SZREG)
+A4OFF=FRAMESZ-(6*SZREG)
+A5OFF=FRAMESZ-(5*SZREG)
+A6OFF=FRAMESZ-(4*SZREG)
+A7OFF=FRAMESZ-(3*SZREG)
+GPOFF=FRAMESZ-(2*SZREG)
+RAOFF=FRAMESZ-(1*SZREG)
+
+F13OFF=FRAMESZ-(16*SZREG)
+F14OFF=FRAMESZ-(15*SZREG)
+F15OFF=FRAMESZ-(14*SZREG)
+F16OFF=FRAMESZ-(13*SZREG)
+F17OFF=FRAMESZ-(12*SZREG)
+F18OFF=FRAMESZ-(11*SZREG)
+F19OFF=FRAMESZ-(10*SZREG)
+
+#define SENTINEL_ENTRY(n) /* defined in cpp file, not here */
+
+#define STUB_ENTRY(x) \
+ .if x < 10; \
+ MAKE_STUB(x, _ZN14nsXPTCStubBase5Stub ##x ##Ev); \
+ .elseif x < 100; \
+ MAKE_STUB(x, _ZN14nsXPTCStubBase6Stub ##x ##Ev); \
+ .elseif x < 1000; \
+ MAKE_STUB(x, _ZN14nsXPTCStubBase7Stub ##x ##Ev); \
+ .else; \
+ .err; \
+ .endif
+
+#define MAKE_STUB(x, name) \
+ .globl name; \
+ .type name,@function; \
+ .aent name,0; \
+name:; \
+ PTR_SUBU sp,FRAMESZ; \
+ SETUP_GP64(GPOFF, name); \
+ li t0,x; \
+ b sharedstub; \
+
+#
+# open a dummy frame for the function entries
+#
+ .text
+ .align 2
+ .type dummy,@function
+ .ent dummy, 0
+dummy:
+ .frame sp, FRAMESZ, ra
+ .mask 0x90000FF0, RAOFF-FRAMESZ
+ .fmask 0x000FF000, F19OFF-FRAMESZ
+
+#include "xptcstubsdef.inc"
+
+sharedstub:
+
+ REG_S a1, A1OFF(sp)
+ REG_S a2, A2OFF(sp)
+ REG_S a3, A3OFF(sp)
+ REG_S a4, A4OFF(sp)
+ REG_S a5, A5OFF(sp)
+ REG_S a6, A6OFF(sp)
+ REG_S a7, A7OFF(sp)
+ REG_S ra, RAOFF(sp)
+
+ s.d $f13, F13OFF(sp)
+ s.d $f14, F14OFF(sp)
+ s.d $f15, F15OFF(sp)
+ s.d $f16, F16OFF(sp)
+ s.d $f17, F17OFF(sp)
+ s.d $f18, F18OFF(sp)
+ s.d $f19, F19OFF(sp)
+
+ # t0 is methodIndex
+ move a1, t0
+
+ # a2 is stack address where extra function params
+ # are stored that do not fit in registers
+ move a2, sp
+ PTR_ADDI a2, FRAMESZ
+
+ # a3 is stack address of a1..a7
+ move a3, sp
+ PTR_ADDI a3, A1OFF
+
+ # a4 is stack address of f13..f19
+ move a4, sp
+ PTR_ADDI a4, F13OFF
+
+ # PrepareAndDispatch(that, methodIndex, args, gprArgs, fpArgs)
+ # a0 a1 a2 a3 a4
+ #
+ jal PrepareAndDispatch
+
+ REG_L ra, RAOFF(sp)
+ RESTORE_GP64
+
+ PTR_ADDU sp, FRAMESZ
+ j ra
+ END(dummy)
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s
new file mode 100644
index 0000000000..9e86848fcf
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s
@@ -0,0 +1,68 @@
+ .LEVEL 1.1
+
+curframesz .EQU 128
+; SharedStub has stack size of 128 bytes
+
+lastframesz .EQU 64
+; the StubN C++ function has a small stack size of 64 bytes
+
+ .SPACE $TEXT$,SORT=8
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
+SharedStub
+ .PROC
+ .CALLINFO CALLER,FRAME=80,SAVE_RP,ARGS_SAVED
+
+ .ENTRY
+ STW %rp,-20(%sp)
+ LDO 128(%sp),%sp
+
+ STW %r19,-32(%r30)
+ STW %r26,-36-curframesz(%r30) ; save arg0 in previous frame
+
+ LDO -80(%r30),%r28
+ FSTD,MA %fr5,8(%r28) ; save darg0
+ FSTD,MA %fr7,8(%r28) ; save darg1
+ FSTW,MA %fr4L,4(%r28) ; save farg0
+ FSTW,MA %fr5L,4(%r28) ; save farg1
+ FSTW,MA %fr6L,4(%r28) ; save farg2
+ FSTW,MA %fr7L,4(%r28) ; save farg3
+
+ ; Former value of register 26 is already properly saved by StubN,
+ ; but register 25-23 are not because of the arguments mismatch
+ STW %r25,-40-curframesz-lastframesz(%r30) ; save r25
+ STW %r24,-44-curframesz-lastframesz(%r30) ; save r24
+ STW %r23,-48-curframesz-lastframesz(%r30) ; save r23
+ COPY %r26,%r25 ; method index is arg1
+ LDW -36-curframesz-lastframesz(%r30),%r26 ; self is arg0
+ LDO -40-curframesz-lastframesz(%r30),%r24 ; normal args is arg2
+ LDO -80(%r30),%r23 ; floating args is arg3
+
+ BL .+8,%r2
+ ADDIL L'PrepareAndDispatch-$PIC_pcrel$0+4,%r2
+ LDO R'PrepareAndDispatch-$PIC_pcrel$1+8(%r1),%r1
+$PIC_pcrel$0
+ LDSID (%r1),%r31
+$PIC_pcrel$1
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+;in=23-26;out=28;
+ BLE 0(%sr0,%r1)
+ COPY %r31,%r2
+
+ LDW -32(%r30),%r19
+
+ LDW -148(%sp),%rp
+ BVE (%rp)
+ .EXIT
+ LDO -128(%sp),%sp
+
+
+ .PROCEND ;in=26;out=28;
+
+ .ALIGN 8
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+ .IMPORT PrepareAndDispatch,CODE
+ .EXPORT SharedStub,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR,LONG_RETURN
+ .END
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s
new file mode 100644
index 0000000000..b45d7763be
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s
@@ -0,0 +1,73 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * 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/. */
+
+ .LEVEL 1.1
+ .TEXT
+ .ALIGN 4
+
+curframesz:
+ .EQU 128
+
+
+; SharedStub has stack size of 128 bytes
+
+lastframesz:
+ .EQU 64
+
+; the StubN C++ function has a small stack size of 64 bytes
+
+
+.globl SharedStub
+ .type SharedStub, @function
+
+SharedStub:
+ .PROC
+ .CALLINFO CALLER,FRAME=80,SAVE_RP
+
+ .ENTRY
+ STW %rp,-20(%sp)
+ LDO 128(%sp),%sp
+
+ STW %r19,-32(%r30)
+ STW %r26,-36-curframesz(%r30) ; save arg0 in previous frame
+
+ LDO -80(%r30),%r28
+ FSTD,MA %fr5,8(%r28) ; save darg0
+ FSTD,MA %fr7,8(%r28) ; save darg1
+ FSTW,MA %fr4L,4(%r28) ; save farg0
+ FSTW,MA %fr5L,4(%r28) ; save farg1
+ FSTW,MA %fr6L,4(%r28) ; save farg2
+ FSTW,MA %fr7L,4(%r28) ; save farg3
+
+ ; Former value of register 26 is already properly saved by StubN,
+ ; but register 25-23 are not because of the argument mismatch
+ STW %r25,-40-curframesz-lastframesz(%r30) ; save r25
+ STW %r24,-44-curframesz-lastframesz(%r30) ; save r24
+ STW %r23,-48-curframesz-lastframesz(%r30) ; save r23
+ COPY %r26,%r25 ; method index is arg1
+ LDW -36-curframesz-lastframesz(%r30),%r26 ; self is arg0
+ LDO -40-curframesz-lastframesz(%r30),%r24 ; normal args is arg2
+ LDO -80(%r30),%r23 ; floating args is arg3
+
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR ;in=23-26;out=28;
+ BL PrepareAndDispatch, %r31
+ COPY %r31,%r2
+
+ LDW -32(%r30),%r19
+
+ LDW -148(%sp),%rp
+ LDO -128(%sp),%sp
+
+
+ BV,N (%rp)
+ NOP
+ NOP
+
+ .EXIT
+ .PROCEND ;in=26;out=28;
+
+ .SIZE SharedStub, .-SharedStub
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S
new file mode 100644
index 0000000000..877e262b98
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S
@@ -0,0 +1,112 @@
+# 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 r0,0; .set r1,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+#if _CALL_ELF == 2
+#define STACK_PARAMS 96
+#else
+#define STACK_PARAMS 112
+#endif
+
+#if _CALL_ELF == 2
+ .section ".text"
+ .type SharedStub,@function
+ .globl SharedStub
+ # Make the symbol hidden so that the branch from the stub does
+ # not go via a PLT. This is not only better for performance,
+ # but may be necessary to avoid linker errors since there is
+ # no place to restore the TOC register in a sibling call.
+ .hidden SharedStub
+ .align 2
+SharedStub:
+0: addis 2,12,(.TOC.-0b)@ha
+ addi 2,2,(.TOC.-0b)@l
+ .localentry SharedStub,.-SharedStub
+#else
+ .section ".text"
+ .align 2
+ .globl SharedStub
+ # Make the symbol hidden so that the branch from the stub does
+ # not go via a PLT. This is not only better for performance,
+ # but may be necessary to avoid linker errors since there is
+ # no place to restore the TOC register in a sibling call.
+ .hidden SharedStub
+ .section ".opd","aw"
+ .align 3
+
+SharedStub:
+ .quad .SharedStub,.TOC.@tocbase
+ .previous
+ .type SharedStub,@function
+
+.SharedStub:
+#endif
+ mflr r0
+
+ std r4, -56(r1) # Save all GPRS
+ std r5, -48(r1)
+ std r6, -40(r1)
+ std r7, -32(r1)
+ std r8, -24(r1)
+ std r9, -16(r1)
+ std r10, -8(r1)
+
+ stfd f13, -64(r1) # ... and FPRS
+ stfd f12, -72(r1)
+ stfd f11, -80(r1)
+ stfd f10, -88(r1)
+ stfd f9, -96(r1)
+ stfd f8, -104(r1)
+ stfd f7, -112(r1)
+ stfd f6, -120(r1)
+ stfd f5, -128(r1)
+ stfd f4, -136(r1)
+ stfd f3, -144(r1)
+ stfd f2, -152(r1)
+ stfd f1, -160(r1)
+
+ subi r6,r1,56 # r6 --> gprData
+ subi r7,r1,160 # r7 --> fprData
+ addi r5,r1,STACK_PARAMS # r5 --> extra stack args
+
+ std r0, 16(r1)
+
+ stdu r1,-288(r1)
+ # r3 has the 'self' pointer
+ # already
+
+ mr r4,r11 # r4 is methodIndex selector,
+ # passed via r11 in the
+ # nsNSStubBase::StubXX() call
+
+ bl PrepareAndDispatch
+ nop
+
+ ld 1,0(r1) # restore stack
+ ld r0,16(r1) # restore LR
+ mtlr r0
+ blr
+
+#if _CALL_ELF == 2
+ .size SharedStub,.-SharedStub
+#else
+ .size SharedStub,.-.SharedStub
+#endif
+
+ # Magic indicating no need for an executable stack
+ .section .note.GNU-stack, "", @progbits ; .previous
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4
new file mode 100644
index 0000000000..6dabf334da
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4
@@ -0,0 +1,119 @@
+# 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 r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+# Define the correct name of the stub function based on the object model
+
+define(STUB_NAME,
+ ifelse(AIX_OBJMODEL, ibm,
+ `Stub'$1`__EI14nsXPTCStubBaseFv',
+ `Stub'$1`__14nsXPTCStubBaseFv'))
+
+define(STUB_ENTRY, `
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.'STUB_NAME($1)`{TC},"'STUB_NAME($1)`"
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .'STUB_NAME($1)`
+ .globl 'STUB_NAME($1)`{DS}
+
+.'STUB_NAME($1)`:
+ li r12, '$1`
+ b .SharedStub
+ nop
+
+
+ .toc
+T.18.'STUB_NAME($1)`:
+ .tc H.18.'STUB_NAME($1)`{TC},'STUB_NAME($1)`{DS}
+ .csect 'STUB_NAME($1)`{DS}
+ .long .'STUB_NAME($1)`
+ .long TOC{TC0}
+ .long 0x00000000
+')
+
+define(SENTINEL_ENTRY, `')
+
+include(xptcstubsdef.inc)
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.SharedStub{TC},"SharedStub"
+
+# .text section
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .SharedStub
+ .globl SharedStub{DS}
+ .extern .PrepareAndDispatch
+
+.SharedStub:
+ mflr r0
+ stw r0,8(sp)
+
+ stwu sp,-176(sp) # room for linkage (24), fprData (104), gprData(28)
+ # outgoing params to PrepareAndDispatch (20)
+
+ stw r4,44(sp) # link area (24) + PrepareAndDispatch params (20)
+ stw r5,48(sp)
+ stw r6,52(sp)
+ stw r7,56(sp)
+ stw r8,60(sp)
+ stw r9,64(sp)
+ stw r10,68(sp)
+ stfd f1,72(sp)
+ stfd f2,80(sp)
+ stfd f3,88(sp)
+ stfd f4,96(sp)
+ stfd f5,104(sp)
+ stfd f6,112(sp)
+ stfd f7,120(sp)
+ stfd f8,128(sp)
+ stfd f9,136(sp)
+ stfd f10,144(sp)
+ stfd f11,152(sp)
+ stfd f12,156(sp)
+ stfd f13,164(sp)
+
+ addi r6,sp,44 # gprData
+
+ addi r7,sp,72 # fprData
+ # r3 has the 'self' pointer already
+ mr r4,r12 # methodIndex selector (it is now LATER)
+ addi r5,sp,232 # pointer to callers args area, beyond r3-r10
+ # mapped range
+
+ bl .PrepareAndDispatch
+ nop
+
+
+ lwz r0,184(sp)
+ addi sp,sp,176
+ mtlr r0
+ blr
+
+# .data section
+
+ .toc # 0x00000038
+T.18.SharedStub:
+ .tc H.18.SharedStub{TC},SharedStub{DS}
+
+ .csect SharedStub{DS}
+ .long .SharedStub # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect SharedStub{DS}
+
+# .bss section
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4
new file mode 100644
index 0000000000..24d713cc9b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4
@@ -0,0 +1,97 @@
+# 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 r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+# Define the correct name of the stub function based on the object model
+define(STUB_NAME,
+ ifelse(AIX_OBJMODEL, ibm,
+ `Stub'$1`__EI14nsXPTCStubBaseFv',
+ `Stub'$1`__14nsXPTCStubBaseFv'))
+define(STUB_ENTRY, `
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.'STUB_NAME($1)`{TC},"'STUB_NAME($1)`"
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .'STUB_NAME($1)`
+ .globl 'STUB_NAME($1)`{DS}
+.'STUB_NAME($1)`:
+ li r12, '$1`
+ b .SharedStub
+ nop
+ .toc
+T.18.'STUB_NAME($1)`:
+ .tc H.18.'STUB_NAME($1)`{TC},'STUB_NAME($1)`{DS}
+ .csect 'STUB_NAME($1)`{DS}
+ .llong .'STUB_NAME($1)`
+ .llong TOC{TC0}
+ .llong 0x00000000
+')
+define(SENTINEL_ENTRY, `')
+include(xptcstubsdef.inc)
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.SharedStub{TC},"SharedStub"
+# .text section
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .SharedStub
+ .globl SharedStub{DS}
+ .extern .PrepareAndDispatch
+.SharedStub:
+ mflr r0
+ std r0,16(sp)
+ stdu sp,-248(sp) # room for linkage (24*2), fprData (104), gprData(28*2)
+ # outgoing params to PrepareAndDispatch (40)
+ std r4,88(sp) # link area (48) + PrepareAndDispatch params (20)
+ std r5,96(sp)
+ std r6,104(sp)
+ std r7,112(sp)
+ std r8,120(sp)
+ std r9,128(sp)
+ std r10,136(sp)
+ stfd f1,144(sp)
+ stfd f2,152(sp)
+ stfd f3,160(sp)
+ stfd f4,168(sp)
+ stfd f5,176(sp)
+ stfd f6,184(sp)
+ stfd f7,192(sp)
+ stfd f8,200(sp)
+ stfd f9,208(sp)
+ stfd f10,216(sp)
+ stfd f11,224(sp)
+ stfd f12,232(sp)
+ stfd f13,240(sp)
+ addi r6,sp,88 # gprData
+ addi r7,sp,144 # fprData
+ # r3 has the 'self' pointer already
+ mr r4,r12 # methodIndex selector (it is now LATER)
+ addi r5,sp,360 # pointer to callers args area, beyond r3-r10
+ # mapped range
+ bl .PrepareAndDispatch
+ nop
+ ld r0,264(sp)
+ addi sp,sp,248
+ mtlr r0
+ blr
+# .data section
+ .toc # 0x00000038
+T.18.SharedStub:
+ .tc H.18.SharedStub{TC},SharedStub{DS}
+ .csect SharedStub{DS}
+ .llong .SharedStub # "\0\0\0\0"
+ .llong TOC{TC0} # "\0\0\0008"
+ .llong 0x00000000 # "\0\0\0\0"
+# End csect SharedStub{DS}
+# .bss section
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4 b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4
new file mode 100644
index 0000000000..dda5378503
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4
@@ -0,0 +1,114 @@
+/* -*- Mode: asm -*- */
+/* 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/. */
+
+ .text
+ .globl _SharedStub
+dnl
+define(STUB_MANGLED_ENTRY,
+` .globl '$2`
+ .align 2
+'$2`:
+ addi r12, 0,'$1`
+ b _SharedStub')
+dnl
+define(STUB_ENTRY,
+` .if '$1` < 10
+STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase5Stub'$1`Ev')
+ .elseif '$1` < 100
+STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase6Stub'$1`Ev')
+ .elseif '$1` < 1000
+STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase7Stub'$1`Ev')
+ .else
+ .err "Stub'$1` >= 1000 not yet supported."
+ .endif
+')
+dnl
+define(SENTINEL_ENTRY, `')
+dnl
+include(xptcstubsdef.inc)
+dnl
+// See also xptcstubs_ppc_rhapsody.cpp:PrepareAndDispatch.
+_SharedStub:
+ // Prolog(ue)
+ mflr r0 // Save the link register in the caller's
+ stw r0, 8(r1) // stack frame
+ stwu r1,-176(r1) // Allocate stack space for our own frame and
+ // adjust stack pointer
+
+ // Linkage area, 0(r1) to 24(r1)
+ // Original sp saved at 0(r1)
+
+ // Parameter area, 20 bytes from 24(r1) to
+ // 44(r1) to accomodate 5 arguments passed
+ // to PrepareAndDispatch
+
+ // Local variables, 132 bytes from 44(r1)
+ // to 176(r1), to accomodate 5 words and
+ // 13 doubles
+
+ stw r4, 44(r1) // Save parameters passed in GPRs r4-r10;
+ stw r5, 48(r1) // a pointer to here will be passed to
+ stw r6, 52(r1) // PrepareAndDispatch for access to
+ stw r7, 56(r1) // arguments passed in registers. r3,
+ stw r8, 60(r1) // the self pointer, is used for the
+ stw r9, 64(r1) // call but isn't otherwise needed in
+ stw r10, 68(r1) // PrepareAndDispatch, so it is not saved.
+
+ stfd f1, 72(r1) // Do the same for floating-point parameters
+ stfd f2, 80(r1) // passed in FPRs f1-f13
+ stfd f3, 88(r1)
+ stfd f4, 96(r1)
+ stfd f5, 104(r1)
+ stfd f6, 112(r1)
+ stfd f7, 120(r1)
+ stfd f8, 128(r1)
+ stfd f9, 136(r1)
+ stfd f10, 144(r1)
+ stfd f11, 152(r1)
+ stfd f12, 160(r1)
+ stfd f13, 168(r1)
+
+ // Set up parameters for call to
+ // PrepareAndDispatch. argument=
+ // 0, pointer to self, already in r3
+ mr r4,r12 // 1, stub number
+ addi r5, r1, 204 // 2, pointer to the parameter area in our
+ // caller's stack, for access to
+ // parameters beyond those passed in
+ // registers. Skip past the first parameter
+ // (corresponding to r3) for the same reason
+ // as above. 176 (size of our frame) + 24
+ // (size of caller's linkage) + 4 (skipped
+ // parameter)
+ addi r6, r1, 44 // 3, pointer to saved GPRs
+ addi r7, r1, 72 // 4, pointer to saved FPRs
+
+ bl L_PrepareAndDispatch$stub
+ // Do it
+ nop // Leave room for linker magic
+
+ // Epilog(ue)
+ lwz r0, 184(r1) // Retrieve old link register value
+ addi r1, r1, 176 // Restore stack pointer
+ mtlr r0 // Restore link register
+ blr // Return
+
+.picsymbol_stub
+L_PrepareAndDispatch$stub: // Standard PIC symbol stub
+ .indirect_symbol _PrepareAndDispatch
+ mflr r0
+ bcl 20,31,L1$pb
+L1$pb:
+ mflr r11
+ addis r11,r11,ha16(L1$lz-L1$pb)
+ mtlr r0
+ lwz r12,lo16(L1$lz-L1$pb)(r11)
+ mtctr r12
+ addi r11,r11,lo16(L1$lz-L1$pb)
+ bctr
+.lazy_symbol_pointer
+L1$lz:
+ .indirect_symbol _PrepareAndDispatch
+ .long dyld_stub_binding_helper
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S
new file mode 100644
index 0000000000..72a5a9f4b9
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S
@@ -0,0 +1,77 @@
+// -*- Mode: Asm -*-
+//
+// 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 r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl SharedStub
+ .type SharedStub,@function
+
+SharedStub:
+ stwu sp,-112(sp) // room for
+ // linkage (8),
+ // gprData (32),
+ // fprData (64),
+ // stack alignment(8)
+ mflr r0
+ stw r0,116(sp) // save LR backchain
+
+ stw r4,12(sp) // save GP registers
+ stw r5,16(sp) // (n.b. that we don't save r3
+ stw r6,20(sp) // because PrepareAndDispatch() is savvy)
+ stw r7,24(sp)
+ stw r8,28(sp)
+ stw r9,32(sp)
+ stw r10,36(sp)
+#ifndef __NO_FPRS__
+ stfd f1,40(sp) // save FP registers
+ stfd f2,48(sp)
+ stfd f3,56(sp)
+ stfd f4,64(sp)
+ stfd f5,72(sp)
+ stfd f6,80(sp)
+ stfd f7,88(sp)
+ stfd f8,96(sp)
+#endif
+
+ // r3 has the 'self' pointer already
+
+ mr r4,r11 // r4 <= methodIndex selector, passed
+ // via r11 in the nsXPTCStubBase::StubXX() call
+
+ addi r5,sp,120 // r5 <= pointer to callers args area,
+ // beyond r3-r10/f1-f8 mapped range
+
+ addi r6,sp,8 // r6 <= gprData
+#ifndef __NO_FPRS__
+ addi r7,sp,40 // r7 <= fprData
+#else
+ li r7, 0 // r7 should be unused
+#endif
+
+ bl PrepareAndDispatch@local // Go!
+
+ lwz r0,116(sp) // restore LR
+ mtlr r0
+ la sp,112(sp) // clean up the stack
+ blr
+
+/* Magic indicating no need for an executable stack */
+.section .note.GNU-stack, "", @progbits ; .previous
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_netbsd.s
new file mode 100644
index 0000000000..8d43165ba4
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_netbsd.s
@@ -0,0 +1,70 @@
+# -*- Mode: Asm -*-
+#
+# 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 r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl SharedStub
+ .type SharedStub,@function
+
+SharedStub:
+ stwu sp,-112(sp) # room for
+ # linkage (8),
+ # gprData (32),
+ # fprData (64),
+ # stack alignment(8)
+ mflr r0
+ stw r0,116(sp) # save LR backchain
+
+ stw r4,12(sp) # save GP registers
+ stw r5,16(sp) # (n.b. that we don't save r3
+ stw r6,20(sp) # because PrepareAndDispatch() is savvy)
+ stw r7,24(sp)
+ stw r8,28(sp)
+ stw r9,32(sp)
+ stw r10,36(sp)
+
+ stfd f1,40(sp) # save FP registers
+ stfd f2,48(sp)
+ stfd f3,56(sp)
+ stfd f4,64(sp)
+ stfd f5,72(sp)
+ stfd f6,80(sp)
+ stfd f7,88(sp)
+ stfd f8,96(sp)
+
+ # r3 has the 'self' pointer already
+
+ mr r4,r11 # r4 <= methodIndex selector, passed
+ # via r11 in the nsXPTCStubBase::StubXX() call
+
+ addi r5,sp,120 # r5 <= pointer to callers args area,
+ # beyond r3-r10/f1-f8 mapped range
+
+ addi r6,sp,8 # r6 <= gprData
+ addi r7,sp,40 # r7 <= fprData
+
+ bl PrepareAndDispatch@local # Go!
+
+ lwz r0,116(sp) # restore LR
+ mtlr r0
+ la sp,112(sp) # clean up the stack
+ blr
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S
new file mode 100644
index 0000000000..dcca082059
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S
@@ -0,0 +1,72 @@
+// -*- Mode: Asm -*-
+//
+// 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 r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl SharedStub
+ .type SharedStub,@function
+
+SharedStub:
+ stwu sp,-112(sp) // room for
+ // linkage (8),
+ // gprData (32),
+ // fprData (64),
+ // stack alignment(8)
+ mflr r0
+ stw r0,116(sp) // save LR backchain
+
+ stw r4,12(sp) // save GP registers
+ stw r5,16(sp) // (n.b. that we don't save r3
+ stw r6,20(sp) // because PrepareAndDispatch() is savvy)
+ stw r7,24(sp)
+ stw r8,28(sp)
+ stw r9,32(sp)
+ stw r10,36(sp)
+
+ stfd f1,40(sp) // save FP registers
+ stfd f2,48(sp)
+ stfd f3,56(sp)
+ stfd f4,64(sp)
+ stfd f5,72(sp)
+ stfd f6,80(sp)
+ stfd f7,88(sp)
+ stfd f8,96(sp)
+
+ // r3 has the 'self' pointer already
+
+ mr r4,r11 // r4 <= methodIndex selector, passed
+ // via r11 in the nsXPTCStubBase::StubXX() call
+
+ addi r5,sp,120 // r5 <= pointer to callers args area,
+ // beyond r3-r10/f1-f8 mapped range
+
+ addi r6,sp,8 // r6 <= gprData
+ addi r7,sp,40 // r7 <= fprData
+
+ bl PrepareAndDispatch@local // Go!
+
+ lwz r0,116(sp) // restore LR
+ mtlr r0
+ la sp,112(sp) // clean up the stack
+ blr
+
+// Magic indicating no need for an executable stack
+.section .note.GNU-stack, "", @progbits ; .previous
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s
new file mode 100644
index 0000000000..ab97a890c3
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc64_openbsd.s
@@ -0,0 +1,50 @@
+/* -*- Mode: asm; tab-width: 2; 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/. */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 0x7ff + 136, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ stx %i1, [%fp + 0x7ff + 136]
+ stx %i2, [%fp + 0x7ff + 144]
+ stx %i3, [%fp + 0x7ff + 152]
+ stx %i4, [%fp + 0x7ff + 160]
+ stx %i5, [%fp + 0x7ff + 168]
+! now we can build our own stack frame
+ save %sp,-(128 + 64),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 64
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s
new file mode 100644
index 0000000000..9b448d7c7d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s
@@ -0,0 +1,49 @@
+/* -*- 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/. */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ st %i1, [%fp + 72]
+ st %i2, [%fp + 76]
+ st %i3, [%fp + 80]
+ st %i4, [%fp + 84]
+ st %i5, [%fp + 88]
+! now we can build our own stack frame
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s
new file mode 100644
index 0000000000..871556d4c6
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s
@@ -0,0 +1,49 @@
+/* -*- 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/. */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ st %i1, [%fp + 72]
+ st %i2, [%fp + 76]
+ st %i3, [%fp + 80]
+ st %i4, [%fp + 84]
+ st %i5, [%fp + 88]
+! now we can build our own stack frame
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s
new file mode 100644
index 0000000000..9b448d7c7d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s
@@ -0,0 +1,49 @@
+/* -*- 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/. */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ st %i1, [%fp + 72]
+ st %i2, [%fp + 76]
+ st %i3, [%fp + 80]
+ st %i4, [%fp + 84]
+ st %i5, [%fp + 88]
+! now we can build our own stack frame
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparcv9_solaris.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparcv9_solaris.s
new file mode 100644
index 0000000000..ab97a890c3
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparcv9_solaris.s
@@ -0,0 +1,50 @@
+/* -*- Mode: asm; tab-width: 2; 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/. */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 0x7ff + 136, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ stx %i1, [%fp + 0x7ff + 136]
+ stx %i2, [%fp + 0x7ff + 144]
+ stx %i3, [%fp + 0x7ff + 152]
+ stx %i4, [%fp + 0x7ff + 160]
+ stx %i5, [%fp + 0x7ff + 168]
+! now we can build our own stack frame
+ save %sp,-(128 + 64),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 64
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, uint32_t index, uint32_t* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_64_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_64_solaris_SUNW.s
new file mode 100644
index 0000000000..aa6d84434a
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_64_solaris_SUNW.s
@@ -0,0 +1,63 @@
+#define STUB_ENTRY1(nn) \
+ .globl __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_; \
+ .hidden __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_; \
+ .type __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_, @function; \
+__1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_: \
+ movl $/**/nn/**/, %eax; \
+ jmp SharedStub; \
+ .size __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_ \
+
+#define STUB_ENTRY2(nn) \
+ .globl __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_; \
+ .hidden __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_; \
+ .type __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_, @function; \
+__1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_: \
+ movl $/**/nn/**/, %eax; \
+ jmp SharedStub; \
+ .size __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_ \
+
+#define STUB_ENTRY3(nn) \
+ .globl __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_; \
+ .hidden __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_; \
+ .type __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_, @function; \
+__1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_: \
+ movl $/**/nn/**/, %eax; \
+ jmp SharedStub; \
+ .size __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_ \
+
+// static nsresult SharedStub(uint32_t methodIndex)
+ .type SharedStub, @function;
+ SharedStub:
+ // make room for gpregs (48), fpregs (64)
+ pushq %rbp;
+ movq %rsp,%rbp;
+ subq $112,%rsp;
+ // save GP registers
+ movq %rdi,-112(%rbp);
+ movq %rsi,-104(%rbp);
+ movq %rdx, -96(%rbp);
+ movq %rcx, -88(%rbp);
+ movq %r8 , -80(%rbp);
+ movq %r9 , -72(%rbp);
+ leaq -112(%rbp),%rcx;
+ // save FP registers
+ movsd %xmm0,-64(%rbp);
+ movsd %xmm1,-56(%rbp);
+ movsd %xmm2,-48(%rbp);
+ movsd %xmm3,-40(%rbp);
+ movsd %xmm4,-32(%rbp);
+ movsd %xmm5,-24(%rbp);
+ movsd %xmm6,-16(%rbp);
+ movsd %xmm7, -8(%rbp);
+ leaq -64(%rbp),%r8;
+ // rdi has the 'self' pointer already
+ movl %eax,%esi;
+ leaq 16(%rbp),%rdx;
+ call PrepareAndDispatch@plt;
+ leave;
+ ret;
+ .size SharedStub, . - SharedStub
+
+#define SENTINEL_ENTRY(nn)
+
+#include "xptcstubsdef_asm.solx86"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_solaris_SUNW.s b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_solaris_SUNW.s
new file mode 100644
index 0000000000..76bdcf925b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_asm_x86_solaris_SUNW.s
@@ -0,0 +1,78 @@
+#define STUB_ENTRY1(nn) \
+ .globl __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_; \
+ .type __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_, @function; \
+__1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_: \
+ push %ebp; \
+ movl %esp,%ebp; \
+ andl $-16,%esp; \
+ push %ebx; \
+ call .CG4./**/nn/**/; \
+.CG4./**/nn/**/: \
+ pop %ebx; \
+ addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx; \
+ leal 0xc(%ebp), %ecx; \
+ pushl %ecx; \
+ pushl $/**/nn/**/; \
+ movl 0x8(%ebp), %ecx; \
+ pushl %ecx; \
+ call __1cSPrepareAndDispatch6FpnOnsXPTCStubBase_IpI_I_; \
+ addl $0xc , %esp; \
+ pop %ebx; \
+ movl %ebp,%esp; \
+ pop %ebp; \
+ ret ; \
+ .size __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseFStub/**/nn/**/6M_I_ \
+
+#define STUB_ENTRY2(nn) \
+ .globl __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_; \
+ .type __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_, @function; \
+__1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_: \
+ push %ebp; \
+ movl %esp,%ebp; \
+ andl $-16,%esp; \
+ push %ebx; \
+ call .CG4./**/nn/**/; \
+.CG4./**/nn/**/: \
+ pop %ebx; \
+ addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx; \
+ leal 0xc(%ebp), %ecx; \
+ pushl %ecx; \
+ pushl $/**/nn/**/; \
+ movl 0x8(%ebp), %ecx; \
+ pushl %ecx; \
+ call __1cSPrepareAndDispatch6FpnOnsXPTCStubBase_IpI_I_; \
+ addl $0xc , %esp; \
+ pop %ebx; \
+ movl %ebp,%esp; \
+ pop %ebp; \
+ ret ; \
+ .size __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseGStub/**/nn/**/6M_I_ \
+
+#define STUB_ENTRY3(nn) \
+ .globl __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_; \
+ .type __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_, @function; \
+__1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_: \
+ push %ebp; \
+ movl %esp,%ebp; \
+ andl $-16,%esp; \
+ push %ebx; \
+ call .CG4./**/nn/**/; \
+.CG4./**/nn/**/: \
+ pop %ebx; \
+ addl $_GLOBAL_OFFSET_TABLE_+0x1,%ebx; \
+ leal 0xc(%ebp), %ecx; \
+ pushl %ecx; \
+ pushl $/**/nn/**/; \
+ movl 0x8(%ebp), %ecx; \
+ pushl %ecx; \
+ call __1cSPrepareAndDispatch6FpnOnsXPTCStubBase_IpI_I_; \
+ addl $0xc , %esp; \
+ pop %ebx; \
+ movl %ebp,%esp; \
+ pop %ebp; \
+ ret ; \
+ .size __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_, . - __1cOnsXPTCStubBaseHStub/**/nn/**/6M_I_ \
+
+#define SENTINEL_ENTRY(nn)
+
+#include "xptcstubsdef_asm.solx86"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp
new file mode 100644
index 0000000000..49edfca440
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp
@@ -0,0 +1,16 @@
+/* -*- Mode: C -*- */
+/* 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/. */
+
+#if defined(__i386__)
+#include "xptcstubs_gcc_x86_unix.cpp"
+#elif defined(__x86_64__)
+#include "xptcstubs_x86_64_darwin.cpp"
+#elif defined(__ppc__)
+#include "xptcstubs_ppc_rhapsody.cpp"
+#elif defined(__arm__)
+#include "xptcstubs_arm.cpp"
+#else
+#error unknown cpu architecture
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp
new file mode 100644
index 0000000000..6811a26ad6
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp
@@ -0,0 +1,139 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+#include "xptc_gcc_x86_unix.h"
+
+extern "C" {
+static nsresult ATTRIBUTE_USED
+__attribute__ ((regparm (3)))
+PrepareAndDispatch(uint32_t methodIndex, nsXPTCStubBase* self, uint32_t* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ 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");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ dp->val.p = (void*) *ap;
+ switch(type)
+ {
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+} // extern "C"
+
+#if !defined(XP_MACOSX)
+
+#define STUB_HEADER(a, b) ".hidden " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev,@function\n"
+
+#define STUB_SIZE(a, b) ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev\n\t"
+
+#else
+
+#define STUB_HEADER(a, b)
+#define STUB_SIZE(a, b)
+
+#endif
+
+// gcc3 mangling tends to insert the length of the method name
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 2\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ STUB_HEADER(5, n) \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ STUB_HEADER(6, n) \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ STUB_HEADER(7, n) \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp " SYMBOL_UNDERSCORE "SharedStub\n\t" \
+ ".if " #n " < 10\n\t" \
+ STUB_SIZE(5, n) \
+ ".elseif " #n " < 100\n\t" \
+ STUB_SIZE(6, n) \
+ ".else\n\t" \
+ STUB_SIZE(7, n) \
+ ".endif");
+
+// static nsresult SharedStub(uint32_t methodIndex) __attribute__((regparm(1)))
+asm(".text\n\t"
+ ".align 2\n\t"
+#if !defined(XP_MACOSX)
+ ".type " SYMBOL_UNDERSCORE "SharedStub,@function\n\t"
+#endif
+ SYMBOL_UNDERSCORE "SharedStub:\n\t"
+ "leal 0x08(%esp), %ecx\n\t"
+ "movl 0x04(%esp), %edx\n\t"
+ "jmp " SYMBOL_UNDERSCORE "PrepareAndDispatch\n\t"
+#if !defined(XP_MACOSX)
+ ".size " SYMBOL_UNDERSCORE "SharedStub,.-" SYMBOL_UNDERSCORE "SharedStub"
+#endif
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+void
+xptc_dummy()
+{
+}
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp
new file mode 100644
index 0000000000..e2d37e4f56
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp
@@ -0,0 +1,151 @@
+
+/* -*- 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"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+// "This code is for IA64 only"
+
+/* Implement shared vtbl methods. */
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint64_t* intargs, uint64_t* floatargs, uint64_t* restargs)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ nsresult result = NS_ERROR_FAILURE;
+ uint64_t* iargs = intargs;
+ uint64_t* fargs = floatargs;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ 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");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for(i = 0; i < paramCount; ++i)
+ {
+ int isfloat = 0;
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ dp->val.p = (void*) *iargs;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) iargs;
+ dp->val.p = (void*) (*(adr+1));
+#endif
+ }
+ else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *(iargs); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(iargs); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *(iargs); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *(iargs); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(iargs); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(iargs); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *(iargs); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *(iargs); break;
+ case nsXPTType::T_FLOAT :
+ isfloat = 1;
+ if (i < 7)
+ dp->val.f = (float) *((double*) fargs); /* register */
+ else
+ dp->val.u32 = *(fargs); /* memory */
+ break;
+ case nsXPTType::T_DOUBLE :
+ isfloat = 1;
+ dp->val.u64 = *(fargs);
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = *(iargs); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(iargs); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *(iargs); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ if (i < 7)
+ {
+ /* we are parsing register arguments */
+ if (i == 6)
+ {
+ // run out of register arguments, move on to memory arguments
+ iargs = restargs;
+ fargs = restargs;
+ }
+ else
+ {
+ ++iargs; // advance one integer register slot
+ if (isfloat) ++fargs; // advance float register slot if isfloat
+ }
+ }
+ else
+ {
+ /* we are parsing memory arguments */
+ ++iargs;
+ ++fargs;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(uint64_t,uint64_t,uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t *);
+
+/* Variable a0-a7 were put there so we can have access to the 8 input
+ registers on Stubxyz entry */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n(uint64_t a1, \
+uint64_t a2,uint64_t a3,uint64_t a4,uint64_t a5,uint64_t a6,uint64_t a7, \
+uint64_t a8) \
+{ uint64_t a0 = (uint64_t) this; \
+ return SharedStub(a0,a1,a2,a3,a4,a5,a6,a7,(uint64_t) n, &a8); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp
new file mode 100644
index 0000000000..fea9e8e3d7
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ipf64.cpp
@@ -0,0 +1,154 @@
+
+/* -*- 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"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+// "This code is for IA64 only"
+
+/* Implement shared vtbl methods. */
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint64_t* intargs, uint64_t* floatargs, uint64_t* restargs)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ nsresult result = NS_ERROR_FAILURE;
+ uint64_t* iargs = intargs;
+ uint64_t* fargs = floatargs;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ 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");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for(i = 0; i < paramCount; ++i)
+ {
+ int isfloat = 0;
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ dp->val.p = (void*) *iargs;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) iargs;
+ dp->val.p = (void*) (*(adr+1));
+#endif
+ }
+ else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *(iargs); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(iargs); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *(iargs); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *(iargs); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(iargs); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(iargs); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *(iargs); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *(iargs); break;
+ case nsXPTType::T_FLOAT :
+ isfloat = 1;
+ if (i < 7)
+ dp->val.f = (float) *((double*) fargs); /* register */
+ else
+ dp->val.u32 = *(fargs); /* memory */
+ break;
+ case nsXPTType::T_DOUBLE :
+ isfloat = 1;
+ dp->val.u64 = *(fargs);
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = *(iargs); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(iargs); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *(iargs); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ if (i < 7)
+ {
+ /* we are parsing register arguments */
+ if (i == 6)
+ {
+ // run out of register arguments, move on to memory arguments
+ iargs = restargs;
+ fargs = restargs;
+ }
+ else
+ {
+ ++iargs; // advance one integer register slot
+ if (isfloat) ++fargs; // advance float register slot if isfloat
+ }
+ }
+ else
+ {
+ /* we are parsing memory arguments */
+ ++iargs;
+ ++fargs;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(uint64_t,uint64_t,uint64_t,uint64_t,
+ uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t *);
+
+/* Variable a0-a7 were put there so we can have access to the 8 input
+ registers on Stubxyz entry */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n(uint64_t a1, \
+uint64_t a2,uint64_t a3,uint64_t a4,uint64_t a5,uint64_t a6,uint64_t a7, \
+uint64_t a8) \
+{ uint64_t a0 = (uint64_t) this; \
+ return SharedStub(a0,a1,a2,a3,a4,a5,a6,a7,(uint64_t) n, &a8); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp
new file mode 100644
index 0000000000..d9c41aee70
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_alpha.cpp
@@ -0,0 +1,187 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+/* Prototype specifies unmangled function name and disables unused warning */
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args)
+__asm__("PrepareAndDispatch") ATTRIBUTE_USED;
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args)
+{
+ const uint8_t PARAM_BUFFER_COUNT = 16;
+ const uint8_t NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+
+ 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");
+
+ // args[0] to args[NUM_ARG_REGS] hold floating point register values
+ uint64_t* ap = args + NUM_ARG_REGS;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break;
+ case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break;
+ case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break;
+ case nsXPTType::T_I64 : dp->val.i64 = (int64_t) *ap; break;
+ case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break;
+ case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break;
+ case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break;
+ case nsXPTType::T_U64 : dp->val.u64 = (uint64_t) *ap; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // floats passed via registers are stored as doubles
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (uint64_t) args[i];
+ dp->val.f = (float) dp->val.d; // convert double to float
+ }
+ else
+ dp->val.u32 = (uint32_t) *ap;
+ break;
+ case nsXPTType::T_DOUBLE :
+ // doubles passed via registers are also stored
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap;
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break;
+ case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break;
+ case nsXPTType::T_WCHAR : dp->val.wc = (char16_t) *ap; break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * SharedStub()
+ * Collects arguments and calls PrepareAndDispatch. The "methodIndex" is
+ * passed to this function via $1 to preserve the argument registers.
+ */
+__asm__(
+ "#### SharedStub ####\n"
+".text\n\t"
+ ".align 5\n\t"
+ ".ent SharedStub\n"
+"SharedStub:\n\t"
+ ".frame $30,96,$26,0\n\t"
+ ".mask 0x4000000,-96\n\t"
+ "ldgp $29,0($27)\n"
+"$SharedStub..ng:\n\t"
+ "subq $30,96,$30\n\t"
+ "stq $26,0($30)\n\t"
+ ".prologue 1\n\t"
+
+ /*
+ * Store arguments passed via registers to the stack.
+ * Floating point registers are stored as doubles and converted
+ * to floats in PrepareAndDispatch if necessary.
+ */
+ "stt $f17,16($30)\n\t" /* floating point registers */
+ "stt $f18,24($30)\n\t"
+ "stt $f19,32($30)\n\t"
+ "stt $f20,40($30)\n\t"
+ "stt $f21,48($30)\n\t"
+ "stq $17,56($30)\n\t" /* integer registers */
+ "stq $18,64($30)\n\t"
+ "stq $19,72($30)\n\t"
+ "stq $20,80($30)\n\t"
+ "stq $21,88($30)\n\t"
+
+ /*
+ * Call PrepareAndDispatch function.
+ */
+ "bis $1,$1,$17\n\t" /* pass "methodIndex" */
+ "addq $30,16,$18\n\t" /* pass "args" */
+ "bsr $26,$PrepareAndDispatch..ng\n\t"
+
+ "ldq $26,0($30)\n\t"
+ "addq $30,96,$30\n\t"
+ "ret $31,($26),1\n\t"
+ ".end SharedStub"
+ );
+
+/*
+ * nsresult nsXPTCStubBase::Stub##n()
+ * Sets register $1 to "methodIndex" and jumps to SharedStub.
+ */
+#define STUB_MANGLED_ENTRY(n, symbol) \
+ "#### Stub"#n" ####" "\n\t" \
+ ".text" "\n\t" \
+ ".align 5" "\n\t" \
+ ".globl " symbol "\n\t" \
+ ".ent " symbol "\n" \
+symbol ":" "\n\t" \
+ ".frame $30,0,$26,0" "\n\t" \
+ "ldgp $29,0($27)" "\n" \
+"$" symbol "..ng:" "\n\t" \
+ ".prologue 1" "\n\t" \
+ "lda $1,"#n "\n\t" \
+ "br $31,$SharedStub..ng" "\n\t" \
+ ".end " symbol
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".if "#n" < 10" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase5Stub"#n"Ev") "\n\t" \
+ ".elseif "#n" < 100" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase6Stub"#n"Ev") "\n\t" \
+ ".elseif "#n" < 1000" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase7Stub"#n"Ev") "\n\t" \
+ ".else" "\n\t" \
+ ".err \"Stub"#n" >= 1000 not yet supported.\"" "\n\t" \
+ ".endif" \
+ );
+
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_m68k.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_m68k.cpp
new file mode 100644
index 0000000000..3720a5c37f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_m68k.cpp
@@ -0,0 +1,98 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+extern "C" {
+ nsresult ATTRIBUTE_USED
+ PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+ {
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ 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");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+
+ switch(type)
+ {
+ // the 8 and 16 bit types will have been promoted to 32 bits before
+ // being pushed onto the stack. Since the 68k is big endian, we
+ // need to skip over the leading high order bytes.
+ case nsXPTType::T_I8 : dp->val.i8 = *(((int8_t*) ap) + 3); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(((int16_t*) ap) + 1); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(((uint8_t*) ap) + 3); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(((uint16_t*)ap) + 1); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((uint32_t* ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(((char*) ap) + 3); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+ }
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ void *frame = __builtin_frame_address(0); \
+ return PrepareAndDispatch(this, n, (uint32_t*)frame + 3); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp
new file mode 100644
index 0000000000..cf4ab1268f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390.cpp
@@ -0,0 +1,183 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+static nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint32_t* a_gpr, uint64_t *a_fpr, uint32_t *a_ov)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no info");
+
+ 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");
+
+ uint32_t gpr = 1, fpr = 0;
+
+ for(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 (gpr < 5)
+ dp->val.p = (void*) *a_gpr++, gpr++;
+ else
+ dp->val.p = (void*) *a_ov++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ dp->val.i8 = *((int32_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i8 = *((int32_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ dp->val.i16 = *((int32_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i16 = *((int32_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ dp->val.i32 = *((int32_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i32 = *((int32_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 4)
+ dp->val.i64 = *((int64_t*) a_gpr), a_gpr+=2, gpr+=2;
+ else
+ dp->val.i64 = *((int64_t*) a_ov ), a_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ dp->val.u8 = *((uint32_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u8 = *((uint32_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ dp->val.u16 = *((uint32_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u16 = *((uint32_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ dp->val.u32 = *((uint32_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u32 = *((uint32_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 4)
+ dp->val.u64 = *((uint64_t*)a_gpr), a_gpr+=2, gpr+=2;
+ else
+ dp->val.u64 = *((uint64_t*)a_ov ), a_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 2)
+ dp->val.f = *((float*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.f = *((float*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 2)
+ dp->val.d = *((double*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.d = *((double*) a_ov ), a_ov+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ dp->val.b = *((uint32_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.b = *((uint32_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ dp->val.c = *((uint32_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.c = *((uint32_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ dp->val.wc = *((uint32_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.wc = *((uint32_t*)a_ov ), a_ov++;
+ break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ uint32_t a_gpr[4]; \
+ uint64_t a_fpr[2]; \
+ uint32_t *a_ov; \
+ \
+ __asm__ __volatile__ \
+ ( \
+ "l %0,0(15)\n\t" \
+ "ahi %0,96\n\t" \
+ "stm 3,6,0(%3)\n\t" \
+ "std 0,%1\n\t" \
+ "std 2,%2\n\t" \
+ : "=&a" (a_ov), \
+ "=m" (a_fpr[0]), \
+ "=m" (a_fpr[1]) \
+ : "a" (a_gpr) \
+ : "memory", "cc", \
+ "3", "4", "5", "6" \
+ ); \
+ \
+ return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp
new file mode 100644
index 0000000000..189cceb826
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_s390x.cpp
@@ -0,0 +1,187 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+static nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint64_t* a_gpr, uint64_t *a_fpr, uint64_t *a_ov)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no info");
+
+ 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");
+
+ uint32_t gpr = 1, fpr = 0;
+
+ for(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 (gpr < 5)
+ dp->val.p = (void*) *a_gpr++, gpr++;
+ else
+ dp->val.p = (void*) *a_ov++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ dp->val.i8 = *((int64_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i8 = *((int64_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ dp->val.i16 = *((int64_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i16 = *((int64_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ dp->val.i32 = *((int64_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i32 = *((int64_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 5)
+ dp->val.i64 = *((int64_t*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i64 = *((int64_t*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ dp->val.u8 = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u8 = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ dp->val.u16 = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u16 = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ dp->val.u32 = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u32 = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 5)
+ dp->val.u64 = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u64 = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 4)
+ dp->val.f = *((float*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.f = *(((float*) a_ov )+1), a_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 4)
+ dp->val.d = *((double*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.d = *((double*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ dp->val.b = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.b = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ dp->val.c = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.c = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ dp->val.wc = *((uint64_t*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.wc = *((uint64_t*)a_ov ), a_ov++;
+ break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ uint64_t a_gpr[4]; \
+ uint64_t a_fpr[4]; \
+ uint64_t *a_ov; \
+ \
+ __asm__ __volatile__ \
+ ( \
+ "lg %0,0(15)\n\t" \
+ "aghi %0,160\n\t" \
+ "stmg 3,6,0(%5)\n\t"\
+ "std 0,%1\n\t" \
+ "std 2,%2\n\t" \
+ "std 4,%3\n\t" \
+ "std 6,%4\n\t" \
+ : "=&a" (a_ov), \
+ "=m" (a_fpr[0]), \
+ "=m" (a_fpr[1]), \
+ "=m" (a_fpr[2]), \
+ "=m" (a_fpr[3]) \
+ : "a" (a_gpr) \
+ : "memory", "cc", \
+ "3", "4", "5", "6" \
+ ); \
+ \
+ return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp
new file mode 100644
index 0000000000..75f8562ced
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips.cpp
@@ -0,0 +1,112 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * 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"
+
+#include <stdint.h>
+
+/*
+ * This is for MIPS O32 ABI
+ * Args contains a0-3 and then the stack.
+ * Because a0 is 'this', we want to skip it
+ */
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+ args++; // always skip over a0
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ 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");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+
+ switch(type)
+ {
+ case nsXPTType::T_I64 :
+ if ((intptr_t)ap & 4) ap++;
+ dp->val.i64 = *((int64_t*) ap); ap++;
+ break;
+ case nsXPTType::T_U64 :
+ if ((intptr_t)ap & 4) ap++;
+ dp->val.u64 = *((int64_t*) ap); ap++;
+ break;
+ case nsXPTType::T_DOUBLE:
+ if ((intptr_t)ap & 4) ap++;
+ dp->val.d = *((double*) ap); ap++;
+ break;
+#ifdef IS_LITTLE_ENDIAN
+ default:
+ dp->val.p = (void*) *ap;
+ break;
+#else
+ case nsXPTType::T_I8 : dp->val.i8 = (int8_t) *ap; break;
+ case nsXPTType::T_I16 : dp->val.i16 = (int16_t) *ap; break;
+ case nsXPTType::T_I32 : dp->val.i32 = (int32_t) *ap; break;
+ case nsXPTType::T_U8 : dp->val.u8 = (uint8_t) *ap; break;
+ case nsXPTType::T_U16 : dp->val.u16 = (uint16_t) *ap; break;
+ case nsXPTType::T_U32 : dp->val.u32 = (uint32_t) *ap; break;
+ case nsXPTType::T_BOOL : dp->val.b = (bool) *ap; break;
+ case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break;
+ case nsXPTType::T_WCHAR : dp->val.wc = (wchar_t) *ap; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *(float *) ap; break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+#endif
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) // done in the .s file
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp
new file mode 100644
index 0000000000..a4b5539406
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_mips64.cpp
@@ -0,0 +1,185 @@
+/* -*- 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"
+
+#if (_MIPS_SIM != _ABIN32) && (_MIPS_SIM != _ABI64)
+#error "This code is for MIPS n32/n64 only"
+#endif
+
+/*
+ * This is for MIPS n32/n64 ABI
+ *
+ * When we're called, the "gp" registers are stored in gprData and
+ * the "fp" registers are stored in fprData. There are 8 regs
+ * available which correspond to the first 7 parameters of the
+ * function and the "this" pointer. If there are additional parms,
+ * they are stored on the stack at address "args".
+ *
+ */
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args,
+ uint64_t *gprData, double *fprData)
+{
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+#define PARAM_FPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ 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 iCount = 0;
+ for(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 (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*)gprData[iCount++];
+ else
+ dp->val.p = (void*)*ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (int8_t)gprData[iCount++];
+ else
+ dp->val.i8 = (int8_t)*ap++;
+ break;
+
+ case nsXPTType::T_I16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (int16_t)gprData[iCount++];
+ else
+ dp->val.i16 = (int16_t)*ap++;
+ break;
+
+ case nsXPTType::T_I32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (int32_t)gprData[iCount++];
+ else
+ dp->val.i32 = (int32_t)*ap++;
+ break;
+
+ case nsXPTType::T_I64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (int64_t)gprData[iCount++];
+ else
+ dp->val.i64 = (int64_t)*ap++;
+ break;
+
+ case nsXPTType::T_U8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (uint8_t)gprData[iCount++];
+ else
+ dp->val.u8 = (uint8_t)*ap++;
+ break;
+
+ case nsXPTType::T_U16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (uint16_t)gprData[iCount++];
+ else
+ dp->val.u16 = (uint16_t)*ap++;
+ break;
+
+ case nsXPTType::T_U32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (uint32_t)gprData[iCount++];
+ else
+ dp->val.u32 = (uint32_t)*ap++;
+ break;
+
+ case nsXPTType::T_U64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (uint64_t)gprData[iCount++];
+ else
+ dp->val.u64 = (uint64_t)*ap++;
+ break;
+
+ case nsXPTType::T_FLOAT:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.f = (double)fprData[iCount++];
+ else
+ dp->val.f = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.d = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (bool)gprData[iCount++];
+ else
+ dp->val.b = (bool)*ap++;
+ break;
+
+ case nsXPTType::T_CHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char)gprData[iCount++];
+ else
+ dp->val.c = (char)*ap++;
+ break;
+
+ case nsXPTType::T_WCHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t)gprData[iCount++];
+ 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;
+}
+
+#define STUB_ENTRY(n) /* defined in the assembly file */
+
+#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/md/unix/xptcstubs_netbsd_m68k.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_netbsd_m68k.cpp
new file mode 100644
index 0000000000..680114fd58
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_netbsd_m68k.cpp
@@ -0,0 +1,115 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if !defined(__NetBSD__) || !defined(__m68k__)
+#error This code is for NetBSD/m68k only
+#endif
+
+extern "C" {
+ static nsresult ATTRIBUTE_USED
+ PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+ {
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ nsIInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ 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");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+
+ switch(type)
+ {
+ // the 8 and 16 bit types will have been promoted to 32 bits before
+ // being pushed onto the stack. Since the 68k is big endian, we
+ // need to skip over the leading high order bytes.
+ case nsXPTType::T_I8 : dp->val.i8 = *(((int8_t*) ap) + 3); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(((int16_t*) ap) + 1); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(((uint8_t*) ap) + 3); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(((uint16_t*)ap) + 1); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *(((char*) ap) + 3); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(((char*) ap) + 3); break;
+ // wchar_t is an int (32 bits) on NetBSD
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+ }
+}
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".global _Stub"#n"__14nsXPTCStubBase\n\t" \
+"_Stub"#n"__14nsXPTCStubBase:\n\t" \
+ "link a6,#0 \n\t" \
+ "lea a6@(12), a0 \n\t" /* pointer to args */ \
+ "movl a0, sp@- \n\t" \
+ "movl #"#n", sp@- \n\t" /* method index */ \
+ "movl a6@(8), sp@- \n\t" /* this */ \
+ "jbsr _PrepareAndDispatch \n\t" \
+ "unlk a6 \n\t" \
+ "rts \n\t" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp
new file mode 100644
index 0000000000..7353709f1d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_pa32.cpp
@@ -0,0 +1,143 @@
+
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+#if _HPUX
+#error "This code is for HP-PA RISC 32 bit mode only"
+#endif
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint32_t* args, uint32_t* floatargs)
+{
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU;
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ int32_t regwords = 1; /* self pointer is not in the variant records */
+ nsresult result = NS_ERROR_FAILURE;
+ uint8_t paramCount;
+ uint8_t i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ 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");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for(i = 0; i < paramCount; ++i, --args)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *args;
+ ++regwords;
+ continue;
+ }
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) args); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) args); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) args); break;
+ case nsXPTType::T_DOUBLE :
+ if (regwords & 1)
+ {
+ ++regwords; /* align on double word */
+ --args;
+ }
+ if (regwords == 0 || regwords == 2)
+ {
+ dp->val.d=*((double*) (floatargs + regwords));
+ --args;
+ }
+ else
+ {
+ dp->val.d = *((double*) --args);
+ }
+ regwords += 2;
+ continue;
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 :
+ if (regwords & 1)
+ {
+ ++regwords; /* align on double word */
+ --args;
+ }
+ ((DU *)dp)->lo = *((uint32_t*) args);
+ ((DU *)dp)->hi = *((uint32_t*) --args);
+ regwords += 2;
+ continue;
+ case nsXPTType::T_FLOAT :
+ if (regwords >= 4)
+ dp->val.f = *((float*) args);
+ else
+ dp->val.f = *((float*) floatargs+4+regwords);
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*) args); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*) args); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*) args); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*) args); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*) args); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) args); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ ++regwords;
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(int);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ return SharedStub(n); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp
new file mode 100644
index 0000000000..95e67cb295
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc64_linux.cpp
@@ -0,0 +1,246 @@
+/* -*- 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/. */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+// The Linux/PPC64 ABI passes the first 8 integral
+// parameters and the first 13 floating point parameters in registers
+// (r3-r10 and f1-f13), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the caller's stack
+// area. The stack pointer has to retain 16-byte alignment.
+
+// The PowerPC64 platform ABI can be found here:
+// http://www.freestandards.org/spec/ELF/ppc64/
+// and in particular:
+// http://www.freestandards.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-CALL
+
+#define PARAM_BUFFER_COUNT 16
+#define GPR_COUNT 7
+#define FPR_COUNT 13
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gprData[]' contains the arguments passed in integer registers
+// - 'fprData[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+#include <stdio.h>
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self,
+ uint64_t methodIndex,
+ uint64_t* args,
+ uint64_t *gprData,
+ double *fprData)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ 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");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint64_t* ap = args;
+ uint64_t tempu64;
+
+ for(i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (i < FPR_COUNT)
+ dp->val.d = fprData[i];
+ else
+ dp->val.d = *(double*) ap;
+ } else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (i < FPR_COUNT)
+ dp->val.f = (float) fprData[i]; // in registers floats are passed as doubles
+ else {
+ float *p = (float *)ap;
+#ifndef __LITTLE_ENDIAN__
+ p++;
+#endif
+ dp->val.f = *p;
+ }
+ } else { /* integer type or pointer */
+ if (i < GPR_COUNT)
+ tempu64 = gprData[i];
+ else
+ tempu64 = *ap;
+
+ if (param.IsOut() || !type.IsArithmetic())
+ dp->val.p = (void*) tempu64;
+ else if (type == nsXPTType::T_I8)
+ dp->val.i8 = (int8_t) tempu64;
+ else if (type == nsXPTType::T_I16)
+ dp->val.i16 = (int16_t) tempu64;
+ else if (type == nsXPTType::T_I32)
+ dp->val.i32 = (int32_t) tempu64;
+ else if (type == nsXPTType::T_I64)
+ dp->val.i64 = (int64_t) tempu64;
+ else if (type == nsXPTType::T_U8)
+ dp->val.u8 = (uint8_t) tempu64;
+ else if (type == nsXPTType::T_U16)
+ dp->val.u16 = (uint16_t) tempu64;
+ else if (type == nsXPTType::T_U32)
+ dp->val.u32 = (uint32_t) tempu64;
+ else if (type == nsXPTType::T_U64)
+ dp->val.u64 = (uint64_t) tempu64;
+ else if (type == nsXPTType::T_BOOL)
+ dp->val.b = (bool) tempu64;
+ else if (type == nsXPTType::T_CHAR)
+ dp->val.c = (char) tempu64;
+ else if (type == nsXPTType::T_WCHAR)
+ dp->val.wc = (wchar_t) tempu64;
+ else
+ NS_ERROR("bad type");
+ }
+
+ if (i >= 7)
+ ap++;
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info,
+ dispatchParams);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+// Load r11 with the constant 'n' and branch to SharedStub().
+//
+// XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
+// however, it's quick, dirty, and'll break when the ABI changes on
+// us, which is what we want ;-).
+
+
+// gcc-3 version
+//
+// As G++3 ABI contains the length of the functionname in the mangled
+// name, it is difficult to get a generic assembler mechanism like
+// in the G++ 2.95 case.
+// Create names would be like:
+// _ZN14nsXPTCStubBase5Stub1Ev
+// _ZN14nsXPTCStubBase6Stub12Ev
+// _ZN14nsXPTCStubBase7Stub123Ev
+// _ZN14nsXPTCStubBase8Stub1234Ev
+// etc.
+// Use assembler directives to get the names right...
+
+#if _CALL_ELF == 2
+# define STUB_ENTRY(n) \
+__asm__ ( \
+ ".section \".text\" \n\t" \
+ ".align 2 \n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
+ "0: addis 2,12,.TOC.-0b@ha \n\t" \
+ "addi 2,2,.TOC.-0b@l \n\t" \
+ ".localentry _ZN14nsXPTCStubBase5Stub"#n"Ev,.-_ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ \
+ ".elseif "#n" < 100 \n\t" \
+ ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ "0: addis 2,12,.TOC.-0b@ha \n\t" \
+ "addi 2,2,.TOC.-0b@l \n\t" \
+ ".localentry _ZN14nsXPTCStubBase6Stub"#n"Ev,.-_ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ \
+ ".elseif "#n" < 1000 \n\t" \
+ ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
+ "0: addis 2,12,.TOC.-0b@ha \n\t" \
+ "addi 2,2,.TOC.-0b@l \n\t" \
+ ".localentry _ZN14nsXPTCStubBase7Stub"#n"Ev,.-_ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ \
+ ".else \n\t" \
+ ".err \"stub number "#n" >= 1000 not yet supported\"\n" \
+ ".endif \n\t" \
+ \
+ "li 11,"#n" \n\t" \
+ "b SharedStub \n" \
+);
+#else
+# define STUB_ENTRY(n) \
+__asm__ ( \
+ ".section \".toc\",\"aw\" \n\t" \
+ ".section \".text\" \n\t" \
+ ".align 2 \n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ ".section \".opd\",\"aw\" \n\t" \
+ ".align 3 \n\t" \
+"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
+ ".quad ._ZN14nsXPTCStubBase5Stub"#n"Ev,.TOC.@tocbase \n\t" \
+ ".previous \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" \
+ ".section \".opd\",\"aw\" \n\t" \
+ ".align 3 \n\t" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ ".quad ._ZN14nsXPTCStubBase6Stub"#n"Ev,.TOC.@tocbase \n\t" \
+ ".previous \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" \
+ ".section \".opd\",\"aw\" \n\t" \
+ ".align 3 \n\t" \
+"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
+ ".quad ._ZN14nsXPTCStubBase7Stub"#n"Ev,.TOC.@tocbase \n\t" \
+ ".previous \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 11,"#n" \n\t" \
+ "b SharedStub \n" \
+);
+#endif
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp
new file mode 100644
index 0000000000..0463c21c5f
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix.cpp
@@ -0,0 +1,185 @@
+/* -*- Mode: C; tab-width: 2; 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+#if defined(AIX)
+
+/*
+ For PPC (AIX & MAC), the first 8 integral and the first 13 f.p. parameters
+ arrive in a separate chunk of data that has been loaded from the registers.
+ The args pointer has been set to the start of the parameters BEYOND the ones
+ arriving in registers
+*/
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args, uint32_t *gprData, double *fprData)
+{
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo; // have to move 64 bit entities as 32 bit halves since
+ } DU; // stack slots are not guaranteed 16 byte aligned
+
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ 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");
+
+ uint32_t* ap = args;
+ uint32_t iCount = 0;
+ uint32_t fpCount = 0;
+ for(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 (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*) gprData[iCount++];
+ else
+ dp->val.p = (void*) *ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (int8_t) gprData[iCount++];
+ else
+ dp->val.i8 = (int8_t) *ap++;
+ break;
+ case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (int16_t) gprData[iCount++];
+ else
+ dp->val.i16 = (int16_t) *ap++;
+ break;
+ case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (int32_t) gprData[iCount++];
+ else
+ dp->val.i32 = (int32_t) *ap++;
+ break;
+ case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->hi = (int32_t) gprData[iCount++];
+ else
+ ((DU *)dp)->hi = (int32_t) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->lo = (uint32_t) gprData[iCount++];
+ else
+ ((DU *)dp)->lo = (uint32_t) *ap++;
+ break;
+ case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (uint8_t) gprData[iCount++];
+ else
+ dp->val.u8 = (uint8_t) *ap++;
+ break;
+ case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (uint16_t) gprData[iCount++];
+ else
+ dp->val.u16 = (uint16_t) *ap++;
+ break;
+ case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (uint32_t) gprData[iCount++];
+ else
+ dp->val.u32 = (uint32_t) *ap++;
+ break;
+ case nsXPTType::T_U64 : if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->hi = (uint32_t) gprData[iCount++];
+ else
+ ((DU *)dp)->hi = (uint32_t) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->lo = (uint32_t) gprData[iCount++];
+ else
+ ((DU *)dp)->lo = (uint32_t) *ap++;
+ break;
+ case nsXPTType::T_FLOAT : if (fpCount < 13) {
+ dp->val.f = (float) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else
+ dp->val.f = *((float*) ap++);
+ break;
+ case nsXPTType::T_DOUBLE : if (fpCount < 13) {
+ dp->val.d = (double) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else {
+ dp->val.f = *((double*) ap);
+ ap += 2;
+ }
+ break;
+ case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (bool) gprData[iCount++];
+ else
+ dp->val.b = (bool) *ap++;
+ break;
+ case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char) gprData[iCount++];
+ else
+ dp->val.c = (char) *ap++;
+ break;
+ case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t) gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t) *ap++;
+ break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex,info,dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n)
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* AIX */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp
new file mode 100644
index 0000000000..08eb557ab6
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_aix64.cpp
@@ -0,0 +1,172 @@
+/* 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+#if defined(AIX)
+
+/*
+ For PPC (AIX & MAC), the first 8 integral and the first 13 f.p. parameters
+ arrive in a separate chunk of data that has been loaded from the registers.
+ The args pointer has been set to the start of the parameters BEYOND the ones
+ arriving in registers
+*/
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args, uint64_t *gprData, double *fprData)
+{
+
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ 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 iCount = 0;
+ uint32_t fpCount = 0;
+ for(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 (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*) gprData[iCount++];
+ else
+ dp->val.p = (void*) *ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (int8_t) gprData[iCount++];
+ else
+ dp->val.i8 = (int8_t) *ap++;
+ break;
+ case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (int16_t) gprData[iCount++];
+ else
+ dp->val.i16 = (int16_t) *ap++;
+ break;
+ case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (int32_t) gprData[iCount++];
+ else
+ dp->val.i32 = (int32_t) *ap++;
+ break;
+ case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (int64_t) gprData[iCount++];
+ else
+ dp->val.i64 = (int64_t) *ap++;
+ break;
+ case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (uint8_t) gprData[iCount++];
+ else
+ dp->val.u8 = (uint8_t) *ap++;
+ break;
+ case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (uint16_t) gprData[iCount++];
+ else
+ dp->val.u16 = (uint16_t) *ap++;
+ break;
+ case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (uint32_t) gprData[iCount++];
+ else
+ dp->val.u32 = (uint32_t) *ap++;
+ break;
+ case nsXPTType::T_U64 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (uint64_t) gprData[iCount++];
+ else
+ dp->val.u64 = (uint64_t) *ap++;
+ break;
+ case nsXPTType::T_FLOAT : if (fpCount < 13) {
+ dp->val.f = (float) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else
+ dp->val.f = *((float*) ap++);
+ break;
+ case nsXPTType::T_DOUBLE : if (fpCount < 13) {
+ dp->val.d = (double) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else {
+ dp->val.f = *((double*) ap);
+ ap += 2;
+ }
+ break;
+ case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (bool) gprData[iCount++];
+ else
+ dp->val.b = (bool) *ap++;
+ break;
+ case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char) gprData[iCount++];
+ else
+ dp->val.c = (char) *ap++;
+ break;
+ case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t) gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t) *ap++;
+ break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex,info,dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n)
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* AIX */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp
new file mode 100644
index 0000000000..86405a8ca1
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_linux.cpp
@@ -0,0 +1,220 @@
+/* -*- 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/. */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
+// parameters and the first 8 floating point parameters in registers
+// (r3-r10 and f1-f8), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area. The stack pointer has to retain 16-byte alignment, longlongs
+// and doubles are aligned on 8-byte boundaries.
+#ifndef __NO_FPRS__
+#define PARAM_BUFFER_COUNT 16
+#define GPR_COUNT 8
+#define FPR_COUNT 8
+#else
+#define PARAM_BUFFER_COUNT 8
+#define GPR_COUNT 8
+#endif
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gprData[]' contains the arguments passed in integer registers
+// - 'fprData[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self,
+ uint32_t methodIndex,
+ uint32_t* args,
+ uint32_t *gprData,
+ double *fprData)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ 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");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint32_t* ap = args;
+ uint32_t gpr = 1; // skip one GPR register
+#ifndef __NO_FPRS__
+ uint32_t fpr = 0;
+#endif
+ uint32_t tempu32;
+ uint64_t tempu64;
+
+ for(i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+#ifndef __NO_FPRS__
+ if (fpr < FPR_COUNT)
+ dp->val.d = fprData[fpr++];
+#else
+ if (gpr & 1)
+ gpr++;
+ if (gpr + 1 < GPR_COUNT) {
+ dp->val.d = *(double*) &gprData[gpr];
+ gpr += 2;
+ }
+#endif
+ else {
+ if ((uint32_t) ap & 4) ap++; // doubles are 8-byte aligned on stack
+ dp->val.d = *(double*) ap;
+ ap += 2;
+ }
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+#ifndef __NO_FPRS__
+ if (fpr < FPR_COUNT)
+ dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles
+#else
+ if (gpr < GPR_COUNT)
+ dp->val.f = *(float*) &gprData[gpr++];
+#endif
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && (type == nsXPTType::T_I64
+ || type == nsXPTType::T_U64)) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((gpr + 1) < GPR_COUNT) {
+ tempu64 = *(uint64_t*) &gprData[gpr];
+ gpr += 2;
+ }
+ else {
+ if ((uint32_t) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(uint64_t*) ap;
+ ap += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ tempu32 = gprData[gpr++];
+ else
+ tempu32 = *ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic()) {
+ if (type == nsXPTType::T_JSVAL)
+ dp->val.p = *((void**) tempu32);
+ else
+ dp->val.p = (void*) tempu32;
+ continue;
+ }
+
+ switch(type) {
+ case nsXPTType::T_I8: dp->val.i8 = (int8_t) tempu32; break;
+ case nsXPTType::T_I16: dp->val.i16 = (int16_t) tempu32; break;
+ case nsXPTType::T_I32: dp->val.i32 = (int32_t) tempu32; break;
+ case nsXPTType::T_I64: dp->val.i64 = (int64_t) tempu64; break;
+ case nsXPTType::T_U8: dp->val.u8 = (uint8_t) tempu32; break;
+ case nsXPTType::T_U16: dp->val.u16 = (uint16_t) tempu32; break;
+ case nsXPTType::T_U32: dp->val.u32 = (uint32_t) tempu32; break;
+ case nsXPTType::T_U64: dp->val.u64 = (uint64_t) tempu64; break;
+ case nsXPTType::T_BOOL: dp->val.b = (bool) tempu32; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break;
+
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex,
+ info,
+ dispatchParams);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+// Load r11 with the constant 'n' and branch to SharedStub().
+//
+// XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
+// however, it's quick, dirty, and'll break when the ABI changes on
+// us, which is what we want ;-).
+
+// gcc-3 version
+//
+// As G++3 ABI contains the length of the functionname in the mangled
+// name, it is difficult to get a generic assembler mechanism like
+// in the G++ 2.95 case.
+// Create names would be like:
+// _ZN14nsXPTCStubBase5Stub1Ev
+// _ZN14nsXPTCStubBase6Stub12Ev
+// _ZN14nsXPTCStubBase7Stub123Ev
+// _ZN14nsXPTCStubBase8Stub1234Ev
+// etc.
+// Use assembler directives to get the names right...
+
+# define STUB_ENTRY(n) \
+__asm__ ( \
+ ".align 2 \n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl _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" \
+ ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ \
+ ".elseif "#n" < 1000 \n\t" \
+ ".globl _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 11,"#n" \n\t" \
+ "b SharedStub@local \n" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_netbsd.cpp
new file mode 100644
index 0000000000..ec359fc995
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_netbsd.cpp
@@ -0,0 +1,185 @@
+/* -*- 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/. */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
+// parameters and the first 8 floating point parameters in registers
+// (r3-r10 and f1-f8), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area. The stack pointer has to retain 16-byte alignment, longlongs
+// and doubles are aligned on 8-byte boundaries.
+
+#define PARAM_BUFFER_COUNT 16
+#define GPR_COUNT 8
+#define FPR_COUNT 8
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gprData[]' contains the arguments passed in integer registers
+// - 'fprData[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self,
+ uint32_t methodIndex,
+ uint32_t* args,
+ uint32_t *gprData,
+ double *fprData)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ nsIInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (! iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ 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");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint32_t* ap = args;
+ uint32_t gpr = 1; // skip one GPR register
+ uint32_t fpr = 0;
+ uint32_t tempu32;
+ uint64_t tempu64;
+
+ for(i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ dp->val.d = fprData[fpr++];
+ else {
+ if ((uint32_t) ap & 4) ap++; // doubles are 8-byte aligned on stack
+ dp->val.d = *(double*) ap;
+ ap += 2;
+ if (gpr < GPR_COUNT)
+ gpr += 2;
+ }
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles
+ else {
+ dp->val.f = *(float*) ap;
+ ap += 1;
+ if (gpr < GPR_COUNT)
+ gpr += 1;
+ }
+ continue;
+ }
+ else if (!param.IsOut() && (type == nsXPTType::T_I64
+ || type == nsXPTType::T_U64)) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((gpr + 1) < GPR_COUNT) {
+ tempu64 = *(uint64_t*) &gprData[gpr];
+ gpr += 2;
+ }
+ else {
+ if ((uint32_t) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(uint64_t*) ap;
+ ap += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ tempu32 = gprData[gpr++];
+ else
+ tempu32 = *ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic()) {
+ if (type == nsXPTType::T_JSVAL)
+ dp->val.p = *((void**) tempu32);
+ else
+ dp->val.p = (void*) tempu32;
+ continue;
+ }
+
+ switch(type) {
+ case nsXPTType::T_I8: dp->val.i8 = (int8_t) tempu32; break;
+ case nsXPTType::T_I16: dp->val.i16 = (int16_t) tempu32; break;
+ case nsXPTType::T_I32: dp->val.i32 = (int32_t) tempu32; break;
+ case nsXPTType::T_I64: dp->val.i64 = (int64_t) tempu64; break;
+ case nsXPTType::T_U8: dp->val.u8 = (uint8_t) tempu32; break;
+ case nsXPTType::T_U16: dp->val.u16 = (uint16_t) tempu32; break;
+ case nsXPTType::T_U32: dp->val.u32 = (uint32_t) tempu32; break;
+ case nsXPTType::T_U64: dp->val.u64 = (uint64_t) tempu64; break;
+ case nsXPTType::T_BOOL: dp->val.b = (bool) tempu32; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break;
+
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+// Load r11 with the constant 'n' and branch to SharedStub().
+//
+// XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
+// however, it's quick, dirty, and'll break when the ABI changes on
+// us, which is what we want ;-).
+
+#define STUB_ENTRY(n) \
+__asm__ ( \
+ ".section \".text\" \n\t" \
+ ".align 2 \n\t" \
+ ".globl Stub"#n"__14nsXPTCStubBase \n\t" \
+ ".type Stub"#n"__14nsXPTCStubBase,@function \n\n" \
+ \
+"Stub"#n"__14nsXPTCStubBase: \n\t" \
+ "li 11,"#n" \n\t" \
+ "b SharedStub@local \n" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp
new file mode 100644
index 0000000000..62a6936438
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_openbsd.cpp
@@ -0,0 +1,202 @@
+/* -*- 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/. */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
+// parameters and the first 8 floating point parameters in registers
+// (r3-r10 and f1-f8), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area. The stack pointer has to retain 16-byte alignment, longlongs
+// and doubles are aligned on 8-byte boundaries.
+
+#define PARAM_BUFFER_COUNT 16
+#define GPR_COUNT 8
+#define FPR_COUNT 8
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gprData[]' contains the arguments passed in integer registers
+// - 'fprData[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self,
+ uint32_t methodIndex,
+ uint32_t* args,
+ uint32_t *gprData,
+ double *fprData)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ 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");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint32_t* ap = args;
+ uint32_t gpr = 1; // skip one GPR register
+ uint32_t fpr = 0;
+ uint32_t tempu32;
+ uint64_t tempu64;
+
+ for(i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ dp->val.d = fprData[fpr++];
+ else {
+ if ((uint32_t) ap & 4) ap++; // doubles are 8-byte aligned on stack
+ dp->val.d = *(double*) ap;
+ ap += 2;
+ }
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && (type == nsXPTType::T_I64
+ || type == nsXPTType::T_U64)) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((gpr + 1) < GPR_COUNT) {
+ tempu64 = *(uint64_t*) &gprData[gpr];
+ gpr += 2;
+ }
+ else {
+ if ((uint32_t) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(uint64_t*) ap;
+ ap += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ tempu32 = gprData[gpr++];
+ else
+ tempu32 = *ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic()) {
+ if (type == nsXPTType::T_JSVAL)
+ dp->val.p = *((void**) tempu32);
+ else
+ dp->val.p = (void*) tempu32;
+ continue;
+ }
+
+ switch(type) {
+ case nsXPTType::T_I8: dp->val.i8 = (int8_t) tempu32; break;
+ case nsXPTType::T_I16: dp->val.i16 = (int16_t) tempu32; break;
+ case nsXPTType::T_I32: dp->val.i32 = (int32_t) tempu32; break;
+ case nsXPTType::T_I64: dp->val.i64 = (int64_t) tempu64; break;
+ case nsXPTType::T_U8: dp->val.u8 = (uint8_t) tempu32; break;
+ case nsXPTType::T_U16: dp->val.u16 = (uint16_t) tempu32; break;
+ case nsXPTType::T_U32: dp->val.u32 = (uint32_t) tempu32; break;
+ case nsXPTType::T_U64: dp->val.u64 = (uint64_t) tempu64; break;
+ case nsXPTType::T_BOOL: dp->val.b = (bool) tempu32; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break;
+
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex,
+ info,
+ dispatchParams);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+// Load r11 with the constant 'n' and branch to SharedStub().
+//
+// XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
+// however, it's quick, dirty, and'll break when the ABI changes on
+// us, which is what we want ;-).
+
+
+// gcc-3 version
+//
+// As G++3 ABI contains the length of the functionname in the mangled
+// name, it is difficult to get a generic assembler mechanism like
+// in the G++ 2.95 case.
+// Create names would be like:
+// _ZN14nsXPTCStubBase5Stub1Ev
+// _ZN14nsXPTCStubBase6Stub12Ev
+// _ZN14nsXPTCStubBase7Stub123Ev
+// _ZN14nsXPTCStubBase8Stub1234Ev
+// etc.
+// Use assembler directives to get the names right...
+
+# define STUB_ENTRY(n) \
+__asm__ ( \
+ ".align 2 \n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl _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" \
+ ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ \
+ ".elseif "#n" < 1000 \n\t" \
+ ".globl _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 11,"#n" \n\t" \
+ "b SharedStub@local \n" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp
new file mode 100644
index 0000000000..4c485a2754
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_ppc_rhapsody.cpp
@@ -0,0 +1,165 @@
+/* -*- Mode: C -*- */
+/* 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"
+
+/* Under the Mac OS X PowerPC ABI, the first 8 integer and 13 floating point
+ * parameters are delivered in registers and are not on the stack, although
+ * stack space is allocated for them. The integer parameters are delivered
+ * in GPRs r3 through r10. The first 8 words of the parameter area on the
+ * stack shadow these registers. A word will either be in a register or on
+ * the stack, but not in both. Although the first floating point parameters
+ * are passed in floating point registers, GPR space and stack space is
+ * reserved for them as well.
+ *
+ * SharedStub has passed pointers to the parameter section of the stack
+ * and saved copies of the GPRs and FPRs used for parameter passing. We
+ * don't care about the first parameter (which is delivered here as the self
+ * pointer), so SharedStub pointed us past that. argsGPR thus points to GPR
+ * r4 (corresponding to the first argument after the self pointer) and
+ * argsStack points to the parameter section of the caller's stack frame
+ * reserved for the same argument. This way, it is possible to reference
+ * either argsGPR or argsStack with the same index.
+ *
+ * Contrary to the assumption made by the previous implementation, the
+ * Mac OS X PowerPC ABI doesn't impose any special alignment restrictions on
+ * parameter sections of stacks. Values that are 64 bits wide appear on the
+ * stack without any special padding.
+ *
+ * See also xptcstubs_asm_ppc_darwin.s.m4:_SharedStub.
+ *
+ * ABI reference:
+ * http://developer.apple.com/documentation/DeveloperTools/Conceptual/
+ * MachORuntime/PowerPCConventions/chapter_3_section_1.html */
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(
+ nsXPTCStubBase *self,
+ uint32_t methodIndex,
+ uint32_t *argsStack,
+ uint32_t *argsGPR,
+ double *argsFPR) {
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_FPR_COUNT 13
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant *dispatchParams = nullptr;
+ const nsXPTMethodInfo *methodInfo;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+ uint32_t argIndex = 0;
+ uint32_t fprIndex = 0;
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU;
+
+ NS_ASSERTION(self, "no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &methodInfo);
+ NS_ASSERTION(methodInfo, "no method info");
+
+ paramCount = methodInfo->GetParamCount();
+
+ if(paramCount > PARAM_BUFFER_COUNT) {
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ }
+ else {
+ dispatchParams = paramBuffer;
+ }
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ for(i = 0; i < paramCount; i++, argIndex++) {
+ const nsXPTParamInfo &param = methodInfo->GetParam(i);
+ const nsXPTType &type = param.GetType();
+ nsXPTCMiniVariant *dp = &dispatchParams[i];
+ uint32_t theParam;
+
+ if(argIndex < PARAM_GPR_COUNT)
+ theParam = argsGPR[argIndex];
+ else
+ theParam = argsStack[argIndex];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ dp->val.p = (void *) theParam;
+ else {
+ switch(type) {
+ case nsXPTType::T_I8:
+ dp->val.i8 = (int8_t) theParam;
+ break;
+ case nsXPTType::T_I16:
+ dp->val.i16 = (int16_t) theParam;
+ break;
+ case nsXPTType::T_I32:
+ dp->val.i32 = (int32_t) theParam;
+ break;
+ case nsXPTType::T_U8:
+ dp->val.u8 = (uint8_t) theParam;
+ break;
+ case nsXPTType::T_U16:
+ dp->val.u16 = (uint16_t) theParam;
+ break;
+ case nsXPTType::T_U32:
+ dp->val.u32 = (uint32_t) theParam;
+ break;
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U64:
+ ((DU *)dp)->hi = (uint32_t) theParam;
+ if(++argIndex < PARAM_GPR_COUNT)
+ ((DU *)dp)->lo = (uint32_t) argsGPR[argIndex];
+ else
+ ((DU *)dp)->lo = (uint32_t) argsStack[argIndex];
+ break;
+ case nsXPTType::T_BOOL:
+ dp->val.b = (bool) theParam;
+ break;
+ case nsXPTType::T_CHAR:
+ dp->val.c = (char) theParam;
+ break;
+ case nsXPTType::T_WCHAR:
+ dp->val.wc = (wchar_t) theParam;
+ break;
+ case nsXPTType::T_FLOAT:
+ if(fprIndex < PARAM_FPR_COUNT)
+ dp->val.f = (float) argsFPR[fprIndex++];
+ else
+ dp->val.f = *(float *) &argsStack[argIndex];
+ break;
+ case nsXPTType::T_DOUBLE:
+ if(fprIndex < PARAM_FPR_COUNT)
+ dp->val.d = argsFPR[fprIndex++];
+ else
+ dp->val.d = *(double *) &argsStack[argIndex];
+ argIndex++;
+ break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+ }
+
+ result = self->mOuter->
+ CallMethod((uint16_t)methodIndex, methodInfo, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n)
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp
new file mode 100644
index 0000000000..b8a09c97e1
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 2; 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ 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");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint64_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_BOOL : dp->val.b = *((int64_t*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((uint64_t*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((int64_t*) ap); break;
+ case nsXPTType::T_I8 : dp->val.i8 = *((int64_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int64_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int64_t*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint64_t*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint64_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint64_t*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*) ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = ((float*) ap)[1]; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp
new file mode 100644
index 0000000000..22bf94d49b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_netbsd.cpp
@@ -0,0 +1,117 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ nsIInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ 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");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (type == nsXPTType::T_JSVAL)
+ dp->val.p = *((void**) *ap);
+ else
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_DOUBLE :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi;
+ ((DU *)dp)->lo = ((DU *)ap)->lo;
+ ap++;
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*)ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*)ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp
new file mode 100644
index 0000000000..55d814b850
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_openbsd.cpp
@@ -0,0 +1,120 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ nsIInterfaceInfo* iface_info = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ 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");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (type == nsXPTType::T_JSVAL)
+ dp->val.p = *((void**) *ap);
+ else
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_DOUBLE :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi;
+ ((DU *)dp)->lo = ((DU *)ap)->lo;
+ ap++;
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*)ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*)ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp
new file mode 100644
index 0000000000..61f3df4ffa
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp
@@ -0,0 +1,112 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+
+ typedef struct {
+ uint32_t hi;
+ uint32_t lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ 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");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (type == nsXPTType::T_JSVAL)
+ dp->val.p = *((void**) *ap);
+ else
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int32_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int32_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_DOUBLE :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi;
+ ((DU *)dp)->lo = ((DU *)ap)->lo;
+ ap++;
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((uint32_t*)ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((uint32_t*)ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((int32_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparcv9_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparcv9_solaris.cpp
new file mode 100644
index 0000000000..583ce9864b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparcv9_solaris.cpp
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 2; 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ 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;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int64_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int64_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int64_t*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint64_t*)ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint64_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint64_t*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = ((float*) ap)[1]; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((uint64_t*)ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((uint64_t*)ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((int64_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" nsresult SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp
new file mode 100644
index 0000000000..ae058567f2
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_darwin.cpp
@@ -0,0 +1,190 @@
+/* -*- 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/. */
+
+// Implement shared vtbl methods.
+
+// Keep this in sync with the linux version.
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+// The Darwin/x86-64 ABI passes the first 6 integer parameters and the
+// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,
+// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area.
+
+const uint32_t PARAM_BUFFER_COUNT = 16;
+const uint32_t GPR_COUNT = 6;
+const uint32_t FPR_COUNT = 8;
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gpregs[]' contains the arguments passed in integer registers
+// - 'fpregs[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex,
+ uint64_t * args, uint64_t * gpregs, double *fpregs)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ 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");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint64_t* ap = args;
+ uint32_t nr_gpr = 1; // skip one GPR register for 'that'
+ uint32_t nr_fpr = 0;
+ uint64_t value;
+
+ for (i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.d = *(double*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else {
+ 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;
+ // Cast to uint8_t first, to remove garbage on upper 56 bits.
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+// Darwin/x86-64 uses gcc >= 4.2
+
+#define STUB_ENTRY(n) \
+asm(".section __TEXT,__text\n\t" \
+ ".align 3\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl __ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ "__ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl __ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ "__ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl __ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ "__ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp SharedStub\n\t");
+
+// static nsresult SharedStub(uint32_t methodIndex)
+asm(".section __TEXT,__text\n\t"
+ ".align 3\n\t"
+ "SharedStub:\n\t"
+ // make room for gpregs (48), fpregs (64)
+ "pushq %rbp\n\t"
+ "movq %rsp,%rbp\n\t"
+ "subq $112,%rsp\n\t"
+ // save GP registers
+ "movq %rdi,-112(%rbp)\n\t"
+ "movq %rsi,-104(%rbp)\n\t"
+ "movq %rdx, -96(%rbp)\n\t"
+ "movq %rcx, -88(%rbp)\n\t"
+ "movq %r8 , -80(%rbp)\n\t"
+ "movq %r9 , -72(%rbp)\n\t"
+ "leaq -112(%rbp),%rcx\n\t"
+ // save FP registers
+ "movsd %xmm0,-64(%rbp)\n\t"
+ "movsd %xmm1,-56(%rbp)\n\t"
+ "movsd %xmm2,-48(%rbp)\n\t"
+ "movsd %xmm3,-40(%rbp)\n\t"
+ "movsd %xmm4,-32(%rbp)\n\t"
+ "movsd %xmm5,-24(%rbp)\n\t"
+ "movsd %xmm6,-16(%rbp)\n\t"
+ "movsd %xmm7, -8(%rbp)\n\t"
+ "leaq -64(%rbp),%r8\n\t"
+ // rdi has the 'self' pointer already
+ "movl %eax,%esi\n\t"
+ "leaq 16(%rbp),%rdx\n\t"
+ "call _PrepareAndDispatch\n\t"
+ "leave\n\t"
+ "ret\n\t");
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp
new file mode 100644
index 0000000000..01044363bf
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_linux.cpp
@@ -0,0 +1,204 @@
+/* -*- 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/. */
+
+// Implement shared vtbl methods.
+
+// Keep this in sync with the darwin version.
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+// The Linux/x86-64 ABI passes the first 6 integer parameters and the
+// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,
+// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area.
+
+const uint32_t PARAM_BUFFER_COUNT = 16;
+const uint32_t GPR_COUNT = 6;
+const uint32_t FPR_COUNT = 8;
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gpregs[]' contains the arguments passed in integer registers
+// - 'fpregs[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex,
+ uint64_t * args, uint64_t * gpregs, double *fpregs)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ 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");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint64_t* ap = args;
+ uint32_t nr_gpr = 1; // skip one GPR register for 'that'
+ uint32_t nr_fpr = 0;
+ uint64_t value;
+
+ for (i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.d = *(double*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else {
+ 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;
+ // Cast to uint8_t first, to remove garbage on upper 56 bits.
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+// Linux/x86-64 uses gcc >= 3.1
+#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" \
+ "_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" \
+ "_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" \
+ "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp SharedStub\n\t" \
+ ".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");
+
+// static nsresult SharedStub(uint32_t methodIndex)
+asm(".section \".text\"\n\t"
+ ".align 2\n\t"
+ ".type SharedStub,@function\n\t"
+ "SharedStub:\n\t"
+ // make room for gpregs (48), fpregs (64)
+ "pushq %rbp\n\t"
+ "movq %rsp,%rbp\n\t"
+ "subq $112,%rsp\n\t"
+ // save GP registers
+ "movq %rdi,-112(%rbp)\n\t"
+ "movq %rsi,-104(%rbp)\n\t"
+ "movq %rdx, -96(%rbp)\n\t"
+ "movq %rcx, -88(%rbp)\n\t"
+ "movq %r8 , -80(%rbp)\n\t"
+ "movq %r9 , -72(%rbp)\n\t"
+ "leaq -112(%rbp),%rcx\n\t"
+ // save FP registers
+ "movsd %xmm0,-64(%rbp)\n\t"
+ "movsd %xmm1,-56(%rbp)\n\t"
+ "movsd %xmm2,-48(%rbp)\n\t"
+ "movsd %xmm3,-40(%rbp)\n\t"
+ "movsd %xmm4,-32(%rbp)\n\t"
+ "movsd %xmm5,-24(%rbp)\n\t"
+ "movsd %xmm6,-16(%rbp)\n\t"
+ "movsd %xmm7, -8(%rbp)\n\t"
+ "leaq -64(%rbp),%r8\n\t"
+ // rdi has the 'self' pointer already
+ "movl %eax,%esi\n\t"
+ "leaq 16(%rbp),%rdx\n\t"
+ "call PrepareAndDispatch@plt\n\t"
+ "leave\n\t"
+ "ret\n\t"
+ ".size SharedStub,.-SharedStub");
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_solaris.cpp
new file mode 100644
index 0000000000..677fa99606
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_64_solaris.cpp
@@ -0,0 +1,139 @@
+/* -*- 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/. */
+
+// Implement shared vtbl methods.
+
+// Keep this in sync with the darwin version.
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+// The Linux/x86-64 ABI passes the first 6 integer parameters and the
+// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,
+// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area.
+
+const uint32_t PARAM_BUFFER_COUNT = 16;
+const uint32_t GPR_COUNT = 6;
+const uint32_t FPR_COUNT = 8;
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gpregs[]' contains the arguments passed in integer registers
+// - 'fpregs[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex,
+ uint64_t * args, uint64_t * gpregs, double *fpregs)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint32_t paramCount;
+ uint32_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ 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");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ uint64_t* ap = args;
+ uint32_t nr_gpr = 1; // skip one GPR register for 'that'
+ uint32_t nr_fpr = 0;
+ uint64_t value;
+
+ for (i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.d = *(double*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else {
+ 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;
+ // Cast to uint8_t first, to remove garbage on upper 56 bits.
+ 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;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t) methodIndex, info, dispatchParams);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n)
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_solaris.cpp
new file mode 100644
index 0000000000..39eec5e545
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_x86_solaris.cpp
@@ -0,0 +1,77 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+nsresult ATTRIBUTE_USED
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint32_t* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ 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");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ dp->val.p = (void*) *ap;
+ switch(type)
+ {
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n)
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/xpcom/reflect/xptcall/md/win32/moz.build b/xpcom/reflect/xptcall/md/win32/moz.build
new file mode 100644
index 0000000000..5dbe41d764
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/moz.build
@@ -0,0 +1,45 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+if CONFIG['TARGET_CPU'] == 'x86_64':
+ if CONFIG['GNU_CXX']:
+ SOURCES += [
+ 'xptcinvoke_x86_64.cpp',
+ 'xptcstubs_x86_64_gnu.cpp',
+ ]
+ SOURCES += [
+ 'xptcinvoke_asm_x86_64_gnu.s'
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke_x86_64.cpp',
+ 'xptcstubs_x86_64.cpp'
+ ]
+ SOURCES += [
+ 'xptcinvoke_asm_x86_64.asm',
+ 'xptcstubs_asm_x86_64.asm'
+ ]
+else:
+ if CONFIG['GNU_CXX']:
+ SOURCES += [
+ 'xptcinvoke_x86_gnu.cpp',
+ 'xptcstubs.cpp',
+ ]
+ else:
+ SOURCES += [
+ 'xptcinvoke.cpp',
+ 'xptcinvoke_asm_x86_msvc.asm',
+ 'xptcstubs.cpp',
+ ]
+ SOURCES['xptcinvoke.cpp'].no_pgo = True
+ SOURCES['xptcinvoke_asm_x86_msvc.asm'].flags += ['-safeseh']
+
+FINAL_LIBRARY = 'xul'
+
+LOCAL_INCLUDES += [
+ '../..',
+ '/xpcom/reflect/xptinfo',
+]
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp
new file mode 100644
index 0000000000..faec869f6d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke.cpp
@@ -0,0 +1,45 @@
+/* -*- 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"
+
+#ifndef WIN32
+#error "This code is for Win32 only"
+#endif
+
+extern "C" void __fastcall
+invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ for(; paramCount > 0; paramCount--, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm
new file mode 100644
index 0000000000..bf7c2ef0c3
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64.asm
@@ -0,0 +1,107 @@
+; 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/.
+
+extrn invoke_copy_to_stack:PROC
+
+
+.CODE
+
+;
+;XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex,
+; uint32_t paramCount, nsXPTCVariant* params)
+;
+
+XPTC__InvokebyIndex PROC FRAME
+
+ ; store register parameters
+
+ mov qword ptr [rsp+32], r9 ; params
+ mov dword ptr [rsp+24], r8d ; paramCount
+ mov dword ptr [rsp+16], edx ; methodIndex
+ mov qword ptr [rsp+8], rcx ; that
+
+ push rbp
+ .PUSHREG rbp
+ mov rbp, rsp ; store current RSP to RBP
+ .SETFRAME rbp, 0
+ .ENDPROLOG
+
+ sub rsp, 32
+
+ ; maybe we don't have any parameters to copy
+
+ test r8d, r8d
+ jz noparams
+
+ ;
+ ; Build stack for stdcall
+ ;
+
+ ; 1st parameter is space for parameters
+
+ mov eax, r8d
+ or eax, 1
+ shl rax, 3 ; *= 8
+ sub rsp, rax
+ mov rcx, rsp
+
+ ; 2nd parameter is parameter count
+
+ mov edx, r8d
+
+ ; 3rd parameter is params
+
+ mov r8, r9
+
+ sub rsp, 40
+ call invoke_copy_to_stack ; rcx = d
+ ; edx = paramCount
+ ; r8 = s
+ add rsp, 32
+
+ ; Current stack is the following.
+ ;
+ ; 0h: [space (for this)]
+ ; 8h: [1st parameter]
+ ; 10h: [2nd parameter]
+ ; 18h: [3rd parameter]
+ ; 20h: [4th parameter]
+ ; ...
+ ;
+ ; On Win64 ABI, the first 4 parameters are passed using registers,
+ ; and others are on stack.
+
+ ; 1st, 2nd and 3rd arguments are passed via registers
+
+ mov rdx, qword ptr [rsp+8] ; 1st parameter
+ movsd xmm1, qword ptr [rsp+8] ; for double
+
+ mov r8, qword ptr [rsp+16] ; 2nd parameter
+ movsd xmm2, qword ptr [rsp+16] ; for double
+
+ mov r9, qword ptr [rsp+24] ; 3rd parameter
+ movsd xmm3, qword ptr [rsp+24] ; for double
+
+ ; rcx register is this
+
+ mov rcx, qword ptr [rbp+8+8] ; that
+
+noparams:
+
+ ; calculate call address
+
+ mov r11, qword ptr [rcx]
+ mov eax, dword ptr [rbp+16+8] ; methodIndex
+
+ call qword ptr [r11+rax*8] ; stdcall, i.e. callee cleans up stack.
+
+ mov rsp, rbp
+ pop rbp
+
+ ret
+
+XPTC__InvokebyIndex ENDP
+
+
+END
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s
new file mode 100644
index 0000000000..006e0444bd
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_64_gnu.s
@@ -0,0 +1,110 @@
+# 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/.
+
+.extern invoke_copy_to_stack
+
+
+.text
+.intel_syntax noprefix
+
+#
+#_XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex,
+# uint32_t paramCount, nsXPTCVariant* params)
+#
+
+.globl XPTC__InvokebyIndex
+.def XPTC__InvokebyIndex
+ .scl 3
+ .type 46
+.endef
+XPTC__InvokebyIndex:
+
+ # store register parameters
+
+ mov qword ptr [rsp+32], r9 # params
+ mov dword ptr [rsp+24], r8d # paramCount
+ mov dword ptr [rsp+16], edx # methodIndex
+ mov qword ptr [rsp+8], rcx # that
+
+ push rbp
+ # .PUSHREG rbp
+ mov rbp, rsp # store current RSP to RBP
+ # .SETFRAME rbp, 0
+ # .ENDPROLOG
+
+ sub rsp, 32
+
+ # maybe we don't have any parameters to copy
+
+ test r8d, r8d
+ jz noparams
+
+ #
+ # Build stack for stdcall
+ #
+
+ # 1st parameter is space for parameters
+
+ mov eax, r8d
+ or eax, 1
+ shl rax, 3 # *= 8
+ sub rsp, rax
+ mov rcx, rsp
+
+ # 2nd parameter is parameter count
+
+ mov edx, r8d
+
+ # 3rd parameter is params
+
+ mov r8, r9
+
+ sub rsp, 40
+ call invoke_copy_to_stack # rcx = d
+ # edx = paramCount
+ # r8 = s
+ add rsp, 32
+
+ # Current stack is the following.
+ #
+ # 0h: [space (for this)]
+ # 8h: [1st parameter]
+ # 10h: [2nd parameter]
+ # 18h: [3rd parameter]
+ # 20h: [4th parameter]
+ # ...
+ #
+ # On Win64 ABI, the first 4 parameters are passed using registers,
+ # and others are on stack.
+
+ # 1st, 2nd and 3rd arguments are passed via registers
+
+ mov rdx, qword ptr [rsp+8] # 1st parameter
+ movsd xmm1, qword ptr [rsp+8] # for double
+
+ mov r8, qword ptr [rsp+16] # 2nd parameter
+ movsd xmm2, qword ptr [rsp+16] # for double
+
+ mov r9, qword ptr [rsp+24] # 3rd parameter
+ movsd xmm3, qword ptr [rsp+24] # for double
+
+ # rcx register is this
+
+ mov rcx, qword ptr [rbp+8+8] # that
+
+noparams:
+
+ # calculate call address
+
+ mov r11, qword ptr [rcx]
+ mov eax, dword ptr [rbp+16+8] # methodIndex
+
+ call qword ptr [r11+rax*8] # stdcall, i.e. callee cleans up stack.
+
+ mov rsp, rbp
+ pop rbp
+
+ ret
+
+
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm
new file mode 100644
index 0000000000..f3b7a1826d
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_asm_x86_msvc.asm
@@ -0,0 +1,63 @@
+; 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/.
+
+ TITLE xptcinvoke_asm_x86_msvc.asm
+ .686P
+ .model flat
+
+PUBLIC _NS_InvokeByIndex
+EXTRN @invoke_copy_to_stack@12:PROC
+
+;
+; extern "C" nsresult __cdecl
+; NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+; uint32_t paramCount, nsXPTCVariant* params)
+;
+
+_TEXT SEGMENT
+_NS_InvokeByIndex PROC
+
+ ; Build frame
+ push ebp
+ mov ebp, esp
+
+ ; Save paramCount for later
+ mov edx, dword ptr [ebp+16]
+
+ ; Do we have any parameters?
+ test edx, edx
+ jz noparams
+
+ ; Build call for copy_to_stack, which is __fastcall
+
+ ; Allocate space for parameters. 8 is the biggest size
+ ; any parameter can be, so assume that all our parameters
+ ; are that large.
+ mov eax, edx
+ shl eax, 3
+ sub esp, eax
+
+ mov ecx, esp
+ push dword ptr [ebp+20]
+ call @invoke_copy_to_stack@12
+noparams:
+ ; Push the `this' parameter for the call.
+ mov ecx, dword ptr [ebp+8]
+ push ecx
+
+ ; Load the vtable.
+ mov edx, dword ptr [ecx]
+
+ ; Call the vtable index at `methodIndex'.
+ mov eax, dword ptr [ebp+12]
+ call dword ptr [edx+eax*4]
+
+ ; Reset and return.
+ mov esp, ebp
+ pop ebp
+ ret
+_NS_InvokeByIndex ENDP
+_TEXT ENDS
+
+END
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp
new file mode 100644
index 0000000000..36b454b352
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_64.cpp
@@ -0,0 +1,59 @@
+/* -*- 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"
+
+extern "C" void
+invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
+{
+ for(; paramCount > 0; paramCount--, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+ /*
+ * AMD64 platform uses 8 bytes align.
+ */
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; break;
+ case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; break;
+ case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult
+XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+extern "C"
+EXPORT_XPCOM_API(nsresult)
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params)
+{
+ return XPTC__InvokebyIndex(that, methodIndex, paramCount, params);
+}
+
diff --git a/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp
new file mode 100644
index 0000000000..0e73e99f3a
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcinvoke_x86_gnu.cpp
@@ -0,0 +1,106 @@
+/* -*- 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"
+
+extern "C" {
+void __attribute__ ((__used__)) __attribute__ ((regparm(3)))
+invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d)
+{
+ for(uint32_t i = paramCount; i >0; i--, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+} // extern "C"
+
+/*
+ EXPORT_XPCOM_API(nsresult)
+ NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
+ uint32_t paramCount, nsXPTCVariant* params);
+
+ Each param takes at most two 4-byte words.
+ It doesn't matter if we push too many words, and calculating the exact
+ amount takes time.
+
+ that = ebp + 0x08
+ methodIndex = ebp + 0x0c
+ paramCount = ebp + 0x10
+ params = ebp + 0x14
+
+*/
+
+__asm__ (
+ ".text\n\t"
+/* alignment here seems unimportant here; this was 16, now it's 2 which
+ is what xptcstubs uses. */
+ ".align 2\n\t"
+ ".globl _NS_InvokeByIndex\n\t"
+ "_NS_InvokeByIndex:\n\t"
+ "pushl %ebp\n\t"
+ "movl %esp, %ebp\n\t"
+ "movl 0x10(%ebp), %eax\n\t"
+ "leal 0(,%eax,8),%edx\n\t"
+
+ /* set up call frame for method. */
+ "subl %edx, %esp\n\t" /* make room for params. */
+/* Align to maximum x86 data size: 128 bits == 16 bytes == XMM register size.
+ * This is to avoid protection faults where SSE+ alignment of stack pointer
+ * is assumed and required, e.g. by GCC4's -ftree-vectorize option.
+ */
+ "andl $0xfffffff0, %esp\n\t" /* drop(?) stack ptr to 128-bit align */
+/* $esp should be aligned to a 16-byte boundary here (note we include an
+ * additional 4 bytes in a later push instruction). This will ensure $ebp
+ * in the function called below is aligned to a 0x8 boundary. SSE instructions
+ * like movapd/movdqa expect memory operand to be aligned on a 16-byte
+ * boundary. The GCC compiler will generate the memory operand using $ebp
+ * with an 8-byte offset.
+ */
+ "subl $0xc, %esp\n\t" /* lower again; push/call below will re-align */
+ "movl %esp, %ecx\n\t" /* ecx = d */
+ "movl 8(%ebp), %edx\n\t" /* edx = this */
+ "pushl %edx\n\t" /* push this. esp % 16 == 0 */
+
+ "movl 0x14(%ebp), %edx\n\t"
+ "call _invoke_copy_to_stack\n\t"
+ "movl 0x08(%ebp), %ecx\n\t" /* 'that' */
+ "movl (%ecx), %edx\n\t"
+ "movl 0x0c(%ebp), %eax\n\t" /* function index */
+ "leal (%edx,%eax,4), %edx\n\t"
+ "call *(%edx)\n\t"
+ "movl %ebp, %esp\n\t"
+ "popl %ebp\n\t"
+ "ret\n"
+ ".section .drectve\n\t"
+ ".ascii \" -export:NS_InvokeByIndex\"\n\t"
+ ".text\n\t"
+);
diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp
new file mode 100644
index 0000000000..e525aebd74
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcstubs.cpp
@@ -0,0 +1,227 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+#ifndef WIN32
+#error "This code is for Win32 only"
+#endif
+
+extern "C" {
+
+#if !defined(__GNUC__) && !defined(__clang__)
+static
+#endif
+nsresult __stdcall
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex,
+ uint32_t* args, uint32_t* stackBytesToPop)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ // If anything fails before stackBytesToPop can be set then
+ // the failure is completely catastrophic!
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ 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");
+
+ uint32_t* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((int8_t*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((int16_t*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((int32_t*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((int64_t*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((uint8_t*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((uint16_t*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((uint32_t*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((uint64_t*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((bool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+ *stackBytesToPop = ((uint32_t)ap) - ((uint32_t)args);
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+} // extern "C"
+
+// declspec(naked) is broken in gcc and clang-cl
+#if !defined(__GNUC__) && !defined(__clang__)
+static
+__declspec(naked)
+void SharedStub(void)
+{
+ __asm {
+ push ebp // set up simple stack frame
+ mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args
+ push ecx // make room for a ptr
+ lea eax, [ebp-4] // pointer to stackBytesToPop
+ push eax
+ lea eax, [ebp+12] // pointer to args
+ push eax
+ push ecx // vtbl_index
+ mov eax, [ebp+8] // this
+ push eax
+ call PrepareAndDispatch
+ mov edx, [ebp+4] // return address
+ mov ecx, [ebp-4] // stackBytesToPop
+ add ecx, 8 // for 'this' and return address
+ mov esp, ebp
+ pop ebp
+ add esp, ecx // fix up stack pointer
+ jmp edx // simulate __stdcall return
+ }
+}
+
+// these macros get expanded (many times) in the file #included below
+#define STUB_ENTRY(n) \
+__declspec(naked) nsresult __stdcall nsXPTCStubBase::Stub##n() \
+{ __asm mov ecx, n __asm jmp SharedStub }
+
+#else
+
+asm(".text\n\t"
+ ".align 4\n\t"
+ "SharedStub:\n\t"
+ "push %ebp\n\t"
+ "mov %esp, %ebp\n\t"
+ "push %ecx\n\t"
+ "lea -4(%ebp), %eax\n\t"
+ "push %eax\n\t"
+ "lea 12(%ebp), %eax\n\t"
+ "push %eax\n\t"
+ "push %ecx\n\t"
+ "movl 8(%ebp), %eax\n\t"
+ "push %eax\n\t"
+ "call _PrepareAndDispatch@16\n\t"
+ "mov 4(%ebp), %edx\n\t"
+ "mov -4(%ebp), %ecx\n\t"
+ "add $8, %ecx\n\t"
+ "mov %ebp, %esp\n\t"
+ "pop %ebp\n\t"
+ "add %ecx, %esp\n\t"
+ "jmp *%edx"
+);
+
+// The clang-cl specific code below is required because mingw uses the gcc name
+// mangling, but clang-cl implements the MSVC name mangling.
+
+#ifdef __clang__
+
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 4\n\t" \
+ ".globl \"?Stub" #n "@nsXPTCStubBase@@UAG?AW4nsresult@@XZ\"\n\t" \
+ ".def \"?Stub" #n "@nsXPTCStubBase@@UAG?AW4nsresult@@XZ\"; \n\t" \
+ ".scl 2\n\t" \
+ ".type 46\n\t" \
+ ".endef\n\t" \
+ "\"?Stub" #n "@nsXPTCStubBase@@UAG?AW4nsresult@@XZ\":\n\t" \
+ "mov $" #n ", %ecx\n\t" \
+ "jmp SharedStub");
+
+#else
+
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 4\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl __ZN14nsXPTCStubBase5Stub" #n "Ev@4\n\t" \
+ ".def __ZN14nsXPTCStubBase5Stub" #n "Ev@4; \n\t" \
+ ".scl 3\n\t" \
+ ".type 46\n\t" \
+ ".endef\n\t" \
+ "__ZN14nsXPTCStubBase5Stub" #n "Ev@4:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl __ZN14nsXPTCStubBase6Stub" #n "Ev@4\n\t" \
+ ".def __ZN14nsXPTCStubBase6Stub" #n "Ev@4\n\t" \
+ ".scl 3\n\t" \
+ ".type 46\n\t" \
+ ".endef\n\t" \
+ "__ZN14nsXPTCStubBase6Stub" #n "Ev@4:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl __ZN14nsXPTCStubBase7Stub" #n "Ev@4\n\t" \
+ ".def __ZN14nsXPTCStubBase7Stub" #n "Ev@4\n\t" \
+ ".scl 3\n\t" \
+ ".type 46\n\t" \
+ ".endef\n\t" \
+ "__ZN14nsXPTCStubBase7Stub" #n "Ev@4:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "mov $" #n ", %ecx\n\t" \
+ "jmp SharedStub");
+
+#endif
+
+#endif /* __GNUC__ || __clang__ */
+
+#define SENTINEL_ENTRY(n) \
+nsresult __stdcall nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4035) // OK to have no return value
+#endif
+#include "xptcstubsdef.inc"
+#ifdef _MSC_VER
+#pragma warning(default : 4035) // restore default
+#endif
+
+void
+#ifdef __GNUC__
+__cdecl
+#endif
+xptc_dummy()
+{
+}
diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm b/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm
new file mode 100644
index 0000000000..db2cc16bee
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_asm_x86_64.asm
@@ -0,0 +1,335 @@
+; 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/.
+
+extrn PrepareAndDispatch:PROC
+
+.code
+
+SharedStub PROC FRAME
+ sub rsp, 104
+ .ALLOCSTACK 104
+ .ENDPROLOG
+
+ ; rcx is this pointer. Need backup for optimized build
+
+ mov qword ptr [rsp+88], rcx
+
+ ;
+ ; fist 4 parameters (1st is "this" pointer) are passed in registers.
+ ;
+
+ ; for floating value
+
+ movsd qword ptr [rsp+64], xmm1
+ movsd qword ptr [rsp+72], xmm2
+ movsd qword ptr [rsp+80], xmm3
+
+ ; for integer value
+
+ mov qword ptr [rsp+40], rdx
+ mov qword ptr [rsp+48], r8
+ mov qword ptr [rsp+56], r9
+
+ ;
+ ; Call PrepareAndDispatch function
+ ;
+
+ ; 5th parameter (floating parameters) of PrepareAndDispatch
+
+ lea r9, qword ptr [rsp+64]
+ mov qword ptr [rsp+32], r9
+
+ ; 4th parameter (normal parameters) of PrepareAndDispatch
+
+ lea r9, qword ptr [rsp+40]
+
+ ; 3rd parameter (pointer to args on stack)
+
+ lea r8, qword ptr [rsp+40+104]
+
+ ; 2nd parameter (vtbl_index)
+
+ mov rdx, r11
+
+ ; 1st parameter (this) (rcx)
+
+ call PrepareAndDispatch
+
+ ; restore rcx
+
+ mov rcx, qword ptr [rsp+88]
+
+ ;
+ ; clean up register
+ ;
+
+ add rsp, 104+8
+
+ ; set return address
+
+ mov rdx, qword ptr [rsp-8]
+
+ ; simulate __stdcall return
+
+ jmp rdx
+
+SharedStub ENDP
+
+
+STUBENTRY MACRO functionname, paramcount
+functionname PROC
+ mov r11, paramcount
+ jmp SharedStub
+functionname ENDP
+ENDM
+
+ STUBENTRY ?Stub3@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 3
+ STUBENTRY ?Stub4@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 4
+ STUBENTRY ?Stub5@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 5
+ STUBENTRY ?Stub6@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 6
+ STUBENTRY ?Stub7@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 7
+ STUBENTRY ?Stub8@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 8
+ STUBENTRY ?Stub9@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 9
+ STUBENTRY ?Stub10@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 10
+ STUBENTRY ?Stub11@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 11
+ STUBENTRY ?Stub12@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 12
+ STUBENTRY ?Stub13@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 13
+ STUBENTRY ?Stub14@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 14
+ STUBENTRY ?Stub15@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 15
+ STUBENTRY ?Stub16@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 16
+ STUBENTRY ?Stub17@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 17
+ STUBENTRY ?Stub18@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 18
+ STUBENTRY ?Stub19@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 19
+ STUBENTRY ?Stub20@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 20
+ STUBENTRY ?Stub21@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 21
+ STUBENTRY ?Stub22@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 22
+ STUBENTRY ?Stub23@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 23
+ STUBENTRY ?Stub24@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 24
+ STUBENTRY ?Stub25@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 25
+ STUBENTRY ?Stub26@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 26
+ STUBENTRY ?Stub27@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 27
+ STUBENTRY ?Stub28@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 28
+ STUBENTRY ?Stub29@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 29
+ STUBENTRY ?Stub30@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 30
+ STUBENTRY ?Stub31@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 31
+ STUBENTRY ?Stub32@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 32
+ STUBENTRY ?Stub33@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 33
+ STUBENTRY ?Stub34@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 34
+ STUBENTRY ?Stub35@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 35
+ STUBENTRY ?Stub36@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 36
+ STUBENTRY ?Stub37@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 37
+ STUBENTRY ?Stub38@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 38
+ STUBENTRY ?Stub39@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 39
+ STUBENTRY ?Stub40@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 40
+ STUBENTRY ?Stub41@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 41
+ STUBENTRY ?Stub42@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 42
+ STUBENTRY ?Stub43@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 43
+ STUBENTRY ?Stub44@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 44
+ STUBENTRY ?Stub45@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 45
+ STUBENTRY ?Stub46@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 46
+ STUBENTRY ?Stub47@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 47
+ STUBENTRY ?Stub48@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 48
+ STUBENTRY ?Stub49@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 49
+ STUBENTRY ?Stub50@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 50
+ STUBENTRY ?Stub51@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 51
+ STUBENTRY ?Stub52@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 52
+ STUBENTRY ?Stub53@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 53
+ STUBENTRY ?Stub54@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 54
+ STUBENTRY ?Stub55@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 55
+ STUBENTRY ?Stub56@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 56
+ STUBENTRY ?Stub57@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 57
+ STUBENTRY ?Stub58@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 58
+ STUBENTRY ?Stub59@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 59
+ STUBENTRY ?Stub60@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 60
+ STUBENTRY ?Stub61@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 61
+ STUBENTRY ?Stub62@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 62
+ STUBENTRY ?Stub63@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 63
+ STUBENTRY ?Stub64@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 64
+ STUBENTRY ?Stub65@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 65
+ STUBENTRY ?Stub66@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 66
+ STUBENTRY ?Stub67@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 67
+ STUBENTRY ?Stub68@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 68
+ STUBENTRY ?Stub69@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 69
+ STUBENTRY ?Stub70@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 70
+ STUBENTRY ?Stub71@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 71
+ STUBENTRY ?Stub72@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 72
+ STUBENTRY ?Stub73@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 73
+ STUBENTRY ?Stub74@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 74
+ STUBENTRY ?Stub75@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 75
+ STUBENTRY ?Stub76@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 76
+ STUBENTRY ?Stub77@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 77
+ STUBENTRY ?Stub78@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 78
+ STUBENTRY ?Stub79@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 79
+ STUBENTRY ?Stub80@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 80
+ STUBENTRY ?Stub81@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 81
+ STUBENTRY ?Stub82@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 82
+ STUBENTRY ?Stub83@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 83
+ STUBENTRY ?Stub84@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 84
+ STUBENTRY ?Stub85@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 85
+ STUBENTRY ?Stub86@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 86
+ STUBENTRY ?Stub87@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 87
+ STUBENTRY ?Stub88@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 88
+ STUBENTRY ?Stub89@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 89
+ STUBENTRY ?Stub90@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 90
+ STUBENTRY ?Stub91@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 91
+ STUBENTRY ?Stub92@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 92
+ STUBENTRY ?Stub93@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 93
+ STUBENTRY ?Stub94@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 94
+ STUBENTRY ?Stub95@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 95
+ STUBENTRY ?Stub96@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 96
+ STUBENTRY ?Stub97@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 97
+ STUBENTRY ?Stub98@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 98
+ STUBENTRY ?Stub99@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 99
+ STUBENTRY ?Stub100@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 100
+ STUBENTRY ?Stub101@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 101
+ STUBENTRY ?Stub102@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 102
+ STUBENTRY ?Stub103@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 103
+ STUBENTRY ?Stub104@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 104
+ STUBENTRY ?Stub105@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 105
+ STUBENTRY ?Stub106@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 106
+ STUBENTRY ?Stub107@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 107
+ STUBENTRY ?Stub108@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 108
+ STUBENTRY ?Stub109@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 109
+ STUBENTRY ?Stub110@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 110
+ STUBENTRY ?Stub111@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 111
+ STUBENTRY ?Stub112@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 112
+ STUBENTRY ?Stub113@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 113
+ STUBENTRY ?Stub114@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 114
+ STUBENTRY ?Stub115@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 115
+ STUBENTRY ?Stub116@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 116
+ STUBENTRY ?Stub117@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 117
+ STUBENTRY ?Stub118@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 118
+ STUBENTRY ?Stub119@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 119
+ STUBENTRY ?Stub120@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 120
+ STUBENTRY ?Stub121@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 121
+ STUBENTRY ?Stub122@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 122
+ STUBENTRY ?Stub123@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 123
+ STUBENTRY ?Stub124@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 124
+ STUBENTRY ?Stub125@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 125
+ STUBENTRY ?Stub126@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 126
+ STUBENTRY ?Stub127@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 127
+ STUBENTRY ?Stub128@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 128
+ STUBENTRY ?Stub129@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 129
+ STUBENTRY ?Stub130@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 130
+ STUBENTRY ?Stub131@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 131
+ STUBENTRY ?Stub132@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 132
+ STUBENTRY ?Stub133@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 133
+ STUBENTRY ?Stub134@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 134
+ STUBENTRY ?Stub135@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 135
+ STUBENTRY ?Stub136@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 136
+ STUBENTRY ?Stub137@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 137
+ STUBENTRY ?Stub138@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 138
+ STUBENTRY ?Stub139@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 139
+ STUBENTRY ?Stub140@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 140
+ STUBENTRY ?Stub141@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 141
+ STUBENTRY ?Stub142@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 142
+ STUBENTRY ?Stub143@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 143
+ STUBENTRY ?Stub144@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 144
+ STUBENTRY ?Stub145@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 145
+ STUBENTRY ?Stub146@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 146
+ STUBENTRY ?Stub147@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 147
+ STUBENTRY ?Stub148@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 148
+ STUBENTRY ?Stub149@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 149
+ STUBENTRY ?Stub150@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 150
+ STUBENTRY ?Stub151@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 151
+ STUBENTRY ?Stub152@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 152
+ STUBENTRY ?Stub153@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 153
+ STUBENTRY ?Stub154@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 154
+ STUBENTRY ?Stub155@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 155
+ STUBENTRY ?Stub156@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 156
+ STUBENTRY ?Stub157@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 157
+ STUBENTRY ?Stub158@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 158
+ STUBENTRY ?Stub159@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 159
+ STUBENTRY ?Stub160@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 160
+ STUBENTRY ?Stub161@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 161
+ STUBENTRY ?Stub162@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 162
+ STUBENTRY ?Stub163@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 163
+ STUBENTRY ?Stub164@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 164
+ STUBENTRY ?Stub165@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 165
+ STUBENTRY ?Stub166@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 166
+ STUBENTRY ?Stub167@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 167
+ STUBENTRY ?Stub168@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 168
+ STUBENTRY ?Stub169@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 169
+ STUBENTRY ?Stub170@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 170
+ STUBENTRY ?Stub171@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 171
+ STUBENTRY ?Stub172@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 172
+ STUBENTRY ?Stub173@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 173
+ STUBENTRY ?Stub174@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 174
+ STUBENTRY ?Stub175@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 175
+ STUBENTRY ?Stub176@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 176
+ STUBENTRY ?Stub177@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 177
+ STUBENTRY ?Stub178@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 178
+ STUBENTRY ?Stub179@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 179
+ STUBENTRY ?Stub180@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 180
+ STUBENTRY ?Stub181@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 181
+ STUBENTRY ?Stub182@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 182
+ STUBENTRY ?Stub183@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 183
+ STUBENTRY ?Stub184@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 184
+ STUBENTRY ?Stub185@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 185
+ STUBENTRY ?Stub186@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 186
+ STUBENTRY ?Stub187@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 187
+ STUBENTRY ?Stub188@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 188
+ STUBENTRY ?Stub189@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 189
+ STUBENTRY ?Stub190@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 190
+ STUBENTRY ?Stub191@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 191
+ STUBENTRY ?Stub192@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 192
+ STUBENTRY ?Stub193@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 193
+ STUBENTRY ?Stub194@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 194
+ STUBENTRY ?Stub195@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 195
+ STUBENTRY ?Stub196@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 196
+ STUBENTRY ?Stub197@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 197
+ STUBENTRY ?Stub198@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 198
+ STUBENTRY ?Stub199@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 199
+ STUBENTRY ?Stub200@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 200
+ STUBENTRY ?Stub201@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 201
+ STUBENTRY ?Stub202@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 202
+ STUBENTRY ?Stub203@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 203
+ STUBENTRY ?Stub204@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 204
+ STUBENTRY ?Stub205@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 205
+ STUBENTRY ?Stub206@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 206
+ STUBENTRY ?Stub207@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 207
+ STUBENTRY ?Stub208@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 208
+ STUBENTRY ?Stub209@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 209
+ STUBENTRY ?Stub210@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 210
+ STUBENTRY ?Stub211@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 211
+ STUBENTRY ?Stub212@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 212
+ STUBENTRY ?Stub213@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 213
+ STUBENTRY ?Stub214@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 214
+ STUBENTRY ?Stub215@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 215
+ STUBENTRY ?Stub216@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 216
+ STUBENTRY ?Stub217@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 217
+ STUBENTRY ?Stub218@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 218
+ STUBENTRY ?Stub219@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 219
+ STUBENTRY ?Stub220@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 220
+ STUBENTRY ?Stub221@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 221
+ STUBENTRY ?Stub222@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 222
+ STUBENTRY ?Stub223@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 223
+ STUBENTRY ?Stub224@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 224
+ STUBENTRY ?Stub225@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 225
+ STUBENTRY ?Stub226@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 226
+ STUBENTRY ?Stub227@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 227
+ STUBENTRY ?Stub228@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 228
+ STUBENTRY ?Stub229@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 229
+ STUBENTRY ?Stub230@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 230
+ STUBENTRY ?Stub231@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 231
+ STUBENTRY ?Stub232@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 232
+ STUBENTRY ?Stub233@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 233
+ STUBENTRY ?Stub234@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 234
+ STUBENTRY ?Stub235@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 235
+ STUBENTRY ?Stub236@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 236
+ STUBENTRY ?Stub237@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 237
+ STUBENTRY ?Stub238@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 238
+ STUBENTRY ?Stub239@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 239
+ STUBENTRY ?Stub240@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 240
+ STUBENTRY ?Stub241@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 241
+ STUBENTRY ?Stub242@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 242
+ STUBENTRY ?Stub243@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 243
+ STUBENTRY ?Stub244@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 244
+ STUBENTRY ?Stub245@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 245
+ STUBENTRY ?Stub246@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 246
+ STUBENTRY ?Stub247@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 247
+ STUBENTRY ?Stub248@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 248
+ STUBENTRY ?Stub249@nsXPTCStubBase@@UEAA?AW4nsresult@@XZ, 249
+
+END
diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp
new file mode 100644
index 0000000000..8ff479d1e7
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64.cpp
@@ -0,0 +1,197 @@
+/* -*- 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/. */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptiprivate.h"
+
+/*
+ * This is for Windows XP 64-Bit Edition / Server 2003 for AMD64 or later.
+ */
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32_t methodIndex, uint64_t* args,
+ uint64_t *gprData, double *fprData)
+{
+#define PARAM_BUFFER_COUNT 16
+//
+// "this" pointer is first parameter, so parameter count is 3.
+//
+#define PARAM_GPR_COUNT 3
+#define PARAM_FPR_COUNT 3
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+
+ 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 iCount = 0;
+
+ for(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 (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*)gprData[iCount++];
+ else
+ dp->val.p = (void*)*ap++;
+
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (int8_t)gprData[iCount++];
+ else
+ dp->val.i8 = *((int8_t*)ap++);
+ break;
+
+ case nsXPTType::T_I16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (int16_t)gprData[iCount++];
+ else
+ dp->val.i16 = *((int16_t*)ap++);
+ break;
+
+ case nsXPTType::T_I32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (int32_t)gprData[iCount++];
+ else
+ dp->val.i32 = *((int32_t*)ap++);
+ break;
+
+ case nsXPTType::T_I64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (int64_t)gprData[iCount++];
+ else
+ dp->val.i64 = *((int64_t*)ap++);
+ break;
+
+ case nsXPTType::T_U8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (uint8_t)gprData[iCount++];
+ else
+ dp->val.u8 = *((uint8_t*)ap++);
+ break;
+
+ case nsXPTType::T_U16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (uint16_t)gprData[iCount++];
+ else
+ dp->val.u16 = *((uint16_t*)ap++);
+ break;
+
+ case nsXPTType::T_U32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (uint32_t)gprData[iCount++];
+ else
+ dp->val.u32 = *((uint32_t*)ap++);
+ break;
+
+ case nsXPTType::T_U64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (uint64_t)gprData[iCount++];
+ else
+ dp->val.u64 = *((uint64_t*)ap++);
+ break;
+
+ case nsXPTType::T_FLOAT:
+ if (iCount < PARAM_FPR_COUNT)
+ // The value in xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.f = *((float*)ap++);
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.d = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (iCount < PARAM_GPR_COUNT)
+ // We need cast to uint8_t to remove garbage on upper 56-bit
+ // at first.
+ dp->val.b = (bool)(uint8_t)gprData[iCount++];
+ else
+ dp->val.b = *((bool*)ap++);
+ break;
+
+ case nsXPTType::T_CHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char)gprData[iCount++];
+ else
+ dp->val.c = *((char*)ap++);
+ break;
+
+ case nsXPTType::T_WCHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t)gprData[iCount++];
+ else
+ dp->val.wc = *((wchar_t*)ap++);
+ break;
+
+ default:
+ NS_ERROR("bad type");
+ break;
+ }
+ }
+
+ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) /* defined in the assembly file */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ERROR("nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+void
+xptc_dummy()
+{
+}
+
diff --git a/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp
new file mode 100644
index 0000000000..2676334d21
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/win32/xptcstubs_x86_64_gnu.cpp
@@ -0,0 +1,297 @@
+/* -*- 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"
+
+/*
+ * This is for Windows 64 bit (x86_64) using GCC syntax
+ * Code was copied from the MSVC version.
+ */
+
+#if !defined(_AMD64_) || !defined(__GNUC__)
+# error xptcstubs_x86_64_gnu.cpp being used unexpectedly
+#endif
+
+extern "C" nsresult __attribute__((__used__))
+PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex,
+ uint64_t * args, uint64_t * gprData, double *fprData)
+{
+#define PARAM_BUFFER_COUNT 16
+//
+// "this" pointer is first parameter, so parameter count is 3.
+//
+#define PARAM_GPR_COUNT 3
+#define PARAM_FPR_COUNT 3
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = nullptr;
+ const nsXPTMethodInfo* info = nullptr;
+ uint8_t paramCount;
+ uint8_t i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self, "no self");
+
+ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
+ NS_ASSERTION(info, "no method info");
+
+ 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 iCount = 0;
+
+ for(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 (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*)gprData[iCount++];
+ else
+ dp->val.p = (void*)*ap++;
+
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (int8_t)gprData[iCount++];
+ else
+ dp->val.i8 = *((int8_t*)ap++);
+ break;
+
+ case nsXPTType::T_I16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (int16_t)gprData[iCount++];
+ else
+ dp->val.i16 = *((int16_t*)ap++);
+ break;
+
+ case nsXPTType::T_I32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (int32_t)gprData[iCount++];
+ else
+ dp->val.i32 = *((int32_t*)ap++);
+ break;
+
+ case nsXPTType::T_I64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (int64_t)gprData[iCount++];
+ else
+ dp->val.i64 = *((int64_t*)ap++);
+ break;
+
+ case nsXPTType::T_U8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (uint8_t)gprData[iCount++];
+ else
+ dp->val.u8 = *((uint8_t*)ap++);
+ break;
+
+ case nsXPTType::T_U16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (uint16_t)gprData[iCount++];
+ else
+ dp->val.u16 = *((uint16_t*)ap++);
+ break;
+
+ case nsXPTType::T_U32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (uint32_t)gprData[iCount++];
+ else
+ dp->val.u32 = *((uint32_t*)ap++);
+ break;
+
+ case nsXPTType::T_U64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (uint64_t)gprData[iCount++];
+ else
+ dp->val.u64 = *((uint64_t*)ap++);
+ break;
+
+ case nsXPTType::T_FLOAT:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.f = (float)fprData[iCount++];
+ else
+ dp->val.f = *((float*)ap++);
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.d = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (bool)gprData[iCount++];
+ else
+ dp->val.b = *((bool*)ap++);
+ break;
+
+ case nsXPTType::T_CHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char)gprData[iCount++];
+ else
+ dp->val.c = *((char*)ap++);
+ break;
+
+ case nsXPTType::T_WCHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t)gprData[iCount++];
+ 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;
+}
+
+__asm__ (
+ ".text\n"
+ ".intel_syntax noprefix\n" /* switch to Intel syntax to look like the MSVC assembly */
+ ".globl SharedStub\n"
+ ".def SharedStub ; .scl 3 ; .type 46 ; .endef \n"
+ "SharedStub:\n"
+ "sub rsp, 104\n"
+
+ /* rcx is this pointer. Need backup for optimized build */
+
+ "mov qword ptr [rsp+88], rcx\n"
+
+ /*
+ * fist 4 parameters (1st is "this" pointer) are passed in registers.
+ */
+
+ /* for floating value */
+
+ "movsd qword ptr [rsp+64], xmm1\n"
+ "movsd qword ptr [rsp+72], xmm2\n"
+ "movsd qword ptr [rsp+80], xmm3\n"
+
+ /* for integer value */
+
+ "mov qword ptr [rsp+40], rdx\n"
+ "mov qword ptr [rsp+48], r8\n"
+ "mov qword ptr [rsp+56], r9\n"
+
+ /*
+ * Call PrepareAndDispatch function
+ */
+
+ /* 5th parameter (floating parameters) of PrepareAndDispatch */
+
+ "lea r9, qword ptr [rsp+64]\n"
+ "mov qword ptr [rsp+32], r9\n"
+
+ /* 4th parameter (normal parameters) of PrepareAndDispatch */
+
+ "lea r9, qword ptr [rsp+40]\n"
+
+ /* 3rd parameter (pointer to args on stack) */
+
+ "lea r8, qword ptr [rsp+40+104]\n"
+
+ /* 2nd parameter (vtbl_index) */
+
+ "mov rdx, r11\n"
+
+ /* 1st parameter (this) (rcx) */
+
+ "call PrepareAndDispatch\n"
+
+ /* restore rcx */
+
+ "mov rcx, qword ptr [rsp+88]\n"
+
+ /*
+ * clean up register
+ */
+
+ "add rsp, 104+8\n"
+
+ /* set return address */
+
+ "mov rdx, qword ptr [rsp-8]\n"
+
+ /* simulate __stdcall return */
+
+ "jmp rdx\n"
+
+ /* back to AT&T syntax */
+ ".att_syntax\n"
+);
+
+#define STUB_ENTRY(n) \
+asm(".intel_syntax noprefix\n" /* this is in intel syntax */ \
+ ".text\n" \
+ ".align 2\n" \
+ ".if " #n " < 10\n" \
+ ".globl _ZN14nsXPTCStubBase5Stub" #n "Ev@4\n" \
+ ".def _ZN14nsXPTCStubBase5Stub" #n "Ev@4\n" \
+ ".scl 3\n" /* private */ \
+ ".type 46\n" /* function returning unsigned int */ \
+ ".endef\n" \
+ "_ZN14nsXPTCStubBase5Stub" #n "Ev@4:\n" \
+ ".elseif " #n " < 100\n" \
+ ".globl _ZN14nsXPTCStubBase6Stub" #n "Ev@4\n" \
+ ".def _ZN14nsXPTCStubBase6Stub" #n "Ev@4\n" \
+ ".scl 3\n" /* private */\
+ ".type 46\n" /* function returning unsigned int */ \
+ ".endef\n" \
+ "_ZN14nsXPTCStubBase6Stub" #n "Ev@4:\n" \
+ ".elseif " #n " < 1000\n" \
+ ".globl _ZN14nsXPTCStubBase7Stub" #n "Ev@4\n" \
+ ".def _ZN14nsXPTCStubBase7Stub" #n "Ev@4\n" \
+ ".scl 3\n" /* private */ \
+ ".type 46\n" /* function returning unsigned int */ \
+ ".endef\n" \
+ "_ZN14nsXPTCStubBase7Stub" #n "Ev@4:\n" \
+ ".else\n" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n" \
+ ".endif\n" \
+ "mov r11, " #n "\n" \
+ "jmp SharedStub\n" \
+ ".att_syntax\n" /* back to AT&T syntax */ \
+ "");
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+