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