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