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:
maxf@magma.ca 2007-11-01 14:07:01 -07:00
parent 50c94f8f78
commit de4d9d267a
8 changed files with 2473 additions and 4 deletions

View File

@ -108,4 +108,4 @@ CXXFLAGS += -DPHOTON_DND
endif
export::
$(INSTALL) nsClipboard.h $(DIST)/include/widget
$(INSTALL) $(srcdir)/nsClipboard.h $(DIST)/include/widget

View File

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

View File

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

View File

@ -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__ */
}
}

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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