mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-30 12:27:29 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
8
xpcom/reflect/moz.build
Normal file
8
xpcom/reflect/moz.build
Normal 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']
|
||||
|
||||
6
xpcom/reflect/xptcall/README
Normal file
6
xpcom/reflect/xptcall/README
Normal 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
|
||||
|
||||
88
xpcom/reflect/xptcall/genstubs.pl
Normal file
88
xpcom/reflect/xptcall/genstubs.pl
Normal 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";
|
||||
}
|
||||
12
xpcom/reflect/xptcall/md/moz.build
Normal file
12
xpcom/reflect/xptcall/md/moz.build
Normal 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']
|
||||
6
xpcom/reflect/xptcall/md/test/README
Normal file
6
xpcom/reflect/xptcall/md/test/README
Normal 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.
|
||||
5
xpcom/reflect/xptcall/md/test/clean.bat
Normal file
5
xpcom/reflect/xptcall/md/test/clean.bat
Normal 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
|
||||
207
xpcom/reflect/xptcall/md/test/invoke_test.cpp
Normal file
207
xpcom/reflect/xptcall/md/test/invoke_test.cpp
Normal 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;
|
||||
}
|
||||
9
xpcom/reflect/xptcall/md/test/mk_invoke.bat
Normal file
9
xpcom/reflect/xptcall/md/test/mk_invoke.bat
Normal 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
|
||||
9
xpcom/reflect/xptcall/md/test/mk_stub.bat
Normal file
9
xpcom/reflect/xptcall/md/test/mk_stub.bat
Normal 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
|
||||
9
xpcom/reflect/xptcall/md/test/moz.build
Normal file
9
xpcom/reflect/xptcall/md/test/moz.build
Normal 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',
|
||||
])
|
||||
213
xpcom/reflect/xptcall/md/test/stub_test.cpp
Normal file
213
xpcom/reflect/xptcall/md/test/stub_test.cpp
Normal 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;
|
||||
}
|
||||
79
xpcom/reflect/xptcall/md/unix/Makefile.in
Normal file
79
xpcom/reflect/xptcall/md/unix/Makefile.in
Normal 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
|
||||
327
xpcom/reflect/xptcall/md/unix/moz.build
Normal file
327
xpcom/reflect/xptcall/md/unix/moz.build
Normal 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
|
||||
66
xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp
Normal file
66
xpcom/reflect/xptcall/md/unix/vtable_layout_x86.cpp
Normal 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);
|
||||
}
|
||||
17
xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h
Normal file
17
xpcom/reflect/xptcall/md/unix/xptc_gcc_x86_unix.h
Normal 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
|
||||
|
||||
140
xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp
Normal file
140
xpcom/reflect/xptcall/md/unix/xptcinvoke_aarch64.cpp
Normal 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);
|
||||
}
|
||||
144
xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp
Normal file
144
xpcom/reflect/xptcall/md/unix/xptcinvoke_alpha_openbsd.cpp
Normal 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"
|
||||
);
|
||||
417
xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp
Normal file
417
xpcom/reflect/xptcall/md/unix/xptcinvoke_arm.cpp
Normal 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
|
||||
181
xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp
Normal file
181
xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp
Normal 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;
|
||||
}
|
||||
183
xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp
Normal file
183
xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_openbsd.cpp
Normal 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;
|
||||
}
|
||||
67
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.s
Normal file
67
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_aarch64.s
Normal 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
|
||||
|
||||
|
||||
145
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s
Normal file
145
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf32.s
Normal 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
|
||||
|
||||
|
||||
146
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s
Normal file
146
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s
Normal 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
|
||||
134
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S
Normal file
134
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips.S
Normal 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)
|
||||
122
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S
Normal file
122
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_mips64.S
Normal 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
|
||||
131
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s
Normal file
131
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_pa32.s
Normal 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
|
||||
|
||||
108
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s
Normal file
108
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_parisc_linux.s
Normal 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
|
||||
|
||||
167
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S
Normal file
167
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc64_linux.S
Normal 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
|
||||
129
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s
Normal file
129
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix.s
Normal 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
|
||||
128
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s
Normal file
128
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_aix64.s
Normal 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
|
||||
124
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
Normal file
124
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
Normal 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
|
||||
98
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S
Normal file
98
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_linux.S
Normal 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
|
||||
95
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_netbsd.s
Normal file
95
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_netbsd.s
Normal 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
|
||||
94
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S
Normal file
94
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_openbsd.S
Normal 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
|
||||
142
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s
Normal file
142
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ppc_rhapsody.s
Normal 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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
55
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s
Normal file
55
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_netbsd.s
Normal 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
|
||||
55
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s
Normal file
55
xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_sparc_openbsd.s
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
16
xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp
Normal file
16
xpcom/reflect/xptcall/md/unix/xptcinvoke_darwin.cpp
Normal 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
|
||||
97
xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp
Normal file
97
xpcom/reflect/xptcall/md/unix/xptcinvoke_gcc_x86_unix.cpp
Normal 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
|
||||
);
|
||||
132
xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp
Normal file
132
xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf32.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
100
xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp
Normal file
100
xpcom/reflect/xptcall/md/unix/xptcinvoke_ipf64.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
144
xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp
Normal file
144
xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp
Normal 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"
|
||||
);
|
||||
130
xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_m68k.cpp
Normal file
130
xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_m68k.cpp
Normal 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;
|
||||
}
|
||||
195
xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp
Normal file
195
xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390.cpp
Normal 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]);
|
||||
}
|
||||
|
||||
190
xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp
Normal file
190
xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_s390x.cpp
Normal 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]);
|
||||
}
|
||||
|
||||
99
xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp
Normal file
99
xpcom/reflect/xptcall/md/unix/xptcinvoke_mips.cpp
Normal 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);
|
||||
}
|
||||
142
xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp
Normal file
142
xpcom/reflect/xptcall/md/unix/xptcinvoke_mips64.cpp
Normal 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*)®s[i] = s->val.f;
|
||||
else
|
||||
*(float*)d++ = s->val.f;
|
||||
break;
|
||||
case nsXPTType::T_DOUBLE:
|
||||
if (i < N_ARG_REGS)
|
||||
*(double*)®s[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);
|
||||
}
|
||||
143
xpcom/reflect/xptcall/md/unix/xptcinvoke_netbsd_m68k.cpp
Normal file
143
xpcom/reflect/xptcall/md/unix/xptcinvoke_netbsd_m68k.cpp
Normal 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;
|
||||
}
|
||||
149
xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp
Normal file
149
xpcom/reflect/xptcall/md/unix/xptcinvoke_pa32.cpp
Normal 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;
|
||||
}
|
||||
|
||||
97
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp
Normal file
97
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc64_linux.cpp
Normal 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);
|
||||
|
||||
74
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp
Normal file
74
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
63
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp
Normal file
63
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_aix64.cpp
Normal 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
|
||||
|
||||
128
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp
Normal file
128
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_linux.cpp
Normal 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);
|
||||
115
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_netbsd.cpp
Normal file
115
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_netbsd.cpp
Normal 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);
|
||||
109
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp
Normal file
109
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_openbsd.cpp
Normal 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);
|
||||
113
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp
Normal file
113
xpcom/reflect/xptcall/md/unix/xptcinvoke_ppc_rhapsody.cpp
Normal 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);
|
||||
}
|
||||
69
xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp
Normal file
69
xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc64_openbsd.cpp
Normal 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;
|
||||
}
|
||||
131
xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp
Normal file
131
xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_netbsd.cpp
Normal 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;
|
||||
}
|
||||
|
||||
128
xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp
Normal file
128
xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_openbsd.cpp
Normal 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;
|
||||
}
|
||||
|
||||
131
xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp
Normal file
131
xpcom/reflect/xptcall/md/unix/xptcinvoke_sparc_solaris.cpp
Normal 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;
|
||||
}
|
||||
|
||||
73
xpcom/reflect/xptcall/md/unix/xptcinvoke_sparcv9_solaris.cpp
Normal file
73
xpcom/reflect/xptcall/md/unix/xptcinvoke_sparcv9_solaris.cpp
Normal 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;
|
||||
}
|
||||
149
xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp
Normal file
149
xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_solaris.cpp
Normal 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;
|
||||
}
|
||||
188
xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp
Normal file
188
xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp
Normal 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
|
||||
67
xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp
Normal file
67
xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_solaris.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
219
xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp
Normal file
219
xpcom/reflect/xptcall/md/unix/xptcstubs_aarch64.cpp
Normal 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"
|
||||
189
xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp
Normal file
189
xpcom/reflect/xptcall/md/unix/xptcstubs_alpha_openbsd.cpp
Normal 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"
|
||||
238
xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp
Normal file
238
xpcom/reflect/xptcall/md/unix/xptcstubs_arm.cpp
Normal 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"
|
||||
113
xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp
Normal file
113
xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp
Normal 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"
|
||||
205
xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp
Normal file
205
xpcom/reflect/xptcall/md/unix/xptcstubs_arm_openbsd.cpp
Normal 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"
|
||||
39
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.s
Normal file
39
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_aarch64.s
Normal 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
|
||||
123
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s
Normal file
123
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf32.s
Normal 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
|
||||
|
||||
|
||||
124
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s
Normal file
124
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ipf64.s
Normal 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
|
||||
116
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S
Normal file
116
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.S
Normal 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)
|
||||
75
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4
Normal file
75
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips.s.m4
Normal 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
|
||||
111
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S
Normal file
111
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_mips64.S
Normal 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)
|
||||
68
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s
Normal file
68
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_pa32.s
Normal 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
|
||||
|
||||
73
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s
Normal file
73
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_parisc_linux.s
Normal 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
|
||||
112
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S
Normal file
112
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc64_linux.S
Normal 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
|
||||
119
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4
Normal file
119
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix.s.m4
Normal 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
|
||||
97
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4
Normal file
97
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_aix64.s.m4
Normal 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
|
||||
114
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4
Normal file
114
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_darwin.s.m4
Normal 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
|
||||
77
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S
Normal file
77
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_linux.S
Normal 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
|
||||
70
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_netbsd.s
Normal file
70
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_netbsd.s
Normal 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
|
||||
|
||||
72
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S
Normal file
72
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_ppc_openbsd.S
Normal 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
|
||||
|
|
@ -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
|
||||
49
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s
Normal file
49
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_netbsd.s
Normal 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
|
||||
49
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s
Normal file
49
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_openbsd.s
Normal 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
|
||||
49
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s
Normal file
49
xpcom/reflect/xptcall/md/unix/xptcstubs_asm_sparc_solaris.s
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
|
|
@ -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"
|
||||
16
xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp
Normal file
16
xpcom/reflect/xptcall/md/unix/xptcstubs_darwin.cpp
Normal 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
|
||||
139
xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp
Normal file
139
xpcom/reflect/xptcall/md/unix/xptcstubs_gcc_x86_unix.cpp
Normal 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()
|
||||
{
|
||||
}
|
||||
151
xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp
Normal file
151
xpcom/reflect/xptcall/md/unix/xptcstubs_ipf32.cpp
Normal 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
Loading…
Add table
Add a link
Reference in a new issue