import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

8
xpcom/reflect/moz.build Normal file
View file

@ -0,0 +1,8 @@
# -*- 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/.
DIRS += ['xptinfo', 'xptcall']

View file

@ -0,0 +1,6 @@
see:
http://www.mozilla.org/scriptable/xptcall-faq.html
and
http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html

View file

@ -0,0 +1,88 @@
#!/usr/local/bin/perl
# 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 is used to generate stub entry points. We generate a file to
# be included in the declaraion and a file to be used for expanding macros
# to represent the implementation of the stubs.
#
# if "$entry_count" is ever changed and the .inc files regenerated then
# the following issues need to be addressed:
#
# 1) The current Linux ARM code has a limitation of only having 256-3 stubs,
# as a result of the limitations of immediate values in ARM assembly.
#
# This number is verified by the IDL parser in xpcom/idl-parser/xpidl.py, as
# well as in xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp, to
# prevent generating interfaces or loading xpt files that would cause the
# stubs to run off the entries.
# If you change this number, please update that location.
# 3 entries are already 'used' by the 3 methods of nsISupports.
# 3+247+5=255 This should get us in under the Linux ARM limitation
$entry_count = 247;
$sentinel_count = 5;
$decl_name = "xptcstubsdecl.inc";
$def_name = "xptcstubsdef.inc";
##
## Write the declarations include file
##
die "Can't open $decl_name" if !open(OUTFILE, ">$decl_name");
print OUTFILE "/* generated file - DO NOT EDIT */\n\n";
print OUTFILE "/* includes ",$entry_count," stub entries, and ",
$sentinel_count," sentinel entries */\n\n";
print OUTFILE "/*\n";
print OUTFILE "* declarations of normal stubs...\n";
print OUTFILE "* 0 is QueryInterface\n";
print OUTFILE "* 1 is AddRef\n";
print OUTFILE "* 2 is Release\n";
print OUTFILE "*/\n";
print OUTFILE "#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__))\n";
for($i = 0; $i < $entry_count; $i++) {
print OUTFILE "NS_IMETHOD Stub",$i+3,"();\n";
}
print OUTFILE "#else\n";
for($i = 0; $i < $entry_count; $i++) {
print OUTFILE "NS_IMETHOD Stub",$i+3,"(uint64_t,uint64_t,\n";
print OUTFILE " uint64_t,uint64_t,uint64_t,uint64_t,uint64_t,uint64_t);\n";
}
print OUTFILE "#endif\n";
print OUTFILE "\n/* declarations of sentinel stubs */\n";
for($i = 0; $i < $sentinel_count; $i++) {
print OUTFILE "NS_IMETHOD Sentinel",$i,"();\n";
}
close(OUTFILE);
##
## Write the definitions include file. This assumes a macro will be used to
## expand the entries written...
##
die "Can't open $def_name" if !open(OUTFILE, ">$def_name");
## Disabled for bug 275004 - followup to fix is Bug 419604
my $warn_inc_is_generated = 0;
if ($warn_inc_is_generated) {
print OUTFILE "/* generated file - DO NOT EDIT */\n\n";
print OUTFILE "/* includes ",$entry_count," stub entries, and ",
$sentinel_count," sentinel entries */\n\n";
}
for($i = 0; $i < $entry_count; $i++) {
print OUTFILE "STUB_ENTRY(",$i+3,")\n";
}
for($i = 0; $i < $sentinel_count; $i++) {
print OUTFILE "SENTINEL_ENTRY(",$i,")\n";
}

View file

@ -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']

View file

@ -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.

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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',
])

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}

View file

@ -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"
);

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
);

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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"
);

View file

@ -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;
}

View file

@ -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]);
}

View file

@ -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]);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}
}
}

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}
}
}
}

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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"

View file

@ -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

View file

@ -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()
{
}

View file

@ -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"

Some files were not shown because too many files have changed in this diff Show more