diff options
Diffstat (limited to 'www/firefox/patches')
9 files changed, 842 insertions, 27 deletions
diff --git a/www/firefox/patches/patch-gfx_ycbcr_yuv__row__arm.s b/www/firefox/patches/patch-gfx_ycbcr_yuv__row__arm.s new file mode 100644 index 00000000000..5215b008a58 --- /dev/null +++ b/www/firefox/patches/patch-gfx_ycbcr_yuv__row__arm.s @@ -0,0 +1,12 @@ +$NetBSD: patch-gfx_ycbcr_yuv__row__arm.s,v 1.1 2014/11/26 14:56:28 ryoon Exp $ + +--- gfx/ycbcr/yuv_row_arm.s.orig 2014-11-13 22:49:57.000000000 +0000 ++++ gfx/ycbcr/yuv_row_arm.s +@@ -299,6 +299,6 @@ s42xbily_neon_done: + .fnend + .size ScaleYCbCr42xToRGB565_BilinearY_Row_NEON, .-ScaleYCbCr42xToRGB565_BilinearY_Row_NEON + +-#if defined(__ELF__)&&defined(__linux__) ++#if defined(__ELF__)&&(defined(__linux__) || defined(__NetBSD__)) + .section .note.GNU-stack,"",%progbits + #endif diff --git a/www/firefox/patches/patch-ipc_chromium_src_base_atomicops.h b/www/firefox/patches/patch-ipc_chromium_src_base_atomicops.h new file mode 100644 index 00000000000..1c0edca930e --- /dev/null +++ b/www/firefox/patches/patch-ipc_chromium_src_base_atomicops.h @@ -0,0 +1,15 @@ +$NetBSD: patch-ipc_chromium_src_base_atomicops.h,v 1.1 2014/11/26 14:56:28 ryoon Exp $ + +* Avoid invalid cast errors under NetBSD/evbearmv7hf-el. + +--- ipc/chromium/src/base/atomicops.h.orig 2014-11-13 22:49:59.000000000 +0000 ++++ ipc/chromium/src/base/atomicops.h +@@ -45,7 +45,7 @@ typedef int64_t Atomic64; + + // Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or + // Atomic64 routines below, depending on your architecture. +-#ifdef OS_OPENBSD ++#if defined(OS_OPENBSD) || (defined(OS_NETBSD) && defined(ARCH_CPU_ARM_FAMILY)) + #ifdef ARCH_CPU_64_BITS + typedef Atomic64 AtomicWord; + #else diff --git a/www/firefox/patches/patch-js_src_assembler_jit_ExecutableAllocator.h b/www/firefox/patches/patch-js_src_assembler_jit_ExecutableAllocator.h new file mode 100644 index 00000000000..4575630c6b4 --- /dev/null +++ b/www/firefox/patches/patch-js_src_assembler_jit_ExecutableAllocator.h @@ -0,0 +1,15 @@ +$NetBSD: patch-js_src_assembler_jit_ExecutableAllocator.h,v 1.1 2014/11/26 14:56:28 ryoon Exp $ + +* Define cacheFlush for NetBSD. + +--- js/src/assembler/jit/ExecutableAllocator.h.orig 2014-11-13 22:50:00.000000000 +0000 ++++ js/src/assembler/jit/ExecutableAllocator.h +@@ -478,7 +478,7 @@ public: + } + #elif WTF_CPU_ARM_TRADITIONAL && WTF_OS_LINUX && WTF_COMPILER_RVCT + static __asm void cacheFlush(void* code, size_t size); +-#elif WTF_CPU_ARM_TRADITIONAL && (WTF_OS_LINUX || WTF_OS_ANDROID) && WTF_COMPILER_GCC ++#elif WTF_CPU_ARM_TRADITIONAL && (WTF_OS_LINUX || WTF_OS_ANDROID || WTF_OS_NETBSD) && WTF_COMPILER_GCC + static void cacheFlush(void* code, size_t size) + { + asm volatile ( diff --git a/www/firefox/patches/patch-js_src_jit_arm_Architecture-arm.cpp b/www/firefox/patches/patch-js_src_jit_arm_Architecture-arm.cpp new file mode 100644 index 00000000000..02583fccc4f --- /dev/null +++ b/www/firefox/patches/patch-js_src_jit_arm_Architecture-arm.cpp @@ -0,0 +1,15 @@ +$NetBSD: patch-js_src_jit_arm_Architecture-arm.cpp,v 1.1 2014/11/26 14:56:28 ryoon Exp $ + +* NetBSD has no asm/hwcap.h (Linux's header file). + +--- js/src/jit/arm/Architecture-arm.cpp.orig 2014-11-13 22:50:01.000000000 +0000 ++++ js/src/jit/arm/Architecture-arm.cpp +@@ -18,7 +18,7 @@ + + #define HWCAP_USE_HARDFP_ABI (1 << 27) + +-#if !(defined(ANDROID) || defined(MOZ_B2G)) && !defined(JS_ARM_SIMULATOR) ++#if !(defined(ANDROID) || defined(MOZ_B2G) || defined(__NetBSD__))) && !defined(JS_ARM_SIMULATOR) + #define HWCAP_ARMv7 (1 << 28) + #include <asm/hwcap.h> + #else diff --git a/www/firefox/patches/patch-media_libtheora_lib_arm_armcpu.c b/www/firefox/patches/patch-media_libtheora_lib_arm_armcpu.c new file mode 100644 index 00000000000..70c7f5088d2 --- /dev/null +++ b/www/firefox/patches/patch-media_libtheora_lib_arm_armcpu.c @@ -0,0 +1,25 @@ +$NetBSD: patch-media_libtheora_lib_arm_armcpu.c,v 1.1 2014/11/26 14:56:28 ryoon Exp $ + +* NetBSD/evbearmv7hf-el's /proc/cpuinfo return empty, use hardcoded flags. + +--- media/libtheora/lib/arm/armcpu.c.orig 2014-11-13 22:50:10.000000000 +0000 ++++ media/libtheora/lib/arm/armcpu.c +@@ -107,6 +107,18 @@ ogg_uint32_t oc_cpu_flags_get(void){ + return flags; + } + ++#elif defined(__NetBSD__) ++ogg_uint32_t oc_cpu_flags_get(void){ ++ ogg_uint32_t flags; ++ /* XXX ryoon: I have no idea about ARM CPU extensions detection mechanism ++ under NetBSD/earm. ++ evbearmv6hf-el machine, Raspberry Pi does not have NEON. ++ evbearmv7hf-el machine, CubieBoard2 does not have EDSP. ++ I have no idea about MEDIA. ++ So I will disable all options. */ ++ flags=0; ++ return flags; ++} + #else + /*The feature registers which can tell us what the processor supports are + accessible in priveleged modes only, so we can't have a general user-space diff --git a/www/firefox/patches/patch-media_libyuv_include_libyuv_scale__row.h b/www/firefox/patches/patch-media_libyuv_include_libyuv_scale__row.h new file mode 100644 index 00000000000..23053964279 --- /dev/null +++ b/www/firefox/patches/patch-media_libyuv_include_libyuv_scale__row.h @@ -0,0 +1,17 @@ +$NetBSD: patch-media_libyuv_include_libyuv_scale__row.h,v 1.1 2014/11/26 14:56:28 ryoon Exp $ + +--- media/libyuv/include/libyuv/scale_row.h.orig 2014-11-13 22:50:11.000000000 +0000 ++++ media/libyuv/include/libyuv/scale_row.h +@@ -219,10 +219,10 @@ void ScaleARGBFilterCols_SSSE3(uint8* ds + void ScaleARGBColsUp2_SSE2(uint8* dst_argb, const uint8* src_argb, + int dst_width, int x, int dx); + // Row functions. +-void ScaleARGBRowDownEven_NEON(const uint8* src_argb, int src_stride, ++void ScaleARGBRowDownEven_NEON(const uint8* src_argb, ptrdiff_t src_stride, + int src_stepx, + uint8* dst_argb, int dst_width); +-void ScaleARGBRowDownEvenBox_NEON(const uint8* src_argb, int src_stride, ++void ScaleARGBRowDownEvenBox_NEON(const uint8* src_argb, ptrdiff_t src_stride, + int src_stepx, + uint8* dst_argb, int dst_width); + void ScaleARGBRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, diff --git a/www/firefox/patches/patch-mfbt_Poison.cpp b/www/firefox/patches/patch-mfbt_Poison.cpp index e880dd530ee..ae4a2f8d282 100644 --- a/www/firefox/patches/patch-mfbt_Poison.cpp +++ b/www/firefox/patches/patch-mfbt_Poison.cpp @@ -1,18 +1,17 @@ -$NetBSD: patch-mfbt_Poison.cpp,v 1.5 2014/10/15 13:07:07 ryoon Exp $ +$NetBSD: patch-mfbt_Poison.cpp,v 1.6 2014/11/26 14:56:28 ryoon Exp $ * Use posix_madvise(3) instead of madvise(3) for Solaris/SunOS. Solaris/SunOS's madvise(3) is not enabled in this context, and its first argument type is different from NetBSD/Linux's one. ---- mfbt/Poison.cpp.orig 2014-10-11 09:06:41.000000000 +0000 +--- mfbt/Poison.cpp.orig 2014-11-13 22:50:12.000000000 +0000 +++ mfbt/Poison.cpp @@ -129,7 +129,11 @@ ReleaseRegion(void* aRegion, uintptr_t a static bool ProbeRegion(uintptr_t aRegion, uintptr_t aSize) { -- if (madvise(reinterpret_cast<void*>(aRegion), aSize, MADV_NORMAL)) { +#if !defined(__sun__) -+ if (madvise(reinterpret_cast<void*>(aRegion), aSize, MADV_NORMAL)) { + if (madvise(reinterpret_cast<void*>(aRegion), aSize, MADV_NORMAL)) { +#else + if (posix_madvise(reinterpret_cast<void*>(aRegion), aSize, MADV_NORMAL)) { +#endif diff --git a/www/firefox/patches/patch-xpcom_reflect_xptcall_md_unix_xptcinvoke__arm__netbsd.cpp b/www/firefox/patches/patch-xpcom_reflect_xptcall_md_unix_xptcinvoke__arm__netbsd.cpp new file mode 100644 index 00000000000..19792af3e0f --- /dev/null +++ b/www/firefox/patches/patch-xpcom_reflect_xptcall_md_unix_xptcinvoke__arm__netbsd.cpp @@ -0,0 +1,527 @@ +$NetBSD: patch-xpcom_reflect_xptcall_md_unix_xptcinvoke__arm__netbsd.cpp,v 1.1 2014/11/26 14:56:28 ryoon Exp $ + +--- xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp.orig 2014-11-13 22:50:21.000000000 +0000 ++++ xpcom/reflect/xptcall/md/unix/xptcinvoke_arm_netbsd.cpp +@@ -7,82 +7,92 @@ + + #include "xptcprivate.h" + +-// Remember that these 'words' are 32bit DWORDS ++#include "mozilla/Compiler.h" + +-static uint32_t +-invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) ++#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) + { +- 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; +- } ++#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; + } +- return result; ++#endif ++ ++ *((uint64_t*) current) = *dw; ++ return current + 1; + } + +-static void +-invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) ++/* 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 : *((int8_t*) d) = s->val.i8; break; +- case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break; ++ 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 : *((uint8_t*) d) = s->val.u8; break; +- case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; 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 : *((uint64_t*)d) = s->val.u64; d++; 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 : *((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; ++ 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; +@@ -91,47 +101,27 @@ invoke_copy_to_stack(uint32_t* d, uint32 + } + } + +-extern "C" +-struct my_params_struct { +- nsISupports* that; +- uint32_t Index; +- uint32_t Count; +- nsXPTCVariant* params; +- uint32_t fn_count; +- uint32_t fn_copy; +-}; ++typedef nsresult (*vtable_func)(nsISupports *, uint32_t, uint32_t, uint32_t); + +-XPTC_PUBLIC_API(nsresult) +-XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, ++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]). ++ * 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 +@@ -139,43 +129,272 @@ XPTC_InvokeByIndex(nsISupports* that, ui + * + */ + +- __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; ++ 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 { ++ 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 diff --git a/www/firefox/patches/patch-xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp b/www/firefox/patches/patch-xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp index 3fc12a432e6..039583f8d5e 100644 --- a/www/firefox/patches/patch-xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp +++ b/www/firefox/patches/patch-xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp @@ -1,31 +1,221 @@ -$NetBSD: patch-xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp,v 1.1 2014/10/15 13:43:32 ryoon Exp $ +$NetBSD: patch-xpcom_reflect_xptcall_md_unix_xptcstubs__arm__netbsd.cpp,v 1.2 2014/11/26 14:56:28 ryoon Exp $ ---- xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp.orig 2014-10-11 09:06:50.000000000 +0000 +--- xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp.orig 2014-11-13 22:50:21.000000000 +0000 +++ xpcom/reflect/xptcall/md/unix/xptcstubs_arm_netbsd.cpp -@@ -86,18 +86,23 @@ PrepareAndDispatch(nsXPTCStubBase* self, - * so they are contiguous with values passed on the stack, and then calls - * PrepareAndDispatch() to do the dirty work. - */ -+#ifndef __ELF__ -+#define SYMBOLPREFIX "_" +@@ -6,15 +6,32 @@ + /* Implement shared vtbl methods. */ + + #include "xptcprivate.h" ++#include "xptiprivate.h" + +-nsresult ATTRIBUTE_USED ++/* 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 and does not support .cfi directives. ++#ifdef __APPLE__ ++#define CFI(str) +#else -+#define SYMBOLPREFIX ++#define CFI(str) str +#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; +- nsIInterfaceInfo* iface_info = nullptr; + const nsXPTMethodInfo* info; + uint8_t paramCount; + uint8_t i; +@@ -22,12 +39,7 @@ PrepareAndDispatch(nsXPTCStubBase* self, + + 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"); +- ++ self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info); + paramCount = info->GetParamCount(); - #define STUB_ENTRY(n) \ - __asm__( \ + // setup variant array pointer +@@ -55,13 +67,16 @@ PrepareAndDispatch(nsXPTCStubBase* self, + 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_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 : dp->val.u64 = *((uint64_t*)ap); 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 : dp->val.d = *((double*) ap); 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; +@@ -71,9 +86,7 @@ PrepareAndDispatch(nsXPTCStubBase* self, + } + } + +- result = self->CallMethod((uint16_t)methodIndex, info, dispatchParams); +- +- NS_RELEASE(iface_info); ++ result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams); + + if(dispatchParams != paramBuffer) + delete [] dispatchParams; +@@ -82,26 +95,118 @@ PrepareAndDispatch(nsXPTCStubBase* self, + } + + /* +- * 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. ++ * 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" ++ ".fnstart\n" ++ CFI(".cfi_startproc\n") ++ "stmfd sp!, {r1, r2, r3}\n" ++ ".save {r1, r2, r3}\n" ++ CFI(".cfi_def_cfa_offset 12\n") ++ CFI(".cfi_offset r3, -4\n") ++ CFI(".cfi_offset r2, -8\n") ++ CFI(".cfi_offset r1, -12\n") ++ "mov r2, sp\n" ++ "str lr, [sp, #-4]!\n" ++ ".save {lr}\n" ++ CFI(".cfi_def_cfa_offset 16\n") ++ CFI(".cfi_offset lr, -16\n") ++ "mov r1, ip\n" ++ "bl _PrepareAndDispatch\n" ++ "ldr pc, [sp], #16\n" ++ CFI(".cfi_endproc\n") ++ ".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__( \ ++ ".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 STUB_ENTRY(n) \ +-__asm__( \ - ".global _Stub"#n"__14nsXPTCStubBase\n\t" \ -"_Stub"#n"__14nsXPTCStubBase:\n\t" \ -+ ".global "SYMBOLPREFIX"Stub"#n"__14nsXPTCStubBase\n\t" \ -+SYMBOLPREFIX"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" \ +- "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" \ -+ "bl "SYMBOLPREFIX"PrepareAndDispatch__FP14nsXPTCStubBaseUiPUi \n\t" \ - "ldmea fp, {fp, sp, lr} \n\t" \ - "add sp, sp, #12 \n\t" \ - "mov pc, lr \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() \ |