1 /* `alloca' standard 4.2 subroutine for 68000's and 16000's and others.
2 Also has _setjmp and _longjmp for pyramids.
3 Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
5 This file is part of SXEmacs
7 SXEmacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 SXEmacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 /* Synched up with: FSF 19.30. */
23 /* Both 68000 systems I have run this on have had broken versions of alloca.
24 Also, I am told that non-berkeley systems do not have it at all.
25 So replace whatever system-provided alloca there may be
26 on all 68000 systems. */
35 #ifndef HAVE_ALLOCA /* define this to use system's alloca */
58 #endif /* hp9000s300 */
62 #ifdef OLD_HP_ASSEMBLER
67 move.l (sp)+,a0 ; pop return addr from top of stack
68 move.l (sp)+,d0 ; pop size in bytes from top of stack
69 add.l #ROUND,d0 ; round size up to long word
70 and.l #MASK,d0 ; mask out lower two bits of size
71 sub.l d0,sp ; allocate by moving stack pointer
72 tst.b PROBE(sp) ; stack probe to allocate pages
73 move.l sp,d0 ; return pointer
74 add.l #-4,sp ; new top of stack
75 jmp (a0) ; not a normal return
76 MASK equ -4 ; Longword alignment
78 PROBE equ -128 ; safety buffer for C compiler scratch
80 #else /* new hp assembler syntax */
82 The new compiler does "move.m <registers> (%sp)" to save registers,
83 so we must copy the saved registers when we mung the sp.
84 The old compiler did "move.m <register> <offset>(%a6)", which
88 set PROBE,-128 # safety for C frame temporaries
89 set MAXREG,22 # d2-d7, a2-a5, fp2-fp7 may have been saved
92 mov.l (%sp)+,%a0 # return address
93 mov.l (%sp)+,%d0 # number of bytes to allocate
94 mov.l %sp,%a1 # save old sp for register copy
95 mov.l %sp,%d1 # compute new sp
96 sub.l %d0,%d1 # space requested
97 and.l &-4,%d1 # round down to longword
98 sub.l &MAXREG*4,%d1 # space for saving registers
99 mov.l %d1,%sp # save new value of sp
100 tst.b PROBE(%sp) # create pages (sigh)
101 mov.l %a2,%d1 # save reg a2
104 copy_regs_loop: /* save caller's saved registers */
106 dbra %d0,copy_regs_loop
107 mov.l %a2,%d0 # return value
108 mov.l %d1,%a2 # restore a2
109 add.l &-4,%sp # adjust tos
111 #endif /* new hp assembler */
113 #ifdef m68k /* SGS assembler totally different */
117 #ifdef MOTOROLA_DELTA
118 /* slightly modified version of alloca to motorola sysV/68 pcc - based
120 this compiler saves used registers relative to %sp instead of %fp.
121 alright, just make new copy of saved register set whenever we allocate
122 new space from stack..
123 this is true at last until SVR3V7 . bug has reported to Motorola. */
124 set MAXREG,10 # max no of registers to save (d2-d7, a2-a5)
125 mov.l (%sp)+,%a1 # pop return addr from top of stack
126 mov.l (%sp)+,%d0 # pop size in bytes from top of stack
127 mov.l %sp,%a0 # save stack pointer for register copy
128 addq.l &3,%d0 # round size up to long word
129 andi.l &-4,%d0 # mask out lower two bits of size
130 mov.l %sp,%d1 # compute new value of sp to d1
131 sub.l %d0,%d1 # pseudo-allocate by moving stack pointer
132 sub.l &MAXREG*4,%d1 # allocate more space for saved regs.
133 mov.l %d1,%sp # actual allocation.
134 move.w &MAXREG-1,%d0 # d0 counts saved regs.
135 mov.l %a2,%d1 # preserve a2.
136 mov.l %sp,%a2 # make pointer to new reg save area.
137 copy_regs_loop: # copy stuff from old save area.
138 mov.l (%a0)+,(%a2)+ # save saved register
139 dbra %d0,copy_regs_loop
140 mov.l %a2,%a0 # now a2 is start of allocated space.
141 mov.l %a2,%d0 # return it in both a0 and d0 to play safe.
142 mov.l %d1,%a2 # restore a2.
143 subq.l &4,%sp # new top of stack
144 jmp (%a1) # far below normal return
145 #else /* not MOTOROLA_DELTA */
146 mov.l (%sp)+,%a1 # pop return addr from top of stack
147 mov.l (%sp)+,%d0 # pop size in bytes from top of stack
148 add.l &R%1,%d0 # round size up to long word
149 and.l &-4,%d0 # mask out lower two bits of size
150 sub.l %d0,%sp # allocate by moving stack pointer
151 tst.b P%1(%sp) # stack probe to allocate pages
152 mov.l %sp,%a0 # return pointer as pointer
153 mov.l %sp,%d0 # return pointer as int to avoid disaster
154 add.l &-4,%sp # new top of stack
155 jmp (%a1) # not a normal return
156 set S%1,64 # safety factor for C compiler scratch
157 set R%1,3+S%1 # add to size for rounding
158 set P%1,-132 # probe this far below current top of stack
159 #endif /* not MOTOROLA_DELTA */
167 * Registers are saved after the corresponding link so we have to explicitly
168 * move them to the top of the stack where they are expected to be.
169 * Since we do not know how many registers were saved in the calling function
170 * we must assume the maximum possible (d2-d7,a2-a5). Hence, we end up
171 * wasting some space on the stack.
173 * The large probe (tst.b) attempts to make up for the fact that we have
174 * potentially used up the space that the caller probed for its own needs.
183 move.l (sp)+,a1 ; pop return address
184 move.l (sp)+,d0 ; pop allocation size
185 move.l sp,d1 ; get current SP value
186 sub.l d0,d1 ; adjust to reflect required size...
187 sub.l #MAXREG*4,d1 ; ...and space needed for registers
188 and.l #-4,d1 ; backup to longword boundary
189 move.l sp,a0 ; save old SP value for register copy
190 move.l d1,sp ; set the new SP value
191 tst.b -4096(sp) ; grab an extra page (to cover caller)
192 move.l a2,d1 ; save callers register
194 move.w #MAXREG-1,d0 ; # of longwords to copy
195 loop: move.l (a0)+,(a2)+ ; copy registers...
196 dbra d0,loop ; ...til there are no more
197 move.l a2,d0 ; end of register area is addr for new space
198 move.l d1,a2 ; restore saved a2.
199 addq.l #4,sp ; caller will increment sp by 4 after return.
200 move.l d0,a0 ; return value in both a0 and d0.
205 /* Some systems want the _, some do not. Win with both kinds. */
215 tstb sp@(0) /* Make stack pages exist */
216 /* Needed on certain systems
217 that lack true demand paging */
221 #endif /* not WICAT */
223 #endif /* not m68k */
224 #endif /* not hp9000s300 */
226 #if defined (ns16000) || defined (ns32000)
230 /* Some systems want the _, some do not. Win with both kinds. */
236 /* Two different assembler syntaxes are used for the same code
237 on different systems. */
241 #define REGISTER(x) x
243 #ifdef NS5 /* ns SysV assembler */
245 #define REGISTER(x) x
248 #define REGISTER(x) 0(x)
253 * The ns16000 is a little more difficult, need to copy regs.
254 * Also the code assumes direct linkage call sequence (no mod table crap).
255 * We have to copy registers, and therefore waste 32 bytes.
263 * old sp -> regs (orig)
268 movd tos,r1 /* pop return addr */
269 negd tos,r0 /* pop amount to allocate */
272 bicb IM/**/3,r0 /* 4-byte align */
274 adjspb IM/**/36 /* space for regs, +4 for caller to pop */
275 movmd 0(r2),4(sp),IM/**/4 /* copy regs */
276 movmd 0x10(r2),0x14(sp),IM/**/4
277 jump REGISTER(r1) /* funky return */
278 #endif /* ns16000 or ns32000 */
284 _alloca: addw $3,pr0 # add 3 (dec) to first argument
285 bicw $3,pr0 # then clear its last 2 bits
286 subw pr0,sp # subtract from SP the val in PR0
287 andw $-32,sp # keep sp aligned on multiple of 32.
288 movw sp,pr0 # ret. current SP
291 #ifdef PYRAMID_OLD /* This isn't needed in system version 4. */
297 __longjmp: jump _longjmp
298 __setjmp: jump _setjmp
311 movw 0(%r8), %r1 /* pc */
314 addw2 %r0, %sp /* make room */
315 movw %sp, %r0 /* return value */
316 jmp (%r1) /* continue... */
324 _TEXT segment dword use32 public 'CODE'
327 ;-------------------------------------------------------------------------
332 pop ecx ; return address
333 pop eax ; amount to alloc
334 add eax,3 ; round it to 32-bit boundary
336 mov edx,esp ; current sp in edx
337 sub edx,eax ; lower the stack
338 xchg esp,edx ; start of allocation in esp, old sp in edx
339 mov eax,esp ; return ptr to base in eax
340 push [edx+8] ; save poss. stored reg. values (esi,edi,ebx)
341 push [edx+4] ; on lowered stack
343 sub esp,4 ; allow for 'add esp, 4'
344 jmp ecx ; jump to return address
354 #endif /* not HAVE_ALLOCA */