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