mac-rom/OS/MemoryMgr/MemoryMgr.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

3854 lines
154 KiB
Plaintext

;__________________________________________________________________________________________________
;
; 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):
;
; <SM32> 10/12/93 SAM Roll in <MC2> from mc900ftjesus.
; <MC2> 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.
; <SM31> 5/20/93 BT Update sources to conditionally compile Figment under the build
; flag "hasNewHeapMgr".
; <SM30> 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.
; <SM29> 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.
; <SM28> 4/22/93 rab Removed code from FlushFontCaches that skipped the routine if
; CurApName wasn't valid. This fixes Radar# 1077877 and 1078314.
; <SM27> 4/12/93 chp Rewrote MoveHHi head patch using half the number of
; instructions.
; <SM26> 3/9/93 rab Bumped StkSlop in MoveHHi from 1024 to 3072 per Jim Reekes
; suggestion in bug #1067917.
; <SM25> 2/22/93 PN Quad-word align the stackbuffer in MoveHHi call for 040
; machines.
; <SM24> 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.
; <SM23> 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.
; <SM22> 12/4/92 RB Rolled in changes to support NuKernel from Wayne Meretski and
; Russell Williams. Make RHBusErrHandler compatible with NuKernel.
; <SM21> 12/4/92 SWC Moved InitMemMgr here from StartInit.a.
; <SM20> 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)
; <SM19> 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.
; <SM18> 11/3/92 RB Do not force 32 bit mode for the LC930 by checking the feature
; conditional Supports24Bit.
; <SM17> 10/26/92 CSS Fix some short branches and remove cache flushing from
; HLock. Also, added Supports24Bit conditional to conditionalize
; _StripAddress.
; <SM16> 9/16/92 CSS Fix bsr to IOPram to use bsr.l.
; <SM15> 7/28/92 PN Put CacheFlush back in HLock for compatibilty's sake
; <SM14> 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.
; <SM13> 7/16/92 PN Take out cpu ³ 020 conditionals
; <SM12> 6/11/92 PN Roll in FixStripAddress from PatchIIciROM.a
; <SM11> 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.
; <SM10> 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.
; <SM9> 4/22/92 TN Clean up BracketSetAppBaseWithInitApplZones, roll in
; AllowNILDisposePtr, ResrvMemGrowSystemHeap,
; NewPtrGrowSystemHeapCleanly MoveHHiPatch from MemoryMgrPatches.a
; <SM8> 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.
; <SM7> 3/26/92 kc Force 32-bit mode. (see <SM3> 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. ¥¥¥¥;
; <SM6> 3/24/92 PN Roll in BracketSetAppBaseWithInitApplZones into _SetappBase By
; calling bsr IAZ three times.
; <SM5> 3/10/92 PN Back out the last change
; <SM4> 3/9/92 kc Don't call jSoundDead untill we install the SoundMgr.
; <SM3> 3/4/92 kc Add a semicolon.
; <SM2> 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.
; <T8> 7/10/91 RP Patched MaxApplZone for line alignment.
; <T7> 7/7/91 RP Patched MaxMem, CompactMem and MaxBlock to line-align free space
; values on 040s.
; <T6> 6/25/91 RP Patched to line align all blocks on 040 CPUs
; <T5> 5/29/91 CCH Backed out revision 4.
; <T4> 5/29/91 WM Changed MOVE to SR into ANDI to SR
; <T3> 4/21/91 CCH Removed HSetState patch since it was not used and is not needed.
; <T2> 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.
;
; <C914> 10/29/87 rwh Port to Modern Victorian (on MvMac)
; <C897> 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
; <PB092> 6/2/87 JTC Roll in patch to MoveHHi to handle teeny leftovers.
;
; <C817> 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.
; <C778> 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.
; <C765> 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.
; <C741> 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.
; <C731> 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.
; <C681> 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.
; <C636> 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.
; <C587> 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.
; <C415> 12/9/86 JTC Reinstate C251 alignment. Change to HeapGuts.a only.
; <A415> 11/17/86 JTC Back out some of the wonderful <C251> 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 <C251> 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.
; <A305> 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.
; <C251> 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.
; <C206> 10/9/86 bbm Modified to mpw aincludes/ changed resourc to resource.
; <C169> 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 ; <sm10>
EXPORT SetApplBase ; <SM20>
If hasNewHeapMgr Then
EXPORT Old_AfterBootSetApplBase ;<SM20>, <SM30 BT>
else
EXPORT AfterBootSetApplBase ;<SM20>
endif
EXPORT IAZ ; <SM19>
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 <SM30 BT>
EXPORT Old_InitMemMgr ; initialize Memory Manager low mem, vectors <SM21>,<SM30 BT>
else
EXPORT InitMemVect ; initialization for Memory Vectors <SM30 BT>
EXPORT InitMemMgr ; initialize Memory Manager low mem, vectors <SM21>,<SM30 BT>
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 <v1.4>
LEA MMTrapTable,A0 ; A3 gets beginning of table
LEA JMemMgr24,A1 ; set A1 to start of 24 bit table <v1.1>
LEA JMemMgr32,A2 ; set A2 to start of 32 bit table <v1.1>
MOVE.L #(((TableEnd-MMTrapTable)>>3)-1),D1 ; get number of entry pairs <v1.9>
@NextEntry
MOVE.L (A0)+,(A1) ; copy offset to entries in 24 bit table <v1.9>
ADD.L D0,(A1)+ ; Add ROM Base to offset <v1.9>
MOVE.L (A0)+,(A2) ; copy offset to entries in 32 bit table <v1.9>
ADD.L D0,(A2)+ ; Add ROM Base to offset <v1.9>
DBRA D1,@NextEntry ; loop until end <v1.9>
ADD.L #$00010000,D0 ; makeup a safe address <v1.9>
MOVE.L D0,$0 ; write address for nil handle <v1.9>
MOVE.L D0,$4 ; write address for nil window pointer <v1.9>
LEA MMNoPrologue,A0 ; get address <v1.9>
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 ; <v1.9>
MOVEM.L (SP)+,D0-D3/A0-A3 ; restore registers <v1.1>
RTS ; <v1.1>
;----------------------------------------------------------------------
; 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 <SM8> <PN>
; 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 <SM8> <PN>
BMI @SkipIt ;still in booting, skip the patch <SM8> <PN>
MOVEM.L A0-A2/D0-D3,-(sp) ; save registers <SM8> <PN>
CLR.L -(SP) ; room for result <SM8> <PN>
MOVE.L applZone,A0 ; point to zone hdr <SM8> <PN>
MOVE.L A0,-(SP) ; push start ptr <SM8> <PN>
MOVE.L (A0),-(SP) ; push zone trailer <SM8> <PN>
_sbKillSomeCaches ; <SM8> <PN>
ADDQ #4,SP ; ignore result <SM8> <PN>
MOVEM.L (sp)+,A0-A2/D0-D3 ; restore registers <SM8> <PN>
@SkipIt
Move.L #JSetApplBase,-(SP) ; get offset onto stack <v1.9>
Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue<v1.9>
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 <C251><sm9>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 ; <C251>
Sub.W #MinFree24,A0 ; Point to new end block. <v1.2>
Cmp.L BkLim(A6),A0 ; New sysZone end <= current?
BLS.S @SABInitAppl ; Yes, just init applZone.
BSR a24ZoneAdjustEnd ; Adjust the sysZone end. <v1.1>
@SABInitAppl
BSR IAZ ; use historical IAZ call <C681>
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 <C251><sm9>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 ; <C251>
Sub.W #MinFree32,A0 ; Point to new end block. <v1.2>
Cmp.L BkLim(A6),A0 ; New sysZone end <= current?
BLS.S @SABInitAppl ; Yes, just init applZone.
BSR a32ZoneAdjustEnd ; Adjust the sysZone end. <v1.1>
@SABInitAppl
BSR.S IAZ ; use historical IAZ call <C681>
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) <SM20> PN
;
If hasNewHeapMgr Then
; <SM30 BT>: 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 ;<SM20> PN
else
AfterBootSetApplBase
endif
_InitApplZone ;<SM20> PN
jsr SetApplBase ;<SM20> PN
_InitApplZone ;<SM20> PN
rts ;<SM20> 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, <C765><C778>
; but uses the more conservative result (D1) from ToMaxLimit rather than <C765><C778>
; the BufPtr-based result (D2) which was historical. <C778>
;
; 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. <C681>
;
; 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 <v1.9>
Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue<v1.9>
RTS
vInitApplZone
MoveA.L jIAZInit,A0 ; get pre-processing routine vector <C681>
JSR (A0) ; do it <C681>
BSR.S IAZ ; get the real zone <C681>
MoveA.L jIAZPostInit,A0 ; get post-processing routine vector <C681>
JSR (A0) ; do it <C681>
MoveQ #0,D0 ; re-stuff the no-error code <16Apr85>
Move.W D0,MemErr ; Record it globally, too <25Apr85>
RTS
;----------------------------------------------------------------------
; IAZ <C681>
; - 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 <C817>
; at boot time. Remove use of antiquated ToMaxLimit. <C817>
Move.l SP,D1 ;current stack <C817>
Sub.L DefltStack,D1 ;enough space for even QD <C817>
Move.L D1,ApplLimit ;Use stack limit, NOT BufPtrÕs <C778>
Move.L D1,HiHeapMark ;Start HiHeapMark in sync with <C778>
;ApplLimit in case of glue MaxApplZone<C778>
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 <v1.2>
BNE.S @1 ;branch if yes <v1.2>
; 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. <v1.2>
BRA.S @5 ; <v1.2>
@1
LEA MinFree32(A0),A0 ;Points to first of cur. applZone. <v1.2>
@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 ; <C681>
;------------------------------------------------------------------- <C681>
; End of historical IAZ.
;------------------------------------------------------------------- <C681>
;----------------------------------------------------------------------
; vIAZInit new <C681>
; - 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 ; <C897><C914><1.7>
MOVE.L jSoundDead,A0 ;get vector to kill all current sounds in ... <C681>
JSR (A0) ;...the application heap <C681>
ENDIF
BSR.L FlushApplVbls ;kill off doomed vbl tasks <27Mar85>, <SM30 BT>
BigJSR FlushApplNM,A0 ; And bogus NM requests <V1.1><1.2>
BSR.S FlushFontCaches ; flush TrueType caches <sm10>stb
BSR.S FlushApplPorts ;kill off doomed grafPorts <C699>
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 <SM8> <PN><sm10>stb
; Registers: saves all registers, trashes condition codes
;----------------------------------------------------------------------
MOVEM.L A0-A2/D0-D3,-(sp) ; save registers <SM8> <PN>
CLR.L -(SP) ; room for result <SM8> <PN>
MOVE.L applZone,A0 ; point to zone hdr <SM8> <PN>
MOVE.L A0,-(SP) ; push start ptr <SM8> <PN>
MOVE.L (A0),-(SP) ; push zone trailer <SM8> <PN>
_sbKillSomeCaches ; <SM8> <PN>
ADDQ #4,SP ; ignore result <SM8> <PN>
MOVEM.L (sp)+,A0-A2/D0-D3 ; restore registers <SM8> <PN>
@SkipIt
RTS
FlushApplPorts
;----------------------------------------------------------------------
; FlushApplPorts new <C681>
; -- 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 <C699>
CMP.L MinusOne,A1 ;are they equal? <C699>
BEQ.S @DONE ;=>if so,invalid portlist, just return <C699>
MOVE.L (A1),A1 ;point to it <C699>
MOVE.L A1,A0 ;save pointer in A0 <C699>
MOVE (A1)+,D1 ;get count of elements? <C699>
BRA.S @NEXT ;=> and dive into loop <C699>
@SEARCH MOVE.L (A1)+,D0 ;get next element from list <C699>
BSR.L AppZoneAddr ;in application area (or zero)? <C699>,<SM30 BT>
BEQ.S @DELETE ;=>yes, delete it <C699>
@NEXT DBRA D1,@SEARCH ;=>else try next in list <C699>
BRA.S @DONE ;=>none left, continue <C699>
@DELETE SUB #1,(A0) ;decrement port count <C699>
MOVE.L -(A1),-(SP) ;stk: port < etc. <C699>
CLR.L -(SP) ;stk: result < port < etc. <C699>
MOVE.L portList,-(SP) ;stk: plist < res < port < etc. <C699>
MOVEQ #2,D0 ;search after length <C699>
MOVE.L D0,-(SP) ;stk: #2 < plist < res < port < etc. <C699>
PEA 12(SP) ;PTR1 = GrafPtr <C699>
MOVEQ #4,D0 ;LEN1 = 4 bytes <C699>
MOVE.L D0,-(SP) ;stk: #4 < ptr1 < #2 < plist < res < port < <C699>
PEA @DONE ;PTR2 = XXX <C699>
CLR.L -(SP) ;LEN2 = 0 <C699>
_Munger ;rhymes with plunger <C699>
ADDQ #8,SP ;strip result, grafPort <C699>
BRA.S @REPEAT ;=>repeat until no more <C699>
@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)? <SM30 BT>
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 <C681>
; - 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 <C681>
_RDrvrInstall ; fix up ram based drivers <C681>
; clear the pack6 resource cache when launching (for Int'l Utilities / Script Mgr)
; moved here from InitApplZone because it seems to make more sense. <sm10>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 <v1.9>
Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue<v1.9>
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>
;---------------------------------------------------------------------- <T6> <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? <T7>
Bpl.s @0 ; Yea? Then don't patch.<T7>
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 <v1.2>
Sub.L D1,A3 ;LimitPtr-MinFree
Move.L D1,TagBC24(A3) ;make limit block <v1.1>
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 <v1.1>
Move.L #JMemMgr24,ZoneJumpV(A6); set jump vector in the zone <v1.1>
BSR a24MakeBKF ;start with 1 large free block <v1.1>
;A0=blk ptr, D0=size
BSR a24HMakeMoreMasters ;HFstFree(A6)=0 <v1.1>
; 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? <T7>
Bpl.s @0 ; Yea? Then don't patch.<T7>
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 <sm10>stb
; get purged. This purgeProc will check to see whether a block which is being <sm10>stb
; purged is a font cache, and save it to disk if it is. <sm10>stb
lea DiskCachePurgeProcedure,A0 ; TrueType purge procedure <sm10>stb
move.l A0,purgeProc(A6) ; install purge procedure <sm10>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 <v1.2>
Sub.L D1,A3 ; LimitPtr-MinFree
Clr.L TagBC32(A3) ; set limit block as free block <v1.1>
Move.L D1,blkSize32(A3) ;make limit block <v1.1>
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 <v1.1>
Move.L #JMemMgr32,ZoneJumpV(A6); set jump vector in the zone <v1.1>
BSR a32MakeBKF ; start with 1 large free block <v1.1>
; A0=blk ptr, D0=size
BSR a32HMakeMoreMasters ; HFstFree(A6)=0 <v1.1>
; 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 <A415>
; but the code is left in to ensure that at least the beginning of the heap is cool. <A415>
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 <sm10>stb
; get purged. This purgeProc will check to see whether a block which is being <sm10>stb
; purged is a font cache, and save it to disk if it is. <sm10>stb
lea DiskCachePurgeProcedure,A0 ; TrueType purge procedure <sm10>stb
move.l A0,purgeProc(A6) ; install purge procedure <sm10>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 <v1.9>
Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue<v1.9>
RTS
vGetZone ; <v1.1>
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 <v1.9>
Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue<v1.9>
RTS
vSetZone ; <v1.1>
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 <v1.9>
MOVE.L RealMemTop,D0 ;make an outlandish request <v1.9>
MOVE.L #JMaxBlock,-(SP) ; get offset to routine <v1.9>
MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue <v1.9>
RTS ; go to routine <v1.9>
@Slime ; <v1.5>
SUBQ.L #4,D0 ;reduce size by 4 byte to account for <v1.5>
;block starts and ends in non long word <v1.5>
;address, if 4 is too big, the extra 2 <v1.5>
;byte can act as margin. <v1.5>
BGE.S @Return ;if less than zero, then return 0 <v1.5>
MoveQ.L #0,D0 ;return 0 for length <v1.5>
@Return ; <v1.5>
RTS ; <v1.5>
CompactMemTrap
MOVE.L #JCompactMem,-(SP) ; get offset to routine <v1.9>
MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue <v1.9>
RTS ; go to routine <v1.9>
v24MaxBlock
MOVEQ #1,D1 ; mark routine as MaxBlock <v1.9>
BRA.S v24CMGuts ; branch to common code <v1.9>
v24CompactMem ;
MOVEQ #0,D1 ; mark as CompactMem <v1.9>
v24CMGuts
BSR a24ActualS ;adjust size <v1.1>
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 <v1.1>
SubQ.L #BlkData24,D0 ;convert back to logical cb <v1.1>
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 <v1.9>
BRA.S v32CMGuts ; branch to common code <v1.9>
v32CompactMem ;
MOVEQ #0,D1 ; mark as CompactMem <v1.9>
v32CMGuts ;entry point from MaxBlock <10Apr85>
BSR a32ActualS ;adjust size <v1.1>
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 <v1.1>
Sub.L #BlkData32,D0 ;convert back to logical cb <v1.1>
Move.L A0,D1 ;was a large enough blk found? <v1.1>
BEq.S PMExit32 ;Eq => NIL, return that <v1.1>
BrA.S PMOK32
;----------------------------------------------------------------------
;
; FUNCTION PurgeMem(cb: LongInt): pblk: Ptr;
;
PurgeMem
MOVE.L #JPurgeMem,-(SP) ; get offset to routine <v1.9>
MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue <v1.9>
RTS ; go to routine <v1.9>
v24PurgeMem ; 24 bit version of Purgemem <v1.1>
BSR a24ActualS ; adjust size <v1.1>
BSR a24PurgeHeap ; Purge the Heap <v1.1>
PMRMExit24 Move.L A0,D0 ; was a large enough blk found?
BNE.S PMNNil24 ; Yes, return success <v1.1>
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 <v1.9>
v32PurgeMem ; 32 bit version of Purgemem <v1.1>
BSR a32ActualS ; adjust size <v1.1>
BSR a32PurgeHeap ; Purge the Heap <v1.1>
PMRMExit32 Move.L A0,D0 ; was a large enough blk found?
BNE.S PMNNil32 ; Yes, return success <v1.1>
MoveQ #memFullErr,D0 ; No, not enough room in mem.
BrA.S PMExit32 ; <v1.1>
PMNNil32
MoveQ #0,D0 ; and show success return
PMOk32
Add.L #BlkData32,A0 ; else, point to data field. <v1.1>
PMExit32
Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue <v1.9>
RTS ; jump to it <v1.9>
;----------------------------------------------------------------------
;
; 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 <v1.9>
MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue <v1.9>
RTS ; go to routine <v1.9>
v24PurgeSpace ; 24 bit version of PurgeSpace <v1.1>
BSR a24TotePurgeables ; returns D0,A0 trashes others... <17Apr85>
BRA.S PurgeSExit ; go to common exit routine <v1.9>
v32PurgeSpace ; 32 bit version of PurgeSpace <v1.1>
BSR a32TotePurgeables ; returns D0,A0 trashes others... <17Apr85>
PurgeSExit Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue <v1.9>
RTS ; jump to it <v1.9>
;----------------------------------------------------------------------
;
; FUNCTION FreeMem: Longint;
; On exit:
; D0 - Returns the number of free bytes in the zone.
FreeMem
MOVE.L #JFreeMem,-(SP) ; get offset to routine <v1.9>
MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue <v1.9>
RTS ; go to routine <v1.9>
vFreeMem ; <v1.1>
Move.L ZCBFree(A6),D0 ; set result
Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue <v1.9>
RTS ; jump to it <v1.9>
;----------------------------------------------------------------------
;
; 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 <SM9> 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) ; <PN> 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 <v1.9>
MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue <v1.9>
RTS ; go to routine <v1.9>
v24ResrvMem ; 24 bit version of PurgeSpace <v1.1>
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 <v1.1>
Add.L D2,D0 ;Increase req count by ptr blk
@1 BSR a24MakePtrSpc ;Make room at the low end. <v1.1>
Move.L A2,A0 ;Ptr to block
BrA.S PMRMExit24 ;Do the purge mem exit trip . . . <v1.1>
v32ResrvMem ; 32 bit version of PurgeSpace <v1.1>
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 <v1.1>
Add.L D2,D0 ;Increase req count by ptr blk
@1 BSR a32MakePtrSpc ;Make room at the low end. <v1.1>
Move.L A2,A0 ;Ptr to block
BrA.S PMRMExit32 ;Do the purge mem exit trip . . . <v1.1>
;----------------------------------------------------------------------
;
; 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 <v1.9>
MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue <v1.9>
RTS ; go to routine <v1.9>
v24MaxMem ; 24 bit version of MaxMem <v1.1>
Move.L RealMemTop,D0 ;BkCompactS(MaxSize <v1.9>
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 <v1.1>
; 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 <v1.1>
Sub.L HeapEnd,D1
Move.L D1,A0 ;return in A0
MMExit24
BRA.S MMExit32 ; jump to common exit <v1.9>
v32MaxMem ; 32 bit version of MaxMem <v1.1>
Move.L RealMemTop,D0 ;BkCompactS(MaxSize <v1.9>
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 <v1.1>
@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 <v1.1>
; 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 <v1.1>
Sub.L HeapEnd,D1
Move.L D1,A0 ;return in A0
MMExit32
Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue <v1.9>
RTS ; jump to it <v1.9>
;----------------------------------------------------------------------
;
; 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 <v1.9>
Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue<v1.9>
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 <C636 JTC>
; stacks are required on color machines are old-style apps are starving them. <C636 JTC>
; On entry, Registers:
; A0 - zone limit (in bytes)
;
SetApplLimit
Move.L #JSetApplLimit,-(SP) ; get offset onto stack <v1.9>
Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue<v1.9>
RTS
v24SetApplLimit ; 24 bit version of setApplLimit <v1.1>
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 <C636>
And.L Lo3Bytes,D1 ; 24-bit SP <C636>
Sub.L DefltStack,D1 ; masked(SP-DefltStack) <C636>
Cmp.L D0,D1 ; (SP-DefltStack) - <suggested> <C636>
BGT.S @1 ; D0 < D1 --> suggested value OK <C636>
MoveA.L D1,A0 ; D1 ² D0 --> use SP-DefltStack <C636>
@1 ; bypass using DefltStack pinning <C636>
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><C765><C778>
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 <v1.1>
Move.L A0,D0 ; suggested new value <v1.1>
Move.L SP,D1 ; try SP-DefltStack <v1.1>
Sub.L DefltStack,D1 ; masked(SP-DefltStack) <C636>
Cmp.L D0,D1 ; (SP-DefltStack) - <suggested> <C636>
BGT.S @1 ; D0 < D1 --> suggested value OK <C636>
MoveA.L D1,A0 ; D1 ² D0 --> use SP-DefltStack <C636>
@1 ; bypass using DefltStack pinning <C636>
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><C765><C778>
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. <C587>
; 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>), <v1.1>
; and HiHeapMark is bkLim of the highest zone to date, the correct arithmetic is <C587>
; StackSpace := ( SP - BKLim(xxx) ) - 16 + 36 = SP - bkLim(xxx) + 20 <v1.1>
; The high bits of ApplZone and HiHeapMark are guaranteed to be clean. <C587>
;
StackSpaceTrap
Move.L #JStackSpace,-(SP) ; get offset onto stack <v1.9>
Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue<v1.9>
RTS
vStackSpace ; <v1.1>
MoveQ #20,D0 ;fudge factor <v1.1>
Add.L SP,D0 ; <09May85>
AndI.W #$FFFC,D0 ;round down to multiple of 4 <C251>
Sub.L HiHeapMark,D0 ; <C587>
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. <C731>
;
; On entry: none
; On exit: D0=0
; Trashes: A0-A1/D0-D2
;
MaxApplZone
Move.L #JMaxApplZone,-(SP) ; get offset onto stack <v1.9>
Move.L vMMNoPrologue,-(SP) ; get vector to MMnoPrologue<v1.9>
RTS
v24MaxApplZone ; 24 bit version of MaxApplZone <v1.1>
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... <SM24>
MoveQ #minFree24,D2 ; beneath this epsilon we will not grow <v1.2>
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? <C731>
BLS.S @noNewHigh ; HiHeapMark ³ A0 => no change <C731>
Move.L A0,HiHeapMark ; HiHeapMark < A0 => reset HiHeapMark <C731>
@noNewHigh ; skip to here when HiHeapMark OK <C731>
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 <v1.1>
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... <SM24>
MoveQ #minFree32,D2 ; beneath this epsilon we will not grow <v1.2>
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 <v1.1>
Move.L D0,BlkSize32(A0); get block size <v1.1>
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? <C731>
BLS.S @noNewHigh ; HiHeapMark ³ A0 => no change <C731>
Move.L A0,HiHeapMark ; HiHeapMark < A0 => reset HiHeapMark <C731>
@noNewHigh ; skip to here when HiHeapMark OK <C731>
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 <v1.1>
Move.L D2,BlkSize32(A0); make it a minFree block <v1.1>
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 <SM9> 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 :-) <SM29> kc
;
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
NewPtrTrap
MOVE.L #JNewPtr,-(SP) ; get offset to routine <v1.9>
MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue <v1.9>
RTS ; go to routine <v1.9>
; --- 24 bit version ----
v24NewPtr ; 24 bit version of NewPtr <v1.1>
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. <v1.1>
BSR a24AllocBk ; Allocate the block <v1.1>
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. <v1.1>
BSR a24AllocBk ; Allocate the block <v1.1>
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 <v1.9>
NPNoMem24
MOVEQ #memFullErr,D0
BRA.S NPExit24
; --- 32 bit version ----
v32NewPtr ; 32 bit version of NewPtr <v1.1>
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. <v1.1>
BSR a32AllocBk ; Allocate the block <v1.1>
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. <v1.1>
BSR a32AllocBk ; Allocate the block <v1.1>
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 <v1.9>
RTS ; jump to it <v1.9>
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 <sm9>stb
bne.w @NonNIL ; not nil, so call the real thing <sm9>stb
move.w d0,MemErr ; return no error even though itÕs not a ptr stb
rts ; <sm9>stb
@NonNIL MOVE.L #jDisposePtr,-(SP) ; get offset to routine <v1.9>
MOVE.L vMMPPrologue,-(SP) ; get vector to MMpprologue <v1.9>
RTS ; go to routine <v1.9>
v24DisposePtr ; 24 bit version of DisposePtr <v1.1>
; Move.L (SP)+,A0 ; restore A0 <v1.1>
DisposeTail24
BTST #ROZ,flags(A6) ; skip if read-only <04Mar85>
BNE.S DisposeSkip ; <04Mar85>
BSR a24FreeBk ; <v1.1>
BrA.S NPOk
v32DisposePtr ; 32 bit version of DisposePtr <v1.1>
; Move.L (SP)+,A0 ; restore A0 <v1.1>
DisposeTail32
BTST #ROZ,flags(A6) ; skip if read-only <04Mar85>
BNE.S DisposeSkip ; <04Mar85>
BSR a32FreeBk ; <v1.1>
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 <v1.9>
MOVE.L vMMPPrologue,-(SP) ; get vector to MMpprologue <v1.9>
RTS ; go to routine <v1.9>
v24GetPtrSize ; 24 bit version of MaxMem <v1.1>
BSR a24GetSize ; Get its size <v1.1>
BrA.S NPExit ; Check Zone, Restore, Return
v32GetPtrSize ; 32 bit version of MaxMem <v1.1>
BSR a32GetSize ; Get its size <v1.1>
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 <v1.9>
MOVE.L vMMPPrologue,-(SP) ; get vector to MMpprologue <v1.9>
RTS ; go to routine <v1.9>
v24SetPtrSize ; 24 bit version of MaxMem <v1.1>
BSR a24SetSize ; set its size <v1.1>
BrA.S NPExit
v32SetPtrSize ; 32 bit version of MaxMem <v1.1>
BSR a32SetSize ; set its size <v1.1>
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 <v1.9>
MOVE.L vMMPPrologue,-(SP) ; get vector to MMpprologue <v1.9>
RTS ; go to routine <v1.9>
vPtrZone ; 24/32 bit version of PtrZone <v1.1>
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 <v1.9>
MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue <v1.9>
RTS ; go to routine <v1.9>
v24NewEmptyHandle ; 24 bit version of NewEmptyHandle <v1.1>
BSR a24NextMaster ; Get next master in A1 <v1.1>
BEQ.S NHNoMaster ; If NIL, exit as in NewHandle
BRA.S NewEHExit ; use common code <v1.1>
v32NewEmptyHandle ; 32 bit version of NewEmptyHandle <v1.1>
BSR a32NextMaster ; Get next master in A1 <v1.1>
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 <v1.9>
RTS ; jump to it <v1.9>
;----------------------------------------------------------------------
;
; 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 <v1.9>
MOVE.L vMMPrologue,-(SP) ; get vector to MMPrologue <v1.9>
RTS ; go to routine <v1.9>
v24NwHandle ; 24 bit version of NwHandle <v1.1>
; from SetRovingPointerBeforeNewHandle patch<SM29> kc
CMPA.L SysZone,a6 ; is this handle going in the System heap? <SM29> kc
BEQ.S @inSysZone ; yup <SM29> kc
BTST #tSysOrCurZone,d1 ; is the "sys" bit set in the trapword? <SM29> kc
BEQ.S @notInSysZone ; nope <SM29> kc
@inSysZone ; <SM29> kc
CLR.L allocPtr(a6) ; clear the rover <SM29> kc
@notInSysZone ; <SM29> kc
BSR a24NextMaster ; Get next master <v1.1>
BNE.S @NHMaster ; If not NIL, go get block <v1.1>
BRA.S NHNoMaster ; if NIL, report error <v1.1>
@NHMaster
BSR a24AllocBk ; try to allocate block <v1.1>
BEq.S NHNoMem ; No luck, fail return
BRA.S HCheckHandle
v32NwHandle ; 32 bit version of NwHandle <v1.1>
; from SetRovingPointerBeforeNewHandle patch<SM29> kc
CMPA.L SysZone,a6 ; is this handle going in the System heap? <SM29> kc
BEQ.S @inSysZone ; yup <SM29> kc
BTST #tSysOrCurZone,d1 ; is the "sys" bit set in the trapword? <SM29> kc
BEQ.S @notInSysZone ; nope <SM29> kc
@inSysZone ; <SM29> kc
CLR.L allocPtr(a6) ; clear the rover <SM29> kc
@notInSysZone ; <SM29> kc
BSR a32NextMaster ; Get next master <v1.1>
BNE.S NHMaster ; If not NIL, go get block <v1.1>
NHNoMaster
MoveQ #memFullErr,D0
BrA.S HNilResult
NHMaster
BSR a32AllocBk ; try to allocate block <v1.1>
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 <v1.9>
RTS ; jump to it <v1.9>
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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
v24DsposeHandle ; 24 bit version of MaxMem <v1.1>
BNE.S DisposeTail24 ; Release block <v1.1>
Bra.S DsposeCommon ; branch to commond code <v1.1>
v32DsposeHandle ; 32 bit version of DsposeHandle <v1.1>
BNE.S DisposeTail32 ; Release block <v1.1>
DsposeCommon ; commond code <v1.1>
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 ? <SM23> PN
bgt.s Nothing ; if in ROM, leave it alone <SM23> 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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
v24GetHandleSize ; 24 bit version of GetHandleSize <v1.1>
BEq.S SHSNil
BSR a24GetSize ; <v1.1>
BrA.S SHSExit
v32GetHandleSize ; 32 bit version of GetHandleSize <v1.1>
BEq.S SHSNil
BSR a32GetSize ; <v1.1>
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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
v24SetHandleSize ; 24 bit version of SetHandleSize <v1.1>
BEQ.S SHSNil
BSR a24SetSize ; Set size as specified in D0 <v1.1>
BrA.S SHSExit ; <v1.1>
v32SetHandleSize ; 32 bit version of SetHandleSize <v1.1>
BNE.S SHSOk
SHSNil
MoveQ #nilHandleErr,D0 ;return error code
BrA.S SHSExit
SHSOk
BSR a32SetSize ;Set size as specified in D0 <v1.1>
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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
vHandleZone ; 24/32 bit version of HandleZone <v1.1>
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) <A305>
; 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 <C778>
; ROMBase, for safety. <C778>
RecoverHandleTrap
Move.L #JRecoverHandle,-(SP) ; get offset to routine onto stack <v1.9>
Move.L vMMRHPrologue,-(SP) ; get vector to MMRHPrologue <v1.9>
RTS ; go to routine <v1.9>
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 <C778><1.7>
LEA RHBusErrHandler,A3 ; our RH version <C778>
Move.L A3,BusErrVct ; <C778><1.7>
Move.L -4(A0),A1 ; Handle, or ROMBase on bus error <C778>
ReturnFromBusErr ; <NK1><SM22> rb
Move.L A2,BusErrVct ;restore old one after danger <C778><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 <v1.9>
RTS
;----------------------------------------------------------------------
; RHBusErr -- bus error handler for RecoverHandle <NK1><SM22> rb, start
; A bus error in RecoverHandle causes ROMBase to be jammed for the relative handle. <NK1>
; Triggered by bus errors in Move.L -4(A0),A1 in RecoverHandle. <NK1>
; <NK1>
; Frame types 7 and B are handled. The PC is jammed with the instruction <NK1>
; following the bus error (it can't be incremented because the emulator <NK1>
; doesn't guarantee valid PC values) and A1 is jammed with ROMbase. The <NK1>
; frame is then mutated into a type 0 frame before RTE. This should work <NK1>
; with VM, NuKernel, and emulator environments. <NK1>
;
; Output: A1 = ROMBase <NK1>
; Regs: A3 <NK1>
;----------------------------------------------------------------------
RHBusErrHandler
movea.l ROMBase,a1 ; stuff fake Nil value into expected dest. reg <NK1>
movea.w (sp),a3 ; <NK1>
cmpi.w #$7008,6(SP) ; type 7 frame? <NK1>
beq.s RHBusErrType7 ; <NK1>
adda.w #(92-8),SP ; Leave space for type 0 frame <NK1>
bra.s RHBusErrCommon ; <NK1>
RHBusErrType7 ; <NK1>
adda.w #(60-8),SP ; Leave space for type 0 frame <NK1>
RHBusErrCommon ; <NK1>
clr.w 6(SP) ; Make it a type 0 frame <NK1>
move.w a3,(sp) ; Return SR <NK1>
lea ReturnFromBusErr,a3 ; <NK1>
move.l a3,2(SP) ; Return PC <NK1>
RTE ; <NK1><SM22> 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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
v24EmptyHandle ; 24 bit version of EmptyHandle <v1.1>
BNE.S @EHNotNIL
MoveQ #0,D0
BrA.S EHExit
@EHNotNIL
BSR a24EH ; Common code with ReAllocHandle <v1.1>
BrA.S EHExit
v32EmptyHandle ; 32 bit version of EmptyHandle <v1.1>
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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
v24ReAllocHandle ; 24 bit version of ReAllocHandle <v1.1>
BEQ.S @RAHCont ; <SM29> kc
; from SetRovingPointerBeforeReallocHandle patch<SM29> kc
CMPA.L SysZone,a6 ; is this handle going in the System heap? <SM29> kc
BEQ.S @inSysZone ; yup <SM29> kc
BTST #tSysOrCurZone,d1 ; is the "sys" bit set in the trapword? <SM29> kc
BEQ.S @notInSysZone ; nope <SM29> kc
@inSysZone ; <SM29> kc
CLR.L allocPtr(a6) ; clear the rover <SM29> kc
@notInSysZone ; <SM29> 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 <v1.1>
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 <v1.1>
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 <v1.1>
BEQ.S @RAHCont ; <SM29> kc
; from SetRovingPointerBeforeReallocHandle patch<SM29> kc
CMPA.L SysZone,a6 ; is this handle going in the System heap? <SM29> kc
BEQ.S @inSysZone ; yup <SM29> kc
BTST #tSysOrCurZone,d1 ; is the "sys" bit set in the trapword? <SM29> kc
BEQ.S @notInSysZone ; nope <SM29> kc
@inSysZone ; <SM29> kc
CLR.L allocPtr(a6) ; clear the rover <SM29> kc
@notInSysZone ; <SM29> 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 ; <SM29> kc
Move.L A1,GZRootHnd ; record handle being reallocated
Clr.L GZRootPtr ; record lack of pointer
BSR a32AllocBk ; try to allocate block <v1.1>
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 <v1.1>
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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
; <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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
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 <v1.3>
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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
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 <v1.3>
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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
v24HNoPurge
BEq.S HFail ; handle was NIL
BClr #Purge,(A1) ; reset the purge bit
BrA.S HGood ;return success <v1.1>
v32HNoPurge
BEq.S HFail ; handle was NIL
BClr #Purge,MPtag32-blkData32(A0);reset the purge bit <v1.3>
HGood
MoveQ #0,D0
BrA.S HExit
HFail
MoveQ #nilHandleErr,D0
HExit
Move.L vMMEpilogue,-(SP) ; get vector to MMEpilogue <v1.9>
RTS ; jump to it <v1.9>
;----------------------------------------------------------------------
;
; 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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
v24HRSRC
BEq.S HFail ;handle was NIL <13Jan86 JTC>
BSet #Resource,(A1) ; <C206>
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 <v1.3>
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 ; <v1.1>
Move.L #jHNoRSRC,-(SP) ; get offset to vector onto stack <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
v24HNoRSRC
BEq.S HFail ; handle was NIL <13Jan86 JTC>
BClr #Resource,(A1) ; reset the RSRC bit <C206>
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 <v1.3>
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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
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 <v.1.9>
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 <v1.3>
GetFlagsExit
Clr.W MemErr ; custom exit, clearing error bits <13Jan86 JTC>
MOVE.L vMMNoErrEpilogue,-(SP) ; get MMNoErrEpilogue vector <v1.9>
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 <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
v24HSetFlags
BEq.S HFail ; if Nil, stuff D0 with error code <13Jan86 JTC>
Move.B D0,(A1) ; stuff flags <v1.3>
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 <v1.3>
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 <v1.9>
Move.L vMMMMPrologue,-(SP) ; get MMMMPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
v24MoreMasters ; 24 bit version of MoreMasters <v1.1>
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 <v1.1>
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 <SM12>
IF Supports24Bit THEN ; <SM17> CSS
BTST.B #Systemis24bit,SystemInfo ; is it 32 bit or 24 bit <SM12>
BEQ.S @1 ; no strip address for 32 bit mode <SM12>
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 <SM 8> 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 <v1.1>
SvBlkSize32 EQU 4 ; saved block size <v1.1>
MyBufCnt32 EQU 8 ; current buffer count <v1.1>
MyBufSize32 EQU 12 ; size of stack buffer <v1.1>
InRgnPtr32 EQU 16 ; region reference point <v1.1>
SavedZone32 EQU 20 ; saved theZone across the call <v1.1>
MyStkBuf32 EQU 24 ; start of stack buffer <v1.1>
LclVarSize32 EQU MyStkBuf32 ; <v1.1>
MoveHHi
Move.L #JMoveHHi,-(SP) ; get offset to vector onto stack <v1.9>
Move.L vMMHPrologue,-(SP) ; get MMHPrologue vector onto stack <v1.9>
RTS ; go to routine <v1.9>
v24MoveHHi ; 24 bit version of MoveHHi <v1.1>
;-------------------------------------------------------------------------------
; First check for the nasties: locked or purged.
;-------------------------------------------------------------------------------
BNE.S @goBubble ; NotEqual => not purged <31mar86>
; <SM29> kc
MOVEQ #NilHandleErr,D0 ; nil handle error <SM29> kc
BRA MHHExit ; go to common exit <SM29> kc
@goBubble ; <SM29> kc
CMPA.L SysZone,a6 ; is this handle in the System heap? <SM29> kc
BNE.S @notInSysZone ; nope <SM29> kc
; <SM29> kc
MOVEQ #noErr,D0 ; yup, don't do anything <SM29> kc
BRA MHHExit ; go to common exit <SM29> kc
@notInSysZone ; <SM29> kc
MOVE.L A1,A4 ; save handle to block for the duration <SM29> kc
TST.B (A4) ; make sure block is unlocked <SM29> kc
BPL.S @goAhead ; yup, all's cool <SM29> kc
; <SM29> kc
MOVEQ #memLockedErr,D0 ; locked handle error <SM29> kc
BRA MHHExit ; <SM29> 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 <SM25>
**** 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><v1.2>
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><v1.2>
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 ; <v1.1>
;-------- 32 bit version ---
v32MoveHHi ; 32 bit version of MoveHHi <v1.1>
;-------------------------------------------------------------------------------
; First check for the nasties: locked or purged.
;-------------------------------------------------------------------------------
BNE.S @goBubble ; NotEqual => not purged <31mar86>
; <SM29> kc
MOVEQ #NilHandleErr,D0 ; nil handle error <SM29> kc
BRA MHHExit ; jump to common exit <SM29> kc
@goBubble ; <SM29> kc
CMPA.L SysZone,a6 ; is this handle in the System heap? <SM29> kc
BNE.S @notInSysZone ; nope <SM29> kc
; <SM29> kc
MOVEQ #noErr,D0 ; yup, don't do anything <SM29> kc
BRA MHHExit ; go to common exit <SM29> kc
@notInSysZone ; <SM29> kc
MOVE.L A1,A4 ; save handle to block for the duration <SM29> kc
TST.B MPtag32-BlkData32(A0) ; make sure block is unlocked <SM29> kc
BPL.S @goAhead ; yup, all's cool <SM29> kc
; <SM29> kc
MOVEQ #memLockedErr,D0 ; locked handle error <SM29> kc
BRA MHHExit ; jump to common exit <SM29> 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 <v1.1>
Move.L BlkSize32(A0),D1 ; get block size <v1.1>
MOVE.L D1,D7 ; save in D7 for the duration <v1.1>
SUB.L #BlkData32,D7 ; adjust for data count only <v1.1>
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? <v1.1>
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 <SM25>
**** 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 ; <v1.1>
MOVE.L TagBC32(A0),OldTagBC32(A5); save 1st long word <v1.1>
Move.L (A4),InRgnPtr32(A5) ; save blk as region hint <v1.1>
Move.L Blksize32(A0),SvBlksize32(A5); save block size <v1.1>
;-------------------------------------------------------------------------------
; 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 <v1.1>
MOVE.L D1,D0 ; <v1.1>
SUB.L #BlkData32,D0 ;last block data space <v1.1>
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><v1.2>
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 ; <SM17> 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 <v1.1>
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 <v1.1>
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><v1.2>
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 <v1.1>
MOVE.L D0,BlkSize32(A2) ; adjust size of remaining free blk <v1.1>
@MNSExact
MOVEM.L (A1),D3-D5 ; save 3 longs at front of blk <v1.1>
MOVE.L A6,Handle32(A1) ; <v1.1>
MOVE.L D6,BlkSize32(A1) ; data size is blk size in this case <v1.1>
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 <v1.1>
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 <v1.1>
SUB.L #blkData32,ZCBFree(A6) ; *** this is a fix *** <v1.1>
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 <v1.1>
MOVE.L D0,BlkSize32(A2) ; set remaining size <v1.1>
@11 MOVE.L A1,A2 ; point A2 to our new block
MOVE.L OldTagBC32(A5),(A2)+ ; TagBC
Move.L SvBlkSize32(A5),(A2)+ ; block size <v1.1>
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 <v1.9>
RTS ; jump to it <v1.9>
;-------------------------------------------------------------------------------------------
; 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 ; <v1.1>
SUB.L #BlkData32,A0 ; start scan from here for speed <v1.1>
BRA.S @FRTLoop
@10 LEA HeapData(A6),A0 ; scan from start of zone
@FRTLoop
MOVE.L BlkSize32(A0),D1 ; block size <v1.1>
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? <v1.1>
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 <v1.1>
ADD.L #BlkData32,D0 ; new physical block size <v1.1>
MOVE.L D0,BlkSize32(A0) ; set size <v1.1>
ADD.L D0,A0 ; point to new free block <v1.1>
Clr.L tagBC32(A0) ; set as free block <v1.1>
MOVE.L D1,BlkSize32(A0) ; set free block size <v1.1>
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 <v1.9>
_CompactMem ; free space to the top . . .
RTS
END ; *********** comment this out for RAMTest