home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 534.lha / NoFragLib / Source / memfunc.s < prev   
Encoding:
Text File  |  1991-08-08  |  17.4 KB  |  405 lines

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