Mercurial > emacs
annotate src/alloca.s @ 51157:aa7ae88aeb60
*** empty log message ***
author | Lute Kamstra <lute@gnu.org> |
---|---|
date | Fri, 23 May 2003 10:10:24 +0000 |
parents | 23a1cea22d13 |
children |
rev | line source |
---|---|
6437 | 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 | |
14414 | 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. */ | |
6437 | 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 | |
43 you | |
44 lose!! | |
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 | |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
14414
diff
changeset
|
62 _alloca |
6437 | 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 | |
72 MASK equ -4 ; Longword alignment | |
73 ROUND equ 3 ; ditto | |
74 PROBE 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 | |
100 copy_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 | |
112 alloca: | |
113 #ifdef MOTOROLA_DELTA | |
114 /* slightly modified version of alloca to motorola sysV/68 pcc - based | |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
14414
diff
changeset
|
115 compiler. |
6437 | 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.. | |
6815 | 119 this is true at last until SVR3V7 . bug has reported to Motorola. */ |
6437 | 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. | |
133 copy_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 | |
175 MAXREG: .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 | |
13691 | 184 and.l #-4,d1 ; backup to longword boundary |
6437 | 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 | |
191 loop: 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 | |
205 alloca: | |
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 | |
230 alloca: | |
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: | |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
14414
diff
changeset
|
254 * new sp -> junk |
6437 | 255 * registers (copy) |
49600
23a1cea22d13
Trailing whitespace deleted.
Juanma Barranquero <lekktu@gmail.com>
parents:
14414
diff
changeset
|
256 * r0 -> new data |
6437 | 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 | |
304 alloca: | |
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' | |
321 assume cs:_TEXT | |
322 | |
323 ;------------------------------------------------------------------------- | |
324 | |
325 public _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 | |
346 end | |
347 | |
348 #endif /* XENIX */ | |
349 | |
350 #endif /* not HAVE_ALLOCA */ |