Description: Fix build for sh4
Author: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>,
        Michael Karcher <debian@mkarcher.dialup.fu-berlin.de>
Last-Update: 2017-01-02

Index: firefox-50.1.0/build/moz.configure/init.configure
===================================================================
--- firefox-50.1.0.orig/build/moz.configure/init.configure
+++ firefox-50.1.0/build/moz.configure/init.configure
@@ -412,6 +412,9 @@ def split_triplet(triplet):
     elif cpu.startswith('aarch64'):
         canonical_cpu = 'aarch64'
         endianness = 'little'
+    elif cpu in ('sh4'):
+        canonical_cpu = 'sh4'
+        endianness = 'little'
     else:
         die('Unknown CPU type: %s' % cpu)
 
Index: firefox-50.1.0/ipc/chromium/src/build/build_config.h
===================================================================
--- firefox-50.1.0.orig/ipc/chromium/src/build/build_config.h
+++ firefox-50.1.0/ipc/chromium/src/build/build_config.h
@@ -107,6 +107,9 @@
 #elif defined(__s390__)
 #define ARCH_CPU_S390 1
 #define ARCH_CPU_32_BITS 1
+#elif defined(__sh__)
+#define ARCH_CPU_SH 1
+#define ARCH_CPU_32_BITS 1
 #elif defined(__alpha__)
 #define ARCH_CPU_ALPHA 1
 #define ARCH_CPU_64_BITS 1
Index: firefox-50.1.0/js/src/jit/AtomicOperations.h
===================================================================
--- firefox-50.1.0.orig/js/src/jit/AtomicOperations.h
+++ firefox-50.1.0/js/src/jit/AtomicOperations.h
@@ -328,6 +328,8 @@ AtomicOperations::isLockfree(int32_t siz
 # include "jit/mips-shared/AtomicOperations-mips-shared.h"
 #elif defined(__ppc__) || defined(__PPC__)
 # include "jit/none/AtomicOperations-ppc.h"
+#elif defined(__sh__)
+# include "jit/none/AtomicOperations-ppc.h"
 #elif defined(__sparc__)
 # include "jit/none/AtomicOperations-sparc.h"
 #elif defined(JS_CODEGEN_NONE)
Index: firefox-50.1.0/js/src/jit/BaselineCacheIR.cpp
===================================================================
--- firefox-50.1.0.orig/js/src/jit/BaselineCacheIR.cpp
+++ firefox-50.1.0/js/src/jit/BaselineCacheIR.cpp
@@ -824,7 +824,7 @@ BaselineCacheIRCompiler::emitLoadFixedSl
     AutoScratchRegister scratch(allocator, masm);
 
     masm.load32(stubAddress(reader.stubOffset()), scratch);
-    masm.loadValue(BaseIndex(obj, scratch, TimesOne), R0);
+    masm.loadValue(BaseIndex(obj, scratch, TimesOne), js::jit::R0);
     emitEnterTypeMonitorIC();
     return true;
 }
@@ -838,7 +838,7 @@ BaselineCacheIRCompiler::emitLoadDynamic
     // We're about to return, so it's safe to clobber obj now.
     masm.load32(stubAddress(reader.stubOffset()), scratch);
     masm.loadPtr(Address(obj, NativeObject::offsetOfSlots()), obj);
-    masm.loadValue(BaseIndex(obj, scratch, TimesOne), R0);
+    masm.loadValue(BaseIndex(obj, scratch, TimesOne), js::jit::R0);
     emitEnterTypeMonitorIC();
     return true;
 }
@@ -853,7 +853,7 @@ BaselineCacheIRCompiler::emitLoadUnboxed
 
     Address fieldOffset(stubAddress(reader.stubOffset()));
     masm.load32(fieldOffset, scratch);
-    masm.loadUnboxedProperty(BaseIndex(obj, scratch, TimesOne), fieldType, R0);
+    masm.loadUnboxedProperty(BaseIndex(obj, scratch, TimesOne), fieldType, js::jit::R0);
 
     if (fieldType == JSVAL_TYPE_OBJECT)
         emitEnterTypeMonitorIC();
@@ -898,7 +898,7 @@ BaselineCacheIRCompiler::emitLoadTypedOb
         Scalar::Type type = ScalarTypeFromSimpleTypeDescrKey(typeDescr);
         monitorLoad = type == Scalar::Uint32;
 
-        masm.loadFromTypedArray(type, Address(scratch1, 0), R0, /* allowDouble = */ true,
+        masm.loadFromTypedArray(type, Address(scratch1, 0), js::jit::R0, /* allowDouble = */ true,
                                 scratch2, nullptr);
     } else {
         ReferenceTypeDescr::Type type = ReferenceTypeFromSimpleTypeDescrKey(typeDescr);
@@ -906,24 +906,24 @@ BaselineCacheIRCompiler::emitLoadTypedOb
 
         switch (type) {
           case ReferenceTypeDescr::TYPE_ANY:
-            masm.loadValue(Address(scratch1, 0), R0);
+            masm.loadValue(Address(scratch1, 0), js::jit::R0);
             break;
 
           case ReferenceTypeDescr::TYPE_OBJECT: {
             Label notNull, done;
             masm.loadPtr(Address(scratch1, 0), scratch1);
             masm.branchTestPtr(Assembler::NonZero, scratch1, scratch1, &notNull);
-            masm.moveValue(NullValue(), R0);
+            masm.moveValue(NullValue(), js::jit::R0);
             masm.jump(&done);
             masm.bind(&notNull);
-            masm.tagValue(JSVAL_TYPE_OBJECT, scratch1, R0);
+            masm.tagValue(JSVAL_TYPE_OBJECT, scratch1, js::jit::R0);
             masm.bind(&done);
             break;
           }
 
           case ReferenceTypeDescr::TYPE_STRING:
             masm.loadPtr(Address(scratch1, 0), scratch1);
-            masm.tagValue(JSVAL_TYPE_STRING, scratch1, R0);
+            masm.tagValue(JSVAL_TYPE_STRING, scratch1, js::jit::R0);
             break;
 
           default:
@@ -941,7 +941,7 @@ BaselineCacheIRCompiler::emitLoadTypedOb
 bool
 BaselineCacheIRCompiler::emitLoadUndefinedResult()
 {
-    masm.moveValue(UndefinedValue(), R0);
+    masm.moveValue(UndefinedValue(), js::jit::R0);
 
     // Normally for this op, the result would have to be monitored by TI.
     // However, since this stub ALWAYS returns UndefinedValue(), and we can be sure
@@ -965,7 +965,7 @@ BaselineCacheIRCompiler::emitLoadInt32Ar
 
     // Guard length fits in an int32.
     masm.branchTest32(Assembler::Signed, scratch, scratch, failure->label());
-    masm.tagValue(JSVAL_TYPE_INT32, scratch, R0);
+    masm.tagValue(JSVAL_TYPE_INT32, scratch, js::jit::R0);
 
     // The int32 type was monitored when attaching the stub, so we can
     // just return.
@@ -977,8 +977,8 @@ bool
 BaselineCacheIRCompiler::emitLoadUnboxedArrayLengthResult()
 {
     Register obj = allocator.useRegister(masm, reader.objOperandId());
-    masm.load32(Address(obj, UnboxedArrayObject::offsetOfLength()), R0.scratchReg());
-    masm.tagValue(JSVAL_TYPE_INT32, R0.scratchReg(), R0);
+    masm.load32(Address(obj, UnboxedArrayObject::offsetOfLength()), js::jit::R0.scratchReg());
+    masm.tagValue(JSVAL_TYPE_INT32, js::jit::R0.scratchReg(), js::jit::R0);
 
     // The int32 type was monitored when attaching the stub, so we can
     // just return.
@@ -1008,7 +1008,7 @@ BaselineCacheIRCompiler::emitLoadArgumen
     // Shift out arguments length and return it. No need to type monitor
     // because this stub always returns int32.
     masm.rshiftPtr(Imm32(ArgumentsObject::PACKED_BITS_COUNT), scratch);
-    masm.tagValue(JSVAL_TYPE_INT32, scratch, R0);
+    masm.tagValue(JSVAL_TYPE_INT32, scratch, js::jit::R0);
     emitReturnFromIC();
     return true;
 }
@@ -1053,7 +1053,7 @@ BaselineCacheIRCompiler::init(CacheKind
         return false;
 
     MOZ_ASSERT(numInputs == 1);
-    allocator.initInputLocation(0, R0);
+    allocator.initInputLocation(0, js::jit::R0);
 
     return true;
 }
Index: firefox-50.1.0/js/src/jit/BaselineDebugModeOSR.cpp
===================================================================
--- firefox-50.1.0.orig/js/src/jit/BaselineDebugModeOSR.cpp
+++ firefox-50.1.0/js/src/jit/BaselineDebugModeOSR.cpp
@@ -992,7 +992,7 @@ SyncBaselineDebugModeOSRInfo(BaselineFra
     if (HasForcedReturn(info, rv)) {
         // Load the frame's rval and overwrite the resume address to go to the
         // epilogue.
-        MOZ_ASSERT(R0 == JSReturnOperand);
+        MOZ_ASSERT(js::jit::R0 == JSReturnOperand);
         info->valueR0 = frame->returnValue();
         info->resumeAddr = frame->script()->baselineScript()->epilogueEntryAddr();
         return;
@@ -1087,8 +1087,8 @@ EmitBaselineDebugModeOSRHandlerTail(Macr
     if (returnFromCallVM) {
         jumpRegs.take(ReturnReg);
     } else {
-        jumpRegs.take(R0);
-        jumpRegs.take(R1);
+        jumpRegs.take(js::jit::R0);
+        jumpRegs.take(js::jit::R1);
     }
     jumpRegs.take(BaselineFrameReg);
     Register target = jumpRegs.takeAny();
@@ -1098,8 +1098,8 @@ EmitBaselineDebugModeOSRHandlerTail(Macr
     if (returnFromCallVM) {
         masm.pop(ReturnReg);
     } else {
-        masm.popValue(R1);
-        masm.popValue(R0);
+        masm.popValue(js::jit::R1);
+        masm.popValue(js::jit::R0);
     }
 
     masm.jump(target);
Index: firefox-50.1.0/media/webrtc/trunk/build/build_config.h
===================================================================
--- firefox-50.1.0.orig/media/webrtc/trunk/build/build_config.h
+++ firefox-50.1.0/media/webrtc/trunk/build/build_config.h
@@ -153,6 +153,9 @@
 #elif defined(__s390__)
 #define ARCH_CPU_S390 1
 #define ARCH_CPU_32_BITS 1
+#elif defined(__sh__)
+#define ARCH_CPU_SH 1
+#define ARCH_CPU_32_BITS 1
 #elif defined(__alpha__)
 #define ARCH_CPU_ALPHA 1
 #define ARCH_CPU_64_BITS 1
Index: firefox-50.1.0/mfbt/tests/TestPoisonArea.cpp
===================================================================
--- firefox-50.1.0.orig/mfbt/tests/TestPoisonArea.cpp
+++ firefox-50.1.0/mfbt/tests/TestPoisonArea.cpp
@@ -154,6 +154,9 @@
 #elif defined __s390__
 #define RETURN_INSTR 0x07fe0000 /* br %r14 */
 
+#elif defined __sh__
+#define RETURN_INSTR 0x0b000b00 /* rts; rts */
+
 #elif defined __aarch64__
 #define RETURN_INSTR 0xd65f03c0 /* ret */
 
Index: firefox-50.1.0/python/mozbuild/mozbuild/configure/constants.py
===================================================================
--- firefox-50.1.0.orig/python/mozbuild/mozbuild/configure/constants.py
+++ firefox-50.1.0/python/mozbuild/mozbuild/configure/constants.py
@@ -50,6 +50,7 @@ CPU = EnumString.subclass(
     'ppc64',
     's390',
     's390x',
+    'sh4',
     'sparc',
     'sparc64',
     'x86',
@@ -78,6 +79,7 @@ CPU_preprocessor_checks = OrderedDict((
     ('sparc', '__sparc__'),
     ('mips64', '__mips64'),
     ('mips32', '__mips__'),
+    ('sh4', '__sh__'),
 ))
 
 assert sorted(CPU_preprocessor_checks.keys()) == sorted(CPU.POSSIBLE_VALUES)
Index: firefox-50.1.0/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
===================================================================
--- firefox-50.1.0.orig/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
+++ firefox-50.1.0/python/mozbuild/mozbuild/test/configure/test_toolchain_configure.py
@@ -997,6 +997,9 @@ class LinuxCrossCompileToolchainTest(Bas
         'mips-unknown-linux-gnu': big_endian + {
             '__mips__': 1,
         },
+        'sh4-unknown-linux-gnu': little_endian + {
+            '__sh__': 1,
+        },
     }
 
     PLATFORMS['powerpc64le-unknown-linux-gnu'] = \
Index: firefox-50.1.0/toolkit/mozapps/installer/find-dupes.py
===================================================================
--- firefox-50.1.0.orig/toolkit/mozapps/installer/find-dupes.py
+++ firefox-50.1.0/toolkit/mozapps/installer/find-dupes.py
@@ -7,6 +7,50 @@ import hashlib
 from mozpack.packager.unpack import UnpackFinder
 from collections import OrderedDict
 
+
+'''
+Allows to read a file-like object in chunks of limited size and
+counts the total bytes read from that object.
+'''
+
+class ChunkedReader:
+    '''
+    Initializes the ChunkedReader for the given file-like offset and
+    an optional chunk size (the default is 2^20 bytes.
+    '''
+    def __init__(self, fh, chunksize = 1024*1024):
+        self._fh = fh
+        self._chunksize = chunksize
+        self._totalsize = None
+
+    '''
+    Returns a generator that returns the chunks of the file-like object.
+    No chunk exceeds the maximal chunk size, and no chunk will be empty.
+    Currently, all chunks but the last provide the full chunk size, but
+    if a similar interface is implemented on zipped streams, alignment
+    with compressed blocks might be a good idea.
+    '''
+    def read_chunks(self):
+        totalsize = 0
+        while True:
+            data = self._fh.read(self._chunksize)
+            if data == "":
+                break
+            totalsize += len(data)
+            yield data
+        self._totalsize = totalsize
+
+    '''
+    Returns the total size of the chunks that were read from the file.
+    This value is only available after the generator returned by
+    read_chunks has been completely iterated. Before that, the return
+    value will be None.
+    '''
+    def totalsize(self):
+        return self._totalsize
+
+
+
 '''
 Find files duplicated in a given packaged directory, independently of its
 package format.
@@ -16,10 +60,13 @@ package format.
 def find_dupes(source):
     md5s = OrderedDict()
     for p, f in UnpackFinder(source):
-        content = f.open().read()
-        m = hashlib.md5(content).digest()
+        cr = ChunkedReader(f.open())
+        h = hashlib.md5()
+        for chunk in cr.read_chunks():
+            h.update(chunk)
+        m = h.digest()
         if not m in md5s:
-            md5s[m] = (len(content), [])
+            md5s[m] = (cr.totalsize(), [])
         md5s[m][1].append(p)
     total = 0
     num_dupes = 0
Index: firefox-50.1.0/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_sh.cpp
===================================================================
--- /dev/null
+++ firefox-50.1.0/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_sh.cpp
@@ -0,0 +1,204 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  - Copyright (C) 2008-2009 STMicroelectronics
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * Based on the neutroni port, however that assumed that the compiler was pushing params
+ * onto the stack. Change to take this into account.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "xptcprivate.h"
+
+extern "C" {
+
+const int c_int_register_params = 4;
+const int c_float_register_params = 8;
+
+static PRUint32 __attribute__((__used__))
+copy_to_stack(PRUint32 **that,PRUint32 methodIndex,PRUint32 paramCount, nsXPTCVariant* s,PRUint32* data)
+{
+	int intCount = 1; // Because of that
+	int floatCount = 0;
+	PRUint32 *intRegParams=data+1 ;
+	float  *floatRegParams = (float *)(data+4);
+
+	/* Push the that register into the right place so it can be restored on exit */
+	*data= (PRUint32)(that);
+	data+=12; /* 4 integer registers, and 8 floating point registers */
+
+	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;
+		}
+	}
+
+	/* Now calculate the return address
+	 * Dereference that to get vtable pointer
+	 */
+	return *( (*(that))+(methodIndex) );
+
+}
+
+}
+
+	/* This was originally done as a C function, but the original code was
+	 * relying on how the compiler laid out the stack. Later versions of
+	 * gcc do a better job of optimising and never push the parameters on the
+	 * stack. So it is simpler to just write the whole thing in assembler anyway
+	 */
+
+	/* 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 bottom of which will be copied to registers r4 to r7
+	   and fr4 to fr11 before calling the target function.
+	*/
+
+/* r4= that, r5=methodIndex,r6=paramCount,r7=params */
+
+ __asm__ (
+
+
+    /* Make space for parameters to be passed to the method.  Assume worst case
+       8 bytes per parameter.  Also leave space for 4 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.
+    */
+	".section .text\n"
+	".balign 4\n"
+	".global NS_InvokeByIndex\n"
+	"NS_InvokeByIndex:\n"
+	"mov.l r14, @-r15 \n\t" // Push frame
+	"sts.l pr, @-r15 \n\t"	// Push link
+	"mov.l r8, @-r15 \n\t"	// Save
+	"mov  r15, r14\n\t"	// Set frame
+	"mov	#3, r1 \n\t" 	// Assume worse case, all params are 64bit, hence *8
+	"mov 	r6, r2\n\t"
+	"shld	r1, r2 \n\t"
+	"mov 	r2, r8  \n\t" 	// Save stack drop
+	"add	#48, r2 \n\t"	// Space for 4 longs, 8 floats
+	"sub	r2, r15 \n\t"	// Drop stack
+	"mov.l 	1f, r1 \n\t"	// Get relative address of copy_to_stack_function
+	"bsrf  	r1 \n\t"
+	  "mov.l   r15, @-r15 \n\t"	//  Params will be dumped here
+	"0:\n\t"
+	"add	#4, r15 \n\t"	// Pop stack ptr param. r0 contains method address
+
+	/* 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.l	@r15+, r4 \n\t" // that
+	"mov.l	@r15+, r5 \n\t"
+	"mov.l	@r15+, r6 \n\t"
+	"mov.l	@r15+, r7 \n\t"
+	"fmov.s	@r15+, fr5 \n\t"
+	"fmov.s	@r15+, fr4 \n\t"
+	"fmov.s	@r15+, fr7 \n\t"
+	"fmov.s	@r15+, fr6 \n\t"
+	"fmov.s	@r15+, fr9 \n\t"
+	"fmov.s	@r15+, fr8 \n\t"
+	"fmov.s	@r15+, fr11 \n\t"
+	"jsr	@r0 \n\t" // Invoke method
+	  "fmov.s	@r15+, fr10 \n\t"
+	"add  r8, r15\n\t"		// Pop stack back
+	"mov.l @r15+, r8\n\t" // Restore r8
+	"lds.l @r15+, pr\n\t"
+	"rts\n\t"
+	  "mov.l @r15+, r14\n\t"
+	".balign 4\n\t"
+	"1: .long copy_to_stack - 0b \n\t"
+   );
+
Index: firefox-50.1.0/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_sh.cpp
===================================================================
--- /dev/null
+++ firefox-50.1.0/xpcom/reflect/xptcall/md/unix/xptcstubs_linux_sh.cpp
@@ -0,0 +1,255 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  - Copyright (C) 2008-2009 STMicroelectronics
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * Based on the neutrino code, with some bug fixes and using the C preprocessor
+ * like all the other ports rather than the python script.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "xptcprivate.h"
+#include "xptiprivate.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;
+	const nsXPTMethodInfo* info;
+	PRUint8 paramCount;
+	PRUint8 i;
+
+	NS_ASSERTION(self,"no self");
+
+	self->mEntry->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->mOuter->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+	if(dispatchParams != paramBuffer)
+		delete [] dispatchParams;
+
+	return result;
+}
+
+
+__asm__ (
+	".text\n"
+	".little\n"
+
+	".globl SharedStub\n"
+	".type  SharedStub, @function\n"
+	"SharedStub:\n"
+	"mov	   r15, r1\n"
+	"mov.l	r14,@-r15\n"
+	"sts.l	pr,@-r15\n"
+	"mov		r15, r14\n"
+
+	/* 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\n"
+	"mov.l r6, @-r15\n"
+	"mov.l r5, @-r15\n"
+	"mov	  r15, r7\n"	/* r7 = PrepareAndDispatch intRegParams param	*/
+
+	"fmov.s fr10, @-r15\n"
+	"fmov.s fr11, @-r15\n"
+	"fmov.s fr8, @-r15\n"
+	"fmov.s fr9, @-r15\n"
+	"fmov.s fr6, @-r15\n"
+	"fmov.s fr7, @-r15\n"
+	"fmov.s fr4, @-r15\n"
+	"fmov.s fr5, @-r15\n"
+	"mov.l  r15, @-r15\n"	/* PrepareAndDispatch floatRegParams param		*/
+
+	"mov	   r1, r6\n"	/* r6 = PrepareAndDispatch data param			*/
+
+	"mov.l  1f, r1\n"
+	"bsrf	   r1\n"		/* Note, following instruction is executed first*/
+	  "mov	   r2, r5\n"		/* r5 = PrepareAndDispatch methodIndex param	*/
+	"0:\n"
+
+	"mov		r14,r15\n"
+	"lds.l	@r15+,pr\n"
+	"mov.l	@r15+,r14\n"
+	"rts\n"
+	  "nop\n"
+	".align 2\n"
+	"1:\n"
+	".long  PrepareAndDispatch - 0b\n"
+	);
+
+#define STUB_ENTRY(n) 						\
+__asm__( 							\
+	".text\n"						\
+	".align 1 \n"						\
+	".if        " #n " < 10\n\t" 				\
+	".globl    _ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" 	\
+	".type     _ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n"\
+	"_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" 		\
+	".elseif    " #n " < 100\n\t" 				\
+	".globl    _ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" 	\
+	".type     _ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n"\
+	"_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" 		\
+	".elseif    " #n " < 1000\n\t" 				\
+	".globl    _ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" 	\
+	".type     _ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n"\
+	"_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" 		\
+	".else\n\t" 						\
+	".err       \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+	".endif\n\t" 						\
+	"mov.l 	1f, r1 \n"					\
+	".if "#n" < 128 \n"					\
+	"braf r1 \n"						\
+	"  mov #"#n",r2 \n"					\
+	".elseif "#n" < 256 \n"					\
+	"mov #"#n", r2 \n"					\
+	"braf r1 \n"						\
+	"  extu.b r2, r2 \n"					\
+	".else \n"						\
+	"mov #"#n" & 0xff,r2 \n"				\
+	"extu.b	r2, r2 \n"					\
+	"mov #"#n">>8, r3 \n"					\
+	"shll8	r3 \n"						\
+	"braf r1 \n"						\
+	"  or r3, r2 \n"					\
+	".endif \n"						\
+	"0: \n"							\
+	".align 2\n"						\
+	"1:\n"							\
+	".long SharedStub - 0b\n"				\
+	);
+
+
+#define SENTINEL_ENTRY(n) 		\
+nsresult nsXPTCStubBase::Sentinel##n()  \
+{ \
+	NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+	return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
Index: firefox-50.1.0/xpcom/reflect/xptcall/md/unix/moz.build
===================================================================
--- firefox-50.1.0.orig/xpcom/reflect/xptcall/md/unix/moz.build
+++ firefox-50.1.0/xpcom/reflect/xptcall/md/unix/moz.build
@@ -316,6 +316,11 @@ if CONFIG['OS_ARCH'] == 'Linux':
             '-fomit-frame-pointer',
             '-mbackchain',
         ]
+    elif CONFIG['OS_TEST'] in ('sh4', 'sh4a'):
+        SOURCES += [
+            'xptcinvoke_linux_sh.cpp',
+            'xptcstubs_linux_sh.cpp',
+        ]
 
 FINAL_LIBRARY = 'xul'
 
