Subject: pkg/12411: lang/sml-nj does not work on NetBSD/sparc
To: None <gnats-bugs@gnats.netbsd.org>
From: None <thesing@cs.uni-sb.de>
List: netbsd-bugs
Date: 03/15/2001 15:37:56
>Number:         12411
>Category:       pkg
>Synopsis:       lang/sml-nj does not work on NetBSD/sparc
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    pkg-manager
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Mar 15 06:39:01 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Stephan Thesing
>Release:        NetBSD-1.4.2
>Organization:
Saarland University
>Environment:
System: NetBSD popl01 1.4.2 NetBSD 1.4.2 (RW4) #0: Wed Mar 22 17:49:17 CET 2000     root@rw4:/usr/src/sys/arch/sparc/compile/RW4 sparc 
Recent pkgsrc 

Architecture: sparc
Machine: sparc
>Description:
The lang/sml-nj package doesn't work on NetBSD/sparc.

Though sml-nj supports the sparc architecture and actually runs under
SunOS (and under emulation on NetBSD), it can not be bootstraped under NetBSD.

Even adding the trivial lines to support NetBSD/sparc in the SMl config
files doesn't help: the bootstrap crashes.
The reason is that the assembly runtime support functions make some
assumptions for the behaviour of the .mul, .umul, .div and .udiv
subroutines in libc that are simply not true under NetBSD.
In essence, .div trashes the SML global alloc pointer register %g6 with
funny results during the bootstrap:-)

>How-To-Repeat:
	Try to build it:-)
>Fix:
Enclosed is a patch that, if applied in pkgsrc/lang/sml-nj adds NetBSD/sparc
support for the package.

The patch adds the following things:
 I. pkgsrc related:
        - Update Makefile to enable NetBSD-sparc
        - Add another patch (patch-ac) that adds support for
          NetBSD/sparc to the SML OS detection script
        - Add patch-ac to patch-sum...
 II. SML related
        - patch-ac adds support for detecting NetBSD/sparc as supported
        - in files/patch-global-names (the patch file for the SML runtime
          sources tree):
                + add some defines for SPARC (stack frame size) in 
                  src/runtime/include/asm-base.h
                + add NetBSD related stuff to the SML CPU dependent assembler
                  code in src/runtime/mach-dep/SPARC.prim.asm:
                  * The .mul, .umul, .div, .udiv routines used in that file
                    behave differently under SunOS and NetBSD, so code has
                    been added to make them act the same (hack:-).
                    Without this, the .div routine globbers the global SML
                    allocation pointer (%g6) sometimes, causing  the bootstrap
                    to fail miserably.
                + add NetBSD in src/runtime/mach-dep/signal-sysdep.h
                + add a Makefile mk.sparc-netbsd in src/runtime/objs
                
With this patch applied, sml-nj can be build on my SS4 under NetBSD-1.4.2 (and
runs actually...:-)
Since I do not have access to other SPARC based machines and did not have
the time to upgrade the SS4 to 1.5, I don't know if it will work under such
conditions.

There might be some problems with this patch:
 - handling of symbols in src/runtime/mach-dep/SPARC.prim.asm may not be
   ELF save (?)
 - Handling of SPARC frame size and alignment should be done differently
   (macro SA, WINDOWSIZE, etc.pp.)
 - the hack in that file is not the fastest one:-)
 - somebody who actually knows SPARC assembler should rewrite the added code

=-=-=-=-=-=-=- SNIPP =-=-=-=-=-=-=-=-=-
--- ./files/patch-global-names.orig	Thu Mar 15 10:08:08 2001
+++ ./files/patch-global-names	Thu Mar 15 14:41:39 2001
@@ -1,11 +1,246 @@
---- src/runtime/include/asm-base.h.orig	Thu Aug  6 15:40:30 1998
-+++ src/runtime/include/asm-base.h	Tue Jan  4 11:13:08 2000
+--- src/runtime/include/asm-base.h.orig	Fri Dec  3 20:59:31 1999
++++ src/runtime/include/asm-base.h	Fri Mar  9 14:53:40 2001
 @@ -16,7 +16,7 @@
  #define FALSE	0
  #define TRUE	1
  
 -#if (!defined(GLOBALS_HAVE_UNDERSCORE)) && (defined(OPSYS_SUNOS) || defined(OPSYS_FREEBSD) || defined(OPSYS_NETBSD) || defined(OPSYS_NEXTSTEP) || defined(OPSYS_WIN32))
-+#if (!defined(GLOBALS_HAVE_UNDERSCORE)) && (defined(OPSYS_SUNOS) || (defined(OPSYS_FREEBSD) && !defined(__ELF__)) || (defined(OPSYS_NETBSD) && !defined(__ELF__)) || defined(OPSYS_NEXTSTEP) || defined(OPSYS_WIN32))
++#if (!defined(GLOBALS_HAVE_UNDERSCORE)) && (defined(OPSYS_SUNOS) || (defined(OPSYS_FREEBSD) && !defined(__ELF__)) || (defined(OPSYS_NETBSD) && !defined(__ELF__))|| defined(OPSYS_NEXTSTEP) || defined(OPSYS_WIN32))
  #  define GLOBALS_HAVE_UNDERSCORE
  #endif
  
+@@ -36,6 +36,11 @@
+ #    define _ASM
+ #    include <sys/stack.h>
+ #    include <sys/trap.h>
++#  elif defined(OPSYS_NETBSD)
++#    include <machine/trap.h>
++#    define WINDOWSIZE (16*4)
++#    define SA(x) (((x)+7)&~7)
++#    define ST_INT_OVERFLOW 0x87
+ #  endif
+ #  define GLOBAL(ID)	.global	CSYM(ID)
+ #  define LABEL(ID)	ID:
+--- src/runtime/mach-dep/SPARC.prim.asm.orig	Fri Dec  3 20:59:32 1999
++++ src/runtime/mach-dep/SPARC.prim.asm	Wed Mar 14 18:39:43 2001
+@@ -462,7 +462,7 @@
+ 	mov	ALLOCPTR,LIMITPTR	    /* (delay slot) */
+ 
+ 
+-#if defined(OPSYS_SUNOS) || defined(OPSYS_NEXTSTEP)
++#if defined(OPSYS_SUNOS) || defined(OPSYS_NEXTSTEP) || defined(OPSYS_NETBSD)
+ /* ZeroLimitPtr:
+  *
+  * Zero the heap limit pointer so that a trap will be generated on the next limit
+@@ -731,13 +731,62 @@
+ 	mov	%g1,%l1			  /* save %g1 which may get trashed */
+ 	mov	%g2,%l2
+ 	mov	%g3,%l3
++#ifdef OPSYS_NETBSD
++			/* NetBSDs .mul trashes these */
++	mov     %i4,%l4
++	mov     %i5,%l5
++	mov	%i0,%l6
++	mov	%i1,%l7
++#endif
+ 	mov	%i2,%o0
+ 	call	.mul
+ 	mov	%i3,%o1			  /* (delay slot) */
+ 	mov	%l1,%g1			  /* restore %g1 */
+ 	mov	%l2,%g2
+ 	mov	%l3,%g3
++#ifdef OPSYS_NETBSD
++	mov     %l4,%i4
++	mov	%l5,%i5
++	mov	%l6,%i0
++	mov	%l7,%i1
++			/* the code below is a hack:
++			 * NetBSDs .mul does a 32x32->64 bit signed multiply
++			 * The SML code assumes that the multiply
++			 * overflowed (over 32bit) if the Z flag is
++			 * clear on return from .mul 
++			 * NetBSDs .mul doesn't do that, so we have to check
++			 * for overflow. This is done in the following way:
++			 * - If the upper 32 bits are clear:
++	 		 *    + if bit 31 is set => overflow
++		         *    + if bit 31 is clear => OK
++			 * - If the upper 32 bits are != -1 => overflow
++			 * - If the upper 32 bits are == -1:
++			 *    + If bit 31 is clear => overflow
++			 *    + If bit 31 is set   => OK
++			 *
++		   	 * I should be shot for this code ...
++			 */
++	cmp %o1,0
++	bnz 4f
++	nop
++	/* is bit 31 of %o0 set ? */
++	addcc %o0,%o0,%o1
++	bcc 2f
++	nop
++5:      restore %o0,0,%o2                 /* result in %o2 (delay slot) */
++        t       ST_INT_OVERFLOW         /* generate overflow trap */
++
++	
++4:	cmp %o1,-1			/* upper 32 bits == -1 ? */
++	bnz 5
++	nop
++	addcc %o0,%o0,%o1		/* bit 31 clear ? */
++	bcc 2f
++	nop
++#else
+ 	bnz	1f			  /* if z is clear, then overflow */
++#endif
++2:
+ 	restore %o0,0,%o2		  /* result in %o2 (delay slot) */
+ 	retl
+ 	nop
+@@ -751,7 +800,15 @@
+  * locals of the new window, since .div is a leaf routine.
+  */
+ _ml_div:
+-	save	%sp,-SA(WINDOWSIZE),%sp
++#ifdef OPSYS_NETBSD
++		/* hack time again: NetBSDs .div trashes too many registers
++		 * we have to store them in the stack frame, so make room
++		 * for six registers (o0-o5) 
++		 */
++	save	%sp,-SA(WINDOWSIZE+24),%sp
++#else
++        save    %sp,-SA(WINDOWSIZE+24),%sp
++#endif
+ 	addcc	%i3,%g0,%o1		/* %o1 is divisor (and check for zero) */
+ 	bz	1f
+ 				    /* save %g1, %g2 and %g3 (using new window) */
+@@ -759,9 +816,30 @@
+ 	mov	%g1,%l1			/* (delay slot) */
+ 	mov	%g2,%l2
+ 	mov	%g3,%l3
++#ifdef OPSYS_NETBSD
++	/* save g6,g7,o0-o5, they get trashed. 
++	   Note that %o0-%o5 are now %i0-%i5, since we did a 'save'
++	   Since %g6 is the global AllocPtr for SML, this 
++	   is rather bad :-)
++	 */  
++	mov %g6,%l4
++	mov %g7,%l5
++	std	%i0,[%fp-16]
++	std	%i2,[%fp-24]
++	std	%i4,[%fp-32]
++#endif
++
+ 	call	.div
+ 	mov	%i2,%o0			/* (delay slot) */
+ 				    /* restore %g1, %g2 and %g3 */
++#ifdef OPSYS_NETBSD
++	mov %l4,%g6
++	mov %l5,%g7
++	ldd	[%fp-32],%i4
++	ldd	[%fp-24],%i2
++	ldd	[%fp-16],%i0
++#endif
++
+ 	mov	%l3,%g3
+ 	mov	%l2,%g2
+ 	mov	%l1,%g1
+@@ -788,11 +866,24 @@
+ 	mov	%g2,%l2
+ 	mov	%g3,%l3
+ 	mov	%i2,%o0
++#ifdef OPSYS_NETBSD
++		/* Save what might be trashed by NetBSDs .umul */
++	mov	%i4,%l4
++	mov	%i5,%l5
++	mov	%i0,%l6
++	mov 	%i1,%l7
++#endif
+ 	call	.umul
+ 	mov	%i3,%o1			  /* (delay slot) */
+ 	mov	%l1,%g1			  /* restore %g1 */
+ 	mov	%l2,%g2
+ 	mov	%l3,%g3
++#ifdef OPSYS_NETBSD
++	mov	%l4,%i4
++	mov	%l5,%i5
++	mov	%l6,%i0
++	mov	%l7,%i1
++#endif
+ 	ret
+ 	restore %o0,0,%o2		  /* result in %o2 (delay slot) */
+ 
+@@ -803,7 +894,12 @@
+  * locals of the new window, since .div is a leaf routine.
+  */
+ _ml_udiv:
+-	save	%sp,-SA(WINDOWSIZE),%sp
++#ifdef OPSYS_NETBSD
++		/* see comment for _ml__div_ */
++	save	%sp,-SA(WINDOWSIZE+24),%sp
++#else
++        save    %sp,-SA(WINDOWSIZE+24),%sp 
++#endif
+ 	addcc	%i3,%g0,%o1		/* %o1 is divisor (and check for zero) */
+ 	bz	1f
+ 				    /* save %g1, %g2 and %g3 (using new window) */
+@@ -811,9 +907,23 @@
+ 	mov	%g1,%l1			/* (delay slot) */
+ 	mov	%g2,%l2
+ 	mov	%g3,%l3
++#ifdef OPSYS_NETBSD
++	mov	%g6,%l4
++	mov 	%g7,%l5
++        std     %i0,[%fp-16]
++        std     %i2,[%fp-24]
++        std     %i4,[%fp-32]
++#endif
+ 	call	.udiv
+ 	mov	%i2,%o0			/* (delay slot) */
+ 				    /* restore %g1, %g2 and %g3 */
++#ifdef OPSYS_NETBSD
++	mov 	%l4,%g6
++	mov 	%l5,%g7
++        ldd     [%fp-32],%i4
++        ldd     [%fp-24],%i2
++        ldd     [%fp-16],%i0
++#endif
+ 	mov	%l3,%g3
+ 	mov	%l2,%g2
+ 	mov	%l1,%g1
+--- src/runtime/mach-dep/signal-sysdep.h.orig	Fri Dec  3 20:59:32 1999
++++ src/runtime/mach-dep/signal-sysdep.h	Mon Mar 12 15:23:01 2001
+@@ -151,7 +151,7 @@
+   /* disable all FP exceptions */
+ #  define SIG_InitFPE()    SetFSR(0)
+ 
+-#  if defined(OPSYS_SUNOS)
++#  if defined(OPSYS_SUNOS) || defined(OPSYS_NETBSD)
+     /** SPARC, SUNOS **/
+ #    define USE_ZERO_LIMIT_PTR_FN
+ #    define SIG_FAULT1		SIGFPE
+--- src/runtime/objs/mk.sparc-netbsd.orig	Thu Jan  1 01:00:00 1970
++++ src/runtime/objs/mk.sparc-netbsd	Tue Mar 13 09:45:58 2001
+@@ -0,0 +1,24 @@
++# mk.sparc-netbsd
++#
++
++SHELL		= /bin/sh
++
++MAKE =		gmake
++GCC =		gcc
++ARFLAGS =	Trcv
++CFLAGS =	-O2 -Wall 
++LDFLAGS=
++CPP =		$(GCC) -x c -E -P
++
++#XOBJS =	xmonitor.o
++#LD_LIBS =	-lX11
++#BASE_DEFS =	-DHEAP_MONITOR -DPOLL_DEBUG
++XOBJS =
++XLIBS =
++DEFS =		$(BASE_DEFS) -DHOST_SPARC -DTARGET_SPARC -DOPSYS_UNIX -DOPSYS_NETBSD -DCALLEESAVE=3 -DUNBOXEDFLOAT=1 
++TARGET =	SPARC
++VERSION =	v-sparc-netbsd
++RUNTIME =	run.sparc-netbsd
++
++all:
++	($(MAKE) RUNTIME="$(RUNTIME)" MAKE="$(MAKE)" VERSION="$(VERSION)" CC="$(CC)" CFLAGS="$(CFLAGS)" CPP="$(CPP)" AS="$(AS)" AR="$(AR)" RANLIB="$(RANLIB)" TARGET=$(TARGET) DEFS="$(DEFS)" XOBJS="$(XOBJS)" XLIBS="$(XLIBS)" LD_LIBS="$(LD_LIBS)" $(RUNTIME))
--- ./files/patch-sum.orig	Thu Mar 15 10:08:08 2001
+++ ./files/patch-sum	Wed Mar 14 18:55:21 2001
@@ -1,3 +1,4 @@
 $NetBSD: patch-sum,v 1.1 2000/01/09 14:53:11 wiz Exp $
 
 MD5 (patch-ab) = 672b1c65fb0b2d4608252a1ace81cf4d
+MD5 (patch-ac) = 65b0378f4250292936adf81b7d563f56
--- ./patches/patch-ac.orig	Thu Mar 15 10:09:33 2001
+++ ./patches/patch-ac	Wed Mar 14 18:48:16 2001
@@ -0,0 +1,11 @@
+--- config/_arch-n-opsys.orig        Fri Oct 20 18:02:25 2000
++++ config/_arch-n-opsys     Fri Mar  9 14:07:05 2001
+@@ -100,6 +100,7 @@
+       i486) ARCH=x86;;
+       i586) ARCH=x86;;
+       i686) ARCH=x86;;
++      sparc) ARCH=sparc;;
+       *) exit 1;;
+     esac
+     ;;
+
--- ./Makefile.orig	Thu Mar 15 10:08:08 2001
+++ ./Makefile	Wed Mar 14 18:51:13 2001
@@ -23,7 +23,7 @@
 # sml-nj also supports hppa, sparc, ppc, mlrisc & alpha
 # pkg support for those platforms, and say, solaris-x86
 # is left as an (easy) exercise for the reader.
-ONLY_FOR_PLATFORM=	NetBSD-*-i386 SunOS-*-sparc
+ONLY_FOR_PLATFORM=	NetBSD-*-i386 SunOS-*-sparc NetBSD-*-sparc
 
 # Other mirror sites that generally carry only released versions of SML
 # 	ftp://rodin.stanford.edu/pub/smlnj/release/
@@ -50,6 +50,9 @@
 OS=		${LOWER_OPSYS}
 .elif ${OPSYS} == "NetBSD" && ${MACHINE_ARCH} == "i386"
 BOX=		x86
+OS=		bsd
+.elif ${OPSYS} == "NetBSD" && ${MACHINE_ARCH} == "sparc"
+BOX=		sparc
 OS=		bsd
 .endif
>Release-Note:
>Audit-Trail:
>Unformatted: