home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / allocp32 / allocp32.asm next >
Encoding:
Assembly Source File  |  1997-10-14  |  12.7 KB  |  339 lines

  1.         opt o+,ow-
  2. ;*************************************************
  3. ;** AllocP32                                    **
  4. ;** Version 2.01                                **
  5. ;**---------------------------------------------**
  6. ;** © 1997 Andreas Kleinert                     **
  7. ;** © 1997 THOR-Software, Thomas Richter        **
  8. ;** rewritten in assembly language with the     **
  9. ;** friendly permission of A. Kleinert          **
  10. ;*************************************************
  11.  
  12.         include INC:exec_lib.asm                ;exec defines
  13.         include INC:macros.asm                  ;macro sets
  14.  
  15.         section main_code,code
  16.  
  17. ;FOLD Main structure
  18. ;*************************************************
  19. ;** Main structure                              **
  20. ;** used by the resident code                   **
  21. ;*************************************************
  22.         rsreset
  23. mn_OldAllocMem:         rs.l 1                  ;AllocMem Vector
  24. mn_OldFreeMem:          rs.l 1                  ;FreeMem Vector
  25. mn_SysBase:             rs.l 1                  ;ExecBase
  26. mn_LayersBase:          rs.l 1                  ;Start address of layers in the ROMs
  27. mn_LayersEnd:           rs.l 1                  ;End address of layers in the ROMs
  28. mn_len:                 rs.b 0
  29. ;ENDFOLD
  30. ;FOLD Start
  31. ;*************************************************
  32. ;** Start                                       **
  33. ;** main program, patch exec and detach         **
  34. ;** does not check for arguments                **
  35. ;*************************************************
  36. Start:
  37.         move.l ExecBase,a6
  38.  
  39.         lea BssBase,a5
  40.  
  41.         jsr Forbid(a6)
  42.         move.l a6,mn_SysBase(a5)
  43.  
  44.         bsr.s FindLayers                        ;locate layers.library
  45.  
  46.         move.l #NewAllocMem,d0
  47.         move.l a6,a1                            ;Library
  48.         lea AllocMem,a0
  49.         move.l (a1,a0.l),mn_OldAllocMem(a5)
  50.         jsr SetFunction(a6)                     ;install patch
  51.         move.l d0,mn_OldAllocMem(a5)            ;Save back old pointer
  52.  
  53.         move.l #NewFreeMem,d0
  54.         move.l a6,a1
  55.         lea FreeMem,a0
  56.         jsr SetFunction(a6)
  57.         move.l d0,mn_OldFreeMem(a5)
  58.  
  59.         lea Start(pc),a0
  60.         clr.l -4(a0)                            ;unlink the resident segment
  61.  
  62.         jsr Permit(a6)
  63.         moveq #0,d0                             ;that's all, folks!
  64.         rts
  65. ;ENDFOLD
  66. ;FOLD FindLayers
  67. ;*************************************************
  68. ;** FindLayers                                  **
  69. ;** the layers library memory allocation is     **
  70. ;** broken and not compatible to this patch     **
  71. ;** we filter all layers.calls out for this     **
  72. ;** reason                                      **
  73. ;** This routine determinates the region in     **
  74. ;** the ROMs where layers is located            **
  75. ;*************************************************
  76. FindLayers:
  77.         saveregs d5-d7/a3-a4
  78.  
  79.         lea LayersName,a1
  80.         move.l mn_SysBase(a5),a6
  81.         jsr FindResident(a6)
  82.         tst.l d0
  83.         beq.s .alertexit
  84.  
  85.         move.l  d0,mn_LayersBase(a5)            ;$46F660
  86.         movea.l mn_SysBase(a5),a0               ;$46F63C,a0
  87.         movea.l $12C(a0),a4
  88.         addi.l  #$40000,d0
  89.         move.l  d0,mn_LayersEnd(a5)             ;$46F664
  90.         moveq   #$7D,d7
  91.         lsl.l   #3,d7
  92.         moveq   #0,d6
  93.         moveq   #0,d5
  94.         movea.l a4,a3
  95.         bra.s .inloop
  96. .cmpnow:
  97.         move.l  (a4),d0
  98.         cmp.l mn_LayersBase(a5),d0
  99.         bls.s .tolow
  100.         cmp.l mn_LayersEnd(a5),d0
  101.         bcc.s .tolow
  102.         move.l d0,mn_LayersEnd(a5)
  103. .tolow:
  104.         addq.l #4,a4
  105.         addq.l #1,d6
  106. .next:
  107.         tst.l (a4)
  108.         bne.s .cmpnow
  109.         move.l  d6,d7
  110.         moveq   #0,d6
  111.         movea.l a3,a4
  112.         addq.l  #1,d5
  113. .inloop
  114.         cmp.l d7,d5
  115.         ble.s .next
  116.         bra.s .exit
  117.  
  118. .alertexit:
  119.         saveregs d7/a5
  120.         move.l $114(a6),a5
  121.         move.l #$0103000f,d7
  122.         jsr Alert(a6)
  123.         loadregs
  124. .exit:
  125.         loadregs
  126.         rts
  127. ;ENDFOLD
  128.  
  129.         dc.b "$VER: AllocP32 2.01",0              ;Version ID
  130. LayersName:
  131.         dc.b "layers.library",0
  132.  
  133.         section resident_code,code
  134. ;FOLD NewAllocMem
  135. ;*************************************************
  136. ;** NewAllocMem                                 **
  137. ;** this is the new AllocMem vector             **
  138. ;** a6=ExecBase, d0=bytesize, d1=req.ments      **
  139. ;**                                             **
  140. ;** no need to patch AllocVec separately,       **
  141. ;** it calls this vector anyways.               **
  142. ;*************************************************
  143. NewAllocMem:
  144.         saveregs d2-d3/a2/a5
  145.  
  146.         lea BssBase,a5
  147.         move.l d0,d2
  148.         move.l $10(a7),a0                       ;get calling PC
  149.         move.l d1,d3                            ;safe back size & reqments
  150.         move.l mn_OldAllocMem(a5),a2            ;get old vector
  151.  
  152.         cmp.l mn_LayersBase(a5),a0
  153.         blo.s .nolayers
  154.         cmp.l mn_LayersEnd(a5),a0               ;if called from layers, use ordinary memory (no way to fix it!)
  155.         blo.s .islayers
  156. .nolayers:
  157.  
  158.         ;now try to get memory in 32 byte blocks.
  159.         ;it's actually not required that the memory is
  160.         ;aligned to 32 byte boundaries, it is only
  161.         ;required that one part of it is in the
  162.         ;cache of the MC and another part is in the
  163.         ;cache of the PPC. Since cache lines of the PPC
  164.         ;are 32 bytes wide, rounding the size to the
  165.         ;next multiple of 32 WOULD be enough, if there
  166.         ;wouldn't be this nasty "feature" of the
  167.         ;layers.library - we aren't allowed there
  168.         ;to do any rounding and must precisely
  169.         ;return the memory block requested. This is
  170.         ;due to the feature of layers to request one
  171.         ;big block of memory, but returning it
  172.         ;in small snippets afterwards. THIS IS
  173.         ;ILLEGAL DUE TO THE RKRM RULES, but CBM didn't
  174.         ;care about it. MungWall and MemSniff have
  175.         ;similar troubles with layers for just the
  176.         ;same reason.
  177.         ;Therefore, we must really ADJUST the memory
  178.         ;returned to 32 byte boundaries.
  179.  
  180.         moveq #8+24+31,d0                       ;eight bytes for magic cookie and block start,
  181.                                                 ;24 bytes for proper alignemt
  182.                                                 ;31 bytes for alignment of the length to the
  183.                                                 ;next 32 byte boundary
  184.         add.l d2,d0                             ;get the size
  185.         and.b #$e0,d0                           ;round to next 32 byte boundary
  186.         bsr.s _Allocate                         ;now try to get the memory
  187.         tst.l d0                                ;got some?
  188.         beq.s .exit                             ;nope!
  189.  
  190.         moveq #31,d1                            ;for rounding
  191.         move.l d0,a0                            ;store address here
  192.         add.l d1,d0                             ;round to next
  193.         and.b #$e0,d0                           ;32 bytes block
  194.         move.l d0,a1                            ;result is here
  195.         move.l a0,(a0)
  196.         move.l a0,(a1)+                         ;store "real" address here (a1 and a0 might be the same, never mind)
  197.                                                 ;for later lookup and
  198.                                                 ;as "magic cookie"
  199.         move.l #'AP32',(a1)+                    ;store "magic cookie" itself
  200.         move.l a1,d0                            ;this is the address we return as result
  201.         bra.s .exit
  202.  
  203. .islayers:
  204.                                                 ;registers are still fine
  205.         bsr.s _Allocate                         ;Allocate the old style
  206.  
  207. .exit:
  208.         loadregs
  209.         rts
  210. ;ENDFOLD
  211. ;FOLD _Allocate
  212. ;*************************************************
  213. ;** _Allocate                                   **
  214. ;** Get memory. bytesize in d0, reqments in d1  **
  215. ;** this part is identical to AllocP            **
  216. ;** *a2 is the pointer to the old AllocMem      **
  217. ;** vector                                      **
  218. ;*************************************************
  219. _Allocate:
  220.         saveregs d2-d3
  221.  
  222.         move.l d1,d3                            ;no expunge?
  223.         bmi.s .tryonce                          ;yes, so try only once
  224.                                                 ;Check if this is an Expunge-Call
  225.         cmp.l #$ffffff00,d0
  226.         bhs.s .tryonce                          ;yes, try only once (to expunge!)
  227.  
  228.         ;remember well: We DO NOT need to round the size
  229.         ;here, this is done by the exec function internally
  230.         ;you are GUARANTEED to get memory aligned to
  231.         ;8 byte boundaries and of a size divisible by 8
  232.  
  233.         move.l d0,d2
  234.         jsr (a2)                                ;try to get memory
  235.         tst.l d0                                ;got it ?
  236.         bne.s .exit                             ;yes, so fine and exit
  237.  
  238.         ;if not: The above memory allocation may have started a flush
  239.         ;operation, but since everything happend in the Forbid() mode
  240.         ;above, some memory-free handlers might not have had a chance
  241.         ;to run. That happens AT LEAST HERE (multitasking!), so
  242.         ;we should try again. Call it an exec-feature!
  243.  
  244.         ;We DO NOT flush the memory with trying to allocate a
  245.         ;memory block of size ~0, since this will flush ALL
  246.         ;libraries & devices which is propably not necessary.
  247.  
  248.         move.l d2,d0
  249.         move.l d3,d1                            ;get parameters
  250.         jsr (a2)
  251.         tst.l d0
  252.         bne.s .exit                             ;now fine ?
  253.  
  254.         ;seems that this hasn't helped yet. So, now let's try it
  255.         ;the hard way: Remove ALL the stuff from memory by
  256.         ;trying the impossible: Public memory of size ~0
  257.  
  258.         moveq #-1,d0
  259.         moveq #1,d1
  260.         jsr (a2)                                ;get ALL of it!
  261.  
  262.         ;no chance that this has worked, but at least, the
  263.         ;memory is clean now!
  264.         ;We try again for a last time and give up if that hasn't
  265.         ;helped.
  266.  
  267.         move.l d2,d0
  268.         move.l d3,d1                    ;get parameters
  269. .tryonce:
  270.         jsr (a2)                        ;try it a last time
  271.  
  272.         ;if this fails, the user has to take care about it!
  273. .exit:
  274.         loadregs
  275.         rts
  276. ;ENDFOLD
  277. ;FOLD NewFreeMem
  278. ;*************************************************
  279. ;** NewFreeMem                                  **
  280. ;** FreeMem replacement *a6=SysBase             **
  281. ;**     *a1=Memory      d0=size                 **
  282. ;*************************************************
  283. NewFreeMem:
  284.         saveregs a2-a3/a5
  285.  
  286.         lea BssBase,a5
  287.  
  288.         move.l d0,d1
  289.         beq.s .exit                             ;size=0 -> exit gracefully
  290.         move.l $c(a7),a0                        ;get calling PC
  291.         move.l a1,d1
  292.         beq.s .exit                             ;address =0 -> exit gracefully
  293.         move.l mn_OldFreeMem(a5),a2             ;get old FreeMem vector
  294.         move.l a1,a3                            ;save memory address
  295.  
  296.         cmp.l mn_LayersBase(a5),a0
  297.         blo.s .nolayers
  298.         cmp.l mn_LayersEnd(a5),a0               ;if called from layers, use ordinary memory (no way to fix it!)
  299.         blo.s .islayers
  300. .nolayers:
  301.  
  302.         cmp.l #'AP32',-(a3)                     ;check for the magic cookie
  303.         bne.s .islayers                         ;if not, we never allocated this memory
  304.  
  305.         move.l -(a3),a0                         ;get base address of this memory
  306.  
  307.                                                 ;and now the same algorithm to
  308.                                                 ;find the size we used
  309.                                                 ;for allocation
  310.  
  311.         moveq #8+24+31,d1                       ;eight bytes for magic cookie and block start,
  312.                                                 ;24 bytes for proper alignemt
  313.                                                 ;31 bytes for alignment of the length to the
  314.                                                 ;next 32 byte boundary
  315.         add.l d0,d1                             ;get the size
  316.         and.b #$e0,d1                           ;round to next 32 byte boundary
  317.  
  318.         cmp.l (a0),a0                           ;is the base setup properly?
  319.         bne.s .islayers                         ;if not, free it the old way
  320.  
  321.         move.l d1,d0                            ;and the calculated size
  322.         move.l a0,a1                            ;if, use the base address
  323.         clr.l 4(a3)                             ;clear cookie explicitly
  324.                                                 ;to avoid later confusion
  325.  
  326. .islayers:                                      ;the registers are still fine here...
  327.         jsr (a2)                                ;call the old vector
  328. .exit:
  329.         loadregs
  330.         rts
  331. ;ENDFOLD
  332.  
  333.  
  334.         section resident_bss,bss
  335. BssBase:
  336.         ds.b mn_len                     ;main structure placed here
  337.  
  338.  
  339.