diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp index beb5deac344..169115145fa 100644 --- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp +++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp @@ -60,8 +60,65 @@ // Remember that these 'words' are 32bit DWORDS +static PRUint32 +invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s) +{ + PRUint32 result = 0; + for(PRUint32 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+=VAR_STACK_SIZE_64; + break; + case nsXPTType::T_U8 : + case nsXPTType::T_U16 : + case nsXPTType::T_U32 : + result++; + break; + case nsXPTType::T_U64 : + result+=VAR_STACK_SIZE_64; + break; + case nsXPTType::T_FLOAT : + result++; + break; + case nsXPTType::T_DOUBLE : + result+=VAR_STACK_SIZE_64; + 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; + } + } -static PRUint32* +#ifdef __ARM_EABI__ + /* Ensure stack is always aligned to doubleword boundary; we take 3 words + * off the stack to r1-r3 later, so it must always be on _odd_ word + * boundary after this */ + if (result % 2 == 0) + result++; +#endif + + return result; +} + +static void invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s) { for(PRUint32 i = 0; i < paramCount; i++, d++, s++) @@ -98,7 +155,6 @@ invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s) break; } } - return d; } extern "C" { @@ -107,6 +163,7 @@ extern "C" { PRUint32 Index; PRUint32 Count; nsXPTCVariant* params; + PRUint32 fn_count; PRUint32 fn_copy; }; } @@ -122,6 +179,7 @@ NS_InvokeByIndex(nsISupports* that, PRUint32 methodIndex, my_params.Count = paramCount; my_params.params = params; my_params.fn_copy = (PRUint32) &invoke_copy_to_stack; + my_params.fn_count = (PRUint32) &invoke_count_words; /* This is to call a given method of class that. * The parameters are in params, the number is in paramCount. @@ -149,20 +207,22 @@ NS_InvokeByIndex(nsISupports* that, PRUint32 methodIndex, */ __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 r4, r0, lsl #3 \n\t" /* This is the amount of bytes needed. */ -#ifdef __ARM_EABI__ - "add r4, r4, #4 \n\t" -#endif + "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... */ - "add r0, %1, #8 \n\t" - "ldmia r0, {r1, r2, ip} \n\t" "mov r0, sp \n\t" /* prepare a pointer an the stack */ - "blx ip \n\t" - "sub r4, r0, sp \n\t" - - "ldmia %1, {r0, r2} \n\t" + "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) */ #if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */ "ldr ip, [r1, r2] \n\t" /* get method adress from vtable */ @@ -177,7 +237,8 @@ NS_InvokeByIndex(nsISupports* that, PRUint32 methodIndex, "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) */ - "blx ip \n\t" + "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)