Mercurial > emacs
annotate src/alloca.s @ 49666:9f435c19ea6f
(struct Lisp_Process): New member filter_multibyte.
| author | Kenichi Handa <handa@m17n.org> |
|---|---|
| date | Mon, 10 Feb 2003 07:45:13 +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 */ |
