comparison src/alloca.s @ 0:376386a54a3c r19-14

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