home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / e20313sr.zip / emacs / 20.3.1 / src / alloca.s < prev    next >
Text File  |  1999-07-31  |  10KB  |  351 lines

  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.  
  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. */
  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
  62. _alloca    
  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
  115.    compiler. 
  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 */
  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
  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
  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:
  254.  * new    sp ->    junk    
  255.  *         registers (copy)
  256.  *    r0 ->    new data        
  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 */
  351.