;__________________________________________________________________________________________________ ; ; File: MemoryMgr.a ; ; Contains: Client interface routines for 32-Bit Macintosh Memory Manager ; ; Supports multiple heap zones with mixed relocatable and non-relocatable storage blocks. ; Reorganized from code designed and written by Bud Tribble, 27-Nov-81, and maintained ; and modified by Angeline Lo, Larry Kenyon, and Andy Hertzfeld. ; ; Written by: Bud Tribble ; ; Copyright © 1981-1993 by Apple Computer, Inc. All rights reserved. ; ; Change History (most recent first): ; ; 10/12/93 SAM Roll in from mc900ftjesus. ; 10/12/93 SAM Updated InitMemMgr to be in sync with the figment version. From ; now on we should always build with Figment and choose which ; memmgr we want at a per launch basis. ; 5/20/93 BT Update sources to conditionally compile Figment under the build ; flag "hasNewHeapMgr". ; 5/18/93 BT Change names of InitMemMgr, InitMemVect, and ; SetApplBaseAfterBoot to "old_Å". Changed some BSR's to BSR.L's. ; All in the name of Figment, our beloved Walt Disney friend. ; 4/23/93 kc Roll in MoveHHi, NewPtr and RealocHandle patches from ; MemoryMgrPatches.a. Integrate some of the other patches to save ; a few cycles. ; 4/22/93 rab Removed code from FlushFontCaches that skipped the routine if ; CurApName wasn't valid. This fixes Radar# 1077877 and 1078314. ; 4/12/93 chp Rewrote MoveHHi head patch using half the number of ; instructions. ; 3/9/93 rab Bumped StkSlop in MoveHHi from 1024 to 3072 per Jim Reekes ; suggestion in bug #1067917. ; 2/22/93 PN Quad-word align the stackbuffer in MoveHHi call for 040 ; machines. ; 1/27/93 kc Fix bug in MaxAppleZone where we were rounding down the address ; of the HeapZone to the nearest quadword but not the address we ; were asking for. Fixes bug 1061295. ; 1/5/93 PN In the SuperMario ROM, many resources are put in ROM that used ; to be in the system disk. DisposeHandle is modified to leave the ; handle alone if it is passed a handle to a table or resource in ; ROM. ; 12/4/92 RB Rolled in changes to support NuKernel from Wayne Meretski and ; Russell Williams. Make RHBusErrHandler compatible with NuKernel. ; 12/4/92 SWC Moved InitMemMgr here from StartInit.a. ; 12/3/92 PN Back out previous change. This is the patch ; BracketSetAppBaseWithInitApplZones ; It will patch out the SetApplBase at Gibbly time when ; InstallMgr get called. The time when this patch applied is ; crucial (during boot time up to gibbly time this patch is NOT to ; be used, it is used after gibbly time) ; 11/19/92 PN Radar #1050264 the SetAppBase was calling bsr IAZ instead of ; _InitApplZone so a lot of clean up code was missing and lead to ; the bug. So I bracket the routine SetApplBase with the whole ; _InitApplZone. This is the patch ; BracketSetAppBasewithInitApplZone. ; 11/3/92 RB Do not force 32 bit mode for the LC930 by checking the feature ; conditional Supports24Bit. ; 10/26/92 CSS Fix some short branches and remove cache flushing from ; HLock. Also, added Supports24Bit conditional to conditionalize ; _StripAddress. ; 9/16/92 CSS Fix bsr to IOPram to use bsr.l. ; 7/28/92 PN Put CacheFlush back in HLock for compatibilty's sake ; 7/28/92 PN Bug fix. NewPtr call that grows the system heap will crash into ; Macsbug. The setting of semaphore flag was done incorrectly in ; ResrvMem and consequently caused the problem. It is fixed. Also, ; I take out the 040 cache flush in HLock to improve performance. ; 7/16/92 PN Take out cpu ³ 020 conditionals ; 6/11/92 PN Roll in FixStripAddress from PatchIIciROM.a ; 5/22/92 kc Append "Trap" to the names of ; CompactMem,GetPtrSize,HandleZone,InitZone,MaxBlock,NewEmptyHandl ; e,PtrZone,PurgeSpace,ReAllocHandle,RecoverHandle,SetHandleSize,S ; etPtrSize and StackSpace to avoid name conflict with the glue. ; 5/7/92 stb Added purge proc in InitZone for the TrueType disk cache (from ; DiskCachePatches.a). Moved some "other mgr" cleanup code around ; so itÕs all grouped nicely. ; 4/22/92 TN Clean up BracketSetAppBaseWithInitApplZones, roll in ; AllowNILDisposePtr, ResrvMemGrowSystemHeap, ; NewPtrGrowSystemHeapCleanly MoveHHiPatch from MemoryMgrPatches.a ; 4/16/92 PN Roll in SetAppBaseCacheCleaner and InitAppZoneCacheCleaner from ; BassPatches.a to remove any app memory allocated by Bass ; whenever the application heap is reformatted. ; 3/26/92 kc Force 32-bit mode. (see in MMU.a)ÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊ ; ¥¥¥¥ This should be backed out as soon as we carve out space for ; the 2 Meg rom from the slot address space. ¥¥¥¥; ; 3/24/92 PN Roll in BracketSetAppBaseWithInitApplZones into _SetappBase By ; calling bsr IAZ three times. ; 3/10/92 PN Back out the last change ; 3/9/92 kc Don't call jSoundDead untill we install the SoundMgr. ; 3/4/92 kc Add a semicolon. ; 3/4/92 kc Roll in vxxHlockPatch, vxxMaxMemPatch, v??CMGutsPatch ; InitxxZoneAlign, vxxMaxApplPatch, InitxxZoneAlign, ; AlignxxTrailer and SetApplBasePatch from Terror. Add patch to ; HLock that flushes cache on 040's. ; 7/10/91 RP Patched MaxApplZone for line alignment. ; 7/7/91 RP Patched MaxMem, CompactMem and MaxBlock to line-align free space ; values on 040s. ; 6/25/91 RP Patched to line align all blocks on 040 CPUs ; 5/29/91 CCH Backed out revision 4. ; 5/29/91 WM Changed MOVE to SR into ANDI to SR ; 4/21/91 CCH Removed HSetState patch since it was not used and is not needed. ; 4/2/91 CCH Patched HLock and HSetState to flush the cache. ; <1> 10/2/91 JSM first checked in ; <0> 10/1/91 JSM Created from Heap32.a. ; ; Modification history from Heap32.a below: ; ; <15> 9/27/91 JSM DonÕt use hasCQD conditional, all future ROMs will have color ; QuickDraw. ; <14> 9/16/91 JSM Cleanup header. ; <13> 6/12/91 LN removed #include 'HardwareEqu.a' ; <12> 12/19/90 DFH Removed StackSpace and MoveHHi jamming of HiHeapMark when ; HiHeapMark >= ApplLimit (from change <4>). This was really just ; a workaround for an app bug (SuperCard 1.00 on a portable), but ; that app has been fixed. Furthermore, the jamming interferes ; with parts of the system that want to use stacks other than the ; current application stack. ; <11> 7/30/90 BG Removed CPU = 040 conditional in preparation to move from Mac040 ; to Mac32 build. ; <10> 7/17/90 dba change names of GetHandleSize and StripAddress so they donÕt ; conflict with glue ; <9> 3/22/90 MSH New PRAM routines in clock.a require a small change to the ; caller. ; <8> 3/8/90 JAL Removed include of QuickEqu.a because it was colliding with StandardEqu.d ; <7> 1/25/90 BG Removed AERRORs from RecoverHandle and RHBusErrHandler. Added ; RH040BusErrHandler, and modified RecoverHandle to use the 040 ; bus error handler when necessary. ; <6> 1/18/90 DVB Include PalettePriv.a ; <5> 1/11/90 CCH Added include of ÒHardwarePrivateEqu.aÓ. ; <4> 1/11/90 MSH StkSpacePatch - Because some apps jam ApplLimit directly, it is ; possible for HiHeapMark>ApplLimit which should never be. This ; fix will jam ApplLimit into HiHeapMark if this is the case. ; MoveHHIPatch - MoveHHi uses HiHeapMark which may be in error due ; to the above problem. This patch forces MoveHHi to make the same ; check as above. ; <3> 1/3/90 BG Modifying the AERROR statements related to the 040 to use the ; correct quoting (single quotes, not double quotes). ; <2> 1/2/90 SWC Modified RecoverHandle to do a last-ditch check to see if a ; handle points to a ROM resource if the handle isn't in the ; system or app heap. Also compressed v24RecoverHandle and ; v32RecoverHandle into essentially one routine since very little ; is different. They'll enter with a value to mask off either 24 ; or 32 bits of an address. ; <2.2> 8/27/89 PKE Delete superfluous withs in InitApplZone; remove unnecessary ; include of 'ScriptPriv.a'. No code changes. ; <2.1> 8/22/89 SES Removed references to nFiles. ; <2.0> 7/14/89 CSL initialized sysheapis32bit flag in systemInfo byte. ; <1.9> 6/15/89 CSL Changed InitMemVect's way to initialize the 24 and 32 bit memory ; trap vector table. Used value from RealMemTop instead of MaxSize ; whenever an outlandish request for memory size. Added vectors ; for MMPrologue, MMPPrologue, MMHPrologue, MMRHPrologue, ; MMnoPrologue, MMEpilogue, MMNoErrEpilogue. MMnoPrologue is a new ; routine to handle routine that did not jump throught any ; Prologue routine. ; <¥1.8> 6/10/89 CEL Moved Private.a QuickDraw Equates into proper QuickDraw private ; file (colorequ.a), got rid of QuickDraw nFiles dependencies and ; fixed up necessary filesÉ ; <1.7> 5/24/89 GGD Converted to feature based conditionals, added checks for 68040 ; in places where changes will most likely be needed and generate ; assembly errors if assembling for a 68040. No code changes. ; <1.6> 4/28/89 CSL fixed bug in Reallochandle ; <1.5> 4/17/89 CSL Fixed the slimy Microsoft bugs in MaxBlock per BBM request. ; <1.4> 3/30/89 CSL write a safe address in address 0 for nil handle. ; <1.3> 3/22/89 CSL now Hlock, Hunlock, HPurge, HnoPurge, HRSRC, HnoRsrc, HGetFlags ; and HSetFlags all jump thu MMHPrologue, also added prevention ; code for slimy Light Speed C. ; <1.2> 3/11/89 CSL replaced reference of minfree by minfree24 and minfree32. ; <1.1> 2/28/89 CSL Added initialization for Jump vectors for MM traps and ; duplicate routines for 32 bit operations. ; <1.0> 2/13/89 CCH Adding to EASE for first time from 24-Bit source. ; ; 10/29/87 rwh Port to Modern Victorian (on MvMac) ; 9/30/87 MSH Port to HcMac (Laguna) by closing sound like numac ; 6/10/87 EHB Roll in patch to iazInit to clean up palette manager ; 6/2/87 JTC Roll in patch to MoveHHi to handle teeny leftovers. ; ; 2/14/87 JTC In the spirit of C778, adjust the initialization of ApplLimit ; and HiHeapMark in IAZ to use simply SP-DefltStack rather than ; old TomaxLimit value. ; 2/10/87 JTC Yet YET YET! another HiHeapMark change. C765 above fails because ; of the Pascal glue in the world that implements MaxApplZone sans ; trap; that code will grow the zone without changing HHM, causing ; many deaths to old apps. So we pin things at ApplLimit, even ; though thatÕs pessimistic. Also, add simple bus error handler to ; RecoverHandle, to jam ROMBase as bogus relative handle. ; 2/5/87 JTC Yet another HiHeapMark (HackHeapMark?) to accommodate the ; nonstandard mem config at boot time. Until now, HHM was set to ; ApplLimit (just below BufPtr) when the ApplZone was created. ; This breaks at start time, when the stack is artificially ; created down at MemTop/2. The change is to tighten HiHeapMark to ; indicate more accurately where the highest zone end is, as ; opposed to where it COULD BE. When the ApplZone is created, we ; set HiHeapMark to HeapEnd; thereafter, InitZone can set it ; higher if a strange zone is built above HiHeapMark, and the ; HeapGuts GrowZone can set it if ApplZone is grown beyond ; HiHeapMark. ; 2/2/87 JTC Undo C587 above, since weÕre using the more conservative ; approach of running with the stack mid-zone. Change to HeapGuts ; only. ; 2/1/87 JTC Fix MaxApplZone to jam HiHeapMark, in case itÕs out of sync with ; ApplLimit due to appÕs jamming latter without calling SetApplLimit. ; 1/24/87 JTC Move init code from Launch to InitApplZone. When 64K ROM patches ; were rolled into Heap, IAZ (the old InitApplZone) was kept ; separate from InitApplZone (the patch stuff, which called IAZ to ; do the real work). The effect was to deprive SetApplBase (who ; called IAZ) of the good init stuff. Because SetApplBase is ; called so early, it cannot benefit from the init code. WARNING: ; after the earliest time, callers of SetAB should also call ; InitApplZone to guarantee the best initialization. Among the new ; init things are the VBL and Snd cleanups and a call to ; _RDrvrInstall, which code is spread between the sound world and ; SegmentLoader.a. ; 1/14/87 JTC Make SetApplLimit sensitive to minimum stack size in DefltStack. ; Old-style apps like MacDraw and MacPaint jam ApplLimit to within ; 8K of SP, causing problems in color. Add bus error handlers to ; xxxPrologue routines DerefHandle and ZoneCheck, to allow bogus ; address to return with error codes rather than Deep6ing. ; 1/3/87 JTC Support boot time sizing of SysZone by making special case of ; (SP < bkLim(SysZone)) in HeapGuts routine MaxLimit. That routine ; constrains the (growing) application zone according to SP and a ; proposed limit; the test against SP is omitted in the case above ; to permit jamming the stack into a system heap block. The basis ; of the trick is that HiHeapMark is the stack lower bound; by ; forcing it to point into the stack block during boot time, stack ; can be allocated correctly by QD, _StackSpace, etc. while the ; heap merrily grows. StackSpace is changed to use HiHeapMark, as ; it should have from Mac+ days. ; 12/9/86 JTC Reinstate C251 alignment. Change to HeapGuts.a only. ; 11/17/86 JTC Back out some of the wonderful alignment feature to ; support our friends at Microsoft who gang-bang a large set of ; handles into a large, fixed block without checking for the 2 ; slop bytes we would like to give them to force longword ; alignment when their request is (2n+1)*2. Parts of that ; force alignment of the beginning of the zone are left in for the ; modest improvement they admit, and because there may be a way to ; salvage the Microsoft-style apps. The principal change is to ; routine ActualS in HeapGuts.a, where the rounding to a multiple ; of 4 is done. ; 10/30/86 JTC Roll in Mac+ patch to RecoverHandle to use the more reasonable ; of SysZone and ApplZone as ÒTheZoneÓ when incoming TheZone is ; one of Sys or Appl. Since RecoverHandle is strange, passing a ; pointer to a handle-related routine, the cleanest way is to ; customize a MMRHPrologue, ÒRHÓ as in RecoverHandle, of course, ; to do the A6 fixing. The only change to the code here in Heap is ; to JSR to MMRHPrologue rather than MMPrologue. MMRHPrologue has ; several extra lines to choose A6 wisely. ; 10/24/86 JTC Changes to support longword alignment of blocks. Since the heap ; header as well as individual block headers are multiples of 4 in ; size, the problem reduces to getting heaps started on longword ; boundaries and then allocating blocks in multiples of longwords. ; The first issue depends on the start code, which determines the ; system zone, maintainence of a 4x system heap (since the app ; heap always starts at its end), and a little change in ; SetAppBase to keep a resized system heap on a long boundary. For ; home-brew heaps that start on 4x+2 boundaries, InitZone contains ; some code to fudge the initial block, necessarily a master ; pointer block, to ensure that all following blocks are longword ; aligned. Code in InitZone ensures that the heap limit is on a ; long boundary. ; Once the zone is aligned, itÕs up to internal code to keep ; allocations properly aligned. Internal routine ActualS is the key. ; It now rounds up to the nearest multiple of 4 (not 2, as before); ; the slop is picked up by internal routine SetLogSize as usual. ; ApplLimit and its associated routine SetApplLimit are left as is, ; since the variable may be tweaked from within an app with impunity. ; Instead, uses of ApplLimit for resizing the zone or calculating ; available size are carefully monitored. Internal routine MaxLimit ; usually brackes uses of ApplLimit, so it is made to round down to ; the nearest multiple of 4. MaxApplZone, which uses ApplLimit ; directly, are modified to round it down to a multiple of 4 first. ; StackSpace rounds the SP down to a multiple of 4 before computing ; available space. ; 10/17/86 CRC InitApplZone sets up FMExist, LastSpExtra only for Font Manager. ; 10/9/86 bbm Modified to mpw aincludes/ changed resourc to resource. ; 9/23/86 JTC Add _StripAddress. ; 3/31/86 BBM added a blank line in order to work with the assembler. ; 2/19/86 BBM Made some modifications to work under MPW ; 1/13/86 JTC 1. Patch InitApplZone to inval font cach by setting LastSPExtra ; to -1. <13Jan86 JTC> ; 2. Save/Restore theZone across MoveHHi so theZone can be set to ; that of the moving handle. ; 3. Add 4 calls to set/clr rsrc bit of handle and pull flag byte ; from master ptr. ; ; 11/1/85 JTC New global HiHeapMark tracks heap ends below SP -- InitApplZone, ; SetApplLimit, <01Nov85> InitZone, MoveHHi. ; ; 10/27/85 BBM needed more space, added three branch shorts. ; 5/29/85 JTC Made a MOVE a MOVEQ to be sure error code is long. <29May85> ; 5/21/85 JTC Distinguish Nil and empty in Disposehandle. <21May85> ; 5/10/85 KWK Removed JSR to OS code. <10May85> ; 5/10/85 JTC InitMem moved to Start code to facilitate separate linking. <10May85> ; 5/9/85 JTC Added call StackSpace. <09May85> ; 5/6/85 JTC Initialize new FontMgr globals. <06May85> ; 5/4/85 JTC Incorporated MoveHHi. <04May85> ; 4/27/85 JTC Moved MakeStkPB into code with conditional assembly, to ; facilitate RAM-based... <27Apr85> ; 4/25/85 JTC Add new common exit for non-MMEpilogue routines to stuff return ; code in MemErr. <25Apr85> Amend RecoverHandle to use special ; MMNoErrEpilogue. ; 4/24/85 JTC Modify HLock, etc. to bypass MMHPrologue to weaken their error ; checking (since <24Apr85> MicroSoft calls with bad handles) but ; to bypass 0 when passed in. ; 4/24/85 JTC Added MaxApplLimit, with slight modifications from OSTraps ; source. <24Apr85> ; 4/23/85 JTC Backed out validity check and error code in RecoverHandle -- ; it's documented as <23Apr85> as such in Inside Mac! Code ; restored to original version. ; 4/17/85 JTC Add call PurgeSpace. <17Apr85> ; 4/16/85 JTC Fix no-error code at end of InitApplZone. <16Apr85> ; 4/14/85 JTC Change InitApplZone to start zone up high in stack. Subject to ; further tuning... <14Apr85> ; 4/13/85 JTC Add validity check and error code to RecoverHandle. <13Apr85> ; 4/10/85 JTC Add call MaxBlock, to return max available free space that could ; be gotten <10Apr85> without purge or grow. Revitalize ; EmptyHandle and DisposeHandle to be effective even in ROZ, so ; that apps trying to make space by deleting, say, Pack5 will get ; past that and into some real space savings. EmptyHandle will ; indeed zero the (bogus) MP, but not attempt to actually free ; space. DisposeHandle will do likewise; and it won't return the ; MP to the free list, since there is a permanent connection ; between ROM bogus MP's and ROM resources. ; 3/12/85 LAK&JTC Modified sys heap start to $1400, making room for 1K ToolTable @ $C00 ; 3/4/85 JTC Changes to support so-called read-only zones (for ROM map zone, ; currently). <04Mar85> ; 1) Add ROZ .EQU 0 to NewEqu, reusing bit fOnCheck. ; 2) Add memROZWarn .EQU -99 to NewEqu -- report error on abuse. ; 3) Add memROZError .EQU -99 to NewEqu -- same thing. ; 4) DisposPtr, DisposHandle -- warning if ROZ. ; 5) ReallocHandle -- if nonempty, don't empty and warn if try to grow ; 6) SetHandleSize, SetPtrSize -- don't shrink it. ; 7) EmptyHandle (the big one) -- don't do it and DON'T signal error! ; 8) Add _NewEmptyHandle, parallel to NewHandle. ; 1/30/85 LAK Added ram patch to InitApplZone for world reinit stuff (with REF ; for MakeStackPB). ; 1/29/85 LAK New system heap start is $C00. ; 1/29/85 JTC Rolled in patches, marked <29jan85>: ; 1) SetApplLimit -- check for memfull error ; 2) MoreMasters -- add new call ; 3) InitZone, SetGrowZone -- change to 2-level GrowZoneProc ; 4) StdGZ -- add standard GrowZoneProc ; 5) MakePtrSpc -- (internal routine) new code after return from MakeSpace ; 1/23/85 LAK Adapted for new equate files. Changed 'MoreMasters' to mAllocCnt. ; 9/12/83 LAK Added GZ semaphores to ReallocHandle. ; 9/10/83 LAK Changed CompactMem to force heap compact by setting FNSelCompct ; bit in flags word. ; 9/4/83 LAK Fixed bug in ReallocHandle (don't dispose handle on memFullErr). ; 8/18/83 LAK Fixed potential problem with ResrvMem (if used to make room for ; a handle, it needs to reserve extra space for a master pointer ; block if we are out of master pointers . . .) ; 8/12/83 LAK Added clear option for NewPtr, NwHandle, and ReAllocHandle. ; 7/31/83 LAK DefltFlags now reside in low memory location mmDefFlags: placed ; there by InitMem and loaded into zone vars by InitZone. ; 7/28/83 LAK CompactMem, PurgeMem, MaxMem, and FreeMem now call MMPrologue ; and MMEpilogue; added ResrvMem. ; 7/24/83 LAK Removed all free-list references; removed .word constants from ; checking code; made numerous optimizations; initialize DefltStack, ; MinStack in InitMem and now use these values instead of hard-wired ; constants. ; 6/21/83 MPH Put FreeList code under assembly switch: FList. ; 6/18/83 MPH Put maintenance of minCBFree under Statistics switch. ; 6/17/83 MPH Space Saving Changes: ; - Removed CallMoveProc calls ; - InitMem: tightened Mask Init ; - SetApplBase: ; Sub.L #x,A0 => Sub.W #x,A0 ; JSR InitApplZone => BSR.S ; - InitApplZone: ; Add.L #x,A0 => Add.W #x,A0 ; Move.L y,x(SP) => Move.L y,-(SP) ; - Removed unneeded Tst.L D0 ; - GetZone: Repackaged checking code ; - SetZone: Repackaged checking code ; - PurgeMem: Moved PMFail to save space, ; - HLock, HUnLock, HPurge, HNoPurge: ; Removed unneeded Move.L A1,A0 at HGood. ; 6/16/83 MPH Removed error return from InitMem, InitApplZone in all cases. ; Fix CompactMem to adjust size correctly. ; Remove unused code at MMFail from MaxMem. ; 6/11/83 theGang Fixed register trashed bug in InitApplZone ; 6/10/83 MPH Changed order of _RsrcZoneInit, _InitZone in InitApplZone. ; Included GrafTypes so that Nil is defined. ; 6/5/83 MPH Fixed InitApplZone by moving IAZCommon to module Heap. ; 6/2/83 MPH More minor revisions for release, share common code. ; 4/12/83 MPH Final revisions for release. ; 2/22/83 LAK,MPH changed to observe pascal regsave conventions ; 2/17/83 LAK default ApplLimit is now figured from current stack pointer; ; initmem just inits the system zone. ; 2/10/83 MPH Changed SetApplLimit to take argument in A0 instead of D0 ; 1/26/83 LAK Changed system heap size to 12K. ; 1/14/83 AJH Changed RsrcZoneInit invocation to a trap ; 10/27/82 MPH Begin Zone refinement per suggestions of Andy J. Hertzfeld ; and Larry A. Kenyon ; 8/16/82 AL Added ReAllocHandle core routine call ; 7/30/82 AL Modified for 128K... 16 MBytes memory expansion ; 4/28/82 AL added locked, purgeble, permanent relocatable blocks ; 4/7/82 AL use A0 to interface ; 1/25/82 BT All routines added, preliminary testing done. ; 12/13/81 BT More routines added. ;__________________________________________________________________________________________________ BLANKS ON STRING ASIS LOAD 'StandardEqu.d' INCLUDE 'ColorEqu.a' INCLUDE 'palettePriv.a' INCLUDE 'MemoryMgrPriv.a' INCLUDE 'FontPrivate.a' INCLUDE 'HardwarePrivateEqu.a' INCLUDE 'UniversalEqu.a' Heap PROC EXPORT ; moved up here to contain equates! IMPORT a24ActualS IMPORT a32ActualS IMPORT a24AllocBk IMPORT a32AllocBk IMPORT a24BkCompactS IMPORT a32BkCompactS IMPORT ClearGZStuff IMPORT a24CompactHp IMPORT a32CompactHp IMPORT a24EH IMPORT a32EH IMPORT a24FreeBk IMPORT a32FreeBk IMPORT a24GetSize IMPORT a32GetSize IMPORT a24HMakeMoreMasters IMPORT a32HMakeMoreMasters IMPORT a24MakeBkf IMPORT a32MakeBkf IMPORT a24MakePtrSpc IMPORT a32MakePtrSpc IMPORT a24MaxLimit IMPORT a32MaxLimit IMPORT ToMaxLimit IMPORT MMNoErrEpilogue IMPORT MMEpilogue IMPORT MMHPrologue IMPORT MMPPrologue IMPORT MMPrologue IMPORT MMRHPrologue IMPORT MMNoPrologue IMPORT MMMMPrologue IMPORT a24NextMaster IMPORT a32NextMaster IMPORT a24PurgeHeap IMPORT a32PurgeHeap IMPORT ReleaseMP IMPORT a24SetSize IMPORT a32SetSize IMPORT StdGZ IMPORT a24ZoneAdjustEnd IMPORT a32ZoneAdjustEnd IMPORT FlushApplVBLs ; code borrowed from SegLoader IMPORT AppZoneAddr ; code borrowed from SegLoader IMPORT FlushApplNM ; from NotificationMgr.c IF RAMTest THEN ELSE IMPORT MakeStkPB ;<30jan85> for initapplzone stuff ENDIF IMPORT a24TotePurgeables ;new guts routine IMPORT a32TotePurgeables ;new guts routine IMPORT BaseofRom IMPORT PramIO IMPORT DiskCachePurgeProcedure ; EXPORT SetApplBase ; If hasNewHeapMgr Then EXPORT Old_AfterBootSetApplBase ;, else EXPORT AfterBootSetApplBase ; endif EXPORT IAZ ; EXPORT InitApplZone EXPORT InitZoneTrap EXPORT GetZone EXPORT SetZone EXPORT MaxBlockTrap EXPORT PurgeSpaceTrap EXPORT CompactMemTrap EXPORT PurgeMem EXPORT FreeMem EXPORT ResrvMem EXPORT MaxMemTrap EXPORT SetGrowZone EXPORT SetApplLimit EXPORT StackSpaceTrap EXPORT MaxApplZone EXPORT NewPtrTrap EXPORT DisposePtr EXPORT GetPtrSizeTrap EXPORT SetPtrSizeTrap EXPORT PtrZoneTrap EXPORT NwHandle EXPORT NewEmptyHandleTrap EXPORT DsposeHandle EXPORT __GetHandleSize EXPORT SetHandleSizeTrap EXPORT HandleZoneTrap EXPORT RecoverHandleTrap EXPORT EmptyHandle EXPORT ReAllocHandleTrap EXPORT HLock EXPORT HUnlock EXPORT HPurge EXPORT HNoPurge EXPORT HRSRC ; set the RSRC bit EXPORT HNoRSRC ; clear the RSRC bit EXPORT HGetFlags ; get flag byte of master ptr EXPORT HSetFlags ; set flag byte of master ptr EXPORT MoreMasters ; new trap added EXPORT __StripAddress EXPORT MoveHHi ; moved in from glue land EXPORT vIAZInit ; init at top of InitApplZone for vector EXPORT vIAZPostInit ; init after zone is created for vector if hasNewHeapMgr Then EXPORT Old_InitMemVect ; initialization for Memory Vectors EXPORT Old_InitMemMgr ; initialize Memory Manager low mem, vectors , else EXPORT InitMemVect ; initialization for Memory Vectors EXPORT InitMemMgr ; initialize Memory Manager low mem, vectors , endif ;---------------------------------------------------------------------- ; PROCEDURE InitMemVect; ; ; This routine initialize the jump vector tables for both 24 and 32 bit ; memory traps. ; MACHINE MC68030 MMTrapTable ; table for all Memory Manager traps ; entries have to be in pairs..... DC.L v24SetApplBase-BaseofROM ; DC.L v32SetApplBase-BaseofROM ; DC.L vInitApplZone-BaseofROM ; DC.L vInitApplZone-BaseofROM ; DC.L v24InitZone-BaseofROM ; DC.L v32InitZone-BaseofROM ; DC.L vGetZone-BaseofROM ; DC.L vGetZone-BaseofROM ; DC.L vSetZone-BaseofROM ; DC.L vSetZone-BaseofROM ; DC.L v24MaxBlock-BaseofROM ; DC.L v32MaxBlock-BaseofROM ; DC.L v24PurgeSpace-BaseofROM ; DC.L v32PurgeSpace-BaseofROM ; DC.L v24CompactMem-BaseofROM ; DC.L v32CompactMem-BaseofROM ; DC.L v24PurgeMem-BaseofROM ; DC.L v32PurgeMem-BaseofROM ; DC.L vFreeMem-BaseofROM ; DC.L vFreeMem-BaseofROM ; DC.L v24ResrvMem-BaseofROM ; DC.L v32ResrvMem-BaseofROM ; DC.L v24MaxMem-BaseofROM ; DC.L v32MaxMem-BaseofROM ; DC.L vSetGrowZone-BaseofROM ; DC.L vSetGrowZone-BaseofROM ; DC.L v24SetApplLimit-BaseofROM ; DC.L v32SetApplLimit-BaseofROM ; DC.L vStackSpace-BaseofROM ; DC.L vStackSpace-BaseofROM ; DC.L v24MaxApplZone-BaseofROM ; DC.L v32MaxApplZone-BaseofROM ; DC.L v24NewPtr-BaseofROM ; DC.L v32NewPtr-BaseofROM ; DC.L v24DisposePtr-BaseofROM ; DC.L v32DisposePtr-BaseofROM ; DC.L v24GetPtrSize-BaseofROM ; DC.L v32GetPtrSize-BaseofROM ; DC.L v24SetPtrSize-BaseofROM ; DC.L v32SetPtrSize-BaseofROM ; DC.L vPtrZone-BaseofROM ; DC.L vPtrZone-BaseofROM ; DC.L v24NwHandle-BaseofROM ; DC.L v32NwHandle-BaseofROM ; DC.L v24NewEmptyHandle-BaseofROM ; DC.L v32NewEmptyHandle-BaseofROM ; DC.L v24DsposeHandle-BaseofROM ; DC.L v32DsposeHandle-BaseofROM ; DC.L v24GetHandleSize-BaseofROM ; DC.L v32GetHandleSize-BaseofROM ; DC.L v24SetHandleSize-BaseofROM ; DC.L v32SetHandleSize-BaseofROM ; DC.L vHandleZone-BaseofROM ; DC.L vHandleZone-BaseofROM ; DC.L v24RecoverHandle-BaseofROM ; DC.L v32RecoverHandle-BaseofROM ; DC.L v24EmptyHandle-BaseofROM ; DC.L v32EmptyHandle-BaseofROM ; DC.L v24ReAllocHandle-BaseofROM ; DC.L v32ReAllocHandle-BaseofROM ; DC.L v24Hlock-BaseofROM ; DC.L v32Hlock-BaseofROM ; DC.L v24HUnlock-BaseofROM ; DC.L v32HUnlock-BaseofROM ; DC.L v24HPurge-BaseofROM ; DC.L v32HPurge-BaseofROM ; DC.L v24HNoPurge-BaseofROM ; DC.L v32HNoPurge-BaseofROM ; DC.L v24HRSRC-BaseofROM ; DC.L v32HRSRC-BaseofROM ; DC.L v24HNoRSRC-BaseofROM ; DC.L v32HNoRSRC-BaseofROM ; DC.L v24HGetFlags-BaseofROM ; DC.L v32HGetFlags-BaseofROM ; DC.L v24HSetFlags-BaseofROM ; DC.L v32HSetFlags-BaseofROM ; DC.L v24MoreMasters-BaseofROM ; DC.L v32MoreMasters-BaseofROM ; DC.L v24MoveHHi-BaseofROM ; DC.L v32MoveHHi-BaseofROM ; TableEnd ;---------------------------------------------------------------- ; InitMemMgr: Set up some low memory constants related to the memory manager. ; Destroys none ; Called by System initialization sequence. ;---------------------------------------------------------------- IF hasNewHeapMgr Then Old_InitMemMgr ELSE InitMemMgr ENDIF IF hasNewHeapMgr Then Old_InitMemVect ELSE InitMemVect ENDIF BSET #MMStartMode,MMFlags ; Force 32-bit mode BSET #MMMixed,MMFlags ; Force 32-bit mode BSET #MMSysheap,MMFlags ; Force 32-bit mode BSET #MMROZheap,MMFlags ; Force 32-bit mode BCLR #mmHighSysHeap,MMFlags ; Force 32-bit mode BCLR.B #Systemis24bit,SystemInfo ; set system to be 32 bit BCLR.B #Sysheapis24bit,SystemInfo ; set system heap to be 32 bit @2 MOVE.L ROMBase,D0 ; get ROMbase LEA MMTrapTable,A0 ; A3 gets beginning of table LEA JMemMgr24,A1 ; set A1 to start of 24 bit table LEA JMemMgr32,A2 ; set A2 to start of 32 bit table MOVE.L #(((TableEnd-MMTrapTable)>>3)-1),D1 ; get number of entry pairs @NextEntry MOVE.L (A0)+,(A1) ; copy offset to entries in 24 bit table ADD.L D0,(A1)+ ; Add ROM Base to offset MOVE.L (A0)+,(A2) ; copy offset to entries in 32 bit table ADD.L D0,(A2)+ ; Add ROM Base to offset DBRA D1,@NextEntry ; loop until end ADD.L #$00010000,D0 ; makeup a safe address MOVE.L D0,$0 ; write address for nil handle MOVE.L D0,$4 ; write address for nil window pointer LEA MMNoPrologue,A0 ; get address Move.L A0,vMMNoPrologue ; LEA MMPPrologue,A0 ; get address Move.L A0,vMMPPrologue ; LEA MMPrologue,A0 ; get address Move.L A0,vMMPrologue ; LEA MMHPrologue,A0 ; get address Move.L A0,vMMHPrologue ; LEA MMRHPrologue,A0 ; get address Move.L A0,vMMRHPrologue ; LEA MMMMPrologue,A0 ; get address Move.L A0,vMMMMPrologue ; LEA MMEpilogue,A0 ; get address Move.L A0,vMMEpilogue ; LEA MMNoErrEpilogue,A0 ; get address Move.L A0,vMMNoErrEpilogue ; MOVEM.L (SP)+,D0-D3/A0-A3 ; restore registers RTS ; ;---------------------------------------------------------------------- ; PROCEDURE SetApplBase(a: Address); ; ; Sets the Application Zone Base, and Inits the Application Zone ; No error setting required here,since IAZ does all the hard work. <25Apr85> ; These days use the full splendor of InitApplZone. ; ; Argument: ; A0: New Base Address for Applic Zone. ; ; Result: ; D0: ec: error code. ; ; Registers: ; D0: amount to adjust counter by, new counter value. ; A0: points to counter, max pair. ; SetApplBase ; Roll in SetAppBaseCacheCleaner from BassPatches.a ; Remove any application memory allocated by Bass whenever the application heap is ; reformatted. SetAppBase and InitApplZone must be patched since they both trash the ; application heap. TST.B CurApName ;checking for app name BMI @SkipIt ;still in booting, skip the patch MOVEM.L A0-A2/D0-D3,-(sp) ; save registers CLR.L -(SP) ; room for result MOVE.L applZone,A0 ; point to zone hdr MOVE.L A0,-(SP) ; push start ptr MOVE.L (A0),-(SP) ; push zone trailer _sbKillSomeCaches ; ADDQ #4,SP ; ignore result MOVEM.L (sp)+,A0-A2/D0-D3 ; restore registers @SkipIt Move.L #JSetApplBase,-(SP) ; get offset onto stack Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue RTS ; 24 bit version v24SetApplBase MoveM.L D3/A2-A6,-(SP) ; Save Registers. Move.L SysZone,A6 ; Get sysZone pointer. Move.L A0,D0 ; round base up to 4x stb Cmpi.b #cpu68040,CPUFlag ; on an 040 or greater? <2> kc.start Blo.s @0 ; No? Then long align. Add.L #15,D0 ; Quad-word align AndI.W #$FFF0,D0 ; D0 = 16x; D0 >= A0 bra.s @continue @0 AddQ.L #3,D0 ; AndI.W #$FFFC,D0 ; D0 = 4x; D0 >= A0 @continue ; <2> kc.end MoveA.L D0,A0 ; Sub.W #MinFree24,A0 ; Point to new end block. Cmp.L BkLim(A6),A0 ; New sysZone end <= current? BLS.S @SABInitAppl ; Yes, just init applZone. BSR a24ZoneAdjustEnd ; Adjust the sysZone end. @SABInitAppl BSR IAZ ; use historical IAZ call MoveM.L (SP)+,D3/A2-A6 RTS ; 32 bit version v32SetApplBase MoveM.L D3/A2-A6,-(SP) ; Save Registers. Move.L SysZone,A6 ; Get sysZone pointer. Move.L A0,D0 ; round base up to 4x stb Cmpi.b #cpu68040,CPUFlag ; on an 040 or greater? <2> kc.start Blo.s @0 ; No? Then long align. Add.L #15,D0 ; Quad-word align AndI.W #$FFF0,D0 ; D0 = 16x; D0 >= A0 bra.s @continue @0 AddQ.L #3,D0 ; AndI.W #$FFFC,D0 ; D0 = 4x; D0 >= A0 @continue ; <2> kc.end MoveA.L D0,A0 ; Sub.W #MinFree32,A0 ; Point to new end block. Cmp.L BkLim(A6),A0 ; New sysZone end <= current? BLS.S @SABInitAppl ; Yes, just init applZone. BSR a32ZoneAdjustEnd ; Adjust the sysZone end. @SABInitAppl BSR.S IAZ ; use historical IAZ call MoveM.L (SP)+,D3/A2-A6 RTS ;---------------------------------------------------------------------- ; PROCEDURE AfterBootSetApplBase(a: Address); ; ; This is the patch BracketSetAppBaseWithInitApplZones ; It will patch out the SetApplBase at Gibbly time when InstallMgr ; get called. The time when this patch applied is crucial (during boot ; time up to gibbly time this patch is NOT to be used, it is used ; after gibbly time) PN ; If hasNewHeapMgr Then ; : Change AfterBootSetApplBase to Old_AfterBootSetApplBase so we can export a wrapper to ; BootRetry instead. The wrapper muxes the call based on if figment is active Old_AfterBootSetApplBase ; PN else AfterBootSetApplBase endif _InitApplZone ; PN jsr SetApplBase ; PN _InitApplZone ; PN rts ; PN ;---------------------------------------------------------------------- ; ; Procedure InitApplZone; ; ; Common code for initializing the Application Zone. Requires SPBot, ; sysZone to be set up. Sets up ApplLimit, applZone. Invokes ; RsrcZoneInit, if needed. Sets up HiHeapMark := ApplLimit, as always, ; but uses the more conservative result (D1) from ToMaxLimit rather than ; the BufPtr-based result (D2) which was historical. ; ; New wrinkle -- start ApplZone up high, then let it grow downwards. <14Apr85> ; Stuff error codes in IAZ (for SetApplBase) and InitApplZone. <25Apr85> ; Init ApplZone and OrgApplZone before InitZone, to simplify MakeMoreMasters <27Apr85> ; Roll all of InitApplZone into one blob, leaving IAZ for history. ; ; Arguments: ; None. ; ; Result: ; D0: ec: error code. ; <0: InitZone failed. ; 0: Success. ; ; Registers: ; D1: appLim: Computed ApplLimit value. ; D2: lTemp: Proposed appl Limit value. ; A0: start: Points to proposed applZone start. ; A0: args: Points to InitZone argument list. ; A1: end: Points to proposed applZone end. ; A6: z: Points to sysZone, eventually applZone. ; InitApplZone Move.L #JInitApplZone,-(SP) ; get offset onto stack Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue RTS vInitApplZone MoveA.L jIAZInit,A0 ; get pre-processing routine vector JSR (A0) ; do it BSR.S IAZ ; get the real zone MoveA.L jIAZPostInit,A0 ; get post-processing routine vector JSR (A0) ; do it MoveQ #0,D0 ; re-stuff the no-error code <16Apr85> Move.W D0,MemErr ; Record it globally, too <25Apr85> RTS ;---------------------------------------------------------------------- ; IAZ ; - Do the real work of initing the appl zone. ; Major change to use stack&BufPtr-based ApplLimit and HiHeapMark, not ; just to hammer BufPtr-MinStack, as has been done since the early days. ; This fixes problems at start time, when SetApplBase is called with the ; stack in mid-ram and StackSpace is forced to say there is no ; Registers: D0-D2/A0-A1 ; Called by InitApplZone and SetApplBase. ;---------------------------------------------------------------------- IAZ Move.L A6,-(SP) ;Save A6. _RsrcZoneInit ;initialize resources in appl heap Clr.L applZone ;No applZone exists during init. ; Do the Launch-type computation of ApplLimit, to give ample stack ; at boot time. Remove use of antiquated ToMaxLimit. Move.l SP,D1 ;current stack Sub.L DefltStack,D1 ;enough space for even QD Move.L D1,ApplLimit ;Use stack limit, NOT BufPtrÕs Move.L D1,HiHeapMark ;Start HiHeapMark in sync with ;ApplLimit in case of glue MaxApplZone Move.L sysZone,A6 ;SysZone pointer. Move.L BkLim(A6),A0 ;Current Last Block in sysZone. TST.B Zone32Flag(A6) ;is it 32 bit zone BNE.S @1 ;branch if yes ; Ordinarily start ApplZone just after SysZone, but if GrowDown is true, <14Apr85> ; and there's room, start up offset by CacheSize. <27Apr85> LEA MinFree24(A0),A0 ;Points to first of cur. applZone. BRA.S @5 ; @1 LEA MinFree32(A0),A0 ;Points to first of cur. applZone. @5 ; Now proceed building the zone... <14Apr85> Move.L A0,A1 ;New Application zone base. Add.W #AppZoneSize,A1 ;Compute new end address. Cmp.L D1,A1 ;New End Address < ApplLimit? BCS.S @10 ;Yes, use new end address. Move.L D1,A1 ;use ApplLimit as end address. @10 ; Move.L A0,StartPtr(SP) ;New Applic Zone Base. ; Move.L A1,LimitPtr(SP) ;New Applic Zone End. ; Move.W #<2*dfltMasters>,CMoreMasters(SP) ; Move.L #0,PGrowZone(SP) ;No Grow Zone procedure. Move.L #0,-(SP) ;No Grow Zone procedure. Move.W #(2*dfltMasters),-(SP) ;Number of masters to alloc. Move.L A1,-(SP) ;New Applic Zone End. Move.L A0,-(SP) ;New Applic Zone Base. Move.L A0,applZone ;Save as the application heap zone. Move.L SP,A0 ;Point to argument block. _InitZone ;Ask OS to do request. Add.W #14,SP ;Restore stack pointer. Move.L theZone,A6 ;Application heap zone. Move.L BkLim(A6),HeapEnd ;Set up HeapEnd. MoveQ #0,D0 ;Success result code. Move.W D0,MemErr ;Record it globally, too <25Apr85> Move.L (SP)+,A6 ;Restore A6. RTS ; ;------------------------------------------------------------------- ; End of historical IAZ. ;------------------------------------------------------------------- ;---------------------------------------------------------------------- ; vIAZInit new ; - Inits before ApplZone is created. ; Registers: D0-D2/A0-A1 ; Called by InitApplZone via jIAZInit vector. ;---------------------------------------------------------------------- vIAZInit MOVE.L IAZNotify,D0 ; anyone to notify? BLE.S @0 ; br if not MOVE.L D0,A0 ; give them a call if so JSR (A0) @0 MOVE.W #-1,WWExist ; $FF for non-existence (also sets QDExist) ST FMExist ; $FF for InitFonts hasnÕt been called ; BSET #7,DSWndUpdate ; cancel pending PaintBehind CLR.L MenuList ; Clr.L LastFOND ; <06May85> ; Move.W #-1,FONDID ; <06May85> Move.L MinusOne,LastSPExtra ; flag to inval cache <13Jan86 JTC> ST SEvtEnb ; re-enable system event MoveQ #(IOVQElSize/2)-1,D0 ; <10May85> @99 Clr.W -(SP) DBrA D0,@99 MoveA.L SP,A0 MOVE.L VCBQHdr+QHead,D0 @2 BEQ.S @4 MOVE.L D0,A1 MOVE.W VCBDrvNum(A1),IOVDrvNum(A0) BEQ.S @3 _FlushVol ; flush all on-line volumes @3 MOVE.L QLink(A1),D0 BRA.S @2 @4 ADD #IOVQElSize,SP ; clean up stack ; Init code moved from Launch CLR.L DragHook ;No drag hook yet CLR.L DeskHook ;No desk hook for hit-testing desk. LEA CloseOrnHook, A0 ; Point to closeOrnHook CLR.L (A0)+ ;clear closeOrnHook CLR.L (A0)+ ;clear RestProc CLR.L (A0)+ ;clear saveProc CLR.W TaskLock ;clear taskLock, fScaleDisable. CLR.L ResErrProc ;and resource error proc. CLR.L EjectNotify ;moved here from InitApplZone (from patches) <24Apr85> IF hasASC THEN ; <1.7> MOVE.L jSoundDead,A0 ;get vector to kill all current sounds in ... JSR (A0) ;...the application heap ENDIF BSR.L FlushApplVbls ;kill off doomed vbl tasks <27Mar85>, BigJSR FlushApplNM,A0 ; And bogus NM requests <1.2> BSR.S FlushFontCaches ; flush TrueType caches stb BSR.S FlushApplPorts ;kill off doomed grafPorts BSR.S FlushPalettes ;as well as doomed palettes <10Jun87 EHB> ; this cleanup is needed, for instance, if an ES is done from MacsBug. <10Jun87 EHB> MOVE.L MainDevice,A0 ; get the main device <10Jun87 EHB> MOVE.L A0,SrcDevice ; set the src device <10Jun87 EHB> MOVE.L A0,theGDevice ; and the current device <10Jun87 EHB> MOVE #$2000,SR ; make sure interrupts enabled <10Jun87 EHB> RTS FlushFontCaches ;---------------------------------------------------------------------- ; Remove any application memory allocated by TrueType whenever the application heap is ; reformatted. SetAppBase and InitApplZone are both patched since they both trash the ; application heap. ; Rolled in InitApplZoneCacheCleaner from BassPatches.a stb ; Registers: saves all registers, trashes condition codes ;---------------------------------------------------------------------- MOVEM.L A0-A2/D0-D3,-(sp) ; save registers CLR.L -(SP) ; room for result MOVE.L applZone,A0 ; point to zone hdr MOVE.L A0,-(SP) ; push start ptr MOVE.L (A0),-(SP) ; push zone trailer _sbKillSomeCaches ; ADDQ #4,SP ; ignore result MOVEM.L (sp)+,A0-A2/D0-D3 ; restore registers @SkipIt RTS FlushApplPorts ;---------------------------------------------------------------------- ; FlushApplPorts new ; -- clean up portList just before ApplZone is eliminated ; Registers: D0-D2/A0-A1 ; Called by vIAZInit. ;---------------------------------------------------------------------- ; Remove from the PortList any ports in the application heap zone @REPEAT MOVE.L portList,A1 ;get the portList CMP.L MinusOne,A1 ;are they equal? BEQ.S @DONE ;=>if so,invalid portlist, just return MOVE.L (A1),A1 ;point to it MOVE.L A1,A0 ;save pointer in A0 MOVE (A1)+,D1 ;get count of elements? BRA.S @NEXT ;=> and dive into loop @SEARCH MOVE.L (A1)+,D0 ;get next element from list BSR.L AppZoneAddr ;in application area (or zero)? , BEQ.S @DELETE ;=>yes, delete it @NEXT DBRA D1,@SEARCH ;=>else try next in list BRA.S @DONE ;=>none left, continue @DELETE SUB #1,(A0) ;decrement port count MOVE.L -(A1),-(SP) ;stk: port < etc. CLR.L -(SP) ;stk: result < port < etc. MOVE.L portList,-(SP) ;stk: plist < res < port < etc. MOVEQ #2,D0 ;search after length MOVE.L D0,-(SP) ;stk: #2 < plist < res < port < etc. PEA 12(SP) ;PTR1 = GrafPtr MOVEQ #4,D0 ;LEN1 = 4 bytes MOVE.L D0,-(SP) ;stk: #4 < ptr1 < #2 < plist < res < port < PEA @DONE ;PTR2 = XXX CLR.L -(SP) ;LEN2 = 0 _Munger ;rhymes with plunger ADDQ #8,SP ;strip result, grafPort BRA.S @REPEAT ;=>repeat until no more @DONE RTS FlushPalettes ; patch rolled in <10Jun87 EHB> ;----------------------------------------------------------------------- ; Call DisposePalette for all palettes in the app heap. ; ; Registers: D0-D2/A0-A1 ; Called by vIAZInit. ;---------------------------------------------------------------------- MOVEM.L A2-A3/D3,-(SP) ; save work registers MOVE.L PMgrHandle,A2 ; get paletteMgr handle CMP.L MinusOne,A2 ; is it there? BEQ.S @DONE ; => no, just return MOVE.L (A2),A1 ; point to data structure MOVE.L PListHandle(A1),A0 ; get handle to palette list _HLock ; and lock it down MOVE.L (A0),A3 ; point to palette list Move APalettes(A1),D3 ; get number of active handles Beq.s @NoPals ; no friends => go home Add FreeSpaces(A1),D3 ; calculate total number of entries BRA.S @FindEnd ; => check for no entries @FindLoop Move.L PaletteRef(A3),D1 ; get first entry BEQ.S @FindNext ; => no palette in entry MOVE.L D1,D0 ; and get for routine BSR.L AppZoneAddr ; in application area (or zero)? BNE.S @FindNext ; => not in app heap MOVE.L D1,-(SP) ; push palette handle _DisposePalette ; and dispose it in place @FindNext AddQ #PLstEntrySz,A3 ; bump to the next entry @FindEnd DBra D3,@FindLoop ; repeat for all spaces @NoPals MOVE.L (A2),A1 ; point to palette stuff MOVE.L PListHandle(A1),A0 ; get handle to palette list _HUnlock ; and unlock it @DONE MOVEM.L (SP)+,A2-A3/D3 ; restore work registers RTS ;---------------------------------------------------------------------- ; vIAZPostInit new ; - last-minute inits after ApplZone has been created. ; Registers: D0-D2/A0-A1 ; Called by InitApplZone via jIAZPostInit vector. ;---------------------------------------------------------------------- vIAZPostInit _InitAllPacks ; reinstall the packages -- may trash MemErr <25Apr85> CLR.W CurApRefNum ; since all app heap res files closed _RDrvrInstall ; fix up ram based drivers ; clear the pack6 resource cache when launching (for Int'l Utilities / Script Mgr) ; moved here from InitApplZone because it seems to make more sense. stb with ExpandMemRec move.l expandMem,a0 ; expand pointer add.w #emItlCache,a0 ; point to cache move.l #emItlCacheSize/4-1,d0 ; dbra ptr @ClearCache clr.l (a0)+ ; clear part of cache dbra d0,@ClearCache ; until done endWith RtS ;---------------------------------------------------------------------- ; InitZone(startPtr, limitPtr: Ptr; mAllocCnt: INTEGER; ; growZone: ProcPtr); ; - Initialize a heap zone, and set theZone to that zone. ; Signal noErr globally, nowadays. <25Apr85> ; Set HiHeapMark if new heap end is below SP. <01Nov85 JTC> ; startPtr - start of heap zone ; limitPtr - end of heap zone ; mAllocCnt - number of master pointers to allocate initially ; and when more are needed. ; growZone - user supplied procedure to grow zone (must be ; supplied): ; FUNCTION growZone(bytesNeeded: LongInt): LongInt; ; (returns the number of bytes zone was grown by) ; <29jan85> User growZone in GZProc, StdGZ salted in spare1 ; ;---------------------------------------------------------------------- InitZoneTrap Move.L #jInitZone,-(SP) ; get offset onto stack Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue RTS v24InitZone MoveM.L A2-A3/A6,-(SP) ;Save registers Move.L A0,A1 ;Argument vector pointer Move.L (A1)+,A6 ;StartPtr (zone obj.) SetZ A6 ;set theZone Move.L A6,A0 ;zone object ptr MOVE.L A6,A2 ;used for filling in fields MoveQ #(HeapData-4)/4,D1 @IZClr24 Clr.L (A0)+ ;Zero heapzone header DBrA D1,@IZClr24 ;leave A0=HeapData(A6) ; note that AllocPtr is zeroed . . . ; Set up hi heap mark according to LimitPtr. <01Nov85 JTC> Move.L (A1)+,D1 ;LimitPtr, to be stripped of high bits <01Nov85 JTC> And.L Lo3Bytes,D1 ;24 bits only <01Nov85 JTC> ;---------------------------------------------------------------------- <2> kc.start ; Align the trailer block on 040 cpus so that when a MoveHHi call is made the block will ; be line aligned. Align24Trailer Cmpi.b #cpu68040,CPUFlag ; Are we on an 040 or greater? Blo.s @0 ; No? Then long align. Tst.l pVMGlobals ; VM running? Bpl.s @0 ; Yea? Then don't patch. Subq.l #16-MinFree24,D1 AndI.w #$FFF0,D1 Add.l #16-MinFree24,D1 MoveA.L D1,A3 ; LimitPtr bra.s @05 @0 AndI.W #$FFFC,D1 ; LimitPtr = 4x MoveA.L D1,A3 ; LimitPtr @05 ; <2> kc.end CmpA.L HiHeapMark,A3 ;24-bit subtract A3-HiHeapMark <01Nov85 JTC> BLT.S @1 ;Less Than (unsigned OK) ==> below HiHeap <01Nov85 JTC> Move.L SP,D1 ;Must strip to compare successfully! <01Nov85 JTC> And.L Lo3Bytes,D1 ;24-bit sp <01Nov85 JTC> CmpA.L D1,A3 ;LimitPtr-SP <01Nov85 JTC> BGT.S @1 ;Greater Than (signed OK) ==> in stack <01Nov85 JTC> Move.L A3,HiHeapMark ;a new 24-bit limit! <01Nov85 JTC> @1 ;bypass point for setting HiHeapMark <01Nov85 JTC> MoveQ #MinFree24,D1 ;MinFree=16 bytes Sub.L D1,A3 ;LimitPtr-MinFree Move.L D1,TagBC24(A3) ;make limit block Move.L A3,(A2)+ ;BkLim(A6) Move.L A0,(A2)+ ;PurgePtr(A6) - rover starts at ; HeapData(A6) AddQ #4,A2 ;skip HFstFree Sub.L A0,A3 ;BkLim(A6) - HeapData(A6) Move.L A3,D0 Move.L D0,(A2)+ ;ZCBFree(A6) Move.W (A1)+,D1 ;CMoreMasters Move.L (A1)+,(A2)+ ;PGrowZone -> GZProc(A6) ; <29jan85> Stuff system growZone into spare1. Use fact that A1 is free; A2 = mAllocCnt(A6) LEA StdGZ,A1 ;system GZProc <29jan85> Move.L A1,(spare1-mAllocCnt)(A2) Move.W D1,(A2)+ ;CMoreMasters -> mAllocCnt(A6) Move.W mmDefFlags,(A2)+ ;Flags(A6) Move.B #Is24Zone,Zone32Flag(A6); set zone to be 24 bit Move.L #JMemMgr24,ZoneJumpV(A6); set jump vector in the zone BSR a24MakeBKF ;start with 1 large free block ;A0=blk ptr, D0=size BSR a24HMakeMoreMasters ;HFstFree(A6)=0 ; After first block of master pointers is allocated, check that zone is line aligned on 040s. <2> kc.start ; If not, pad the mp block out by two bytes, diminishing the free block following and the ; the global free count. This ensures that all subsequent allocations will be aligned. ; Be sure to update the allocation rover, which may be pointing to the big free block. Init24ZoneAlign Cmpi.b #cpu68040,CPUFlag ; Are we on an 040 or greater? Blt.s @0 ; No? Then long align. Tst.l pVMGlobals ; VM running? Bpl.s @0 ; Yea? Then don't patch. LEA heapData(A6),A0 ; A0 -> mp block Move.l A0,D0 ; Add.l #BlkData24,D0 Move.L (A0),D1 ; D0 := length of mp block And.L Lo3Bytes,D1 ; Add.l D1,D0 And.l #$F,D0 ; Eq => multiple of 16, ok BEq.S @postMPAlign ; Not.b D0 ; Get remainder. And.b #$F,D0 ; Only care about bottom 4 bits. Addq.b #1,D0 ; Add in 1. Sub.L D0,ZCBFree(A6) ; taking up xx free bytes for pad MoveA.L A0,A1 ; AddA.L D1,A1 ; A1 -> free block after mp Add.B D0,(A0) ; increment slop count Add.L D0,(A0) ; increment block size Sub.L D0,(A1) ; decrement free block size Move.L (A1),0(A1,D0) ; move relevant part of free block header Add.L D0,A1 ; A1 -> new free block Move.L A1,allocPtr(A6) ; be sure rover is valid Bra.s @postMPAlign @0 Move.L A6,D0 ; BTst #1,D0 ; Eq => multiple of 4, ok BEq.S @postMPAlign ; SubQ.L #2,ZCBFree(A6) ; taking up 2 free bytes for pad LEA heapData(A6),A0 ; A0 -> mp block MoveA.L A0,A1 ; Move.L (A0),D0 ; D0 := length of mp block And.L Lo3Bytes,D0 ; AddA.L D0,A1 ; A1 -> free block after mp AddQ.B #2,(A0) ; increment slop count AddQ.L #2,(A0) ; increment block size SubQ.L #2,(A1) ; decrement free block size Move.L (A1),2(A1) ; move relevant part of free block header AddQ.L #2,A1 ; A1 -> new free block Move.L A1,allocPtr(A6) ; be sure rover is valid <2> kc.end @postMPAlign ; TrueType has a disk-based cache which puts font caches onto disk when they stb ; get purged. This purgeProc will check to see whether a block which is being stb ; purged is a font cache, and save it to disk if it is. stb lea DiskCachePurgeProcedure,A0 ; TrueType purge procedure stb move.l A0,purgeProc(A6) ; install purge procedure stb MoveM.L (SP)+,A2-A3/A6 ;Restore registers MoveQ #0,D0 ;Success return <25Apr85> Move.W D0,MemErr ;Record it globally, too <25Apr85> RTS ;and return to caller v32InitZone MoveM.L A2-A3/A6,-(SP) ;Save registers Move.L A0,A1 ;Argument vector pointer Move.L (A1)+,A6 ;StartPtr (zone obj.) SetZ A6 ;set theZone Move.L A6,A0 ;zone object ptr MOVE.L A6,A2 ;used for filling in fields MoveQ #(HeapData-4)/4,D1 @IZClr32 Clr.L (A0)+ ; Zero heapzone header DBrA D1,@IZClr32 ; leave A0=HeapData(A6) ; note that AllocPtr is zeroed . . . ; Set up hi heap mark according to LimitPtr. <01Nov85 JTC> Move.L (A1)+,D1 ; LimitPtr, to be stripped of high bits <01Nov85 JTC> Cmpi.b #cpu68040,CPUFlag ; Are we on an 040 or greater? <2> kc.start Blt.s @0 ; No? Then long align. Subq.l #4,D1 AndI.w #$FFF0,D1 Addq.l #4,D1 MoveA.L D1,A3 ; LimitPtr bra.s @05 @0 AndI.W #$FFFC,D1 ; LimitPtr = 4x MoveA.L D1,A3 ; LimitPtr @05 ; <2> kc.end CmpA.L HiHeapMark,A3 ; ??-bit subtract A3-HiHeapMark <01Nov85 JTC> BLT.S @1 ; Less Than (unsigned OK) ==> below HiHeap <01Nov85 JTC> Move.L SP,D1 ; Must strip to compare successfully! <01Nov85 JTC> CmpA.L D1,A3 ; LimitPtr-SP <01Nov85 JTC> BGT.S @1 ; Greater Than (signed OK) ==> in stack <01Nov85 JTC> Move.L A3,HiHeapMark ; new limit <01Nov85 JTC> @1 ; bypass point for setting HiHeapMark <01Nov85 JTC> MoveQ #MinFree32,D1 ; MinFree=16 bytes Sub.L D1,A3 ; LimitPtr-MinFree Clr.L TagBC32(A3) ; set limit block as free block Move.L D1,blkSize32(A3) ;make limit block Move.L A3,(A2)+ ; BkLim(A6) Move.L A0,(A2)+ ; PurgePtr(A6) - rover starts at ; HeapData(A6) AddQ #4,A2 ; skip HFstFree Sub.L A0,A3 ; BkLim(A6) - HeapData(A6) Move.L A3,D0 Move.L D0,(A2)+ ; ZCBFree(A6) Move.W (A1)+,D1 ; CMoreMasters Move.L (A1)+,(A2)+ ; PGrowZone -> GZProc(A6) ; <29jan85> Stuff system growZone into spare1. Use fact that A1 is free; A2 = mAllocCnt(A6) LEA StdGZ,A1 ; system GZProc <29jan85> Move.L A1,(spare1-mAllocCnt)(A2) Move.W D1,(A2)+ ; CMoreMasters -> mAllocCnt(A6) Move.W mmDefFlags,(A2)+ ; Flags(A6) Move.B #Is32Zone,Zone32Flag(A6); set zone to be 32 bit Move.L #JMemMgr32,ZoneJumpV(A6); set jump vector in the zone BSR a32MakeBKF ; start with 1 large free block ; A0=blk ptr, D0=size BSR a32HMakeMoreMasters ; HFstFree(A6)=0 ; After first block of master pointers is allocated, check that zone is longword aligned. ; If not, pad the mp block out by two bytes, diminishing the free block following and the ; the global free count. This ensures that all subsequent allocations will be aligned. ; Be sure to update the allocation rover, which may be pointing to the big free block. ; ; This attempt is feeble given the removal of alignment in routine ActualS in HeapGuts.a ; but the code is left in to ensure that at least the beginning of the heap is cool. Cmpi.b #cpu68040,CPUFlag ; Are we on an 040 or greater? <2> kc.start Blt.s @not040 ; No? Then long align. LEA heapData(A6),A0 ; A0 -> mp block Move.l A0,D0 ; Add.l #BlkData32,D0 Move.L BlkSize32(A0),D1 ; D0 := length of mp block Add.l D1,D0 And.l #$F,D0 ; Eq => multiple of 16, ok BEq.S @postMPAlign ; Not.b D0 ; Get remainder. And.b #$F,D0 ; Only care about bottom 4 bits. Addq.b #1,D0 ; Add in 1. Sub.L D0,ZCBFree(A6) ; taking up xx free bytes for pad MoveA.L A0,A1 ; AddA.L D1,A1 ; A1 -> free block after mp Add.B D0,SizeCor32(A0) ; increment slop count Add.L D0,BlkSize32(A0) ; increment block size Sub.L D0,BlkSize32(A1) ; decrement free block size Move.L BlkSize32(A1),BlkSize32(A1,D0) ; move relevant part of free block header Add.L D0,A1 ; A1 -> new free block Clr.l tagBC32(A1) ; Clear off old blocksize. Move.L A1,allocPtr(A6) ; be sure rover is valid Bra.s @postMPAlign @not040 Move.L A6,D0 ; BTst #1,D0 ; Eq => multiple of 4, ok BEq.S @postMPAlign ; SubQ.L #2,ZCBFree(A6) ; taking up 2 free bytes for pad LEA heapData(A6),A0 ; A0 -> mp block MoveA.L A0,A1 ; Move.L BlkSize32(A0),D0 ; D0 := length of mp block AddA.L D0,A1 ; A1 -> free block after mp AddQ.B #2,SizeCor32(A0) ; increment slop count AddQ.L #2,BlkSize32(A0) ; increment block size SubQ.L #2,BlkSize32(A1) ; decrement free block size Move.L BlkSize32(A1),2+BlkSize32(A1) ; move block size Move.L (A1),2(A1) ; move relevant part of free block header AddQ.L #2,A1 ; A1 -> new free block Move.L A1,allocPtr(A6) ; be sure rover is valid @postMPAlign ; <2> kc.end ; TrueType has a disk-based cache which puts font caches onto disk when they stb ; get purged. This purgeProc will check to see whether a block which is being stb ; purged is a font cache, and save it to disk if it is. stb lea DiskCachePurgeProcedure,A0 ; TrueType purge procedure stb move.l A0,purgeProc(A6) ; install purge procedure stb MoveM.L (SP)+,A2-A3/A6 ; Restore registers IZCleanExit ; Common no-error exit <25Apr85> MoveQ #0,D0 ; Success return <25Apr85> Move.W D0,MemErr ;Record it globally, too <25Apr85> RTS ;and return to caller ;---------------------------------------------------------------------- ; ; FUNCTION GetZone: Ptr; ; ; - Returns the global pointer to the current heap ; Uses A0 only. ; GetZone Move.L #JGetZone,-(SP) ; get offset onto stack Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue RTS vGetZone ; GetZ A0 ;Set up return value BrA.S IZCleanExit ;Use common routine above <25Apr85> ;---------------------------------------------------------------------- ; ;PROCEDURE SetZone(Hz: Ptr); ; ; - Set global pointer to the current heap zone ; Uses A0 only. ; SetZone Move.L #JSetZone,-(SP) ; get offset onto stack Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue RTS vSetZone ; SetZ A0 ;Set up return value BrA.S IZCleanExit ;Use common routine above <25Apr85> ;---------------------------------------------------------------------- ; ; FUNCTION CompactMem(cb: LongInt):[pblk: Ptr; cbFound: LongInt]; ; FUNCTION MaxBlock :[pblk: Ptr; cbFound: LongInt]; ; ; MaxBlock is modeled on CompactMem, but calls with #MaxMem as requested size ; (in order to find the largest available space) and with FNSelCompct=0 to ; prevent costly compaction. ; MaxBlockTrap ;new routine <10Apr85> PEA @Slime ;slimy solution for slimy problem MOVE.L RealMemTop,D0 ;make an outlandish request MOVE.L #JMaxBlock,-(SP) ; get offset to routine MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue RTS ; go to routine @Slime ; SUBQ.L #4,D0 ;reduce size by 4 byte to account for ;block starts and ends in non long word ;address, if 4 is too big, the extra 2 ;byte can act as margin. BGE.S @Return ;if less than zero, then return 0 MoveQ.L #0,D0 ;return 0 for length @Return ; RTS ; CompactMemTrap MOVE.L #JCompactMem,-(SP) ; get offset to routine MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue RTS ; go to routine v24MaxBlock MOVEQ #1,D1 ; mark routine as MaxBlock BRA.S v24CMGuts ; branch to common code v24CompactMem ; MOVEQ #0,D1 ; mark as CompactMem v24CMGuts BSR a24ActualS ;adjust size LEA Flags(A6),A1 ;useful address Move.B (A1),D2 ;preserve current flags in D2 TST.B D1 ;nonzero means MaxBlock <10Apr85> BNE.S @1 ;don't do compaction <10Apr85> BSet #FNSelCompct,(A1) ;compact always for CompactMem <10Apr85> BRA.S @3 ; <10Apr85> @1 ; <10Apr85> BClr #FNSelCompct,(A1) ;never compact for MaxBlock <10Apr85> @3 ; <10Apr85> Bsr.l a24CompactHp ;compact heap <2> kc.start Move.B D2,(A1) ;restore flags Cmpi.b #cpu68040,CPUFlag ; Are we on an 040 or greater? Blt.s @0 ; No? Then no alignment. Tst.l pVMGlobals ; VM running? Bpl.s @0 ; Yea? Then no alignment. AndI.W #$FFF0,D1 ; Line align result. @0 Move.L D1,D0 ;Size of largest block found <2> kc.end BEq PMExit24 ;hasty exit through our epilogue SubQ.L #BlkData24,D0 ;convert back to logical cb Move.L A0,D1 ;was a large enough blk found? BEq.S PMExit24 ;Eq => NIL, return that BrA.S PMOK24 v32MaxBlock MOVEQ #1,D1 ; mark routine as MaxBlock BRA.S v32CMGuts ; branch to common code v32CompactMem ; MOVEQ #0,D1 ; mark as CompactMem v32CMGuts ;entry point from MaxBlock <10Apr85> BSR a32ActualS ;adjust size LEA Flags(A6),A1 ;useful address Move.B (A1),D2 ;preserve current flags in D2 TST.B D1 ;nonzero means MaxBlock <10Apr85> BNE.S @1 ;don't do compaction <10Apr85> BSet #FNSelCompct,(A1) ;compact always for CompactMem <10Apr85> BRA.S @3 ; <10Apr85> @1 ; <10Apr85> BClr #FNSelCompct,(A1) ;never compact for MaxBlock <10Apr85> @3 ; <10Apr85> Bsr.l a32CompactHp ;compact heap <2> kc.start Move.B D2,(A1) ;restore flags Cmpi.b #cpu68040,CPUFlag ; Are we on an 040 or greater? Blt.s @0 ; No? Then no alignment. AndI.W #$FFF0,D1 ; Line align result. @0 Move.L D1,D0 ;Size of largest block found <2> kc.end BEq.S PMExit32 ;hasty exit through our epilogue Sub.L #BlkData32,D0 ;convert back to logical cb Move.L A0,D1 ;was a large enough blk found? BEq.S PMExit32 ;Eq => NIL, return that BrA.S PMOK32 ;---------------------------------------------------------------------- ; ; FUNCTION PurgeMem(cb: LongInt): pblk: Ptr; ; PurgeMem MOVE.L #JPurgeMem,-(SP) ; get offset to routine MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue RTS ; go to routine v24PurgeMem ; 24 bit version of Purgemem BSR a24ActualS ; adjust size BSR a24PurgeHeap ; Purge the Heap PMRMExit24 Move.L A0,D0 ; was a large enough blk found? BNE.S PMNNil24 ; Yes, return success MoveQ #memFullErr,D0 ; No, not enough room in mem. BrA.S PMExit24 PMNNil24 MoveQ #0,D0 ; and show success return PMOk24 AddQ.L #BlkData24,A0 ; else, point to data field. PMExit24 BRA.S PMExit32 ; go to common exit v32PurgeMem ; 32 bit version of Purgemem BSR a32ActualS ; adjust size BSR a32PurgeHeap ; Purge the Heap PMRMExit32 Move.L A0,D0 ; was a large enough blk found? BNE.S PMNNil32 ; Yes, return success MoveQ #memFullErr,D0 ; No, not enough room in mem. BrA.S PMExit32 ; PMNNil32 MoveQ #0,D0 ; and show success return PMOk32 Add.L #BlkData32,A0 ; else, point to data field. PMExit32 Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue RTS ; jump to it ;---------------------------------------------------------------------- ; ; FUNCTION PurgeSpace: [totalPurgeAndFree, contigPurgeAndFree : LongInt]; <17Apr85> ; On exit: ; D0 - total number of purgeable and free bytes in zone ; A0 - maximum possible contiguous space after purge (that is, max total of free ; and purgeable by 'region'. ; This function scans only; it does not purge, compact, nor allocate! ; PurgeSpaceTrap MOVE.L #JPurgeSpace,-(SP) ; get offset to routine MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue RTS ; go to routine v24PurgeSpace ; 24 bit version of PurgeSpace BSR a24TotePurgeables ; returns D0,A0 trashes others... <17Apr85> BRA.S PurgeSExit ; go to common exit routine v32PurgeSpace ; 32 bit version of PurgeSpace BSR a32TotePurgeables ; returns D0,A0 trashes others... <17Apr85> PurgeSExit Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue RTS ; jump to it ;---------------------------------------------------------------------- ; ; FUNCTION FreeMem: Longint; ; On exit: ; D0 - Returns the number of free bytes in the zone. FreeMem MOVE.L #JFreeMem,-(SP) ; get offset to routine MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue RTS ; go to routine vFreeMem ; Move.L ZCBFree(A6),D0 ; set result Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue RTS ; jump to it ;---------------------------------------------------------------------- ; ; PROCEDURE ResrvMem; ; On exit: ; A0 - ptr to free block made or found. ; D0 - 0 if large enough block was found, memfullerr if not. ; ; This routine is used to open a block of free space as low in the heap ; as possible; it should be called before NwHandle if that handle is to ; be locked permanently (i.e., when using handles as non-relocatables) to ; prevent fragmentation of the heap. ; ; Arguments: ; D0: size of block required (logical size). ; ; ÑÑÑÑÑÑÑÑÑ SuperMario roll in tcn ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ ; ResrvMem - make it grow System Heap, too. ; ResrvMem will not grow any heap other than ApplZone. This is a problem with the new, growable system heap. ; Process Mgr will grow the system heap for NewHandle calls. ResrvMem usually precedes a NewHandle, ; HLock sequence. If ResrvMem fails, the following NewHandle will cause the heap to grow (if it can). ; Then the block is allocated where the free space was made -- at the top. ; ; This proc not only causes the heap to grow, it also calls ResrvMem again to see how low the free block ; can be made. ; ; Notes: ; NewPtr calls ResrvMem again while doing the StdGZProc. We want it to call the user gzproc, so ; itÕs important that ResrvMem return an error when itÕs reentered. ThatÕs why we have a semaphore. ; ; See also: NewPtr ; ;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ ResrvMem ; -- roll in start -- move.l A1,-(SP) ; save A1 move.l ExpandMem,A1 ; is this a reentry? tst.l ExpandMemRec.emResrvMemSemaphore(A1) bne.s @leaveNowStillBusy ; yup, get out. move.l #1,ExpandMemRec.emResrvMemSemaphore(a1) ; nope, set the semaphore movem.l d0-d1,-(sp) ; save how much was asked for jsr GetTheMem ; go get it tst.w d0 ; test for os error beq.s @leaveNowPopEm ; if zero, space was reserved and weÕre done ; move.l 4(sp),d1 ; restore the trap word our caller used <5> btst #tSysOrCurZone,d1 ; is this a _Resrvmem ,SYS? bne.s @yupItsTheSystemHeap move.l sysZone,a0 ; is this the (growable) system zone? cmp.l theZone,a0 bne.s @leaveNowPopEm ; no, get out and leave other heaps alone @yupItsTheSystemHeap move.l (sp),d0 ; restore the amount being requested <5> _NewPtr ,SYS ; force open a slot, even though itÕs probably at the top of the heap ; because we just made the heap grow. bne @leaveNowPopEm ; leave if we couldnÕt get any space _DisposPtr ; ok, we got it. now free it movem.l (sp),d0-d1 ; ask ResrvMem again for this much. It will do a better job now that jsr GetTheMem ; we know we have enough free space. ; dispatcher sets the z flag based on the function result @leaveNowPopEm addq #8,sp @leaveNow move.l ExpandMem,A1 clr.l ExpandMemRec.emResrvMemSemaphore(A1) move.l (SP)+,A1 ; restore A1 rts @leaveNowStillBusy move.l (SP)+,A1 ; restore A1 moveq #memFullErr,d0 ; failure move.w d0,MemErr rts ; -- roll in end -- GetTheMem MOVE.L #JResrvMem,-(SP) ; get offset to routine MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue RTS ; go to routine v24ResrvMem ; 24 bit version of PurgeSpace TST.L HFstFree(A6) ;Any masters left? BNE.S @1 ;br if so Move.W mAllocCnt(A6),D2 ;Number of masters to make. Ext.L D2 ASL.L #2,D2 ;Convert MP count to byte count. AddQ.L #BlkData24,D2 ;And block header Add.L D2,D0 ;Increase req count by ptr blk @1 BSR a24MakePtrSpc ;Make room at the low end. Move.L A2,A0 ;Ptr to block BrA.S PMRMExit24 ;Do the purge mem exit trip . . . v32ResrvMem ; 32 bit version of PurgeSpace TST.L HFstFree(A6) ;Any masters left? BNE.S @1 ;br if so Move.W mAllocCnt(A6),D2 ;Number of masters to make. Ext.L D2 ASL.L #2,D2 ;Convert MP count to byte count. Add.L #BlkData32,D2 ;And block header Add.L D2,D0 ;Increase req count by ptr blk @1 BSR a32MakePtrSpc ;Make room at the low end. Move.L A2,A0 ;Ptr to block BrA.S PMRMExit32 ;Do the purge mem exit trip . . . ;---------------------------------------------------------------------- ; ; FUNCTION MaxMem: LongInt; ; On exit: ; If request pertains to application heap: ; A0 - returns the size of memory available for the application heap to grow ; D0 - Returns the size of the largest available contiguous free space. ; If request pertains to any other heap heap: ; A0 - 0, since only application heap may grow ; D0 - Returns the size of the largest available contiguous free space. ;---------------------------------------------------------------------- MaxMemTrap MOVE.L #JMaxMem,-(SP) ; get offset to routine MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue RTS ; go to routine v24MaxMem ; 24 bit version of MaxMem Move.L RealMemTop,D0 ;BkCompactS(MaxSize MoveQ #0,D2 ; False <2> kc.start Bsr.l a24BkCompactS Cmpi.b #cpu68040,CPUFlag ; Are we on an 040 or greater? Blt.s @0 ; No? Then no alignment. Tst.l pVMGlobals ; VM running? Bpl.s @0 ; Yea? Then no alignment. AndI.W #$FFF0,D1 ; Line align result. @0 Move.L D1,D0 ;return adjusted max <2> kc.end BEq.S @1 ;block size, unless 0 SubQ.L #BlkData24,D0 ;Allow for overhead @1 Sub.L A0,A0 ;if not applZone => return 0 in A0 Move.L applZone,A1 ;If request not for Cmp.L theZone,A1 ;applic heap... BNE.S MMExit24 ;then return ; Now return the size of memory available for the application heap to grow Move.L ApplLimit,D2 ;static applLimit BSR a24MaxLimit ;don't get closer than MinStack Sub.L HeapEnd,D1 Move.L D1,A0 ;return in A0 MMExit24 BRA.S MMExit32 ; jump to common exit v32MaxMem ; 32 bit version of MaxMem Move.L RealMemTop,D0 ;BkCompactS(MaxSize MoveQ #0,D2 ; False <2> kc.start Bsr.l a32BkCompactS Cmpi.b #cpu68040,CPUFlag ; Are we on an 040 or greater? Blt.s @0 ; No? Then no alignment. AndI.W #$FFF0,D1 ; Line align result. @0 Move.L D1,D0 ;return adjusted max <2> kc.end BEq.S @1 ;block size, unless 0 Sub.L #BlkData32,D0 ;Allow for overhead @1 Sub.L A0,A0 ;if not applZone => return 0 in A0 Move.L applZone,A1 ;If request not for Cmp.L theZone,A1 ;applic heap... BNE.S MMExit32 ;then return ; Now return the size of memory available for the application heap to grow Move.L ApplLimit,D2 ;static applLimit BSR a32MaxLimit ;don't get closer than MinStack Sub.L HeapEnd,D1 Move.L D1,A0 ;return in A0 MMExit32 Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue RTS ; jump to it ;---------------------------------------------------------------------- ; ; PROCEDURE SetGrowZone(GrowZone: Ptr); ; ; - sets the GrowZone procedure for the current heap zone to be ; that supplied by the user ; On entry, Registers: ; A0 - GrowZone procedures' address ; SetGrowZone Move.L #JSetGrowZone,-(SP) ; get offset onto stack Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue RTS vSetGrowZone GetZ A1 ; A1 - theZone Move.L A0,GZProc(A1) ; set user's GrowZone procedure BrA.S SALOk ;---------------------------------------------------------------------- ; ; PROCEDURE SetApplLimit(zonelimit: Long); ; ; - sets the limit of the application zone ; - <29jan85> Now checks it, too! ; Return error code globally now. <25Apr85> ; Mask A0 with Lo3Bytes before compare with HiHeapMark or BKLim. <01Nov85 JTC> ; Pin minimum allowed stack to DefltStack in low memory, since larger ; stacks are required on color machines are old-style apps are starving them. ; On entry, Registers: ; A0 - zone limit (in bytes) ; SetApplLimit Move.L #JSetApplLimit,-(SP) ; get offset onto stack Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue RTS v24SetApplLimit ; 24 bit version of setApplLimit Move.L A0,D0 ; suggested new value <01Nov85 JTC> And.L Lo3Bytes,D0 ; 24-bit address candidate for new limit <01Nov85 JTC> MoveA.L D0,A0 ; presume this is lower value <01Nov85 JTC> Move.L SP,D1 ; try SP-DefltStack And.L Lo3Bytes,D1 ; 24-bit SP Sub.L DefltStack,D1 ; masked(SP-DefltStack) Cmp.L D0,D1 ; (SP-DefltStack) - BGT.S @1 ; D0 < D1 --> suggested value OK MoveA.L D1,A0 ; D1 ² D0 --> use SP-DefltStack @1 ; bypass using DefltStack pinning Move.L A0,ApplLimit ; Set the application limit ; (don't worry, GrowZone checks it dynamically) ; the above claim is B.S. <29jan85> Move.L A0,HiHeapMark ; New high! <01Nov85 JTC> Move.L ApplZone,A1 ; point to the app zone <29jan85> Move.L BKLim(A1),A1 ; point to limit block <29jan85> MoveQ #MemFullErr,D0 ; presume the worst <29jan85> Cmp.L A0,A1 ; BKLim - ApplZone <29jan85> BHi.S SALNotOk ; Hi ==> already beyond limit <29jan85> ; LowOrSame ==> fall through Ok <29jan85> SALOk MoveQ #0,D0 ; return success SALNotOk ; get here if memFull above <29jan85> Move.W D0,MemErr ; stuff error globally <25Apr85> RTS v32SetApplLimit ; 32 bit version of setApplLimit Move.L A0,D0 ; suggested new value Move.L SP,D1 ; try SP-DefltStack Sub.L DefltStack,D1 ; masked(SP-DefltStack) Cmp.L D0,D1 ; (SP-DefltStack) - BGT.S @1 ; D0 < D1 --> suggested value OK MoveA.L D1,A0 ; D1 ² D0 --> use SP-DefltStack @1 ; bypass using DefltStack pinning Move.L A0,ApplLimit ; Set the application limit ; (don't worry, GrowZone checks it dynamically) ; the above claim is B.S. <29jan85> Move.L A0,HiHeapMark ; New high! <01Nov85 JTC> Move.L ApplZone,A1 ; point to the app zone <29jan85> Move.L BKLim(A1),A1 ; point to limit block <29jan85> MoveQ #MemFullErr,D0 ; presume the worst <29jan85> Cmp.L A0,A1 ; BKLim - ApplZone <29jan85> BHi.S @SALNotOk ; Hi ==> already beyond limit <29jan85> ; LowOrSame ==> fall through Ok <29jan85> MoveQ #0,D0 ; return success @SALNotOk ; get here if memFull above <29jan85> Move.W D0,MemErr ; stuff error globally <25Apr85> RTS ;---------------------------------------------------------------------- ; ; FUNCTION StackSpace : LongInt; <09May85> ; ; - returns Delta between SP and HiHeapMark. ; Stack on entry is: ; ret to dispatch << A0-A1 << ret within dispatch << D1-D2/A2 << trash long << ret to app ; so there are 4 + 8 + 4 + 12 + 4 + 4 = 36 more bytes available than indicated by the current ; SP. Since bkLim(xxx) refers to the beginning of a 16-byte block (change from 12 byte < v1,1>), ; and HiHeapMark is bkLim of the highest zone to date, the correct arithmetic is ; StackSpace := ( SP - BKLim(xxx) ) - 16 + 36 = SP - bkLim(xxx) + 20 ; The high bits of ApplZone and HiHeapMark are guaranteed to be clean. ; StackSpaceTrap Move.L #JStackSpace,-(SP) ; get offset onto stack Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue RTS vStackSpace ; MoveQ #20,D0 ;fudge factor Add.L SP,D0 ; <09May85> AndI.W #$FFFC,D0 ;round down to multiple of 4 Sub.L HiHeapMark,D0 ; Clr.W MemErr ;no problem here <09May85> RtS ;---------------------------------------------------------------------- ; ; PROCEDURE MaxApplZone; ; ; - lengthens the application zone out to ApplLimit, without extending the latter. <24Apr85> ; This routine depends on the values of bkLim(ApplZone), ApplLimit, and HeapEnd being ; free of extraneous high bits, since address arithmetic (comparable to that of ZoneAdjustEnd, ; MaxLimit, and GrowZone in HeapGuts) is performed. Also, ApplLimit is forced to be (unsigned) ; greater or equal to HeapEnd, so their difference may be interpreted as unsigned. ; ; Uses SALOk to stuff noErr code. <25Apr85> ; Take care to force HiHeapMark if it was less than current ApplLimit. ; ; On entry: none ; On exit: D0=0 ; Trashes: A0-A1/D0-D2 ; MaxApplZone Move.L #JMaxApplZone,-(SP) ; get offset onto stack Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue RTS v24MaxApplZone ; 24 bit version of MaxApplZone Move.L ApplLimit,D0 ; alleged end of the zone Cmpi.b #cpu68040,CPUFlag ; Are we on an 040 or greater? <2> kc.start Blt.s @0 ; No? Then no alignment. Tst.l pVMGlobals ; VM running? Bpl.s @0 ; Yea? Then no alignment. Andi.w #$FFF0,D0 ; Force line alignment. Sub.l #BlkData24,D0 ; Header size. Bra.s @1 @0 AndI.W #$FFFC,D0 ; round down to multiple of 16 @1 Move.L D0,D1 ; <2> kc.end LEA HeapEnd,A1 ; we'll use and possibly set this value Sub.L (A1),D0 ; amount of heap growth, if any; (this value is NONNEGATIVE) NOT! BCS.S @MAZFini ; Carry Set => minFree > delta, no dice... MoveQ #minFree24,D2 ; beneath this epsilon we will not grow Cmp.L D2,D0 BCS.S @MAZFini ; Carry Set => minFree > delta, no dice... MoveA.L (A1),A0 ; current bkLim ptr is the new (large) free block Move.L D0,(A0) ; force large free block there, freeing A0 Move.L D1,(A1) ; new heapEnd := bkLim, freeing A1 MoveA.L D1,A0 ; we need it as a ptr, in an A-register CmpA.L HiHeapMark,A0 ; is this a new high for heap extents? BLS.S @noNewHigh ; HiHeapMark ³ A0 => no change Move.L A0,HiHeapMark ; HiHeapMark < A0 => reset HiHeapMark @noNewHigh ; skip to here when HiHeapMark OK MoveA.L ApplZone,A1 ; now adjust the zone header Move.L A0,bkLim(A1) Move.L D2,(A0) ; make it a minFree block Add.L D0,ZCBFree(A1) ; adjust free block count @MAZFini BrA.S SALOk ; stuff the noErr code there <25Apr85> v32MaxApplZone ; 32 bit version of MaxApplZone Move.L ApplLimit,D0 ; alleged end of the zone Cmpi.b #cpu68040,CPUFlag ; Are we on an 040 or greater? <2> kc.start Blt.s @0 ; No? Then no alignment. Andi.w #$FFF0,D0 ; Force line alignment. Sub.l #BlkData32,D0 ; Header size. Bra.s @1 @0 AndI.W #$FFFC,D0 ; round down to multiple of 16 @1 Move.L D0,D1 ; <2> kc.end LEA HeapEnd,A1 ; we'll use and possibly set this value Sub.L (A1),D0 ; amount of heap growth, if any; this value is NONNEGATIVE!! BCS.S @MAZFini ; Carry Set => minFree > delta, no dice... MoveQ #minFree32,D2 ; beneath this epsilon we will not grow Cmp.L D2,D0 BCS.S @MAZFini ; Carry Set => minFree > delta, no dice... MoveA.L (A1),A0 ; current bkLim ptr is the new (large) free block Clr.L TagBC32(A0) ; set as free block Move.L D0,BlkSize32(A0); get block size Move.L D1,(A1) ; new heapEnd := bkLim, freeing A1 MoveA.L D1,A0 ; we need it as a ptr, in an A-register CmpA.L HiHeapMark,A0 ; is this a new high for heap extents? BLS.S @noNewHigh ; HiHeapMark ³ A0 => no change Move.L A0,HiHeapMark ; HiHeapMark < A0 => reset HiHeapMark @noNewHigh ; skip to here when HiHeapMark OK MoveA.L ApplZone,A1 ; now adjust the zone header Move.L A0,bkLim(A1) Clr.L tagBC32(A0) ; clear 1st long word in header block Move.L D2,BlkSize32(A0); make it a minFree block Add.L D0,ZCBFree(A1) ; adjust free block count @MAZFini BrA.S SALOk ; stuff the noErr code there <25Apr85> ;---------------------------------------------------------------------- ; ; FUNCTION NewPtr(byteCount: LongInt): Ptr; ; ; On entry: D0 - size in bytes to allocate ; On exit : A0 - Returns a pointer to a block of (data) size byteCount. ; ;---------------------------------------------------------------------- ; ÑÑÑÑÑÑÑÑÑÑÑSuperMario roll in tcn ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ ; NewPtr - make it grow System Heap and place the block down low, too. ; Now that the system heap can grow, all of a sudden NewPtr is dropping locked blocks at the top of ; the heap. This stems from the fact the routine which reserves the block (MkPtrSpace) only grows ApplZone. ; This proc calls NewPtr, then checks to see whether the heap grew. If it did, this throws away the ; newly allocated block and calls NewPtr again. This gives MkPtrSpace the chance to allocate space ; down low because now thereÕs room to put relocatable blocks (the space the heap growing gave us). ; ; See also: ResrvMemGrowSystemHeap ; ; I re-rolled this patch so it won't overload the cpu :-) kc ; ;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ NewPtrTrap MOVE.L #JNewPtr,-(SP) ; get offset to routine MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue RTS ; go to routine ; --- 24 bit version ---- v24NewPtr ; 24 bit version of NewPtr CMPA.L SysZone,a6 ; is this handle going in the System heap? BEQ.S NPSysZone24 ; yup BTST #tSysOrCurZone,d1 ; is the "sys" bit set in the trapword? BEQ.S NPNotSysZone24 ; nope NPSysZone24 MOVE.L bkLim(a6),-(sp) ; save the end of system zone SUB.L A1,A1 ; Handle Nil => fixed block BSR a24MakePtrSpc ; Make room at the low end. BSR a24AllocBk ; Allocate the block MOVE.L (sp)+,A1 ; Recover the old end of system zone BEQ.S NPNoMem24 ; Br if out of mem CMP.L bkLim(a6),A1 ; Did the system heap grow? BEQ.S NPCheckClear24 ; No, carry on as normal BSR a24FreeBk ; Yes, free the block and try again. NPNotSysZone24 SUB.L A1,A1 ; Handle Nil => fixed block BSR a24MakePtrSpc ; Make room at the low end. BSR a24AllocBk ; Allocate the block BEQ.S NPNoMem24 ; Br if out of mem NPCheckClear24 BSR CheckClear ; Clear block if requested NPOk24 MOVEQ #0,D0 NPExit24 BRA.S NPExit ; jump to common exit NPNoMem24 MOVEQ #memFullErr,D0 BRA.S NPExit24 ; --- 32 bit version ---- v32NewPtr ; 32 bit version of NewPtr CMPA.L SysZone,a6 ; is this handle going in the System heap? BEQ.S NPSysZone32 ; yup BTST #tSysOrCurZone,d1 ; is the "sys" bit set in the trapword? BEQ.S NPNotSysZone32 ; nope NPSysZone32 MOVE.L bkLim(a6),-(sp) ; save the end of system zone SUB.L A1,A1 ; Handle Nil => fixed block BSR a32MakePtrSpc ; Make room at the low end. BSR a32AllocBk ; Allocate the block MOVE.L (sp)+,A1 ; Recover the old end of system zone BEQ.S NPNoMem ; Br if out of mem CMP.L bkLim(a6),A1 ; Did the system heap grow? BEQ.S NPCheckClear32 ; No, carry on as normal BSR a32FreeBk ; Yes, free the block and try again. NPNotSysZone32 SUB.L A1,A1 ; Handle Nil => fixed block BSR a32MakePtrSpc ; Make room at the low end. BSR a32AllocBk ; Allocate the block BEQ.S NPNoMem ; Br if out of mem NPCheckClear32 BSR CheckClear ; Clear block if requested NPOk MOVEQ #0,D0 NPExit MOVE.L vMMEpilogue,-(SP) ; get vector to MMEpilogue RTS ; jump to it NPNoMem MOVEQ #memFullErr,D0 BrA.S NPExit ;---------------------------------------------------------------------- ; ; PROCEDURE DisposePtr(p: Ptr); ; ; On entry: A0 - ptr to block to be disposed ; - Disposes of previousely allocated Ptr object -- unless ROZ <04Mar85> ; ;---------------------------------------------------------------------- DisposePtr move.l a0,d0 ; be cool when a NIL ptr comes through stb bne.w @NonNIL ; not nil, so call the real thing stb move.w d0,MemErr ; return no error even though itÕs not a ptr stb rts ; stb @NonNIL MOVE.L #jDisposePtr,-(SP) ; get offset to routine MOVE.L vMMPPrologue,-(SP) ; get vector to MMpprologue RTS ; go to routine v24DisposePtr ; 24 bit version of DisposePtr ; Move.L (SP)+,A0 ; restore A0 DisposeTail24 BTST #ROZ,flags(A6) ; skip if read-only <04Mar85> BNE.S DisposeSkip ; <04Mar85> BSR a24FreeBk ; BrA.S NPOk v32DisposePtr ; 32 bit version of DisposePtr ; Move.L (SP)+,A0 ; restore A0 DisposeTail32 BTST #ROZ,flags(A6) ; skip if read-only <04Mar85> BNE.S DisposeSkip ; <04Mar85> BSR a32FreeBk ; BrA.S NPOk DisposeSkip MOVEQ #memROZWarn,D0 ; deliver warning <04Mar85> BRA.S NPExit ; <04Mar85> ;---------------------------------------------------------------------- ; ; FUNCTION GetPtrSize(p: Ptr): Size; ; ; On entry: A0.L- ptr ; On exit : D0.L- size in bytes ; Returns the actual data size of a Ptr object. GetPtrSizeTrap MOVE.L #jGetPtrSize,-(SP) ; get offset to routine MOVE.L vMMPPrologue,-(SP) ; get vector to MMpprologue RTS ; go to routine v24GetPtrSize ; 24 bit version of MaxMem BSR a24GetSize ; Get its size BrA.S NPExit ; Check Zone, Restore, Return v32GetPtrSize ; 32 bit version of MaxMem BSR a32GetSize ; Get its size BrA.S NPExit ; Check Zone, Restore, Return ;---------------------------------------------------------------------- ; ; FUNCTION SetPtrSize(blk: Ptr; cb: Size): result; ; ; This routine is used to set the size of non-relocatable memory blocks ; ; Arguments: ; D0 - cb: new block size ; A0 - blk: pointer to block data ; A1 - h: NIL, set up by MMPPrologue ; ; Result: ; D0 - 0 => success; memFullErr => failure ; ; Registers: ; ; A0 - next free block ; A1 - current free block ; A2 - theZone ; D0 - number of bytes needed ; D1 - number of bytes in current free block ; D2 - new block length (temporary) ; SetPtrSizeTrap MOVE.L #jSetPtrSize,-(SP) ; get offset to routine MOVE.L vMMPPrologue,-(SP) ; get vector to MMpprologue RTS ; go to routine v24SetPtrSize ; 24 bit version of MaxMem BSR a24SetSize ; set its size BrA.S NPExit v32SetPtrSize ; 32 bit version of MaxMem BSR a32SetSize ; set its size BrA.S NPExit ;---------------------------------------------------------------------- ; ; FUNCTION PtrZone(p: Ptr): Zone; ; ; Returns the zone in which a memory block belongs. ; ; Argument: ; A0: p: pointer for block ; ; Result: ; D0: ec: error code ; A0: zone: zone in which block belongs ; PtrZoneTrap MOVE.L #jPtrZone,-(SP) ; get offset to routine MOVE.L vMMPPrologue,-(SP) ; get vector to MMpprologue RTS ; go to routine vPtrZone ; 24/32 bit version of PtrZone Move.L A6,A0 BrA.S NPOk CheckClear BTst #ClearBit,D1 ;clear the allocated memory? BEq.S @2 ;br if not Move.L A0,-(SP) ;preserve A0 AddQ.L #1,D0 ;increment allocation size LSR.L #1,D0 ;get word size @1 Clr.W (A0)+ ;clear it out SubQ.L #1,D0 BGT.S @1 Move.L (SP)+,A0 ;restore A0 @2 RTS ;---------------------------------------------------------------------- ; ; FUNCTION NewEmptyHandle: Handle; ; On entry: ; no input assumptions ; On exit: ; A0 - handle ; D0 - error code ; - Allocate an empty master pointer in the zone pool. ; Registers: NewEmptyHandleTrap MOVE.L #JNewEmptyHandle,-(SP) ; get offset to routine MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue RTS ; go to routine v24NewEmptyHandle ; 24 bit version of NewEmptyHandle BSR a24NextMaster ; Get next master in A1 BEQ.S NHNoMaster ; If NIL, exit as in NewHandle BRA.S NewEHExit ; use common code v32NewEmptyHandle ; 32 bit version of NewEmptyHandle BSR a32NextMaster ; Get next master in A1 BEQ.S NHNoMaster ; If NIL, exit as in NewHandle NewEHExit Move.L A1,A0 ; Get it to A0 for return CLR.L (A0) ; Make it NIL MoveQ #0,D0 ; Show success Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue RTS ; jump to it ;---------------------------------------------------------------------- ; ; FUNCTION NwHandle(cb: Size): Handle; ; On entry: ; D0 - size to allocate ; On exit: ; A0 - handle ; - Allocate a relocatable object with its master pointer in the ; zone pool. ; Registers: NwHandle MOVE.L #JNwHandle,-(SP) ; get offset to routine MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue RTS ; go to routine v24NwHandle ; 24 bit version of NwHandle ; from SetRovingPointerBeforeNewHandle patch kc CMPA.L SysZone,a6 ; is this handle going in the System heap? kc BEQ.S @inSysZone ; yup kc BTST #tSysOrCurZone,d1 ; is the "sys" bit set in the trapword? kc BEQ.S @notInSysZone ; nope kc @inSysZone ; kc CLR.L allocPtr(a6) ; clear the rover kc @notInSysZone ; kc BSR a24NextMaster ; Get next master BNE.S @NHMaster ; If not NIL, go get block BRA.S NHNoMaster ; if NIL, report error @NHMaster BSR a24AllocBk ; try to allocate block BEq.S NHNoMem ; No luck, fail return BRA.S HCheckHandle v32NwHandle ; 32 bit version of NwHandle ; from SetRovingPointerBeforeNewHandle patch kc CMPA.L SysZone,a6 ; is this handle going in the System heap? kc BEQ.S @inSysZone ; yup kc BTST #tSysOrCurZone,d1 ; is the "sys" bit set in the trapword? kc BEQ.S @notInSysZone ; nope kc @inSysZone ; kc CLR.L allocPtr(a6) ; clear the rover kc @notInSysZone ; kc BSR a32NextMaster ; Get next master BNE.S NHMaster ; If not NIL, go get block NHNoMaster MoveQ #memFullErr,D0 BrA.S HNilResult NHMaster BSR a32AllocBk ; try to allocate block BEq.S NHNoMem ; No luck, fail return HCheckHandle BSR.S CheckClear ; Clear memory if requested Move.L A1,A0 NHOk MoveQ #0,D0 NHExit Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue RTS ; jump to it NHNoMem MoveQ #memFullErr,D0 BrA.S HReleaseMP ;---------------------------------------------------------------------- ; ; PROCEDURE DsposeHandle(h: Handle); ; On entry: ; A0 - handle to block to be disposed -- unless ROZ <04Mar85> ; Reactivated even if ROZ to just clear (bogus) MP <10Apr85> ; Distinguish Nil and Empty cases from MMHPrologue. <21May85> ;---------------------------------------------------------------------- DsposeHandle Move.L #JDsposeHandle,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24DsposeHandle ; 24 bit version of MaxMem BNE.S DisposeTail24 ; Release block Bra.S DsposeCommon ; branch to commond code v32DsposeHandle ; 32 bit version of DsposeHandle BNE.S DisposeTail32 ; Release block DsposeCommon ; commond code Move.L A1,D0 ; Masked handle: EQ => Nil passed <21May85> BEq.S HNilResult ; No master ptr to release <21May85> BTST #ROZ,flags(A6) ; skip if ROZ <10Apr85> BNE.S HROZResult ; <10Apr85> cmp.l ROMBase,d0 ; is it a ROM resource ? PN bgt.s Nothing ; if in ROM, leave it alone PN MoveQ #0,D0 ; Success result HReleaseMP BSR ReleaseMP ; Return MP to list HNilResult Sub.L A0,A0 ; Return NIL in A0 for NwHandle BrA.S NHExit HROZResult CLR.L (A1) ; just clear the (bogus) MP <10Apr85> Nothing BRA.S NHOk ; go to MMEpilogue, sans error <10Apr85> ;---------------------------------------------------------------------- ; FUNCTION GetHandleSize(h: Handle): LongInt; ; On entry: A0 - handle ; On exit : D0 - size in bytes ; Returns the actual data size of a Handle object. __GetHandleSize Move.L #JGetHandleSize,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24GetHandleSize ; 24 bit version of GetHandleSize BEq.S SHSNil BSR a24GetSize ; BrA.S SHSExit v32GetHandleSize ; 32 bit version of GetHandleSize BEq.S SHSNil BSR a32GetSize ; BrA.S SHSExit ;---------------------------------------------------------------------- ; ; FUNCTION SetHandleSize(h: Handle; cb: LongInt): result; ; ; This routine is used to change the size of a relocatable memory block. ; The block handle remains the same; the Master Pointer is unchanged if ; the new length is less than or equal to the old. ; ; Arguments: ; D0 - cb: new block size ; A0 - handle: pointer to master pointer ; ; Result: ; D0 - 0 => success; memFullErr => failure ; ; Registers: ; ; A0 - next free block ; A1 - handle ; SetHandleSizeTrap Move.L #JSetHandleSize,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24SetHandleSize ; 24 bit version of SetHandleSize BEQ.S SHSNil BSR a24SetSize ; Set size as specified in D0 BrA.S SHSExit ; v32SetHandleSize ; 32 bit version of SetHandleSize BNE.S SHSOk SHSNil MoveQ #nilHandleErr,D0 ;return error code BrA.S SHSExit SHSOk BSR a32SetSize ;Set size as specified in D0 SHSExit Move.L A1,A0 ;restore A0 for RecoverHandle BrA.S NHExit ;---------------------------------------------------------------------- ; ; FUNCTION HandleZone(h: Handle): Zone; ; ; Returns the zone in which a memory block belongs. ; ; Argument: ; A0: h: handle for block ; ; Result: ; D0: ec: error code ; A0: zone: zone in which block belongs ; HandleZoneTrap Move.L #JHandleZone,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine vHandleZone ; 24/32 bit version of HandleZone Move.L A6,A0 BrA.S NHOk ;---------------------------------------------------------------------- ; FUNCTION RecoverHandle(ptr: Ptr): Handle; ; On entry: A0 - pointer ; On exit : A0 - handle ; Must preserve D0!!!!! (As per 64K ROM, that is.) <25Apr85> ; Given a ptr to an alleged handle data block, returns the handle. Because of ; 64K ROM permissiveness, no error can be returned in D0, just in MemErr. ; Uses own exit sequence to MMNoErrEpilogue and stuffs MemErr on its own. <25Apr85> ; To effect patch from Mac+, special MMRHPrologue (ÒRHÓ as in RecoverHandle) ; is used to ensure the the more reasonable of SysZone and ApplZone is used for A6 ; when incoming TheZone is one of Sys or Appl. ; Put a bus error handler on the fetch of the relative handle, pinning to ; ROMBase, for safety. RecoverHandleTrap Move.L #JRecoverHandle,-(SP) ; get offset to routine onto stack Move.L vMMRHPrologue,-(SP) ; get vector to MMRHPrologue RTS ; go to routine v24RecoverHandle ; 24 bit version of RecoverHandle <2> MOVE.L Lo3Bytes,D2 ; mask to strip extraneous bits <2> BRA.S vRecoverHandle ; <2> v32RecoverHandle ; 32 bit version of RecoverHandle <2> MOVEQ #-1,D2 ; no extraneous address bits in 32-bit mode <2> vRecoverHandle Move.L BusErrVct,A2 ; save current bus error handler <1.7> LEA RHBusErrHandler,A3 ; our RH version Move.L A3,BusErrVct ; <1.7> Move.L -4(A0),A1 ; Handle, or ROMBase on bus error ReturnFromBusErr ; rb Move.L A2,BusErrVct ;restore old one after danger <1.7> Add.L A6,A1 ; The following code tests for bad mp, but can only set MemErr <25Apr85> MOVE.L A0,D1 ; original pointer <2> AND.L D2,D1 ; stripped to RAW address <2> AND.L (A1),D2 ; master pointer value stripped to RAW address <2> Sub.L D1,D2 ; if equal, have required error code! Beq.S RecoverExit ; If we get here, the pointer either didn't point to a block in the suspected ; heap or is a bogus block pointer. We'll assume it's the first case and try ; looking in the ROZ created for the ROM resource map before giving up completely. ; This will not affect the performance of RecoverHandle() since this code is only ; executed as part of the error path (which shouldn't be taken most of the time). ; Also, it assumes that the ROZ is ALWAYS a 32-bit heap zone. MOVEA.L A6,A3 ; save the previous zone start pointer <2> MOVEA.L RomMapHndl,A6 ; get the handle to the ROM resource map <2> MOVEA.L (A6),A2 ; and de-reference it <2> SUBA.L -4(A2),A6 ; calculate heap start based on rel hdl in MP <2> CMPA.L A3,A6 ; have we been here before? <2> BNE.S v32RecoverHandle ; -> no, try again with the ROZ <2> MoveQ #memBCErr,D2 ; block check failure <13Apr85> RecoverExit Move.W D2,MemErr ; stuff global error code (is anybody out there?)<25Apr85> MoveA.L A1,A0 ; restore A0=handle <25Apr85> Move.L vMMNoErrEpilogue,-(SP) ; get MMNoErrEpilogue vector RTS ;---------------------------------------------------------------------- ; RHBusErr -- bus error handler for RecoverHandle rb, start ; A bus error in RecoverHandle causes ROMBase to be jammed for the relative handle. ; Triggered by bus errors in Move.L -4(A0),A1 in RecoverHandle. ; ; Frame types 7 and B are handled. The PC is jammed with the instruction ; following the bus error (it can't be incremented because the emulator ; doesn't guarantee valid PC values) and A1 is jammed with ROMbase. The ; frame is then mutated into a type 0 frame before RTE. This should work ; with VM, NuKernel, and emulator environments. ; ; Output: A1 = ROMBase ; Regs: A3 ;---------------------------------------------------------------------- RHBusErrHandler movea.l ROMBase,a1 ; stuff fake Nil value into expected dest. reg movea.w (sp),a3 ; cmpi.w #$7008,6(SP) ; type 7 frame? beq.s RHBusErrType7 ; adda.w #(92-8),SP ; Leave space for type 0 frame bra.s RHBusErrCommon ; RHBusErrType7 ; adda.w #(60-8),SP ; Leave space for type 0 frame RHBusErrCommon ; clr.w 6(SP) ; Make it a type 0 frame move.w a3,(sp) ; Return SR lea ReturnFromBusErr,a3 ; move.l a3,2(SP) ; Return PC RTE ; rb, end ;---------------------------------------------------------------------- ; ; PROCEDURE EmptyHandle(h: Handle); ; - Deallocates data block pointed to by the given handle & zeroes the MP ; Note that EH will not deallocate the data block if it's a ROZ. <10Apr85> ; On entry, Registers: ; A0 - Handle EmptyHandle Move.L #JEmptyHandle,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24EmptyHandle ; 24 bit version of EmptyHandle BNE.S @EHNotNIL MoveQ #0,D0 BrA.S EHExit @EHNotNIL BSR a24EH ; Common code with ReAllocHandle BrA.S EHExit v32EmptyHandle ; 32 bit version of EmptyHandle BNE.S EHNotNIL MoveQ #0,D0 BrA.S EHExit EHNotNIL BSR a32EH ;Common code with ReAllocHandle EHExit BrA.S SHSExit ;---------------------------------------------------------------------- ; ; PROCEDURE: ReAllocHandle ; Arguments: D0 (input) -- size to allocate (long) ; A0 (input) -- original handle ; D0 (output) -- result code (MemFullErr) ; A0 (output) -- original handle or nil if unsuccessful ; Function: Allocate a relocatable object given its original Handle. ; This is useful when a relocatable data block is purged: it can ; be retrieved without having to destroy the handle & having to ; update every copy of the handle. ; ; If the handle in A0 does not point to a purged block, the ; block is freed first. ; ; This sets up the GZ root semaphores for the grow zone proc ; so it doesn't mess with the handle in question. ; ; If ROZ and empty handle, just do it; if non-empty give warning or error <04Mar85> ; depending on whether no larger or growing. <04Mar85> ; ;---------------------------------------------------------------------- ReAllocHandleTrap Move.L #JReAllocHandle,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24ReAllocHandle ; 24 bit version of ReAllocHandle BEQ.S @RAHCont ; kc ; from SetRovingPointerBeforeReallocHandle patch kc CMPA.L SysZone,a6 ; is this handle going in the System heap? kc BEQ.S @inSysZone ; yup kc BTST #tSysOrCurZone,d1 ; is the "sys" bit set in the trapword? kc BEQ.S @notInSysZone ; nope kc @inSysZone ; kc CLR.L allocPtr(a6) ; clear the rover kc @notInSysZone ; kc BTST #ROZ,flags(A6) ; Bypass if ROZ <04Mar85> BNE.S @RAHSkip ; <04Mar85> BSR a24EH ; Empty the Handle for sure BNE.S SHSExit ; EH failed, return error code Move.L D2,D0 ; restore D0 (saved by MMHPrologue) @RAHCont Move.L A1,GZRootHnd ; record handle being reallocated Clr.L GZRootPtr ; record lack of pointer BSR a24AllocBk ; try to allocate block BSR ClearGZStuff ; clean up gz safety stuff Move.L A0,D2 ; see if alloc bk worked BNE HCheckHandle ; If ok, take the NewHandle exit route. MoveQ #memFullErr,D0 ; If we can't find the space, just report Bra.S SHSExit ; the error, leaving handle alone . . . @RAHSkip BSR a24GetSize ; D0 := current data size CMP.L D0,D2 ; requested - current ... unsigned <04Mar85> BHI.S RAHError ; it's erroneous to grow <04Mar85> MOVEQ #memROZWarn,D0 ; <04Mar85> BRA.S SHSExit ; <04Mar85> v32ReAllocHandle ; 32 bit version of ReAllocHandle BEQ.S @RAHCont ; kc ; from SetRovingPointerBeforeReallocHandle patch kc CMPA.L SysZone,a6 ; is this handle going in the System heap? kc BEQ.S @inSysZone ; yup kc BTST #tSysOrCurZone,d1 ; is the "sys" bit set in the trapword? kc BEQ.S @notInSysZone ; nope kc @inSysZone ; kc CLR.L allocPtr(a6) ; clear the rover kc @notInSysZone ; kc BTST #ROZ,flags(A6) ; Bypass if ROZ <04Mar85> BNE.S RAHSkip ; <04Mar85> BSR a32EH ; Empty the Handle for sure BNE.S SHSExit ; EH failed, return error code Move.L D2,D0 ; restore D0 (saved by MMHPrologue) @RAHCont ; kc Move.L A1,GZRootHnd ; record handle being reallocated Clr.L GZRootPtr ; record lack of pointer BSR a32AllocBk ; try to allocate block BSR ClearGZStuff ; clean up gz safety stuff Move.L A0,D2 ; see if alloc bk worked BNE HCheckHandle ; If ok, take the NewHandle exit route. MoveQ #memFullErr,D0 ; If we can't find the space, just report Bra.S SHSExit ; the error, leaving handle alone . . . RAHSkip BSR a32GetSize ; D0 := current data size CMP.L D0,D2 ; requested - current ... unsigned <04Mar85> BHI.S RAHError ; it's erroneous to grow <04Mar85> MOVEQ #memROZWarn,D0 ; <04Mar85> BRA.S SHSExit ; <04Mar85> RAHError MOVEQ #memROZError,D0 ; <04Mar85> BRA.S SHSExit ; <04Mar85> ;---------------------------------------------------------------------- ; ; PROCEDURE HLock(h: Handle); ; ; - Lock the relocatable block pointed to by the given handle. ; ; On entry, Registers: ; ; A0 - Handle ; HLock Move.L #JHLock,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine ; <2> kc.start v24Hlock BEQ HFail ; handle was NIL BSET #Lock,(A1) ; set the lock bit BRA HGood ; return success v32Hlock BEQ HFail ; handle was NIL bset #Lock,MPtag32-blkData32(A0) ; set the lock bit BRA HGood ; return success ;---------------------------------------------------------------------- ; ; PROCEDURE HUnLock(h: Handle); ; ; - Unlock the relocatable block pointed to by the given handle. ; ; On entry, Registers: ; ; A0 - Handle ; HUnlock Move.L #JHUnLock,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24HUnlock BEq HFail ; handle was NIL BClr #Lock,(A1) ; reset the lock bit BrA HGood ; return success v32HUnlock BEq.S HFail ; handle was NIL BClr #Lock,MPtag32-blkData32(A0) ;reset the lock bit BrA.S HGood ; return success ;---------------------------------------------------------------------- ; ; PROCEDURE HPurge(h: Handle); ; ; - Enable purging the relocatable block pointed to by the given handle. ; ; On entry, Registers: ; ; A0 - Handle ; HPurge Move.L #JHPurge,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24HPurge BEq.S HFail ; handle was NIL BSet #Purge,(A1) ; set the purge bit BrA.S HGood ; return success v32HPurge BEq.S HFail ; handle was NIL BSet #Purge,MPtag32-blkData32(A0);set the purge bit BrA.S HGood ; return success ;---------------------------------------------------------------------- ; ; PROCEDURE HNoPurge(h: Handle); ; ; - Disable purging the relocatable block pointed to by the given handle. ; Stuff error code globally. <25Apr85> ; ; On entry, Registers: ; ; A0 - Handle ; HNoPurge Move.L #JHNoPurge,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24HNoPurge BEq.S HFail ; handle was NIL BClr #Purge,(A1) ; reset the purge bit BrA.S HGood ;return success v32HNoPurge BEq.S HFail ; handle was NIL BClr #Purge,MPtag32-blkData32(A0);reset the purge bit HGood MoveQ #0,D0 BrA.S HExit HFail MoveQ #nilHandleErr,D0 HExit Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue RTS ; jump to it ;---------------------------------------------------------------------- ; ; PROCEDURE HRSRC(h: Handle); <13Jan86 JTC> ; ; - Set the resource bit of the relocatable block pointed to by the given handle. ; ; On entry, Registers: ; ; A0 - Handle ; HRSRC ; <13Jan86 JTC> Move.L #JHRSRC,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24HRSRC BEq.S HFail ;handle was NIL <13Jan86 JTC> BSet #Resource,(A1) ; BrA.S HGood ;return success <13Jan86 JTC> v32HRSRC BEq.S HFail ;handle was NIL <13Jan86 JTC> BSet #Resource,MPtag32-blkData32(A0) ;set the Resource bit BrA.S HGood ;return success <13Jan86 JTC> ;---------------------------------------------------------------------- ; ; PROCEDURE HNoRSRC(h: Handle); <13Jan86 JTC> ; ; - Clear the resource bit of the relocatable block pointed to by the given handle. ; ; On entry, Registers: ; ; A0 - Handle ; HNoRSRC ; Move.L #jHNoRSRC,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24HNoRSRC BEq.S HFail ; handle was NIL <13Jan86 JTC> BClr #Resource,(A1) ; reset the RSRC bit BrA.S HGood ; return success <13Jan86 JTC> v32HNoRSRC BEq.S HFail ; handle was NIL <13Jan86 JTC> BClr #Resource,MPtag32-blkData32(A0) ;reset the RSRC bit BrA.S HGood ; return success <13Jan86 JTC> ;---------------------------------------------------------------------- ; ; FUNCTION HGetFlags(h: Handle) : BYTE; <13Jan86 JTC> ; ; - Fetch the flag byte of the master pointer of the given handle. ; ; On entry, Registers: ; A0 - Handle ; On exit, Registers: ; D0 - flag byte in D0.B, rest of bits clear ; HGetFlags ; <13Jan86 JTC> Move.L #JHGetFlags,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24HGetFlags BEq.S HFail ; if Nil, stuff D0 with error code <13Jan86 JTC> MoveQ #0,D0 ; init high bits <13Jan86 JTC> Move.B (A1),D0 ; stuff the flag byte <13Jan86 JTC> Bra.S GetFlagsExit ; exit through common code v32HGetFlags BEq.S HFail ; if Nil, stuff D0 with error code <13Jan86 JTC> MoveQ #0,D0 ; init high bits <13Jan86 JTC> Move.B MPtag32-BlkData32(A0),D0 ;stuff the flag byte GetFlagsExit Clr.W MemErr ; custom exit, clearing error bits <13Jan86 JTC> MOVE.L vMMNoErrEpilogue,-(SP) ; get MMNoErrEpilogue vector RtS ; <13Jan86 JTC> ;---------------------------------------------------------------------- ; ; PROCEDURE HSetFlags(h: Handle; f: BYTE); <13Jan86 JTC> ; ; - Set the flag byte of the master pointer of the given handle. ; ; On entry, Registers: ; A0 - Handle ; D0 - flag byte in D0.B, rest of bits don't care ; HSetFlags ; <13Jan86 JTC> Move.L #JHSetFlags,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24HSetFlags BEq.S HFail ; if Nil, stuff D0 with error code <13Jan86 JTC> Move.B D0,(A1) ; stuff flags Bra.S HGood ; return OK <13Jan86 JTC> v32HSetFlags BEq.S HFail ; if Nil, stuff D0 with error code <13Jan86 JTC> Move.B D0,MPtag32-BlkData32(A0) ;stuff the flag byte Bra.S HGood ; return OK <13Jan86 JTC> ;---------------------------------------------------------------------- ; ; PROCEDURE MoreMasters(); ; ; - Direct call from app, as opposed to demand requisition of MPs. <29jan85> ; Stuff error code globally, now. <25Apr85> ; ; No parameters. ; MoreMasters Move.L #jMoreMasters,-(SP) ; get offset to vector onto stack Move.L vMMMMPrologue,-(SP) ; get MMMMPrologue vector onto stack RTS ; go to routine v24MoreMasters ; 24 bit version of MoreMasters MOVEQ #0,D0 ; assume success BSR a24HMakeMoreMasters ; call ROM routine BNE.S @1 ; br for success MOVEQ #MemFullErr,D0 ; change D0 from 0 to error code @1 MOVE.L (SP)+,A6 ; restore A6 Move.W D0,MemErr ; global error code <25Apr85> RTS ; that's all v32MoreMasters ; 32 bit version of MoreMasters MOVEQ #0,D0 ; assume success BSR a32HMakeMoreMasters ; call ROM routine BNE.S @1 ; br for success MOVEQ #MemFullErr,D0 ; change D0 from 0 to error code @1 MOVE.L (SP)+,A6 ; restore A6 Move.W D0,MemErr ; global error code <25Apr85> RTS ; that's all ;---------------------------------------------------------------------- ; ; FUNCTION StripAddress(p: Ptr): Ptr; ; ; Make an address in D0 suitable for use in the current environment. Ultimately, ; this should test some flag and mask suitable bits. ; ; D0 <-> Address to be stripped. ; __StripAddress ;Roll in FixStripAddress to not check the MMStartMode IF Supports24Bit THEN ; CSS BTST.B #Systemis24bit,SystemInfo ; is it 32 bit or 24 bit BEQ.S @1 ; no strip address for 32 bit mode AND.L Lo3Bytes,D0 @1 ENDIF RTS ;-------------------- Moved in from RAM-based glue ----------------------------------------- <04May85> ;------------------------------------------------------------------------------------------- ; PROCEDURE MoveHHi( h : Handle ); ; ; Moves h up to the top of its region (space between two locked/nonrelocatable objects or ; between a lockek/nonreloc and the heap end), but with neither purge nor heap growth, only ; compaction. The idea is to use a stack buffer to move slices of the rising block in steps, ; compacting along the way to free space at the top. Requires about 1K of stack space. ; If the block is already high, MoveHHi does nothing. ; ; Arguments: A0 = handle to be moved high ; Results: D0 = error code = 0 no error ; NilHandleErr ; LkdHandleErr ; StackErr ; Register conventions: ; ; A6 - theZone pointer ; A5 - stack locals, buffer ; A4 - handle of block we are moving ; A3 - BkLim(theZone) ; ; D6 - current BC of block moved so far (not including header) ; D7 - current BC of block left to move (not including header) ;------------------------------------------------------------------------------------------- ; ; Modification History: ; 11-Apr-84 LAK Mask dereferenced handle for end-of-heap compare (get rid of ; any lock/purge/rsrc bits set . . . ; 11-Jul-84 MDB, MPH Correctly save Master Pointer flag bits. ; 14-Nov-84 RS,SC nilHandleErr, already locked err, no compact if there is enough ; room in heap to make copy of block. ; 27-Nov-84 RS fix so that multiple heap compacts are not done if not needed. ; ie. if after a compact there is a large enough free block up high to ; move all the remaining ; 14-Mar-85 CC changed to proc that returns error in MemErr; check for new ROM ; 02 May 85 JTC Moved to ROM, with general scouring. Fixed subtle bug where a free block ; smaller than minFree would be 'allocated' after a slide. ; <01Nov85 JTC> Now take stack space bounded above by what is needed (if not smaller than minimum ; acceptable) and what is available based on HiHeapMark. ;-------------------------- Post V. 1.0 System Tools --------------------------------------- ; <13Jan86 JTC> Stuff TheZone across call, so that secondary calls such as _CompactMem will ; operate on same heap. The trick is to save incoming TheZone in the stack ; frame until exit, but to be careful about the various exit pts through MMEpilogue. ;------------------------------------------------------------------------------------------- ; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ SuperMario roll in tcn ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ ; MoveHHi - do not let it happen to a handle in the System Heap. ; ; MoveHHi is usually called because the caller is about to lock the handle down. This is ; the right thing to do in app heaps, but is bad for the System Heap. Immobile blocks in ; the System Heap limit the extendability of the Process Mgr heap. ; ; Assumptions: ; This assumes that the system heap is the lowest heap in memory. In particular, this check will ; disable MoveHHi in subzones residing in the system heap. This behavior has been around for a ; while in MultiFinder, but should go away when we rewrite this patch. ; ; To Do: Rewrite, using the relative handle to find the zone start, comparing that to ; SysZone. This will need a safe dereference, perhaps borrowed from the IIci ROM, ; which would include a bus-error handler. ; ;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ StkSlop EQU 3072 ; leave 3K for system StackErr EQU -1 ; not enuf stack space for us OldTagBC24 EQU 0 ; first long in original blk MyBufCnt24 EQU 4 ; current buffer count MyBufSize24 EQU 8 ; size of stack buffer InRgnPtr24 EQU 12 ; region reference point SvTagByte24 EQU 16 ; saved tag byte SavedZone24 EQU 18 ; saved theZone across the call <13Jan86 JTC> MyStkBuf24 EQU 22 ; start of stack buffer <13Jan86 JTC> LclVarSize24 EQU MyStkBuf24 OldTagBC32 EQU 0 ; first long in original blk SvBlkSize32 EQU 4 ; saved block size MyBufCnt32 EQU 8 ; current buffer count MyBufSize32 EQU 12 ; size of stack buffer InRgnPtr32 EQU 16 ; region reference point SavedZone32 EQU 20 ; saved theZone across the call MyStkBuf32 EQU 24 ; start of stack buffer LclVarSize32 EQU MyStkBuf32 ; MoveHHi Move.L #JMoveHHi,-(SP) ; get offset to vector onto stack Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack RTS ; go to routine v24MoveHHi ; 24 bit version of MoveHHi ;------------------------------------------------------------------------------- ; First check for the nasties: locked or purged. ;------------------------------------------------------------------------------- BNE.S @goBubble ; NotEqual => not purged <31mar86> ; kc MOVEQ #NilHandleErr,D0 ; nil handle error kc BRA MHHExit ; go to common exit kc @goBubble ; kc CMPA.L SysZone,a6 ; is this handle in the System heap? kc BNE.S @notInSysZone ; nope kc ; kc MOVEQ #noErr,D0 ; yup, don't do anything kc BRA MHHExit ; go to common exit kc @notInSysZone ; kc MOVE.L A1,A4 ; save handle to block for the duration kc TST.B (A4) ; make sure block is unlocked kc BPL.S @goAhead ; yup, all's cool kc ; kc MOVEQ #memLockedErr,D0 ; locked handle error kc BRA MHHExit ; kc @goAhead MOVE.L BkLim(A6),A3 ; last memory block, for the duration <04May85> ;------------------------------------------------------------------------------- ; See if we aren't already packed at top, in which case a compact is avoided. ; Set up D7 for the duration. ;------------------------------------------------------------------------------- SUBQ.L #BlkData24,A0 ; point to actual block MOVE.L TagBC24(A0),D1 ; block header AND.L Lo3Bytes,D1 ; isolate the block size MOVE.L D1,D7 ; save in D7 for the duration SUBQ.L #BlkData24,D7 ; adjust for data count only MOVEQ #noErr,D0 ; assume no move necessary, ok exit ADD.L D1,A0 ; point to next block CMP.L A3,A0 ; is it already at the limit? BCC MHHExit ; exit if so . . . TST.B TagBC24(A0) ; ck for Free, Rel, or NRel BEQ.S @1 ; br if Free BPL MHHExit ; exit if NRel (we're at region top) MOVE.L Handle24(A0),A0 ; handle offset ADD.L A6,A0 ; master ptr TST.B (A0) ; locked Rel? BMI MHHExit ; exit if so ;------------------------------------------------------------------------------- ; Set up stack buffer and local vars, with frame ptr in A5 (for the variety's sake). ; Use as much stack as is available (knowing there will be no ApplZone growth), ; but no less than 128 bytes, permitting 768 bytes for intermediate stack activity. ; New intelligence: <01Nov85 JTC> ; The basic buffer is bounded first by the new HiHeapMark (rather than the old ; BKLim(ApplZone)). Then it is bounded by the size of the block to be moved plus ; a modicum of stack slop. ; Once the frame is set up, save theZone and stuff A6 there, for subsequent MM calls<13Jan86 JTC> ;------------------------------------------------------------------------------- @1 MOVE.L SP,D1 ; figure out the size of our stack buffer AND.L Lo3Bytes,D1 ; why not be safe with our pointer arithmetic? <01Nov85 JTC> SUB.L HiHeapMark,D1 ; distance between stack and highest nonstack zone <01Nov85 JTC> AND.L #$FFFFFFF0,D1 ; quad-word align the stack buffer for 040 **** MOVE.L ApplZone,A0 ; (make sure we use appl zone for this) <01Nov85 JTC> **** SUB.L BkLim(A0),D1 ; distance between stack and appl heapzone <01Nov85 JTC> MOVE.L #StkSlop,D2 ; we demand at least this much raw space MOVE.L D2,D0 ; in case of much space, just take what is needed <01Nov85 JTC> ADD.L D7,D0 ; block size + slop <01Nov85 JTC> CMP.L D0,D1 ; available-(what's needed for this case) <01Nov85 JTC> BLT.S @3 ; Less Than (signed OK) ==> no excess stack <01Nov85 JTC> MOVE.L D0,D1 ; use more parsimonious stack block <01Nov85 JTC> @3 ; bypass using smaller stack request <01Nov85 JTC> MOVEQ #StackErr,D0 ; assume error CMP.L D2,D1 ; make sure there's at least 1K BLT MHHExit ; just exit if not SUB.L #128,D2 ; just use a little of the slop (was SUB.W) <01Nov85 JTC> SUB.L D2,D1 ; buffer size is what's left SUB.L D1,SP ; buffer SUB.W #LclVarSize24,SP ; and space for locals MOVE.L SP,A5 ; save pointer in A5 MOVE.L D1,MyBufSize24(A5) ; save buffer size MOVE.L theZone,SavedZone24(A5) ; preserve incoming theZone... <13Jan86 JTC> MOVE.L A6,theZone ; ...to be replace by handle's zone <13Jan86 JTC> MOVE.L (A4),A0 ; also keep TagBC of block we are moving SUBQ #BlkData24,A0 MOVE.L TagBC24(A0),OldTagBC24(A5) MOVE.L (A4),D0 ; deref handle AND.L Lo3Bytes,D0 ; get rid of lock, purge, etc. bits MOVE.L D0,InRgnPtr24(A5) ; save blk as region hint Move.B (A4),SvTagByte24(A5) ; Save tag byte. ;------------------------------------------------------------------------------- ; Don't do compact if there is a free block at the top of the region that ; is large enough to hold the contents of the block to be moved up. ;------------------------------------------------------------------------------- BSR a24FindRgnTop ;get A2 pointing to the last block before end of region TST.B (A2) ;is it free? BNE.S @goCont ;no, do the buffering stuff MOVE.L TagBC24(A2),D1 ;get the size of the block MOVE.L D1,D0 SUBQ.L #BlkData24,D0 ;last block data space CMP.L D0,D7 ;is it enough space? BHI.S @goCont ;no, do the buffering stuff SUB.L D7,D0 ;must be nonnegative! <02May85> BEQ.S @5 ;if just enough space, go do it! <02May85> MOVEQ #minFree24,D2 ;need at least this much to have a free block <02May85> CMP.L D2,D0 ; <02May85> BCS.S @goCont ;Carry Set => not minFree left, do it the hard way <02May85> @5 MOVE.L (A4),A0 ;ptr to the block we are moving from MOVE.L A2,A1 ;ptr to free block ADD.L D1,A1 ;ptr to end of free block ;------------------------------------------------------------------------------- ; One-shot move: ; D7 = amount of move ; A0 = ptr to migrating block data ; A1 = ptr to END of free block at top of region ;------------------------------------------------------------------------------- @moveRest MOVE.L D7,D0 ;number of bytes of data to move SUB.L D0,A1 ;grab what we need SUB.L D0,ZCBFree(A6) ; _BlockMove ;move the bits MOVE.L A4,A0 ;get the handle _EmptyHandle ;empty it out BRA.S @MNSFinish ;------------------------------------------------------------------------------------------- ; Entry to fill/compact/stuff loop... ;------------------------------------------------------------------------------------------- @goCont MOVEQ #0,D6 ; D6 holds number of bytes moved up . . . BSR a24FillStkBuf ; this does it and also adjusts handlesize BSR DoCompact ; then move everything down BSR a24FindRgnTop ;------------------------------------------------------------------------------- ; The top of the MoveNxtSeg loop: ; The stack buffer is full, the heap is compacted, A2 points to the free block ; (at least as large as the buffer) at the region's top. This sequence loads ; the buffer's contents up high in the region. ;------------------------------------------------------------------------------- @MoveNxtSeg MOVE.L TagBC24(A2),D1 ; size of free block we have at top now MOVE.L MyBufCnt24(A5),D0 ; stack buffer count LEA MyStkBuf24(A5),A0 ; source MOVE.L A2,A1 ; compute destination ADD.L D1,A1 ; point to end of free block SUB.L D0,A1 ; grab what we need ADD.L D0,D6 ; update count moved SUB.L D0,ZCBFree(A6) ; *** this is a fix *** _BlockMove ; move it in TST.L D7 ; are we done? BEQ.S @MNSFinish ; br if so <27oct85> BBM ;------------------------------------------------------------------------------- ; There's more to move than the bufferfull we just did. If there's just enough ; free space, or enough to move the block and have at least a minFree block, ; then exit via moveRest stub earlier. Otherwise, continue looping with the ; stack buffer... ;------------------------------------------------------------------------------- MOVE.L A1,D0 ; ptr to dest data SUB.L A2,D0 ; free bytes remaining BEQ.S @MNSExact ; br if none MOVE.L D0,D1 ; get the #free bytes remaining SUBQ.L #BlkData24,D1 ; #free for real data SUB.L D7,D1 ; enough for the remaining bytes? BCS.S @MNSAdj ; Carry Set => not enough, keep buffering <02May85> BEQ.S @MNSEscape ; EQual => just enough, so do it <02May85> MOVEQ #minFree24,D2 ; if unequal, must be this much to be worthwhile <02May85> CMP.L D1,D2 ; extra VERSUS minFree <02May85> BCC.S @MNSAdj ; not enough extra for a free block: the hard way <02Jun87> ; CC => D1 < minFree => fiddle the slack space <02Jun87> @MNSEscape MOVE.L (A4),A0 ; yes, move it. get source ptr BRA.S @moveRest @MNSAdj MOVE.L D0,TagBC24(A2) ; adjust size of remaining free blk @MNSExact MOVEM.L (A1),D4-D5 ; save 2 longs at front of blk MOVE.L A6,Handle24(A1) MOVE.L D6,TagBC24(A1) ; data size is blk size in this case . . . MOVE.B #$40,TagBC24(A1) ; make it an nrel blk MOVE.L A1,-(SP) BSR a24FillStkBuf ; this does it and also adjusts handlesize <27oct85> BBM BSR DoCompact ; then move everything down BSR a24FindRgnTop ; point A2 to free bk at top . . . <27oct85> BBM MOVE.L (SP)+,A1 MOVEM.L D4-D5,(A1) ; restore data at front of blk BRA @MoveNxtSeg ; then go again ;------------------------------------------------------------------------------- ; Clean-up code: set up any free block left over; set up header of relocated block; ; update master pointer; recover stack space and saved registers. ; Registers: A6 Zone ; A5 Local variables and buffer on stack ; A4 Handle of migrating block ; A2 Ptr to any free space ; A1 Ptr to moved block ;------------------------------------------------------------------------------- @MNSFinish SUBQ.L #8,A1 ; grab 8 more bytes for block header SUBQ.L #8,ZCBFree(A6) ; *** this is a fix *** MOVE.L A1,D0 ; figure free space left SUB.L A2,D0 BEQ.S @11 ; br if we used it all MOVE.L D0,TagBC24(A2) ; create a free block of remaining size @11 MOVE.L A1,A2 ; point A2 to our new block MOVE.L OldTagBC24(A5),(A2)+ ; TagBC MOVE.L A4,A0 SUB.L A6,A0 ; form handle offset MOVE.L A0,(A2)+ ; Handle MOVE.L A2,(A4) ; update master pointer with ptr to text of block MOVE.B SvTagByte24(A5),(A4) ; and restore flags . . . MOVE.L SavedZone24(A5),theZone ; and theZone <13Jan86 JTC> MOVEQ #noErr,D0 ; ok! ADD.L MyBufSize24(A5),SP ; recover buffer space ADD.W #LclVarSize24,SP ; and locals space BRA MHHExit ; ;-------- 32 bit version --- v32MoveHHi ; 32 bit version of MoveHHi ;------------------------------------------------------------------------------- ; First check for the nasties: locked or purged. ;------------------------------------------------------------------------------- BNE.S @goBubble ; NotEqual => not purged <31mar86> ; kc MOVEQ #NilHandleErr,D0 ; nil handle error kc BRA MHHExit ; jump to common exit kc @goBubble ; kc CMPA.L SysZone,a6 ; is this handle in the System heap? kc BNE.S @notInSysZone ; nope kc ; kc MOVEQ #noErr,D0 ; yup, don't do anything kc BRA MHHExit ; go to common exit kc @notInSysZone ; kc MOVE.L A1,A4 ; save handle to block for the duration kc TST.B MPtag32-BlkData32(A0) ; make sure block is unlocked kc BPL.S @goAhead ; yup, all's cool kc ; kc MOVEQ #memLockedErr,D0 ; locked handle error kc BRA MHHExit ; jump to common exit kc @goAhead MOVE.L BkLim(A6),A3 ; last memory block, for the duration <04May85> ;------------------------------------------------------------------------------- ; See if we aren't already packed at top, in which case a compact is avoided. ; Set up D7 for the duration. ;------------------------------------------------------------------------------- SUB.L #BlkData32,A0 ; point to actual block Move.L BlkSize32(A0),D1 ; get block size MOVE.L D1,D7 ; save in D7 for the duration SUB.L #BlkData32,D7 ; adjust for data count only MOVEQ #noErr,D0 ; assume no move necessary, ok exit ADD.L D1,A0 ; point to next block CMP.L A3,A0 ; is it already at the limit? BCC MHHExit ; exit if so . . . TST.B TagBC32(A0) ; ck for Free, Rel, or NRel BEQ.S @1 ; br if Free BPL MHHExit ; exit if NRel (we're at region top) Tst.B MPtag32(A0) ; locked Rel? BMI MHHExit ; exit if so ;------------------------------------------------------------------------------- ; Set up stack buffer and local vars, with frame ptr in A5 (for the variety's sake). ; Use as much stack as is available (knowing there will be no ApplZone growth), ; but no less than 128 bytes, permitting 768 bytes for intermediate stack activity. ; New intelligence: <01Nov85 JTC> ; The basic buffer is bounded first by the new HiHeapMark (rather than the old ; BKLim(ApplZone)). Then it is bounded by the size of the block to be moved plus ; a modicum of stack slop. ; Once the frame is set up, save theZone and stuff A6 there, for subsequent MM calls<13Jan86 JTC> ;------------------------------------------------------------------------------- @1 MOVE.L SP,D1 ; figure out the size of our stack buffer SUB.L HiHeapMark,D1 ; distance between stack and highest nonstack zone <01Nov85 JTC> AND.L #$FFFFFFF0,D1 ; quad-word align the stack buffer for 040 **** MOVE.L ApplZone,A0 ; (make sure we use appl zone for this) <01Nov85 JTC> **** SUB.L BkLim(A0),D1 ; distance between stack and appl heapzone <01Nov85 JTC> MOVE.L #StkSlop,D2 ; we demand at least this much raw space MOVE.L D2,D0 ; in case of much space, just take what is needed <01Nov85 JTC> ADD.L D7,D0 ; block size + slop <01Nov85 JTC> CMP.L D0,D1 ; available-(what's needed for this case) <01Nov85 JTC> BLT.S @3 ; Less Than (signed OK) ==> no excess stack <01Nov85 JTC> MOVE.L D0,D1 ; use more parsimonious stack block <01Nov85 JTC> @3 ; bypass using smaller stack request <01Nov85 JTC> MOVEQ #StackErr,D0 ; assume error CMP.L D2,D1 ; make sure there's at least 1K BLT MHHExit ; just exit if not SUB.L #128,D2 ; just use a little of the slop (was SUB.W) <01Nov85 JTC> SUB.L D2,D1 ; buffer size is what's left SUB.L D1,SP ; buffer SUB.W #LclVarSize32,SP ; and space for locals MOVE.L SP,A5 ; save pointer in A5 MOVE.L D1,MyBufSize32(A5) ; save buffer size MOVE.L theZone,SavedZone32(A5) ; preserve incoming theZone... <13Jan86 JTC> MOVE.L A6,theZone ; ...to be replace by handle's zone <13Jan86 JTC> MOVE.L (A4),A0 ; also keep TagBC of block we are moving SUB.L #BlkData32,A0 ; MOVE.L TagBC32(A0),OldTagBC32(A5); save 1st long word Move.L (A4),InRgnPtr32(A5) ; save blk as region hint Move.L Blksize32(A0),SvBlksize32(A5); save block size ;------------------------------------------------------------------------------- ; Don't do compact if there is a free block at the top of the region that ; is large enough to hold the contents of the block to be moved up. ;------------------------------------------------------------------------------- BSR a32FindRgnTop ;get A2 pointing to the last block before end of region TST.B (A2) ;is it free? BNE.S @goCont ;no, do the buffering stuff MOVE.L BlkSize32(A2),D1 ;get the size of the block MOVE.L D1,D0 ; SUB.L #BlkData32,D0 ;last block data space CMP.L D0,D7 ;is it enough space? BHI.S @goCont ;no, do the buffering stuff SUB.L D7,D0 ;must be nonnegative! <02May85> BEQ.S @5 ;if just enough space, go do it! <02May85> MOVEQ #minFree32,D2 ;need at least this much to have a free block <02May85> CMP.L D2,D0 ; <02May85> BCS.S @goCont ;Carry Set => not minFree left, do it the hard way <02May85> @5 MOVE.L (A4),A0 ;ptr to the block we are moving from MOVE.L A2,A1 ;ptr to free block ADD.L D1,A1 ;ptr to end of free block ;------------------------------------------------------------------------------- ; One-shot move: ; D7 = amount of move ; A0 = ptr to migrating block data ; A1 = ptr to END of free block at top of region ;------------------------------------------------------------------------------- @moveRest MOVE.L D7,D0 ;number of bytes of data to move SUB.L D0,A1 ;grab what we need SUB.L D0,ZCBFree(A6) ; _BlockMove ;move the bits MOVE.L A4,A0 ;get the handle _EmptyHandle ;empty it out BRA @MNSFinish ; CSS ;------------------------------------------------------------------------------------------- ; Entry to fill/compact/stuff loop... ;------------------------------------------------------------------------------------------- @goCont MOVEQ #0,D6 ; D6 holds number of bytes moved up . . . BSR a32FillStkBuf ; this does it and also adjusts handlesize BSR DoCompact ; then move everything down BSR a32FindRgnTop ;------------------------------------------------------------------------------- ; The top of the MoveNxtSeg loop: ; The stack buffer is full, the heap is compacted, A2 points to the free block ; (at least as large as the buffer) at the region's top. This sequence loads ; the buffer's contents up high in the region. ;------------------------------------------------------------------------------- @MoveNxtSeg MOVE.L BlkSize32(A2),D1 ; size of free block we have at top MOVE.L MyBufCnt32(A5),D0 ; stack buffer count LEA MyStkBuf32(A5),A0 ; source MOVE.L A2,A1 ; compute destination ADD.L D1,A1 ; point to end of free block SUB.L D0,A1 ; grab what we need ADD.L D0,D6 ; update count moved SUB.L D0,ZCBFree(A6) ; *** this is a fix *** _BlockMove ; move it in TST.L D7 ; are we done? BEQ.S @MNSFinish ; br if so <27oct85> BBM ;------------------------------------------------------------------------------- ; There's more to move than the bufferfull we just did. If there's just enough ; free space, or enough to move the block and have at least a minFree block, ; then exit via moveRest stub earlier. Otherwise, continue looping with the ; stack buffer... ;------------------------------------------------------------------------------- MOVE.L A1,D0 ; ptr to dest data SUB.L A2,D0 ; free bytes remaining BEQ.S @MNSExact ; br if none MOVE.L D0,D1 ; get the #free bytes remaining SUB.L #BlkData32,D1 ;#free for real data SUB.L D7,D1 ; enough for the remaining bytes? BCS.S @MNSAdj ; Carry Set => not enough, keep buffering <02May85> BEQ.S @MNSEscape ; EQual => just enough, so do it <02May85> MOVEQ #minFree32,D2 ; if unequal, must be this much to be worthwhile <02May85> CMP.L D1,D2 ; extra VERSUS minFree <02May85> BCC.S @MNSAdj ; not enough extra for a free block: the hard way <02Jun87> ; CC => D1 < minFree => fiddle the slack space <02Jun87> @MNSEscape MOVE.L (A4),A0 ; yes, move it. get source ptr BRA.S @moveRest @MNSAdj Clr.L TagBC32(A2) ; make it a free block MOVE.L D0,BlkSize32(A2) ; adjust size of remaining free blk @MNSExact MOVEM.L (A1),D3-D5 ; save 3 longs at front of blk MOVE.L A6,Handle32(A1) ; MOVE.L D6,BlkSize32(A1) ; data size is blk size in this case MOVE.B #$40,TagBC32(A1) ; make it an nrel blk MOVE.L A1,-(SP) BSR a32FillStkBuf ; this does it and also adjusts handlesize <27oct85> BBM BSR DoCompact ; then move everything down BSR a32FindRgnTop ; point A2 to free bk at top . . . <27oct85> BBM MOVE.L (SP)+,A1 MOVEM.L D3-D5,(A1) ; restore data at front of blk BRA @MoveNxtSeg ; then go again ;------------------------------------------------------------------------------- ; Clean-up code: set up any free block left over; set up header of relocated block; ; update master pointer; recover stack space and saved registers. ; Registers: A6 Zone ; A5 Local variables and buffer on stack ; A4 Handle of migrating block ; A2 Ptr to any free space ; A1 Ptr to moved block ;------------------------------------------------------------------------------- @MNSFinish SUB.L #blkData32,A1 ; grab 12 more bytes for block header SUB.L #blkData32,ZCBFree(A6) ; *** this is a fix *** MOVE.L A1,D0 ; figure free space left SUB.L A2,D0 BEQ.S @11 ; br if we used it all Clr.L TagBC32(A2) ; create a free block MOVE.L D0,BlkSize32(A2) ; set remaining size @11 MOVE.L A1,A2 ; point A2 to our new block MOVE.L OldTagBC32(A5),(A2)+ ; TagBC Move.L SvBlkSize32(A5),(A2)+ ; block size MOVE.L A4,A0 SUB.L A6,A0 ; form handle offset MOVE.L A0,(A2)+ ; Handle MOVE.L A2,(A4) ; update master pointer with ptr to text of block MOVE.L SavedZone32(A5),theZone ; and theZone <13Jan86 JTC> MOVEQ #noErr,D0 ; ok! ADD.L MyBufSize32(A5),SP ; recover buffer space ADD.W #LclVarSize32,SP ; and locals space MHHExit Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue RTS ; jump to it ;------------------------------------------------------------------------------------------- ; Utility FUNCTION FindRgnTop( zone : Ptr; localVars : Ptr; hand : Handle; EOZ : Ptr ) : Ptr; ; ; Return a pointer to the last block beyond the handle in question, but before the next locked ; or nonrelocatable or trailing block. ; ; Arguments: A6 = heap zone ; A5 = ptr to local vars and buffer on stack ; A4 = handle in migration ; A3 = last block in zone ; ; Results: A2 = ptr to 'last' block ; ; Registers: D0-D1/A0-A1 ; ; Called at labels: moveRest (just before), goCont, moveNxtSeg ;------------------------------------------------------------------------------------------- a24FindRgnTop MOVE.L (A4),D0 ; deref handle BEQ.S @10 ; br if nil (disposed) AND.L Lo3Bytes,D0 ; get rid of lock, purge, etc. bits MOVE.L D0,A0 SUBQ #BlkData24,A0 ; start scan from here for speed BRA.S @FRTLoop @10 LEA HeapData(A6),A0 ; scan from start of zone @FRTLoop MOVE.L TagBC24(A0),D1 ; block header AND.L Lo3Bytes,D1 ; isolate the block size TST.B TagBC24(A0) ; ck for Free, Rel, or NRel BEQ.S @1 ; br if Free BPL.S @2 ; br if NReloc (end of region) MOVE.L Handle24(A0),A1 ; handle offset ADD.L A6,A1 ; master ptr TST.B (A1) ; locked Rel? BMI.S @2 ; br if Locked (end of region) @1 MOVE.L A0,A2 ; remember this as the last block ADD.L D1,A0 ; point to next block CMP.L A3,A0 ; reached the end of zone? BCS.S @FRTLoop ; loop if not (fruitloops) BRA.S @3 ; otherwise exit (must be in last rgn) @2 CMP.L InRgnPtr24(A5),A0 ; are we in the correct region? BLS.S @1 ; keep looking, if not @3 RTS ; ; ------- 32 bit version ; a32FindRgnTop MOVE.L (A4),D0 ; deref handle BEQ.S @10 ; br if nil (disposed) MOVE.L D0,A0 ; SUB.L #BlkData32,A0 ; start scan from here for speed BRA.S @FRTLoop @10 LEA HeapData(A6),A0 ; scan from start of zone @FRTLoop MOVE.L BlkSize32(A0),D1 ; block size TST.B TagBC32(A0) ; ck for Free, Rel, or NRel BEQ.S @1 ; br if Free BPL.S @2 ; br if NReloc (end of region) Tst.B MPtag32(A0) ; locked Rel? BMI.S @2 ; br if Locked (end of region) @1 MOVE.L A0,A2 ; remember this as the last block ADD.L D1,A0 ; point to next block CMP.L A3,A0 ; reached the end of zone? BCS.S @FRTLoop ; loop if not (fruitloops) BRA.S @3 ; otherwise exit (must be in last rgn) @2 CMP.L InRgnPtr32(A5),A0 ; are we in the correct region? BLS.S @1 ; keep looking, if not @3 RTS ;------------------------------------------------------------------------------------------- ; Utility PROCEDURE FilStkBuf( VAR curDataSize : LongInt; zone : Ptr; localVars : Ptr; hand : Handle; ); ; ; Fill stack buffer with MIN(MyBufSize,HandleSize) bytes from block in migration. If moving entire ; handle, just empty that handle on completion. Otherwise, adjust the size of the depleted handle and ; create a new free block. ; ; Arguments: D7 curDataSize = amount left to move ; A6 zone = heap zone ; A5 localVars = ptr to stack vars and buffer ; A4 hand = handle to block being moved ; ; Results: D7 updated curDataSize ; ; Called after labels: goCont, moveNxtSeg ; ; Registers: D0-D2/A0-A1 ;------------------------------------------------------------------------------------------- a24FillStkBuf MOVE.L MyBufSize24(A5),D0 ; figure MIN(MyBufSize,HandleSize) CMP.L D7,D0 ; D7 is current data size of blk we're moving BLT.S @1 MOVE.L D7,D0 ; use current size if <= buffer size @1 LEA MyStkBuf24(A5),A1 ; destination MOVE.L (A4),A0 ; BlkData pointer ADD.L D7,A0 ; end of block pointer SUB.L D0,A0 ; source (move last D0 bytes of blk) SUB.L D0,D7 ; adjust current size MOVE.L D0,MyBufCnt24(A5) ; set up buffer count MOVE.L D0,D1 ; and save in D1 (size of new free blk) _BlockMove MOVE.L A4,A0 ; HBlk MOVE.L D7,D0 ; remaining bytes in block BNE.S @2 ; br if space left _EmptyHandle ; get rid of entire blk when 0 (updates freemem) RTS ; We still haven't emptied the block, so create a smaller block with data size ; D0=D7 and a free block of size D1 (the amount we moved). Note that by virtue ; of this style of block truncation, the physical/logical size fudge factor is ; guaranteed to be zero. @2 MOVE.L (A0),A0 ; ptr to data portion of what's left SUBQ #BlkData24,A0 ; ptr to block that's left MOVE.B TagBC24(A0),D2 ; save Tag ADDQ.L #BlkData24,D0 ; new physical block size MOVE.L D0,TagBC24(A0) ; set BC MOVE.B D2,TagBC24(A0) ; and restore tag ADD.L D0,A0 ; point to new free block MOVE.L D1,TagBC24(A0) ; set Tag=free, BC ADD.L D1, ZCBFree(A6) ; update free count. RTS ; 32 bit version a32FillStkBuf MOVE.L MyBufSize32(A5),D0 ; figure MIN(MyBufSize,HandleSize) CMP.L D7,D0 ; D7 is current data size of blk we're moving BLT.S @1 MOVE.L D7,D0 ; use current size if <= buffer size @1 LEA MyStkBuf32(A5),A1 ; destination MOVE.L (A4),A0 ; BlkData pointer ADD.L D7,A0 ; end of block pointer SUB.L D0,A0 ; source (move last D0 bytes of blk) SUB.L D0,D7 ; adjust current size MOVE.L D0,MyBufCnt32(A5) ; set up buffer count MOVE.L D0,D1 ; and save in D1 (size of new free blk) _BlockMove MOVE.L A4,A0 ; HBlk MOVE.L D7,D0 ; remaining bytes in block BNE.S @2 ; br if space left _EmptyHandle ; get rid of entire blk when 0 (updates freemem) RTS ; We still haven't emptied the block, so create a smaller block with data size ; D0=D7 and a free block of size D1 (the amount we moved). Note that by virtue ; of this style of block truncation, the physical/logical size fudge factor is ; guaranteed to be zero. @2 MOVE.L (A0),A0 ; ptr to data portion of what's left SUB.L #BlkData32,A0 ; ptr to block that's left ADD.L #BlkData32,D0 ; new physical block size MOVE.L D0,BlkSize32(A0) ; set size ADD.L D0,A0 ; point to new free block Clr.L tagBC32(A0) ; set as free block MOVE.L D1,BlkSize32(A0) ; set free block size ADD.L D1, ZCBFree(A6) ; update free count. RTS ;------------------------------------------------------------------------------------------- ; Utility PROCEDURE DoCompact; ; ; Arguments: none ; Results: thoroughly compacted heap ; Registers: D0 ; Called at labels: goCont, moveNxtSeg ;------------------------------------------------------------------------------------------- DoCompact MOVE.L RealMemTop,D0 ; compact to push all the _CompactMem ; free space to the top . . . RTS END ; *********** comment this out for RAMTest