зеркало из https://github.com/mozilla/pjs.git
Changes for SH4 and ARM processors. These were made by Roger Maclean, reviewed by me. r=rmaclean@qnx.com This change is for the QNX (Photon) platform only. It will not affect the runtime or build of other Mozilla platforms since QNX source is not part of Tinderbox builds. None of the changes will affect non-QNX builds in any way. You can contact me at: mfeil@qnx.com
This commit is contained in:
Родитель
d7a6337c05
Коммит
4e83ba0266
|
@ -108,4 +108,4 @@ CXXFLAGS += -DPHOTON_DND
|
|||
endif
|
||||
|
||||
export::
|
||||
$(INSTALL) nsClipboard.h $(DIST)/include/widget
|
||||
$(INSTALL) $(srcdir)/nsClipboard.h $(DIST)/include/widget
|
||||
|
|
|
@ -102,9 +102,19 @@ endif
|
|||
#
|
||||
# Neutrino/Intel (uses the same unixish_x86 code)
|
||||
#
|
||||
ifeq ($(OS_TARGET)$(OS_TEST),NTOx86)
|
||||
ifeq ($(OS_TARGET),NTO)
|
||||
ifeq ($(OS_TEST),x86)
|
||||
CPPSRCS := xptcinvoke_unixish_x86.cpp xptcstubs_unixish_x86.cpp
|
||||
endif
|
||||
ifeq ($(OS_TEST),arm)
|
||||
CPPSRCS := xptcinvoke_arm.cpp xptcstubs_arm.cpp
|
||||
endif
|
||||
ifeq ($(OS_TEST),sh)
|
||||
CPPSRCS := xptcinvoke_nto_shle.cpp xptcstubs_nto_shle.cpp
|
||||
ASFILES := xptcstubs_asm_shle.s
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
######################################################################
|
||||
# Solaris/Intel
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
#include "xptcprivate.h"
|
||||
|
||||
#if !defined(LINUX) || !defined(__arm__)
|
||||
#if !defined(__arm__)
|
||||
#error "This code is for Linux ARM only. Check that it works on your system, too.\nBeware that this code is highly compiler dependent."
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
#include "xptcprivate.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
const int c_int_register_params = 3;
|
||||
const int c_float_register_params = 8;
|
||||
|
||||
static void
|
||||
copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, int size, PRUint32* data)
|
||||
{
|
||||
int intCount = 0;
|
||||
int floatCount = 0;
|
||||
PRUint32 *intRegParams = data + (size / sizeof(PRUint32)) - c_int_register_params;
|
||||
float *floatRegParams = (float *)intRegParams - c_float_register_params;
|
||||
|
||||
for ( PRUint32 i = 0; i < paramCount; ++i, ++s )
|
||||
{
|
||||
nsXPTType type = s->IsPtrData() ? nsXPTType::T_I32 : s->type;
|
||||
|
||||
switch ( type ) {
|
||||
case nsXPTType::T_I64:
|
||||
case nsXPTType::T_U64:
|
||||
// Space to pass in registers?
|
||||
if ( (c_int_register_params - intCount) >= 2 ) {
|
||||
*((PRInt64 *) intRegParams) = s->val.i64;
|
||||
intRegParams += 2;
|
||||
intCount += 2;
|
||||
}
|
||||
else {
|
||||
*((PRInt64*) data) = s->val.i64;
|
||||
data += 2;
|
||||
}
|
||||
break;
|
||||
case nsXPTType::T_FLOAT:
|
||||
// Space to pass in registers?
|
||||
if ( floatCount < c_float_register_params ) {
|
||||
*floatRegParams = s->val.f;
|
||||
++floatCount;
|
||||
++floatRegParams;
|
||||
}
|
||||
else {
|
||||
*((float*) data) = s->val.f;
|
||||
++data;
|
||||
}
|
||||
break;
|
||||
case nsXPTType::T_DOUBLE:
|
||||
// Space to pass in registers?
|
||||
if ( (c_float_register_params - floatCount) >= 2 ) {
|
||||
if ( (floatCount & 1) != 0 ) {
|
||||
++floatCount;
|
||||
++floatRegParams;
|
||||
}
|
||||
*(double *)floatRegParams = s->val.d;
|
||||
floatCount += 2;
|
||||
floatRegParams += 2;
|
||||
}
|
||||
else {
|
||||
*((double *) data) = s->val.d;
|
||||
data += 2;
|
||||
}
|
||||
break;
|
||||
default: // 32 (non-float) value
|
||||
PRInt32 value = (PRInt32) (s->IsPtrData() ? s->ptr : s->val.p);
|
||||
// Space to pass in registers?
|
||||
if ( intCount < c_int_register_params ) {
|
||||
*intRegParams = value;
|
||||
++intRegParams;
|
||||
++intCount;
|
||||
}
|
||||
else {
|
||||
*data = value;
|
||||
++data;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XPTC_PUBLIC_API(nsresult)
|
||||
XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
|
||||
PRUint32 paramCount, nsXPTCVariant* params)
|
||||
{
|
||||
#ifdef __GNUC__ /* Gnu compiler. */
|
||||
int result;
|
||||
void (*fn_copy) (PRUint32 paramCount, nsXPTCVariant* s, int size, PRUint32* d) = copy_to_stack;
|
||||
|
||||
/* Because the SH processor passes the first few parameters in registers
|
||||
it is a bit tricky setting things up right. To make things easier,
|
||||
all the hard work will be done by copy_to_stack above. We pass to it
|
||||
a chunk of memory, the top of which will be copied to registers r5 to r7
|
||||
and fr4 to fr11 before calling the target function.
|
||||
*/
|
||||
|
||||
__asm__ __volatile__(
|
||||
/* Make space for parameters to be passed to the method. Assume worst case
|
||||
8 bytes per parameter. Also leave space for 3 longs and 8 floats that
|
||||
will be put into registers. The worst case is all int64 parameters
|
||||
and even in this case 8 bytes are passed in registers so we can
|
||||
deduct this from our allocation.
|
||||
*/
|
||||
"mov.l @(8,r14), r4 \n\t" // copy_to_stack paramCount parameter
|
||||
"mov r4, r6 \n\t"
|
||||
"mov #3, r1 \n\t"
|
||||
"shld r1, r6 \n\t"
|
||||
"add #36, r6 \n\t" // Space for 3 longs, 8 floats - 8 bytes
|
||||
"sub r6, r15 \n\t"
|
||||
"mov r15, r7 \n\t"
|
||||
"mov.l @(20,r14), r1 \n\t" // fn_copy
|
||||
"jsr @r1 \n\t" // Note, next instruction is executed first
|
||||
"mov.l @(12,r14), r5 \n\t" // copy_to_stack data parameter
|
||||
|
||||
/* Now everything is laid out nicely in the stack. We just have to
|
||||
load values at the top end of the memory area into registers and
|
||||
make the call. We may load more things into registers than needed,
|
||||
but nobody will care about that.
|
||||
*/
|
||||
"mov r14, r1 \n\t"
|
||||
"add #-44, r1 \n\t"
|
||||
"fmov.s @r1+, fr5 \n\t"
|
||||
"fmov.s @r1+, fr4 \n\t"
|
||||
"fmov.s @r1+, fr7 \n\t"
|
||||
"fmov.s @r1+, fr6 \n\t"
|
||||
"fmov.s @r1+, fr9 \n\t"
|
||||
"fmov.s @r1+, fr8 \n\t"
|
||||
"fmov.s @r1+, fr11 \n\t"
|
||||
"fmov.s @r1+, fr10 \n\t"
|
||||
"mov.l @r1+, r5 \n\t"
|
||||
"mov.l @r1+, r6 \n\t"
|
||||
"mov.l @r1+, r7 \n\t"
|
||||
"mov.l @r14, r1 \n\t" // that -> r1
|
||||
"mov.l @r1, r1 \n\t" // vtbl -> r1
|
||||
"mov.l @(4,r14), r4 \n\t" // methodIndex -> r4
|
||||
"shll2 r4 \n\t"
|
||||
"add r4, r1 \n\t"
|
||||
"mov.l @r1, r1 \n\t" // method addr -> r1
|
||||
"jsr @r1 \n\t"
|
||||
"mov.l @r14, r4 \n\t" // that -> r4 (note, executed before jsr)
|
||||
"mov.l r0, @(16,r14) \n\r" // Save return value in result
|
||||
: : : "r1", "r4", "r6", "r7", "pr", "dr4", "dr6", "dr8"
|
||||
);
|
||||
|
||||
return result;
|
||||
|
||||
#else
|
||||
#error "can't find a compiler to use"
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -41,7 +41,7 @@
|
|||
#include "xptcprivate.h"
|
||||
#include "xptiprivate.h"
|
||||
|
||||
#if !defined(LINUX) || !defined(__arm__)
|
||||
#if !defined(__arm__)
|
||||
#error "This code is for Linux ARM only. Please check if it works for you, too.\nDepends strongly on gcc behaviour."
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bin/python
|
||||
# Script for generating the assembler code requried for virtual function
|
||||
# stubs for SuperH processor in little-endian mode (perhaps it works big-endian
|
||||
# too, I haven't checked).
|
||||
|
||||
f = open("xptcstubs_asm_shle.s", 'w')
|
||||
|
||||
prefix = "_ZN14nsXPTCStubBase"
|
||||
minStub = 3
|
||||
maxStub = 250
|
||||
|
||||
# Frequency with which we store the address of the function to branch to
|
||||
# If too high, we'll get errors from the assembler.
|
||||
jumpRepeat = 20
|
||||
jumpCount = 0
|
||||
labelIndex = 2
|
||||
|
||||
f.write("""
|
||||
/* Automatically generated by xptcstubs_asm_shle.py */
|
||||
.text
|
||||
.little
|
||||
.section .rodata
|
||||
|
||||
.globl SharedStub
|
||||
.type SharedStub, @function
|
||||
SharedStub:
|
||||
mov r15, r1
|
||||
mov.l r14,@-r15
|
||||
sts.l pr,@-r15
|
||||
mov r15, r14
|
||||
|
||||
/* Some parameters might have been passed in registers, so push them
|
||||
* all onto the stack, PrepareAndDispatch can then work out whats what
|
||||
* given method type information.
|
||||
*/
|
||||
mov.l r7, @-r15
|
||||
mov.l r6, @-r15
|
||||
mov.l r5, @-r15
|
||||
mov r15, r7 /* r7 = PrepareAndDispatch intRegParams param */
|
||||
|
||||
fmov.s fr10, @-r15
|
||||
fmov.s fr11, @-r15
|
||||
fmov.s fr8, @-r15
|
||||
fmov.s fr9, @-r15
|
||||
fmov.s fr6, @-r15
|
||||
fmov.s fr7, @-r15
|
||||
fmov.s fr4, @-r15
|
||||
fmov.s fr5, @-r15
|
||||
mov.l r15, @-r15 /* PrepareAndDispatch floatRegParams param */
|
||||
|
||||
mov r1, r6 /* r6 = PrepareAndDispatch data param */
|
||||
|
||||
mov.l .L1, r1
|
||||
jsr @r1 /* Note, following instruction is executed first*/
|
||||
mov r2, r5 /* r5 = PrepareAndDispatch methodIndex param */
|
||||
|
||||
mov r14,r15
|
||||
lds.l @r15+,pr
|
||||
mov.l @r15+,r14
|
||||
rts
|
||||
nop
|
||||
.align 2
|
||||
.L1:
|
||||
.long PrepareAndDispatch
|
||||
|
||||
/* Stubs. Each stub simply saves the method number in r1 and jumps
|
||||
* to SharedStub which does all the processing common to all stubs.
|
||||
*/
|
||||
""")
|
||||
|
||||
for i in range(minStub,maxStub):
|
||||
jumpCount = jumpCount + 1
|
||||
if jumpCount == jumpRepeat:
|
||||
f.write( '\t.align 2\n')
|
||||
f.write( '.L' + str(labelIndex) + ':\n')
|
||||
f.write( '\t.long\tSharedStub\n\n')
|
||||
jumpCount = 0
|
||||
labelIndex = labelIndex + 1
|
||||
funcName = 'Stub' + str(i)
|
||||
name = prefix + str(len(funcName)) + funcName + 'Ev'
|
||||
f.write( '\t.globl ' + name + '\n')
|
||||
f.write( '\t.type ' + name + ' @function\n')
|
||||
f.write( '\t.align 1\n')
|
||||
f.write( name + ':\n')
|
||||
f.write( '\tmov.l\t.L' + str(labelIndex) + ', r1\n')
|
||||
f.write( '\tjmp\t@r1\n')
|
||||
f.write( '\tmov\t#' + str(i) + ', r2 /* Executed before jmp */\n\n')
|
||||
|
||||
f.write( '\t.align 2\n')
|
||||
f.write( '.L' + str(labelIndex) + ':\n')
|
||||
f.write( '\t.long\tSharedStub\n')
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,140 @@
|
|||
#include "xptcprivate.h"
|
||||
|
||||
const int c_int_register_params = 3;
|
||||
const int c_float_register_params = 8;
|
||||
|
||||
/*
|
||||
Dispatch function for all stubs.
|
||||
|
||||
The parameters to the original function are spread between 'data' which
|
||||
is value of the stack pointer when the stub was called, intRegParams which
|
||||
points to an area containing the values of r5, r6 and r7 when the stub was
|
||||
called and floatRegParams which points to an area containing the values
|
||||
of float registers fr4 to fr11 when the stub was called.
|
||||
|
||||
*/
|
||||
extern "C" nsresult
|
||||
PrepareAndDispatch(nsXPTCStubBase* self, int methodIndex, PRUint32* data,
|
||||
PRUint32 *intRegParams, float *floatRegParams)
|
||||
{
|
||||
#define PARAM_BUFFER_COUNT 16
|
||||
|
||||
nsresult result = NS_ERROR_FAILURE;
|
||||
int intCount = 0;
|
||||
int floatCount = 0;
|
||||
nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
|
||||
nsXPTCMiniVariant* dispatchParams = NULL;
|
||||
nsIInterfaceInfo* iface_info = NULL;
|
||||
const nsXPTMethodInfo* info;
|
||||
PRUint8 paramCount;
|
||||
PRUint8 i;
|
||||
|
||||
NS_ASSERTION(self,"no self");
|
||||
|
||||
self->GetInterfaceInfo(&iface_info);
|
||||
NS_ASSERTION(iface_info,"no interface info");
|
||||
|
||||
iface_info->GetMethodInfo(PRUint16(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");
|
||||
|
||||
for ( i = 0; i < paramCount; ++i ) {
|
||||
const nsXPTParamInfo& param = info->GetParam(i);
|
||||
nsXPTCMiniVariant* dp = &dispatchParams[i];
|
||||
nsXPTType type = param.IsOut() ? nsXPTType::T_I32 : param.GetType();
|
||||
|
||||
switch ( type ) {
|
||||
case nsXPTType::T_I64:
|
||||
case nsXPTType::T_U64:
|
||||
// Was this passed in a register?
|
||||
if ( (c_int_register_params - intCount) >= 2 ) {
|
||||
dp->val.i64 = *((PRInt64 *) intRegParams);
|
||||
intRegParams += 2;
|
||||
intCount += 2;
|
||||
}
|
||||
else {
|
||||
dp->val.i64 = *((PRInt64*) data);
|
||||
data += 2;
|
||||
}
|
||||
break;
|
||||
case nsXPTType::T_FLOAT:
|
||||
// Was this passed in a register?
|
||||
if ( floatCount < c_float_register_params ) {
|
||||
dp->val.f = *floatRegParams;
|
||||
++floatCount;
|
||||
++floatRegParams;
|
||||
}
|
||||
else {
|
||||
dp->val.f = *((float*) data);
|
||||
++data;
|
||||
}
|
||||
break;
|
||||
case nsXPTType::T_DOUBLE:
|
||||
// Was this passed in a register?
|
||||
if ( (c_float_register_params - floatCount) >= 2 ) {
|
||||
if ( floatCount & 1 != 0 ) {
|
||||
++floatCount;
|
||||
++floatRegParams;
|
||||
}
|
||||
dp->val.d = *(double *)floatRegParams;
|
||||
floatCount += 2;
|
||||
floatRegParams += 2;
|
||||
}
|
||||
else {
|
||||
dp->val.d = *((double *) data);
|
||||
data += 2;
|
||||
}
|
||||
break;
|
||||
default: // 32-bit (non-float) value
|
||||
// Was this passed in a register?
|
||||
if ( intCount < c_int_register_params ) {
|
||||
dp->val.i32 = *intRegParams;
|
||||
++intRegParams;
|
||||
++intCount;
|
||||
}
|
||||
else {
|
||||
dp->val.i32 = *data;
|
||||
++data;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
|
||||
|
||||
NS_RELEASE(iface_info);
|
||||
|
||||
if(dispatchParams != paramBuffer)
|
||||
delete [] dispatchParams;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__ /* Gnu Compiler. */
|
||||
|
||||
/* Stubs are defined in xptcstubs_asm_shle.s, so just define STUB_ENTRY(n) as
|
||||
nothing. Defining the stubs as assembler here unnecessarily painful and
|
||||
larger than necessary since gcc won't give use naked functions.
|
||||
*/
|
||||
#define STUB_ENTRY(n)
|
||||
|
||||
#define SENTINEL_ENTRY(n) \
|
||||
nsresult nsXPTCStubBase::Sentinel##n() \
|
||||
{ \
|
||||
NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
|
||||
return NS_ERROR_NOT_IMPLEMENTED; \
|
||||
}
|
||||
|
||||
#else
|
||||
#error "can't find a compiler to use"
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#include "xptcstubsdef.inc"
|
Загрузка…
Ссылка в новой задаче