Upgraded to mh-e version 6.1.1.
[bpt/emacs.git] / src / alloca.s
CommitLineData
d5b2fb1e
RS
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.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
ba4a8e51
KH
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
d5b2fb1e
RS
18
19/* Both 68000 systems I have run this on have had broken versions of alloca.
20 Also, I am told that non-berkeley systems do not have it at all.
21 So replace whatever system-provided alloca there may be
22 on all 68000 systems. */
23
24#define NOT_C_CODE
25#ifdef emacs
26#include <config.h>
27#else
28#include "config.h"
29#endif
30
31#ifndef HAVE_ALLOCA /* define this to use system's alloca */
32
33#ifndef hp9000s300
34#ifndef m68k
35#ifndef m68000
36#ifndef WICAT
37#ifndef ns32000
38#ifndef ns16000
39#ifndef sequent
40#ifndef pyramid
41#ifndef ATT3B5
42#ifndef XENIX
43you
44lose!!
45#endif /* XENIX */
46#endif /* ATT3B5 */
47#endif /* pyramid */
48#endif /* sequent */
49#endif /* ns16000 */
50#endif /* ns32000 */
51#endif /* WICAT */
52#endif /* m68000 */
53#endif /* m68k */
54#endif /* hp9000s300 */
55
56
57#ifdef hp9000s300
58#ifdef OLD_HP_ASSEMBLER
59 data
60 text
61 globl _alloca
62_alloca
63 move.l (sp)+,a0 ; pop return addr from top of stack
64 move.l (sp)+,d0 ; pop size in bytes from top of stack
65 add.l #ROUND,d0 ; round size up to long word
66 and.l #MASK,d0 ; mask out lower two bits of size
67 sub.l d0,sp ; allocate by moving stack pointer
68 tst.b PROBE(sp) ; stack probe to allocate pages
69 move.l sp,d0 ; return pointer
70 add.l #-4,sp ; new top of stack
71 jmp (a0) ; not a normal return
72MASK equ -4 ; Longword alignment
73ROUND equ 3 ; ditto
74PROBE equ -128 ; safety buffer for C compiler scratch
75 data
76#else /* new hp assembler syntax */
77/*
78 The new compiler does "move.m <registers> (%sp)" to save registers,
79 so we must copy the saved registers when we mung the sp.
80 The old compiler did "move.m <register> <offset>(%a6)", which
81 gave us no trouble
82 */
83 text
84 set PROBE,-128 # safety for C frame temporaries
85 set MAXREG,22 # d2-d7, a2-a5, fp2-fp7 may have been saved
86 global _alloca
87_alloca:
88 mov.l (%sp)+,%a0 # return address
89 mov.l (%sp)+,%d0 # number of bytes to allocate
90 mov.l %sp,%a1 # save old sp for register copy
91 mov.l %sp,%d1 # compute new sp
92 sub.l %d0,%d1 # space requested
93 and.l &-4,%d1 # round down to longword
94 sub.l &MAXREG*4,%d1 # space for saving registers
95 mov.l %d1,%sp # save new value of sp
96 tst.b PROBE(%sp) # create pages (sigh)
97 mov.l %a2,%d1 # save reg a2
98 mov.l %sp,%a2
99 move.w &MAXREG-1,%d0
100copy_regs_loop: /* save caller's saved registers */
101 mov.l (%a1)+,(%a2)+
102 dbra %d0,copy_regs_loop
103 mov.l %a2,%d0 # return value
104 mov.l %d1,%a2 # restore a2
105 add.l &-4,%sp # adjust tos
106 jmp (%a0) # rts
107#endif /* new hp assembler */
108#else
109#ifdef m68k /* SGS assembler totally different */
110 file "alloca.s"
111 global alloca
112alloca:
113#ifdef MOTOROLA_DELTA
114/* slightly modified version of alloca to motorola sysV/68 pcc - based
115 compiler.
116 this compiler saves used registers relative to %sp instead of %fp.
117 alright, just make new copy of saved register set whenever we allocate
118 new space from stack..
6998c541 119 this is true at last until SVR3V7 . bug has reported to Motorola. */
d5b2fb1e
RS
120 set MAXREG,10 # max no of registers to save (d2-d7, a2-a5)
121 mov.l (%sp)+,%a1 # pop return addr from top of stack
122 mov.l (%sp)+,%d0 # pop size in bytes from top of stack
123 mov.l %sp,%a0 # save stack pointer for register copy
124 addq.l &3,%d0 # round size up to long word
125 andi.l &-4,%d0 # mask out lower two bits of size
126 mov.l %sp,%d1 # compute new value of sp to d1
127 sub.l %d0,%d1 # pseudo-allocate by moving stack pointer
128 sub.l &MAXREG*4,%d1 # allocate more space for saved regs.
129 mov.l %d1,%sp # actual allocation.
130 move.w &MAXREG-1,%d0 # d0 counts saved regs.
131 mov.l %a2,%d1 # preserve a2.
132 mov.l %sp,%a2 # make pointer to new reg save area.
133copy_regs_loop: # copy stuff from old save area.
134 mov.l (%a0)+,(%a2)+ # save saved register
135 dbra %d0,copy_regs_loop
136 mov.l %a2,%a0 # now a2 is start of allocated space.
137 mov.l %a2,%d0 # return it in both a0 and d0 to play safe.
138 mov.l %d1,%a2 # restore a2.
139 subq.l &4,%sp # new top of stack
140 jmp (%a1) # far below normal return
141#else /* not MOTOROLA_DELTA */
142 mov.l (%sp)+,%a1 # pop return addr from top of stack
143 mov.l (%sp)+,%d0 # pop size in bytes from top of stack
144 add.l &R%1,%d0 # round size up to long word
145 and.l &-4,%d0 # mask out lower two bits of size
146 sub.l %d0,%sp # allocate by moving stack pointer
147 tst.b P%1(%sp) # stack probe to allocate pages
148 mov.l %sp,%a0 # return pointer as pointer
149 mov.l %sp,%d0 # return pointer as int to avoid disaster
150 add.l &-4,%sp # new top of stack
151 jmp (%a1) # not a normal return
152 set S%1,64 # safety factor for C compiler scratch
153 set R%1,3+S%1 # add to size for rounding
154 set P%1,-132 # probe this far below current top of stack
155#endif /* not MOTOROLA_DELTA */
156
157#else /* not m68k */
158
159#ifdef m68000
160
161#ifdef WICAT
162/*
163 * Registers are saved after the corresponding link so we have to explicitly
164 * move them to the top of the stack where they are expected to be.
165 * Since we do not know how many registers were saved in the calling function
166 * we must assume the maximum possible (d2-d7,a2-a5). Hence, we end up
167 * wasting some space on the stack.
168 *
169 * The large probe (tst.b) attempts to make up for the fact that we have
170 * potentially used up the space that the caller probed for its own needs.
171 */
172 .procss m0
173 .config "68000 1"
174 .module _alloca
175MAXREG: .const 10
176 .sect text
177 .global _alloca
178_alloca:
179 move.l (sp)+,a1 ; pop return address
180 move.l (sp)+,d0 ; pop allocation size
181 move.l sp,d1 ; get current SP value
182 sub.l d0,d1 ; adjust to reflect required size...
183 sub.l #MAXREG*4,d1 ; ...and space needed for registers
168c8aec 184 and.l #-4,d1 ; backup to longword boundary
d5b2fb1e
RS
185 move.l sp,a0 ; save old SP value for register copy
186 move.l d1,sp ; set the new SP value
187 tst.b -4096(sp) ; grab an extra page (to cover caller)
188 move.l a2,d1 ; save callers register
189 move.l sp,a2
190 move.w #MAXREG-1,d0 ; # of longwords to copy
191loop: move.l (a0)+,(a2)+ ; copy registers...
192 dbra d0,loop ; ...til there are no more
193 move.l a2,d0 ; end of register area is addr for new space
194 move.l d1,a2 ; restore saved a2.
195 addq.l #4,sp ; caller will increment sp by 4 after return.
196 move.l d0,a0 ; return value in both a0 and d0.
197 jmp (a1)
198 .end _alloca
199#else
200
201/* Some systems want the _, some do not. Win with both kinds. */
202.globl _alloca
203_alloca:
204.globl alloca
205alloca:
206 movl sp@+,a0
207 movl a7,d0
208 subl sp@,d0
209 andl #~3,d0
210 movl d0,sp
211 tstb sp@(0) /* Make stack pages exist */
212 /* Needed on certain systems
213 that lack true demand paging */
214 addql #4,d0
215 jmp a0@
216
217#endif /* not WICAT */
218#endif /* m68000 */
219#endif /* not m68k */
220#endif /* not hp9000s300 */
221
222#if defined (ns16000) || defined (ns32000)
223
224 .text
225 .align 2
226/* Some systems want the _, some do not. Win with both kinds. */
227.globl _alloca
228_alloca:
229.globl alloca
230alloca:
231
232/* Two different assembler syntaxes are used for the same code
233 on different systems. */
234
235#ifdef sequent
236#define IM
237#define REGISTER(x) x
238#else
239#ifdef NS5 /* ns SysV assembler */
240#define IM $
241#define REGISTER(x) x
242#else
243#define IM $
244#define REGISTER(x) 0(x)
245#endif
246#endif
247
248/*
249 * The ns16000 is a little more difficult, need to copy regs.
250 * Also the code assumes direct linkage call sequence (no mod table crap).
251 * We have to copy registers, and therefore waste 32 bytes.
252 *
253 * Stack layout:
254 * new sp -> junk
255 * registers (copy)
256 * r0 -> new data
257 * | (orig retval)
258 * | (orig arg)
259 * old sp -> regs (orig)
260 * local data
261 * fp -> old fp
262 */
263
264 movd tos,r1 /* pop return addr */
265 negd tos,r0 /* pop amount to allocate */
266 sprd sp,r2
267 addd r2,r0
268 bicb IM/**/3,r0 /* 4-byte align */
269 lprd sp,r0
270 adjspb IM/**/36 /* space for regs, +4 for caller to pop */
271 movmd 0(r2),4(sp),IM/**/4 /* copy regs */
272 movmd 0x10(r2),0x14(sp),IM/**/4
273 jump REGISTER(r1) /* funky return */
274#endif /* ns16000 or ns32000 */
275
276#ifdef pyramid
277
278.globl _alloca
279
280_alloca: addw $3,pr0 # add 3 (dec) to first argument
281 bicw $3,pr0 # then clear its last 2 bits
282 subw pr0,sp # subtract from SP the val in PR0
283 andw $-32,sp # keep sp aligned on multiple of 32.
284 movw sp,pr0 # ret. current SP
285 ret
286
287#ifdef PYRAMID_OLD /* This isn't needed in system version 4. */
288.globl __longjmp
289.globl _longjmp
290.globl __setjmp
291.globl _setjmp
292
293__longjmp: jump _longjmp
294__setjmp: jump _setjmp
295#endif
296
297#endif /* pyramid */
298
299#ifdef ATT3B5
300
301 .align 4
302 .globl alloca
303
304alloca:
305 movw %ap, %r8
306 subw2 $9*4, %r8
307 movw 0(%r8), %r1 /* pc */
308 movw 4(%r8), %fp
309 movw 8(%r8), %sp
310 addw2 %r0, %sp /* make room */
311 movw %sp, %r0 /* return value */
312 jmp (%r1) /* continue... */
313
314#endif /* ATT3B5 */
315
316#ifdef XENIX
317
318.386
319
320_TEXT segment dword use32 public 'CODE'
321assume cs:_TEXT
322
323;-------------------------------------------------------------------------
324
325public _alloca
326_alloca proc near
327
328 pop ecx ; return address
329 pop eax ; amount to alloc
330 add eax,3 ; round it to 32-bit boundary
331 and al,11111100B ;
332 mov edx,esp ; current sp in edx
333 sub edx,eax ; lower the stack
334 xchg esp,edx ; start of allocation in esp, old sp in edx
335 mov eax,esp ; return ptr to base in eax
336 push [edx+8] ; save poss. stored reg. values (esi,edi,ebx)
337 push [edx+4] ; on lowered stack
338 push [edx] ;
339 sub esp,4 ; allow for 'add esp, 4'
340 jmp ecx ; jump to return address
341
342_alloca endp
343
344_TEXT ends
345
346end
347
348#endif /* XENIX */
349
350#endif /* not HAVE_ALLOCA */