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