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