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