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/unix/moz.build32
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s52
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S122
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp4
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp141
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp75
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s49
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp7
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcstubs_sparc_solaris.cpp112
9 files changed, 590 insertions, 4 deletions
diff --git a/xpcom/reflect/xptcall/md/unix/moz.build b/xpcom/reflect/xptcall/md/unix/moz.build
index d455ed8549..8ee7b31817 100644
--- a/xpcom/reflect/xptcall/md/unix/moz.build
+++ b/xpcom/reflect/xptcall/md/unix/moz.build
@@ -46,6 +46,21 @@ if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD'):
'xptcstubs_ipf64.cpp'
]
+# Without the need to accomodate the Sun compiler, Solaris/GCC support is pretty
+# standard, actually. Not all that different from Linux.
+
+if CONFIG['OS_ARCH'] == 'SunOS':
+ if CONFIG['OS_TEST'] == 'x86_64':
+ SOURCES += [
+ 'xptcinvoke_asm_x86_64_unix.S',
+ 'xptcinvoke_x86_64_solaris.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_TEST'] == 'alpha':
if CONFIG['OS_ARCH'] in ('Linux', 'FreeBSD', 'NetBSD'):
@@ -186,7 +201,11 @@ if CONFIG['OS_ARCH'] == 'OpenBSD' and CONFIG['OS_TEST'] == 'sparc':
'xptcstubs_sparc_openbsd.cpp',
]
-if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD') and CONFIG['OS_TEST'] == 'sparc64':
+# Mozilla discovered at some point that Solaris and Linux can also use these
+# files for 64-bit SPARC with no ill effects, so basically the entire mess that
+# was there before is no longer needed.
+
+if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD', 'SunOS') and CONFIG['OS_TEST'] == 'sparc64':
SOURCES += [
'xptcinvoke_asm_sparc64_openbsd.s',
'xptcinvoke_sparc64_openbsd.cpp',
@@ -194,6 +213,17 @@ if CONFIG['OS_ARCH'] in ('OpenBSD', 'FreeBSD') and CONFIG['OS_TEST'] == 'sparc64
'xptcstubs_sparc64_openbsd.cpp',
]
+# As for the 32-bit SPARC build? That would look like the Linux version with
+# one file changed.
+
+if CONFIG['OS_ARCH'] == 'SunOS' and CONFIG['OS_TEST'] == 'sparc':
+ SOURCES += [
+ 'xptcinvoke_asm_sparc_solaris_GCC3.s',
+ 'xptcinvoke_sparc_solaris.cpp',
+ 'xptcstubs_asm_sparc_solaris.s',
+ 'xptcstubs_sparc_solaris.cpp',
+ ]
+
if CONFIG['OS_ARCH'] == 'Linux':
if CONFIG['OS_TEST'] == 's390':
SOURCES += [
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_x86_64_unix.S b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S
new file mode 100644
index 0000000000..131cfc3343
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S
@@ -0,0 +1,122 @@
+# 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/.
+
+# Darwin gives a leading '_' to symbols defined in C code.
+#ifdef XP_DARWIN
+#define SYM(x) _ ## x
+#define CFI_STARTPROC
+#define CFI_ENDPROC
+#define CFI_DEF_CFA_OFFSET(offset)
+#define CFI_OFFSET(reg, offset)
+#define CFI_DEF_CFA_REGISTER(reg)
+#define CFI_DEF_CFA(reg, offset)
+#else
+#define SYM(x) x
+#define CFI_STARTPROC .cfi_startproc
+#define CFI_ENDPROC .cfi_endproc
+#define CFI_DEF_CFA_OFFSET(offset) .cfi_def_cfa_offset offset
+#define CFI_OFFSET(reg, offset) .cfi_offset reg, offset
+#define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
+#define CFI_DEF_CFA(reg, offset) .cfi_def_cfa reg, offset
+#endif
+
+.intel_syntax noprefix
+
+# nsresult NS_InvokeByIndex(nsISupports* this, uint32_t aVtableIndex,
+# uint32_t argc, nsXPTCVariant* argv);
+.text
+.global SYM(NS_InvokeByIndex)
+#ifndef XP_DARWIN
+.type NS_InvokeByIndex, @function
+#endif
+.align 4
+SYM(NS_InvokeByIndex):
+ CFI_STARTPROC
+ push rbp
+ CFI_DEF_CFA_OFFSET(16)
+ CFI_OFFSET(6, -16)
+ mov rbp, rsp
+ CFI_DEF_CFA_REGISTER(6)
+
+# save r12 and r13 because we use them and they are callee saved.
+ push r12
+ push r13
+ CFI_OFFSET(12, -24)
+ CFI_OFFSET(13, -32)
+
+# save this and the vtable index because we need them after setting up the
+# stack.
+ mov r12, rdi
+ mov r13, rsi
+
+# allocate space for stack arguments, in theory we only need 8 * (argc - 5)
+# bytes because at least 5 arguments will go in registers, but for now it is
+# just simpler to allocate 8 * argc bytes. Note that we treat the this
+# pointer specially.
+ lea eax, [edx * 8]
+ sub rsp, rax
+
+# If there is an odd number of args the stack can be misaligned so realign it.
+ and rsp, 0xfffffffffffffff0
+
+# pass the stack slot area to InvokeCopyToStack.
+ mov r8, rsp
+
+# setup space for the register slots: there are 5 integer ones and 8 floating
+# point ones. So we need 104 bytes of space, but we allocate 112 to keep rsp
+# aligned to 16 bytes.
+ sub rsp, 112
+
+# the first argument to InvokeCopyToStack is the integer register area, and the
+# second is the floating point area.
+ mov rdi, rsp
+ lea rsi, [rsp + 40]
+
+# The 3rd and 4th arguments to InvokeCopyToStack are already in the right
+# registers. So now we can just call InvokeCopyToStack.
+ call SYM(InvokeCopyToStack)
+
+# setup this
+ mov rdi, r12
+
+# copy the integer arguments into place.
+ mov rsi, [rsp]
+ mov rdx, [rsp + 8]
+ mov rcx, [rsp + 16]
+ mov r8, [rsp + 24]
+ mov r9, [rsp + 32]
+
+# copy the float arguments into place
+ movsd xmm0, [rsp + 40]
+ movsd xmm1, [rsp + 48]
+ movsd xmm2, [rsp + 56]
+ movsd xmm3, [rsp + 64]
+ movsd xmm4, [rsp + 72]
+ movsd xmm5, [rsp + 80]
+ movsd xmm6, [rsp + 88]
+ movsd xmm7, [rsp + 96]
+
+# get rid of the scratch space for registers
+ add rsp, 112
+
+# load the function pointer and call
+ lea eax, [r13d * 8]
+ add rax, [rdi]
+ call [rax]
+
+# r12 and r13 were pushed relative to the old stack pointer which is now the
+# frame pointer.
+ mov r12, [rbp - 0x8]
+ mov r13, [rbp - 0x10]
+
+ mov rsp, rbp
+ pop rbp
+ CFI_DEF_CFA(7, 8)
+ ret
+ CFI_ENDPROC
+
+#ifndef XP_DARWIN
+// Magic indicating no need for an executable stack
+.section .note.GNU-stack, "", @progbits ; .previous
+#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp
index 050f9414de..1b5039ed95 100644
--- a/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp
@@ -30,9 +30,9 @@ invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
{
if (regCount < 5) regCount++;
- if (l_s->IsPtrData())
+ if (l_s->IsIndirect())
{
- *l_d = (uint64_t)l_s->ptr;
+ *l_d = (uint64_t) &l_s->val;
continue;
}
switch (l_s->type)
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..c1b679779b
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp
@@ -0,0 +1,141 @@
+/* -*- 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_x86_64_solaris.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp
new file mode 100644
index 0000000000..a9db2a693a
--- /dev/null
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp
@@ -0,0 +1,75 @@
+/* -*- 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, but 1 is |this| which isn't
+// considered here.
+const uint32_t GPR_COUNT = 5;
+
+// 8 floating point parameters are passed in SSE registers
+const uint32_t FPR_COUNT = 8;
+
+extern "C" void
+InvokeCopyToStack(uint64_t * gpregs, double * fpregs,
+ uint32_t paramCount, nsXPTCVariant * s,
+ uint64_t* d)
+{
+ uint32_t nr_gpr = 0u; // 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;
+ }
+ }
+}
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_sparc64_openbsd.cpp b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp
index b8a09c97e1..e28a037940 100644
--- a/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp
+++ b/xpcom/reflect/xptcall/md/unix/xptcstubs_sparc64_openbsd.cpp
@@ -85,8 +85,13 @@ PrepareAndDispatch(nsXPTCStubBase* self, uint64_t methodIndex, uint64_t* args)
extern "C" nsresult SharedStub(int, int*);
+/*
+ * Avoid GCC stack protector to wipe out imput registers since the compiler
+ * thinks the function takes no arguments.
+ */
+
#define STUB_ENTRY(n) \
-nsresult nsXPTCStubBase::Stub##n() \
+nsresult __attribute__((__optimize__("no-stack-protector"))) nsXPTCStubBase::Stub##n() \
{ \
int dummy; /* defeat tail-call optimization */ \
return SharedStub(n, &dummy); \
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__ */