changeset 6437:f9920b777c65

Initial revision
author Richard M. Stallman <rms@gnu.org>
date Sun, 20 Mar 1994 06:30:14 +0000
parents 722cd14b5f94
children 45ab50a1dc55
files src/alloca.s
diffstat 1 files changed, 350 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/alloca.s	Sun Mar 20 06:30:14 1994 +0000
@@ -0,0 +1,350 @@
+/* `alloca' standard 4.2 subroutine for 68000's and 16000's and others.
+   Also has _setjmp and _longjmp for pyramids.
+   Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Both 68000 systems I have run this on have had broken versions of alloca.
+   Also, I am told that non-berkeley systems do not have it at all.
+   So replace whatever system-provided alloca there may be
+   on all 68000 systems.  */
+
+#define NOT_C_CODE
+#ifdef emacs
+#include <config.h>
+#else
+#include "config.h"
+#endif
+
+#ifndef HAVE_ALLOCA  /* define this to use system's alloca */
+
+#ifndef hp9000s300
+#ifndef m68k
+#ifndef m68000
+#ifndef WICAT
+#ifndef ns32000
+#ifndef ns16000
+#ifndef sequent
+#ifndef pyramid
+#ifndef ATT3B5
+#ifndef XENIX
+you
+lose!!
+#endif /* XENIX */
+#endif /* ATT3B5 */
+#endif /* pyramid */
+#endif /* sequent */
+#endif /* ns16000 */
+#endif /* ns32000 */
+#endif /* WICAT */
+#endif /* m68000 */
+#endif /* m68k */
+#endif /* hp9000s300 */
+
+
+#ifdef hp9000s300
+#ifdef OLD_HP_ASSEMBLER
+	data
+	text
+	globl	_alloca
+_alloca	
+	move.l	(sp)+,a0	; pop return addr from top of stack
+	move.l	(sp)+,d0	; pop size in bytes from top of stack
+	add.l	#ROUND,d0	; round size up to long word
+	and.l	#MASK,d0	; mask out lower two bits of size
+	sub.l	d0,sp		; allocate by moving stack pointer
+	tst.b	PROBE(sp)	; stack probe to allocate pages
+	move.l	sp,d0		; return pointer
+	add.l	#-4,sp		; new top of stack
+	jmp	(a0)		; not a normal return
+MASK	equ	-4		; Longword alignment
+ROUND	equ	3		; ditto
+PROBE	equ	-128		; safety buffer for C compiler scratch
+	data
+#else /* new hp assembler syntax */
+/*
+  The new compiler does "move.m <registers> (%sp)" to save registers,
+    so we must copy the saved registers when we mung the sp.
+  The old compiler did "move.m <register> <offset>(%a6)", which
+    gave us no trouble
+ */
+	text
+	set	PROBE,-128	# safety for C frame temporaries
+	set	MAXREG,22	# d2-d7, a2-a5, fp2-fp7 may have been saved
+	global	_alloca
+_alloca:
+	mov.l	(%sp)+,%a0	# return address
+	mov.l	(%sp)+,%d0	# number of bytes to allocate
+	mov.l	%sp,%a1		# save old sp for register copy
+	mov.l	%sp,%d1		# compute new sp
+	sub.l	%d0,%d1		# space requested
+	and.l	&-4,%d1		# round down to longword
+	sub.l	&MAXREG*4,%d1	# space for saving registers
+	mov.l	%d1,%sp		# save new value of sp
+	tst.b	PROBE(%sp)	# create pages (sigh)
+	mov.l	%a2,%d1		# save reg a2
+	mov.l	%sp,%a2
+	move.w	&MAXREG-1,%d0
+copy_regs_loop:			/* save caller's saved registers */
+	mov.l	(%a1)+,(%a2)+
+	dbra	%d0,copy_regs_loop
+	mov.l	%a2,%d0		# return value
+	mov.l	%d1,%a2		# restore a2
+	add.l	&-4,%sp		# adjust tos
+	jmp	(%a0)		# rts
+#endif /* new hp assembler */
+#else
+#ifdef m68k			/* SGS assembler totally different */
+	file	"alloca.s"
+	global	alloca
+alloca:
+#ifdef MOTOROLA_DELTA
+/* slightly modified version of alloca to motorola sysV/68 pcc - based
+   compiler. 
+   this compiler saves used registers relative to %sp instead of %fp.
+   alright, just make new copy of saved register set whenever we allocate
+   new space from stack..
+   this is true at last until SVR3V5.1 . bug has reported to Motorola. */
+	set	MAXREG,10	# max no of registers to save (d2-d7, a2-a5)
+        mov.l   (%sp)+,%a1	# pop return addr from top of stack
+        mov.l   (%sp)+,%d0	# pop size in bytes from top of stack
+	mov.l	%sp,%a0		# save stack pointer for register copy
+        addq.l  &3,%d0		# round size up to long word
+        andi.l  &-4,%d0		# mask out lower two bits of size
+	mov.l	%sp,%d1		# compute new value of sp to d1
+        sub.l	%d0,%d1		# pseudo-allocate by moving stack pointer
+	sub.l	&MAXREG*4,%d1	# allocate more space for saved regs.
+	mov.l	%d1,%sp		# actual allocation.
+	move.w	&MAXREG-1,%d0	# d0 counts saved regs.
+	mov.l	%a2,%d1		# preserve a2.
+	mov.l	%sp,%a2		# make pointer to new reg save area.
+copy_regs_loop: 		# copy stuff from old save area.
+	mov.l	(%a0)+,(%a2)+	# save saved register
+	dbra	%d0,copy_regs_loop
+        mov.l   %a2,%a0		# now a2 is start of allocated space.
+	mov.l	%a2,%d0		# return it in both a0 and d0 to play safe.
+	mov.l	%d1,%a2		# restore a2.
+        subq.l  &4,%sp		# new top of stack
+        jmp     (%a1)		# far below normal return
+#else /* not MOTOROLA_DELTA */
+	mov.l	(%sp)+,%a1	# pop return addr from top of stack
+	mov.l	(%sp)+,%d0	# pop size in bytes from top of stack
+	add.l	&R%1,%d0	# round size up to long word
+	and.l	&-4,%d0		# mask out lower two bits of size
+	sub.l	%d0,%sp		# allocate by moving stack pointer
+	tst.b	P%1(%sp)	# stack probe to allocate pages
+	mov.l	%sp,%a0		# return pointer as pointer
+	mov.l	%sp,%d0		# return pointer as int to avoid disaster
+	add.l	&-4,%sp		# new top of stack
+	jmp	(%a1)		# not a normal return
+	set	S%1,64		# safety factor for C compiler scratch
+	set	R%1,3+S%1	# add to size for rounding
+	set	P%1,-132	# probe this far below current top of stack
+#endif /* not MOTOROLA_DELTA */
+
+#else /* not m68k */
+
+#ifdef m68000
+
+#ifdef WICAT
+/*
+ * Registers are saved after the corresponding link so we have to explicitly
+ * move them to the top of the stack where they are expected to be.
+ * Since we do not know how many registers were saved in the calling function
+ * we must assume the maximum possible (d2-d7,a2-a5).  Hence, we end up
+ * wasting some space on the stack.
+ *
+ * The large probe (tst.b) attempts to make up for the fact that we have
+ * potentially used up the space that the caller probed for its own needs.
+ */
+	.procss m0
+	.config "68000 1"
+	.module	_alloca
+MAXREG:	.const	10
+	.sect	text
+	.global	_alloca
+_alloca:
+	move.l	(sp)+,a1	; pop return address
+	move.l	(sp)+,d0	; pop allocation size
+	move.l	sp,d1		; get current SP value
+	sub.l	d0,d1		; adjust to reflect required size...
+	sub.l	#MAXREG*4,d1	; ...and space needed for registers
+	and.l	#-4,d1		; backup to longword boundry
+	move.l	sp,a0		; save old SP value for register copy
+	move.l	d1,sp		; set the new SP value
+	tst.b	-4096(sp)	; grab an extra page (to cover caller)
+	move.l	a2,d1		; save callers register
+	move.l	sp,a2
+	move.w	#MAXREG-1,d0	; # of longwords to copy
+loop:	move.l	(a0)+,(a2)+	; copy registers...
+	dbra	d0,loop		; ...til there are no more
+	move.l	a2,d0		; end of register area is addr for new space
+	move.l	d1,a2		; restore saved a2.
+	addq.l	#4,sp		; caller will increment sp by 4 after return.
+	move.l	d0,a0		; return value in both a0 and d0.
+	jmp	(a1)
+	.end	_alloca
+#else
+
+/* Some systems want the _, some do not.  Win with both kinds.  */
+.globl	_alloca
+_alloca:
+.globl	alloca
+alloca:
+	movl	sp@+,a0
+	movl	a7,d0
+	subl	sp@,d0
+	andl	#~3,d0
+	movl	d0,sp
+	tstb	sp@(0)		/* Make stack pages exist  */
+				/* Needed on certain systems
+				   that lack true demand paging */
+	addql	#4,d0
+	jmp	a0@
+
+#endif /* not WICAT */
+#endif /* m68000 */
+#endif /* not m68k */
+#endif /* not hp9000s300 */
+
+#if defined (ns16000) || defined (ns32000)
+
+	.text
+	.align	2
+/* Some systems want the _, some do not.  Win with both kinds.  */
+.globl	_alloca
+_alloca:
+.globl	alloca
+alloca:
+
+/* Two different assembler syntaxes are used for the same code
+	on different systems.  */
+
+#ifdef sequent
+#define IM
+#define REGISTER(x) x
+#else
+#ifdef NS5   /* ns SysV assembler */
+#define IM $
+#define REGISTER(x) x
+#else
+#define IM $
+#define REGISTER(x) 0(x)
+#endif
+#endif
+
+/*
+ * The ns16000 is a little more difficult, need to copy regs.
+ * Also the code assumes direct linkage call sequence (no mod table crap).
+ * We have to copy registers, and therefore waste 32 bytes.
+ *
+ * Stack layout:
+ * new	sp ->	junk	
+ *	 	registers (copy)
+ *	r0 ->	new data		
+ *		 | 	  (orig retval)
+ *		 |	  (orig arg)
+ * old  sp ->	regs	  (orig)
+ *		local data
+ *	fp ->	old fp
+ */
+
+	movd	tos,r1		/*  pop return addr */
+	negd	tos,r0		/*  pop amount to allocate */
+	sprd	sp,r2
+	addd	r2,r0
+	bicb	IM/**/3,r0	/*  4-byte align */
+	lprd	sp,r0
+	adjspb	IM/**/36	/*  space for regs, +4 for caller to pop */
+	movmd	0(r2),4(sp),IM/**/4	/*  copy regs */
+	movmd	0x10(r2),0x14(sp),IM/**/4
+	jump	REGISTER(r1)	/* funky return */
+#endif /* ns16000 or ns32000 */
+
+#ifdef pyramid
+
+.globl _alloca
+
+_alloca: addw $3,pr0	# add 3 (dec) to first argument
+	bicw $3,pr0	# then clear its last 2 bits
+	subw pr0,sp	# subtract from SP the val in PR0
+	andw $-32,sp	# keep sp aligned on multiple of 32.
+	movw sp,pr0	# ret. current SP
+	ret
+
+#ifdef PYRAMID_OLD /* This isn't needed in system version 4.  */
+.globl __longjmp
+.globl _longjmp
+.globl __setjmp
+.globl _setjmp
+
+__longjmp: jump _longjmp
+__setjmp:  jump _setjmp
+#endif
+
+#endif /* pyramid */
+
+#ifdef ATT3B5
+
+	.align 4
+	.globl alloca
+
+alloca:
+	movw %ap, %r8
+	subw2 $9*4, %r8
+	movw 0(%r8), %r1    /* pc */
+	movw 4(%r8), %fp
+	movw 8(%r8), %sp
+	addw2 %r0, %sp /* make room */
+	movw %sp, %r0 /* return value */
+	jmp (%r1) /* continue... */
+
+#endif /* ATT3B5 */
+
+#ifdef XENIX
+
+.386
+
+_TEXT segment dword use32 public 'CODE'
+assume   cs:_TEXT
+
+;-------------------------------------------------------------------------
+
+public _alloca
+_alloca proc near
+
+	pop	ecx		; return address
+	pop	eax		; amount to alloc
+	add	eax,3		; round it to 32-bit boundary
+	and	al,11111100B	;
+	mov	edx,esp		; current sp in edx
+	sub	edx,eax		; lower the stack
+	xchg	esp,edx		; start of allocation in esp, old sp in edx
+	mov	eax,esp		; return ptr to base in eax
+	push	[edx+8]		; save poss. stored reg. values (esi,edi,ebx)
+	push	[edx+4]		;  on lowered stack
+	push	[edx]		;
+	sub	esp,4		; allow for 'add esp, 4'
+	jmp	ecx		; jump to return address
+
+_alloca endp
+
+_TEXT	ends
+
+end
+
+#endif /* XENIX */
+
+#endif /* not HAVE_ALLOCA */