Bug#553593: xulrunner: Please port to sh4

Nobuhiro Iwamatsu iwamatsu at nigauri.org
Sun Nov 1 10:37:01 UTC 2009


Package: xulrunner
Version: 1.9.1.4-1
Severity: important
Tags: patch
User: debian-sh4 at superh.org
Usertags: sh4

Hi,

I am now trying to run Debian on Renesas SH CPU(sh4)[0].
Current postgresql package doesn't support sh4[1].
I made a patch to revise to be able to build.
I attach patch. Would you apply it?

[0]: http://buildd.debian-ports.org/status/architecture.php?suite=unstable&a=sh4&buildd=
[1]: http://buildd.debian-ports.org/fetch.php?pkg=xulrunner&arch=sh4&ver=1.9.1.4-1&stamp=1257038103&file=log&as=raw

Best regards,
  Nobuhiro
-------------- next part --------------
Adds support for SuperH to firefox, main work is in the xpcom stuff.
This work was based on the SuperH work done for Neutrono.

--- /dev/null	2008-03-10 11:17:51.957003185 +0000
+++ a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_sh.cpp	2008-04-30 16:30:58.000000000 +0100
@@ -0,0 +1,165 @@
+/* Based on the neutroni port, however that assumed that the compiler was pushing params
+ * onto the stack. Change to take this into account.
+ */
+
+#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_P\n"
+	"NS_InvokeByIndex_P:\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 address of copy_to_stack_function
+	"jsr  	@r1 \n\t"
+	  "mov.l   r15, @-r15 \n\t"	//  Params will be dumped here
+	"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 \n\t"
+   );
+    
--- /dev/null	2008-03-10 11:17:51.957003185 +0000
+++ a/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_sh.cpp	2008-04-30 16:24:03.000000000 +0100
@@ -0,0 +1,235 @@
+/* Based on the neutrino code, with some bug fixes and using the C preprocessor
+ * like all the other ports rather than the python script.
+ */
+
+
+#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"
+	".section	.rodata\n"
+
+	".globl SharedStub\n"
+	".type  SharedStub, @function\n"
+	"SharedStub:\n"
+	"mov	   r15, r1\n"
+	"mov.l	r14, at -r15\n"	
+	"sts.l	pr, at -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"
+	"jsr	   @r1\n"		/* Note, following instruction is executed first*/
+	  "mov	   r2, r5\n"		/* r5 = PrepareAndDispatch methodIndex param	*/
+
+	"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\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, at function\n"\
+	"_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" 		\
+	".elseif    " #n " < 100\n\t" 				\
+	".globl    _ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" 	\
+	".type     _ZN14nsXPTCStubBase6Stub" #n "Ev, at function\n"\
+	"_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" 		\
+	".elseif    " #n " < 1000\n\t" 				\
+	".globl    _ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" 	\
+	".type     _ZN14nsXPTCStubBase7Stub" #n "Ev, at 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"					\
+	"jmp @r1 \n"						\
+	"  mov #"#n",r2 \n"					\
+	".elseif "#n" < 256 \n"					\
+	"mov #"#n", r2 \n"					\
+	"jmp @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"						\
+	"jmp @r1 \n"						\
+	"  or r3, r2 \n"					\
+	".endif \n"						\
+	".if "#n" % 20 == 0\n"					\
+	".align 2\n"						\
+	"1:\n"							\
+	".long SharedStub\n"					\
+	".endif\n"						\
+	);
+	
+
+/* Due to the fact that the SH4 can only load forward labels, we have 
+ * to use sentinel_entry to output the last label. A better solution 
+ * would be to introduce a STUB_LAST macro in the defs.in file, but
+ * this will do for now
+ */
+
+#define SENTINEL_ENTRY(n) 		\
+__asm__( 				\
+".if "#n" == 0  \n"			\
+	".text \n"			\
+	".align 2\n"			\
+	"1:\n"				\
+	".long SharedStub\n"		\
+".endif\n"				\
+); 					\
+					\
+nsresult nsXPTCStubBase::Sentinel##n()  \
+{ \
+	NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+	return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
--- a/xpcom/reflect/xptcall/src/md/unix/Makefile.in	2009-10-29 07:34:30.000000000 +0000
+++ b/xpcom/reflect/xptcall/src/md/unix/Makefile.in	2009-10-29 07:34:59.000000000 +0000
@@ -448,6 +448,15 @@
 CXXFLAGS	+= -fno-strict-aliasing -fno-inline -fomit-frame-pointer -mbackchain
 endif
 
+############
+# SuperH
+############
+#
+#
+#
+ifeq (sh,$(findstring sh,$(OS_TEST)))
+CPPSRCS                := xptcinvoke_linux_sh.cpp xptcstubs_linux_sh.cpp
+endif
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1


More information about the pkg-mozilla-maintainers mailing list