diff options
author | Richard M. Stallman <rms@gnu.org> | 1994-03-20 06:30:14 +0000 |
---|---|---|
committer | Richard M. Stallman <rms@gnu.org> | 1994-03-20 06:30:14 +0000 |
commit | 8400fbcabeb1faffb6d88ad461a0c448204c009b (patch) | |
tree | 78f96f45644009d92c8acfd77b44cabd444f3b9b /src/alloca.s | |
parent | 3eac514d1f7a5a979290856e621050e5c3bc1541 (diff) | |
download | emacs-8400fbcabeb1faffb6d88ad461a0c448204c009b.tar.gz |
Initial revision
Diffstat (limited to 'src/alloca.s')
-rw-r--r-- | src/alloca.s | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/src/alloca.s b/src/alloca.s new file mode 100644 index 00000000000..2892aaf8f11 --- /dev/null +++ b/src/alloca.s @@ -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 */ |