A registerised mips-linux port of GHC

Thiemo Seufer ths at networkno.de
Thu Aug 24 06:46:45 EDT 2006


Thiemo Seufer wrote:
> Hello All,
> 
> I currently try to get a ghc port on mips-linux going. I understand
> Igloo does the same ATM, and things look promising so far.
> 
> However, the port is currently unregisterised, and I would like to
> improve it a bit. A registerised port seems to be achievable with
> a moderate amount of work. I looked a bit around in the code, and
> have now a few questions:
> 
> - The example of other ports suggests the useful maximum of general
>   purpose registers for GHC is 8. I also presume that unmentioned
>   registers aren't touched by haskell code. Is this correct?
> 
> - The comments in the source suggest that callee-saved registers are
>   preferable, without further explanation. I would expect a mix of
>   caller- and callee-saved registers to be potentially better. Any
>   advice on this?
> 
> - The mips ABI defines 8 (or 9 when including the frame pointer)
>   registers as callee-saved, and more than 9 caller-saved temporaries.
>   With four registers taken for stack/heap pointers this leaves a
>   5/3 split of callee-saved/caller-saved registers, if all my
>   assumptions above are ok. Are there other considerations to take
>   into account for the register layout?

I decided to ignore the performance tuning for now and used a register
mapping which is compatible to all three relevant MIPS ABIs. It uses
4 callee-saved registers as R1-R4, plus 4 temporaries (caller-saved)
registers as R5-R8.

With the appended patch to support a registerised build of GHC 6.4.2 on
Debian mips-linux I got those testsuite results:

OVERALL SUMMARY for test run started at Wed Aug 23 20:12:05 BST 2006
     674 total tests, which gave rise to
    1883 test cases, of which
      21 caused framework failures
     369 were skipped

    1407 expected passes
      22 expected failures
       0 unexpected passes
      41 unexpected failures

Unexpected failures:
   barton-mangler-bug(normal,opt,prof,threaded)
   cabal01(normal)
   cg005(prof)
   char001(prof)
   directory001(prof)
   driver062.2(normal)
   drvrun006(normal)
   drvrun018(opt)
   enum02(threaded)
   exceptions001(normal)
   ext1(prof)
   fed001(normal,opt,prof,threaded)
   ffi006(normal,opt,prof,threaded)
   ffi007(normal,opt,prof,threaded)
   ffi008(normal)
   finalization001(threaded)
   freeNames(threaded)
   galois_raytrace(opt,prof)
   ioref001(normal,prof,threaded)
   joao-circular(normal,opt,prof,threaded)
   ratio001(prof)
   uri001(prof)
   xmlish(prof)


Not all that bad for a first attempt. Some of the failures are probably
due to the lack of MIPS support in ghc/rts/Adjustor.c, AFAIU this means
C -> haskell calls don't work for now.

I made ghc6 .deb packages from the unmodified Debian source, another
set of packages built with the appended patch, plus a haddock package
which is needed as a build-dependency. All are available from
http://people.debian.org/~ths/ghc6/ and
http://people.debian.org/~ths/haddock/
There are no little endian mipsel packages yet.

So if you happen to have a Debian mips installation around and want to
try ghc6, feel free. :-)


Thiemo


diff -urpN restrap2/ghc6-6.4.2/ghc/includes/MachRegs.h hackage/ghc6-6.4.2/ghc/includes/MachRegs.h
--- restrap2/ghc6-6.4.2/ghc/includes/MachRegs.h	2005-07-13 09:47:05.000000000 +0100
+++ hackage/ghc6-6.4.2/ghc/includes/MachRegs.h	2006-08-22 21:42:31.000000000 +0100
@@ -399,10 +399,6 @@
 
 #define REG(x) __asm__("$" #x)
 
-#define CALLER_SAVES_R1
-#define CALLER_SAVES_R2
-#define CALLER_SAVES_R3
-#define CALLER_SAVES_R4
 #define CALLER_SAVES_R5
 #define CALLER_SAVES_R6
 #define CALLER_SAVES_R7
@@ -410,14 +406,14 @@
 
 #define CALLER_SAVES_USER
 
-#define REG_R1		9
-#define REG_R2    	10
-#define REG_R3    	11
-#define REG_R4    	12
-#define REG_R5    	13
-#define REG_R6    	14
-#define REG_R7    	15
-#define REG_R8    	24
+#define REG_R1		16
+#define REG_R2    	17
+#define REG_R3    	18
+#define REG_R4    	19
+#define REG_R5    	12
+#define REG_R6    	13
+#define REG_R7    	14
+#define REG_R8    	15
 
 #define REG_F1		f20
 #define REG_F2		f22
@@ -427,11 +423,13 @@
 #define REG_D1		f28
 #define REG_D2		f30
 
-#define REG_Sp    	16
-#define REG_SpLim    	18
+#define REG_Sp    	20
+#define REG_SpLim    	21
 
-#define REG_Hp	    	19
-#define REG_HpLim	20
+#define REG_Hp	    	22
+#define REG_HpLim	23
+
+#define REG_Base	30
 
 #endif /* mipse[lb] */
 
diff -urpN restrap2/ghc6-6.4.2/ghc/includes/TailCalls.h hackage/ghc6-6.4.2/ghc/includes/TailCalls.h
--- restrap2/ghc6-6.4.2/ghc/includes/TailCalls.h	2005-03-08 09:38:57.000000000 +0000
+++ hackage/ghc6-6.4.2/ghc/includes/TailCalls.h	2006-08-22 20:45:52.000000000 +0100
@@ -245,6 +245,29 @@ but uses $$dyncall if necessary to cope,
 #endif
 
 /* -----------------------------------------------------------------------------
+   Tail calling on MIPS
+   -------------------------------------------------------------------------- */
+
+#ifdef mips_HOST_ARCH
+
+#if IN_STG_CODE
+register void *_procedure __asm__("$25");
+#endif
+
+#define JMP_(cont)				\
+    {						\
+       _procedure = (void *)(cont);		\
+       __DISCARD__();				\
+       goto *_procedure;			\
+    }
+
+/* Don't need these for MIPS mangling */
+#define FB_
+#define FE_
+
+#endif /* mips_HOST_ARCH */
+
+/* -----------------------------------------------------------------------------
   FUNBEGIN and FUNEND.
 
   These are markers indicating the start and end of Real Code in a
diff -urpN restrap2/ghc6-6.4.2/ghc/rts/StgCRun.c hackage/ghc6-6.4.2/ghc/rts/StgCRun.c
--- restrap2/ghc6-6.4.2/ghc/rts/StgCRun.c	2006-03-22 10:29:51.000000000 +0000
+++ hackage/ghc6-6.4.2/ghc/rts/StgCRun.c	2006-08-22 21:54:33.000000000 +0100
@@ -877,4 +877,37 @@ StgRunIsImplementedInAssembler(void)
 
 #endif
 
+/* -----------------------------------------------------------------------------
+   MIPS architecture
+   -------------------------------------------------------------------------- */
+
+#ifdef mips_HOST_ARCH
+
+StgThreadReturnCode
+StgRun(StgFunPtr f, StgRegTable *basereg)
+{
+    register StgThreadReturnCode __v0 __asm__("$2");
+
+    __asm__ __volatile__(
+	"	la	$25, %1			\n"
+	"	move	$30, %2			\n"
+	"	jr	%1			\n"
+	"	.align 3			\n"
+	"	.globl " STG_RETURN "		\n"
+	"	.aent " STG_RETURN "		\n"
+	STG_RETURN ":				\n"
+	"	move	%0, $16			\n"
+	"	move	$3, $17			\n"
+	: "=r" (__v0),
+	: "r" (f), "r" (basereg)
+	"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
+	"$25", "$28", "$30",
+	"$f20", "$f22", "$f24", "$f26", "$f28", "$f30",
+	"memory");
+
+    return __v0;
+}
+
+#endif /* mips_HOST_ARCH */
+
 #endif /* !USE_MINIINTERPRETER */


More information about the Glasgow-haskell-users mailing list