|
|
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 distributed in the hope that it will be useful, ! 8: but WITHOUT ANY WARRANTY. No author or distributor ! 9: accepts responsibility to anyone for the consequences of using it ! 10: or for whether it serves any particular purpose or works at all, ! 11: unless he says so in writing. Refer to the GNU Emacs General Public ! 12: License for full details. ! 13: ! 14: Everyone is granted permission to copy, modify and redistribute ! 15: GNU Emacs, but only under the conditions described in the ! 16: GNU Emacs General Public License. A copy of this license is ! 17: supposed to have been given to you along with GNU Emacs so you ! 18: can know your rights and responsibilities. It should be in a ! 19: file named COPYING. Among other things, the copyright notice ! 20: and this notice must be preserved on all copies. */ ! 21: ! 22: ! 23: /* Both 68000 systems I have run this on have had broken versions of alloca. ! 24: Also, I am told that non-berkeley systems do not have it at all. ! 25: So replace whatever system-provided alloca there may be ! 26: on all 68000 systems. */ ! 27: ! 28: #define NOT_C_CODE ! 29: #include "config.h" ! 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 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 /* ns16000 */ ! 49: #endif /* WICAT */ ! 50: #endif /* m68000 */ ! 51: #endif /* m68k */ ! 52: #endif /* hp9000s300 */ ! 53: ! 54: ! 55: #ifdef hp9000s300 ! 56: #ifdef OLD_HP_ASSEMBLER ! 57: data ! 58: text ! 59: globl _alloca ! 60: _alloca ! 61: move.l (sp)+,a0 ; pop return addr from top of stack ! 62: move.l (sp)+,d0 ; pop size in bytes from top of stack ! 63: add.l #ROUND,d0 ; round size up to long word ! 64: and.l #MASK,d0 ; mask out lower two bits of size ! 65: sub.l d0,sp ; allocate by moving stack pointer ! 66: tst.b PROBE(sp) ; stack probe to allocate pages ! 67: move.l sp,d0 ; return pointer ! 68: add.l #-4,sp ; new top of stack ! 69: jmp (a0) ; not a normal return ! 70: MASK equ -4 ; Longword alignment ! 71: ROUND equ 3 ; ditto ! 72: PROBE equ -128 ; safety buffer for C compiler scratch ! 73: data ! 74: #else /* new hp assembler syntax */ ! 75: /* ! 76: The new compiler does "move.m <registers> (%sp)" to save registers, ! 77: so we must copy the saved registers when we mung the sp. ! 78: The old compiler did "move.m <register> <offset>(%a6)", which ! 79: gave us no trouble ! 80: */ ! 81: text ! 82: set PROBE,-128 # safety for C frame temporaries ! 83: set MAXREG,22 # d2-d7, a2-a5, fp2-fp7 may have been saved ! 84: global _alloca ! 85: _alloca: ! 86: mov.l (%sp)+,%a0 # return addess ! 87: mov.l (%sp)+,%d0 # number of bytes to allocate ! 88: mov.l %sp,%a1 # save old sp for register copy ! 89: mov.l %sp,%d1 # compute new sp ! 90: sub.l %d0,%d1 # space requested ! 91: and.l &-4,%d1 # round down to longword ! 92: sub.l &MAXREG*4,%d1 # space for saving registers ! 93: mov.l %d1,%sp # save new value of sp ! 94: tst.b PROBE(%sp) # create pages (sigh) ! 95: move.w &MAXREG-1,%d0 ! 96: copy_regs_loop: /* save caller's saved registers */ ! 97: mov.l (%a1)+,(%sp)+ ! 98: dbra %d0,copy_regs_loop ! 99: mov.l %sp,%d0 # return value ! 100: mov.l %d1,%sp ! 101: add.l &-4,%sp # adjust tos ! 102: jmp (%a0) # rts ! 103: #endif /* new hp assembler */ ! 104: #else ! 105: #ifdef m68k /* SGS assembler totally different */ ! 106: file "alloca.s" ! 107: global alloca ! 108: alloca: ! 109: mov.l (%sp)+,%a1 # pop return addr from top of stack ! 110: mov.l (%sp)+,%d0 # pop size in bytes from top of stack ! 111: add.l &R%1,%d0 # round size up to long word ! 112: and.l &-4,%d0 # mask out lower two bits of size ! 113: sub.l %d0,%sp # allocate by moving stack pointer ! 114: tst.b P%1(%sp) # stack probe to allocate pages ! 115: mov.l %sp,%a0 # return pointer as pointer ! 116: mov.l %sp,%d0 # return pointer as int to avoid disaster ! 117: add.l &-4,%sp # new top of stack ! 118: jmp (%a1) # not a normal return ! 119: set S%1,64 # safety factor for C compiler scratch ! 120: set R%1,3+S%1 # add to size for rounding ! 121: set P%1,-132 # probe this far below current top of stack ! 122: ! 123: #else /* not m68k */ ! 124: ! 125: #ifdef m68000 ! 126: ! 127: #ifdef WICAT ! 128: /* ! 129: * Registers are saved after the corresponding link so we have to explicitly ! 130: * move them to the top of the stack where they are expected to be. ! 131: * Since we do not know how many registers were saved in the calling function ! 132: * we must assume the maximum possible (d2-d7,a2-a5). Hence, we end up ! 133: * wasting some space on the stack. ! 134: * ! 135: * The large probe (tst.b) attempts to make up for the fact that we have ! 136: * potentially used up the space that the caller probed for its own needs. ! 137: */ ! 138: .procss m0 ! 139: .config "68000 1" ! 140: .module _alloca ! 141: MAXREG: .const 10 ! 142: .sect text ! 143: .global _alloca ! 144: _alloca: ! 145: move.l (sp)+,a1 ; pop return address ! 146: move.l (sp)+,d0 ; pop allocation size ! 147: move.l sp,d1 ; get current SP value ! 148: sub.l d0,d1 ; adjust to reflect required size... ! 149: sub.l #MAXREG*4,d1 ; ...and space needed for registers ! 150: and.l #-4,d1 ; backup to longword boundry ! 151: move.l sp,a0 ; save old SP value for register copy ! 152: move.l d1,sp ; set the new SP value ! 153: tst.b -4096(sp) ; grab an extra page (to cover caller) ! 154: move.l a2,d1 ; save callers register ! 155: move.l sp,a2 ! 156: move.w #MAXREG-1,d0 ; # of longwords to copy ! 157: loop: move.l (a0)+,(a2)+ ; copy registers... ! 158: dbra d0,loop ; ...til there are no more ! 159: move.l a2,d0 ; end of register area is addr for new space ! 160: move.l d1,a2 ; restore saved a2. ! 161: addq.l #4,sp ; caller will increment sp by 4 after return. ! 162: move.l d0,a0 ; return value in both a0 and d0. ! 163: jmp (a1) ! 164: .end _alloca ! 165: #else ! 166: ! 167: /* Some systems want the _, some do not. Win with both kinds. */ ! 168: .globl _alloca ! 169: _alloca: ! 170: .globl alloca ! 171: alloca: ! 172: movl sp@+,a0 ! 173: movl a7,d0 ! 174: subl sp@,d0 ! 175: andl #~3,d0 ! 176: movl d0,sp ! 177: tstb sp@(0) /* Make stack pages exist */ ! 178: /* Needed on certain systems ! 179: that lack true demand paging */ ! 180: addql #4,d0 ! 181: jmp a0@ ! 182: ! 183: #endif /* not WICAT */ ! 184: #endif /* m68000 */ ! 185: #endif /* not m68k */ ! 186: #endif /* not hp9000s300 */ ! 187: ! 188: #ifdef ns16000 ! 189: ! 190: .text ! 191: .align 2 ! 192: /* Some systems want the _, some do not. Win with both kinds. */ ! 193: .globl _alloca ! 194: _alloca: ! 195: .globl alloca ! 196: alloca: ! 197: ! 198: /* Two different assembler syntaxes are used for the same code ! 199: on different systems. */ ! 200: ! 201: #ifdef sequent ! 202: #define IM ! 203: #define REGISTER(x) x ! 204: #else ! 205: #define IM $ ! 206: #define REGISTER(x) 0(x) ! 207: #endif ! 208: ! 209: /* ! 210: * The ns16000 is a little more difficult, need to copy regs. ! 211: * Also the code assumes direct linkage call sequence (no mod table crap). ! 212: * We have to copy registers, and therefore waste 32 bytes. ! 213: * ! 214: * Stack layout: ! 215: * new sp -> junk ! 216: * registers (copy) ! 217: * r0 -> new data ! 218: * | (orig retval) ! 219: * | (orig arg) ! 220: * old sp -> regs (orig) ! 221: * local data ! 222: * fp -> old fp ! 223: */ ! 224: ! 225: movd tos,r1 /* pop return addr */ ! 226: negd tos,r0 /* pop amount to allocate */ ! 227: sprd sp,r2 ! 228: addd r2,r0 ! 229: bicb IM/**/3,r0 /* 4-byte align */ ! 230: lprd sp,r0 ! 231: adjspb IM/**/36 /* space for regs, +4 for caller to pop */ ! 232: movmd 0(r2),4(sp),IM/**/4 /* copy regs */ ! 233: movmd 0x10(r2),0x14(sp),IM/**/4 ! 234: jump REGISTER(r1) /* funky return */ ! 235: #endif /* ns16000 */ ! 236: ! 237: #ifdef pyramid ! 238: ! 239: .globl _alloca ! 240: ! 241: _alloca: addw $3,pr0 # add 3 (dec) to first argument ! 242: bicw $3,pr0 # then clear its last 2 bits ! 243: subw pr0,sp # subtract from SP the val in PR0 ! 244: andw $-32,sp # keep sp aligned on multiple of 32. ! 245: movw sp,pr0 # ret. current SP ! 246: ret ! 247: ! 248: #ifdef PYRAMID_OLD /* This isn't needed in system version 4. */ ! 249: .globl __longjmp ! 250: .globl _longjmp ! 251: .globl __setjmp ! 252: .globl _setjmp ! 253: ! 254: __longjmp: jump _longjmp ! 255: __setjmp: jump _setjmp ! 256: #endif ! 257: ! 258: #endif /* pyramid */ ! 259: ! 260: #ifdef ATT3B5 ! 261: ! 262: .align 4 ! 263: .globl alloca ! 264: ! 265: alloca: ! 266: movw %ap, %r8 ! 267: subw2 $9*4, %r8 ! 268: movw 0(%r8), %r1 /* pc */ ! 269: movw 4(%r8), %fp ! 270: movw 8(%r8), %sp ! 271: addw2 %r0, %sp /* make room */ ! 272: movw %sp, %r0 /* return value */ ! 273: jmp (%r1) /* continue... */ ! 274: ! 275: #endif /* ATT3B5 */ ! 276: ! 277: #ifdef XENIX ! 278: ! 279: .386 ! 280: ! 281: _TEXT segment dword use32 public 'CODE' ! 282: assume cs:_TEXT ! 283: ! 284: ;------------------------------------------------------------------------- ! 285: ! 286: public _alloca ! 287: _alloca proc near ! 288: ! 289: pop ecx ; return address ! 290: pop eax ; amount to alloc ! 291: add eax,3 ; round it to 32-bit boundary ! 292: and al,11111100B ; ! 293: mov edx,esp ; current sp in edx ! 294: sub edx,eax ; lower the stack ! 295: xchg esp,edx ; start of allocation in esp, old sp in edx ! 296: mov eax,esp ; return ptr to base in eax ! 297: push [edx+8] ; save poss. stored reg. values (esi,edi,ebx) ! 298: push [edx+4] ; on lowered stack ! 299: push [edx] ; ! 300: sub esp,4 ; allow for 'add esp, 4' ! 301: jmp ecx ; jump to return address ! 302: ! 303: _alloca endp ! 304: ! 305: _TEXT ends ! 306: ! 307: end ! 308: ! 309: #endif /* XENIX */ ! 310: ! 311: #endif /* not HAVE_ALLOCA */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.