home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / programs / develop / gadtoolsbox / nofraglib / source / memfunc.s < prev   
Text File  |  1995-02-27  |  18KB  |  414 lines

  1.                 opt     l+,o+,ow-,inconce
  2.  
  3. *-- AutoRev header do NOT edit!
  4. *
  5. *   Program         :   memfunc.s
  6. *   Copyright       :   © Copyright 1991-92 Jaba Development
  7. *   Author          :   Jan van den Baard
  8. *   Creation Date   :   06-Apr-91
  9. *   Current version :   2.2
  10. *   Translator      :   Devpac version 2.14
  11. *
  12. *   REVISION HISTORY
  13. *
  14. *   Date          Version         Comment
  15. *   ---------     -------         ------------------------------------------
  16. *   12-Apr-92     2.2             Should be enforcer and mungwall free now.
  17. *   19-May-91     2.1             Added 'Vec' routines.
  18. *   06-Apr-91     1.1             Initial version!
  19. *
  20. *-- REV_END --*
  21.  
  22.             incdir      'sys:asm20/'
  23.             include     'mymacros.i'
  24.             include     'libraries/nofrag.i'
  25.             include     'exec/exec_lib.i'
  26.  
  27.             xdef        GetMemoryChain
  28.             xdef        AllocItem
  29.             xdef        FreeItem
  30.             xdef        FreeMemoryChain
  31.             xdef        AllocVecItem
  32.             xdef        FreeVecItem
  33.  
  34. ROUND       MACRO
  35.             addq.l      #7,\1
  36.             and.l       #-8,\1
  37.             ENDM
  38.  
  39. _SysBase    EQU         $0004
  40.  
  41. ;
  42. ; Allocate and initialize a MemoryChain for use. It allocates the structure
  43. ; from the system free memory pool and then initializes it.
  44. ;
  45. GetMemoryChain:
  46.             pushem.l    d2/a2/a6
  47.             move.l      d0,d2               ; block size to d2
  48.             move.l      (_SysBase).w,a6
  49.             moveq       #mc_SIZEOF,d0
  50.             move.l      #MEMF_PUBLIC!MEMF_CLEAR,d1
  51.             libcall     AllocMem            ; allocate chain structure
  52.             move.l      d0,a2               ; put it in a2
  53.             tst.l       d0
  54.             beq.s       NoChain             ; FAILED !?!?!
  55.             lea.l       mc_Blocks(a2),a0
  56.             NEWLIST     a0                  ; initialize block list
  57.             lea.l       mc_Items(a2),a0
  58.             NEWLIST     a0                  ; initialize item list
  59.             ROUND       d2                  ; allign the block size
  60.             move.l      d2,mc_BlockSize(a2) ; put it in the structure
  61.             move.l      a2,d0
  62. NoChain:    popem.l     d2/a2/a6
  63.             rts
  64.  
  65. ;
  66. ; Deallocate a block of memory. It removes all "Free Items" from the
  67. ; chain it's "Free Item List" and then deallocates the memory the
  68. ; block used.
  69. ;
  70. FreeBlock:  pushem.l    a2-a3/a5-a6
  71.             move.l      a0,a2               ; chain to a2
  72.             move.l      a1,a3               ; block to a3
  73.             lea.l       mc_Items(a2),a5
  74.             move.l      il_First(a5),a5     ; first item in a5
  75. FBLoop:     tst.l       mit_Next(a5)        ; is there a next item ?
  76.             beq.s       FBDone              ; no.. done
  77.             cmp.l       mit_Block(a5),a3    ; item in the block ?
  78.             bne.s       FBNotSame           ; no.. get next item
  79.             move.l      a5,a1
  80.             REMOVE                          ; remove item from the list
  81.             lea.l       mc_Items(a2),a5
  82.             move.l      il_First(a5),a5
  83.             bra.s       FBLoop              ; start from the begin
  84. FBNotSame:  move.l      mit_Next(a5),a5
  85.             bra.s       FBLoop              ; try the next item
  86. FBDone:     move.l      a3,a1
  87.             REMOVE                          ; remove block from the list
  88.             move.l      (_SysBase).w,a6
  89.             move.l      a3,a1
  90.             move.l      mc_BlockSize(a2),d0
  91.             add.l       #mb_SIZEOF,d0
  92.             libcall     FreeMem             ; free the block's memory
  93.             popem.l     a2-a3/a5-a6
  94.             rts
  95.  
  96. ;
  97. ; Allocate a block of memory for a chain. This routine allocates enough
  98. ; memory from the system free memory pool to hold the MemoryBlock
  99. ; structure and the number of bytes specified with GetMemoryChain().
  100. ; Then it initializes the MemoryBlock structure and creates one "Free Item"
  101. ; the size of the whole block. Then it hangs this item in the chain it's
  102. ; "Free Item List"
  103. ;
  104. AllocBlock: pushem.l    d2/a2-a3/a5-a6
  105.             move.l      a0,a2               ; chain to a2
  106.             move.l      d0,d2               ; reqs to d2
  107.             move.l      d2,d1
  108.             move.l      mc_BlockSize(a2),d0
  109.             add.l       #mb_SIZEOF,d0       ; add room for Block structure
  110.             move.l      (_SysBase).w,a6
  111.             libcall     AllocMem            ; allocate the memory
  112.             move.l      d0,a3               ; put it in a3
  113.             tst.l       d0
  114.             beq.s       ABNoMem             ; FAILED !?!?!
  115.             move.l      d2,mb_Requirements(a3) ; set block reqs
  116.             clr.l       mb_BytesUsed(a3)    ; clear bytes used counter
  117.             lea.l       mc_Blocks(a2),a0
  118.             move.l      a3,a1
  119.             ADDHEAD                         ; add block in the list
  120.             move.l      a3,a5
  121.             add.l       #mb_SIZEOF,a5       ; get first item in a5
  122.             move.l      a3,mit_Block(a5)    ; set it's block
  123.             move.l      mc_BlockSize(a2),mit_Size(a5) ; set it's size
  124.             lea.l       mc_Items(a2),a0
  125.             move.l      a5,a1
  126.             ADDHEAD                         ; add item in the list
  127.             move.l      a3,d0               ; return the block
  128. ABEnd:      popem.l     d2/a2-a3/a5-a6
  129.             rts
  130. ABNoMem:    cldat       d0                  ; alloc failed.. return 0
  131.             bra.s       ABEnd
  132.  
  133. ;
  134. ; This routine optimizes a MemoryBlock. It looks up all "Free Items"
  135. ; located in the block and hangs them in a seperate list. Then it starts
  136. ; to look for items that are located directly after eachother in memory.
  137. ; If it find such items it will merge them together into on bigger item.
  138. ; It continues to do this until it doesn't find items located after each-
  139. ; other anymore. This will prevent the fragmentizing in the memory chain
  140. ; itself.
  141. ;
  142. OptimizeBlock:
  143.             link        a6,#-il_SIZEOF      ; create stack space
  144.             pushem.l    d2/a2-a6
  145.             move.l      a0,a2               ; chain to a2
  146.             move.l      a1,a3               ; block to a3
  147.             lea.l       -il_SIZEOF(a6),a0
  148.             NEWLIST     a0                  ; init buffer list
  149.             lea.l       mc_Items(a2),a4
  150.             move.l      il_First(a4),a4     ; first item to a4
  151. OBLoop1:    tst.l       mit_Next(a4)        ; is there a next item ?
  152.             beq.s       OBDone1             ; no.. done
  153.             cmp.l       mit_Block(a4),a3    ; item in the block ?
  154.             bne.s       OBNotSame1          ; no.. skip it
  155.             move.l      a4,a1
  156.             REMOVE                          ; remove item
  157.             lea.l       -il_SIZEOF(a6),a0
  158.             move.l      a4,a1
  159.             ADDTAIL                         ; put item in buffer list
  160.             lea.l       mc_Items(a2),a4
  161.             move.l      il_First(a4),a4
  162.             bra.s       OBLoop1             ; start from the begin
  163. OBNotSame1: move.l      mit_Next(a4),a4
  164.             bra.s       OBLoop1             ; try the next item
  165. OBDone1:    lea.l       -il_SIZEOF(a6),a0
  166.             move.l      il_First(a0),a4     ; first buffer item in a4
  167. OBLoop2:    tst.l       mit_Next(a4)        ; is there a next item ?
  168.             beq.s       OBDone2             ; no.. done
  169.             move.l      a4,d2
  170.             add.l       mit_Size(a4),d2     ; addres behind item to d2
  171.             move.l      a4,a5
  172. OBLoop3:    tst.l       mit_Next(a5)        ; is there a next item ?
  173.             beq.s       OBDone3             ; no.. done
  174.             cmp.l       d2,a5               ; d2 is a5 ?
  175.             bne.s       OBNotSame2          ; no.. skip it
  176.             move.l      mit_Size(a5),d0
  177.             add.l       d0,mit_Size(a4)     ; join a4 with a5
  178.             add.l       d0,d2
  179.             move.l      a5,a1
  180.             REMOVE                          ; remove a5 from the list
  181.             lea.l       -il_SIZEOF(a6),a0
  182.             move.l      il_First(a0),a5
  183.             bra.s       OBLoop3             ; start from the begin
  184. OBNotSame2: move.l      mit_Next(a5),a5
  185.             bra.s       OBLoop3             ; try the next item
  186. OBDone3:    move.l      mit_Next(a4),a4
  187.             bra.s       OBLoop2             ; try the next item
  188. OBDone2:    lea.l       -il_SIZEOF(a6),a0
  189.             REMHEAD                         ; remove item from the buffer
  190.             tst.l       d0                  ; is it 0 ?
  191.             beq.s       NoMore              ; yes.. all done
  192.             move.l      d0,a1
  193.             lea.l       mc_Items(a2),a0
  194.             ADDHEAD                         ; add it to the list
  195.             bra.s       OBDone2
  196. NoMore:     popem.l     d2/a2-a6
  197.             unlk        a6
  198.             rts
  199.  
  200. ;
  201. ; This routines looks through the "Free Item List" of the chain to find
  202. ; a "Free Item" that meets the requested size and requirements.
  203. ;
  204. FindSpace:  pushem.l    d2-d3/a2-a3
  205.             move.l      a0,a2               ; chain to a2
  206.             move.l      d0,d2               ; size to d2
  207.             move.l      d1,d3               ; reqs to d3
  208.             lea.l       mc_Items(a2),a3
  209.             move.l      il_First(a3),a3     ; first item to a3
  210. FSLoop:     tst.l       mit_Next(a3)        ; is there a next item ?
  211.             beq.s       FSDone              ; no.. done
  212.             move.l      mit_Block(a3),a0
  213.             cmp.l       mb_Requirements(a0),d3 ; requirements OK ?
  214.             bne.s       FSNotSame           ; no.. skip it
  215.             cmp.l       mit_Size(a3),d2     ; size OK ?
  216.             bhi.s       FSNotSame           ; no.. skip it
  217.             move.l      a3,d0               ; return the item
  218.             bra.s       FSEnd
  219. FSNotSame:  move.l      mit_Next(a3),a3
  220.             bra.s       FSLoop              ; try the next item
  221. FSDone:     cldat       d0                  ; no item found
  222. FSEnd:      popem.l     d2-d3/a2-a3
  223.             rts
  224.  
  225. ;
  226. ; Allocate memory from a chain. This routine uses FindSpace() to find a
  227. ; suitable "Free Item" in the chain. If it does not find such an item it
  228. ; will allocate a new MemoryBlock.
  229. ;
  230. AllocItem:  pushem.l    d2-d4/a2-a5
  231.             move.l      a0,a2               ; chain to a2
  232.             move.l      d0,d2               ; size to d2
  233.             move.l      d1,d3               ; reqs to d3
  234.             bclr.l      #16,d3              ; clear MEMF_CLEAR   bit
  235.             bclr.l      #17,d3              ; clear MEMF_LARGEST bit
  236.             cmp.l       #mit_SIZEOF,D2      ; size > mit_SIZEOF ?
  237.             bhi.s       ASOK                ; yes.. ok
  238.             move.l      #mit_SIZEOF,d2      ; else make it that big
  239. ASOK:       ROUND       d2                  ; allign the size
  240.             cmp.l       mc_BlockSize(a2),d2
  241.             bhi.s       NoMem
  242.             move.l      d3,d1
  243.             move.l      d2,d0
  244.             move.l      a2,a0
  245.             bsr         FindSpace           ; find a suitable item
  246.             move.l      d0,a4               ; put it in a4
  247.             tst.l       d0
  248.             bne.s       HaveSpace           ; found one..
  249.             move.l      d3,d0
  250.             move.l      a2,a0
  251.             bsr         AllocBlock          ; allocate a block
  252.             move.l      d0,a4               ; put it in a4
  253.             tst.l       d0
  254.             beq         NoMem               ; no more memory (wheeee)
  255.             add.l       #mb_SIZEOF,a4       ; get first item
  256. ;
  257. ; NOTE: This routine will split up the item if the size left
  258. ; is big enough to hold a "MemoryItem" structure. If not it won't
  259. ; split the item up the size left will not be used again. This means
  260. ; that after a chain has been used for some time to (de)allocate items
  261. ; in it is possible that not all bytes of a block can be used.
  262. ;
  263. HaveSpace:  move.l      mit_Block(a4),a3    ; get block in a3
  264.             cmp.l       mit_Size(a4),d2     ; size equals item size ?
  265.             beq.s       NoSplit             ; yes.. don't split it
  266.             move.l      mit_Size(a4),d4
  267.             sub.l       d2,d4
  268.             cmp.l       #mit_SIZEOF,d4      ; size left < mit_SIZEOF ?
  269.             bcs.s       NoSplit             ; yes.. don't split it
  270.             move.l      a4,a5
  271.             add.l       d2,a5               ; new item in a5
  272.             move.l      d4,mit_Size(a5)     ; set new item size
  273.             move.l      a3,mit_Block(a5)    ; set new item block
  274.             lea.l       mc_Items(a2),a0
  275.             move.l      a5,a1
  276.             ADDHEAD                         ; add it in the list
  277. NoSplit:    move.l      a4,a1
  278.             REMOVE                          ; remove it from the list
  279.             move.l      a4,a0
  280.             move.l      d2,d0
  281.             bsr         ClearAlloc          ; clear memory
  282.             add.l       d2,mb_BytesUsed(a3) ; increase bytes used counter
  283.             move.l      a4,d0               ; return the pointer
  284. AIEnd:      popem.l     d2-d4/a2-a5
  285.             rts
  286. NoMem:      cldat   d0                      ; no memory.. return 0
  287.             bra.s   AIEnd
  288.  
  289. ;
  290. ; Free memory in a MemoryChain. This routine takes the pointer it has
  291. ; been passed and check to see what block it was allocated in. Then it
  292. ; will convert the memory pointed to in a "Free Item" and hang it in the
  293. ; "Free Item List" of the chain. If the MemoryBlock is empty after this
  294. ; the routine will deallocate the block.
  295. ;
  296. FreeItem:   pushem.l    d2/a2-a4
  297.             move.l      a0,a2               ; chain to a2
  298.             move.l      a1,a3               ; memptr to a3
  299.             move.l      d0,d2               ; size to d2
  300.             cmp.l       #mit_SIZEOF,d2      ; size > mit_SIZEOF ?
  301.             bhi.s       FSOK                ; yes.. ok
  302.             move.l      #mit_SIZEOF,d2      ; else make it that big
  303. FSOK:       ROUND       d2                  ; allign the size
  304.             bsr         FindBlock           ; find it's block
  305.             move.l      d0,a4               ; and put it in a4
  306.             tst.l       d0
  307.             beq         FRDone              ; block 0.. don't free
  308.             move.l      a4,mit_Block(a3)    ; set item block
  309.             move.l      d2,mit_Size(a3)     ; set item size
  310.             sub.l       d2,mb_BytesUsed(a4) ; decrease bytes used count
  311.             move.l      a3,a1
  312.             lea.l       mc_Items(a2),a0
  313.             ADDHEAD                         ; add item in the list
  314.             tst.l       mb_BytesUsed(a4)
  315.             bne.s       FROpt               ; block not free
  316.             move.l      mit_Block(a3),a1
  317.             move.l      a2,a0
  318.             bsr         FreeBlock           ; free the block
  319.             bra.s       FRDone
  320. FROpt:      move.l      a2,a0
  321.             move.l      a4,a1
  322.             bsr         OptimizeBlock       ; optimize the block
  323. FRDone:     popem.l     d2/a2-a4
  324.             rts
  325.  
  326. ;
  327. ; This routine looks for the block in which memory was allocated.
  328. ;
  329. FindBlock:  push.l      a2
  330.             lea.l       mc_Blocks(a0),a2
  331.             move.l      bl_First(a2),a2     ; first block to a2
  332. FBBLoop:    tst.l       mb_Next(a2)         ; is there a next block ?
  333.             beq.s       FBBDone             ; no.. done
  334.             move.l      a2,d0
  335.             cmp.l       d0,a1               ; memptr < block start ?
  336.             bmi.s       FBBNotSame          ; yes.. skip it
  337.             add.l       #mb_SIZEOF,d0
  338.             add.l       mc_BlockSize(a0),d0
  339.             cmp.l       d0,a1               ; memptr > block end ?
  340.             bhi.s       FBBNotSame          ; yes.. skip it
  341.             move.l      a2,d0               ; return block
  342.             bra.s       EndFBB
  343. FBBNotSame: move.l      mb_Next(a2),a2
  344.             bra.s       FBBLoop             ; try the next block
  345. FBBDone:    cldat       d0                  ; block not found.. return 0
  346. EndFBB:     pop.l       a2
  347.             rts
  348.  
  349. ;
  350. ; Deallocate all MemoryBlocks from the chain and, if requested,
  351. ; deallocate the chain to.
  352. ;
  353. FreeMemoryChain:
  354.             pushem.l    d2/a2-a3/a6
  355.             move.l      a0,a2               ; chain to a2
  356.             move.l      d0,d2               ; struct free flag
  357.             move.l      (_SysBase).w,a6
  358. FMCLoop:    lea.l       mc_Blocks(a2),a0
  359.             REMHEAD                         ; remove a block
  360.             move.l      d0,a1               ; put it in a1
  361.             tst.l       d0
  362.             beq.s       ChkDone             ; block 0 then done
  363.             move.l      mc_BlockSize(a2),d0
  364.             add.l       #mb_SIZEOF,d0
  365.             libcall     FreeMem             ; free it's memory
  366.             bra.s       FMCLoop
  367. ChkDone:    tst.l       d2
  368.             bne.s       AllDone             ; free structure!
  369.             lea.l       mc_Items(a2),a0
  370.             NEWLIST     a0
  371.             lea.l       mc_Blocks(a2),a0
  372.             NEWLIST     a0
  373.             bra.s       FMCEnd
  374. AllDone:    move.l      a2,a1
  375.             moveq       #mc_SIZEOF,d0
  376.             libcall     FreeMem             ; free the chain structure
  377. FMCEnd:     popem.l     d2/a2-a3/a6
  378.             rts
  379.  
  380. ;
  381. ; Fill the allocated item with zero's.
  382. ;
  383. ClearAlloc: lsr.l       #2,d0               ; size / 4
  384.             dec.l       d0
  385. Loop:       clr.l       (a0)+               ; clear a long word
  386.             dbra        d0,Loop
  387.             rts
  388.  
  389. ;
  390. ; The same as AllocItem() exept that it remebers the size
  391. ; allocated.
  392. ;
  393. AllocVecItem:
  394.             push.l      d2
  395.             addq.l      #4,d0               ; make room to store size
  396.             move.l      d0,d2               ; save to size
  397.             bsr         AllocItem           ; allocate the item
  398.             move.l      d0,a0               ; result to a0
  399.             tst.l       d0
  400.             beq.s       NoVecMem            ; failed !?!?!
  401.             move.l      d2,(a0)+            ; store size
  402.             move.l      a0,d0               ; return memory pointer
  403. NoVecMem:   pop.l       d2
  404.             rts
  405.  
  406. ;
  407. ; Free the memory allocated with AllocVecItem()
  408. ;
  409. FreeVecItem:
  410.             subq.l      #4,a1               ; get orig alloc address
  411.             move.l      (a1),d0             ; get the size
  412.             bsr         FreeItem            ; free the memory
  413.             rts
  414.