root/trunk/src/alloca.s

Revision 1447, 9.8 kB (checked in by cvs2svn, 5 years ago)

190 copies to tags/branches

Line 
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
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. */
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
62 _alloca
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
115    compiler.
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..
119    this is true at last until SVR3V7 . bug has reported to Motorola. */
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
184         and.l   #-4,d1          ; backup to longword boundary
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:
254  * new  sp ->   junk   
255  *              registers (copy)
256  *      r0 ->   new data               
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 */
Note: See TracBrowser for help on using the browser.