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.
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
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.
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. */
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. */
31 #ifndef HAVE_ALLOCA /* define this to use system's alloca */
54 #endif /* hp9000s300 */
58 #ifdef OLD_HP_ASSEMBLER
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
74 PROBE equ
-128 ; safety buffer for C compiler scratch
76 #else /* new hp assembler syntax */
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
84 set PROBE
,-128 # safety for C frame temporaries
85 set MAXREG
,22 # d2-d7, a2-a5, fp2-fp7 may have been saved
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
100 copy_regs_loop
: /* save caller's saved registers */
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
107 #endif /* new hp assembler */
109 #ifdef m68k /* SGS assembler totally different */
113 #ifdef MOTOROLA_DELTA
114 /* slightly modified version of alloca to motorola sysV/68 pcc - based
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 */
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.
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.
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
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.
201 /* Some systems want the _, some do not. Win with both kinds. */
211 tstb sp@
(0) /* Make stack pages exist */
212 /* Needed on certain systems
213 that lack true demand paging */
217 #endif /* not WICAT */
219 #endif /* not m68k */
220 #endif /* not hp9000s300 */
222 #if defined (ns16000) || defined (ns32000)
226 /* Some systems want the _, some do not. Win with both kinds. */
232 /* Two different assembler syntaxes are used for the same code
233 on different systems. */
237 #define REGISTER(x) x
239 #ifdef NS5 /* ns SysV assembler */
241 #define REGISTER(x) x
244 #define REGISTER(x) 0(x)
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.
259 * old sp -> regs (orig)
264 movd tos
,r1 /* pop return addr */
265 negd tos
,r0 /* pop amount to allocate */
268 bicb IM
/**/3,r0 /* 4-byte align */
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 */
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
287 #ifdef PYRAMID_OLD /* This isn't needed in system version 4. */
293 __longjmp
: jump _longjmp
294 __setjmp
: jump _setjmp
307 movw
0(%r8), %r1 /* pc */
310 addw2
%r0, %sp
/* make room */
311 movw
%sp
, %r0 /* return value */
312 jmp
(%r1) /* continue... */
320 _TEXT segment dword use32 public
'CODE'
323 ;
-------------------------------------------------------------------------
328 pop ecx ; return address
329 pop eax ; amount to alloc
330 add eax
,3 ; round it to
32-bit boundary
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
339 sub esp
,4 ; allow for
'add esp, 4'
340 jmp ecx ; jump to return address
350 #endif /* not HAVE_ALLOCA */