2023-05-22 16:17:35 +02:00
;--------------------------------------------------------------------
DEBUGMEM MACRO
IFGE DEBUG_DETAIL - 10
bsr fw_DebugMemoryManagement
ENDC
ENDM
;--------------------------------------------------------------------
; Initializes the memory stacks for chip- and fast-mem
;
fw_InitMemoryManagement:
move.l fw_ChipMemStack ( a6 ), d0
move.l fw_ChipMemStackEnd ( a6 ), d1
move.l fw_FastMemStack ( a6 ), d2
move.l fw_FastMemStackEnd ( a6 ), d3
PUTMSG 10 , < "Chipmem %p - %p, Fastmem %p - %p" > , d0 , d1 , d2 , d3
lea fw_MemBottomStack ( a6 ), a1
move.l d0 , cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 )
move.l d0 , cf_ChipMemLevel + mtb_MinLevelPtr ( a1 )
move.l d2 , cf_FastMemLevel + mtb_CurrLevelPtr ( a1 )
move.l d2 , cf_FastMemLevel + mtb_MinLevelPtr ( a1 )
;clr.w fw_CurrMemBottomLevel(a6)
lea fw_MemTopStack ( a6 ), a1
move.l d1 , cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 )
move.l d1 , cf_ChipMemLevel + mtb_MinLevelPtr ( a1 )
move.l d3 , cf_FastMemLevel + mtb_CurrLevelPtr ( a1 )
move.l d3 , cf_FastMemLevel + mtb_MinLevelPtr ( a1 )
;clr.w fw_CurrMemTopLevel(a6)
DEBUGMEM
rts
;--------------------------------------------------------------------
; Frees all allocated memory
;
; Frees the memory of the current stack and current direction.
; Memory of other allocation direction is unchanged.
;
fw_DropCurrentMemoryAllocations:
2024-09-15 17:43:33 +02:00
PUTMSG 10 , < "%d: DropCurrentMemoryAllocations" > , fw_FrameCounter - 2 ( a6 )
2023-05-22 16:17:35 +02:00
IFGE DEBUG_DETAIL - 20
PUSHM a0 / a1 / d0
ELSE
PUSHM a1
ENDC
DEBUGMEM
IF FW_TOP_BOTTOM_MEM_SECTIONS
bsr fw_DetectAllocationDirection
bne.s .toptobottom
ENDC
PUTMSG 10 , < "DOWN: Freeing all" >
lea fw_MemBottomStack ( a6 ), a1
adda.w fw_CurrMemBottomLevel ( a6 ), a1
IFGE DEBUG_DETAIL - 20
move.l cf_ChipMemLevel + mtb_MinLevelPtr ( a1 ), a0
move.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 ), d0
sub.l a0 , d0
bsr fw_FillWithGarbage
move.l cf_FastMemLevel + mtb_MinLevelPtr ( a1 ), a0
move.l cf_FastMemLevel + mtb_CurrLevelPtr ( a1 ), d0
sub.l a0 , d0
bsr fw_FillWithGarbage
ENDC
.cont
move.l cf_ChipMemLevel + mtb_MinLevelPtr ( a1 ), cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 )
move.l cf_FastMemLevel + mtb_MinLevelPtr ( a1 ), cf_FastMemLevel + mtb_CurrLevelPtr ( a1 )
DEBUGMEM
POPM
rts
IF FW_TOP_BOTTOM_MEM_SECTIONS
.toptobottom
PUTMSG 10 , < "UP: Freeing all" >
lea fw_MemTopStack ( a6 ), a1
adda.w fw_CurrMemTopLevel ( a6 ), a1
IFGE DEBUG_DETAIL - 20
move.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 ), a0
move.l cf_ChipMemLevel + mtb_MinLevelPtr ( a1 ), d0
sub.l a0 , d0
bsr fw_FillWithGarbage
move.l cf_FastMemLevel + mtb_CurrLevelPtr ( a1 ), a0
move.l cf_FastMemLevel + mtb_MinLevelPtr ( a1 ), d0
sub.l a0 , d0
bsr fw_FillWithGarbage
ENDC
bra.s .cont
ENDC
;--------------------------------------------------------------------
; Pushes the current memory allocation state to the stack
;
; This only pushes the state for the current memory allocation
; direction onto the stack. All allocated memory upto this point
; will be kept safe and will no longer be freed automatically.
;
fw_PushMemoryState:
PUSHM a1 / d0 - d1
moveq.l # cf_SIZEOF , d0
IF FW_TOP_BOTTOM_MEM_SECTIONS
bsr fw_DetectAllocationDirection
bne.s .toptobottom
ENDC
PUTMSG 10 , < "UP: ++++++ Pushing mem state ++++++" >
add.w fw_CurrMemBottomLevel ( a6 ), d0
move.w d0 , fw_CurrMemBottomLevel ( a6 )
lea fw_MemBottomStack ( a6 , d0.w ), a1
.cont
move.l cf_ChipMemLevel + mtb_CurrLevelPtr - cf_SIZEOF ( a1 ), d0
move.l cf_FastMemLevel + mtb_CurrLevelPtr - cf_SIZEOF ( a1 ), d1
move.l d0 , cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 )
move.l d0 , cf_ChipMemLevel + mtb_MinLevelPtr ( a1 )
move.l d1 , cf_FastMemLevel + mtb_CurrLevelPtr ( a1 )
move.l d1 , cf_FastMemLevel + mtb_MinLevelPtr ( a1 )
DEBUGMEM
POPM
rts
IF FW_TOP_BOTTOM_MEM_SECTIONS
.toptobottom
PUTMSG 10 , < "DOWN: ++++++ Pushing mem state ++++++" >
add.w fw_CurrMemTopLevel ( a6 ), d0
move.w d0 , fw_CurrMemTopLevel ( a6 )
lea fw_MemTopStack ( a6 , d0.w ), a1
bra.s .cont
ENDC
;--------------------------------------------------------------------
; Restore the last memory state from the memory stack for the current
; allocation direction. All memory from the previous allocation is
; freed.
;
; With debug enabled, freed memory is also overwritten with garbage.
;
; Out: All registers unchanged.
;
fw_PopMemoryState:
PUSHM a0 / d0
DEBUGMEM
IF FW_TOP_BOTTOM_MEM_SECTIONS
bsr fw_DetectAllocationDirection
bne .toptobottom
ENDC
IFGE DEBUG_DETAIL - 10
PUTMSG 10 , < "UP: ------ Popping mem state ------" >
bsr fw_DropCurrentMemoryAllocations
sub.w # cf_SIZEOF , fw_CurrMemBottomLevel ( a6 )
bmi.s .errorbottom
ELSE
sub.w # cf_SIZEOF , fw_CurrMemBottomLevel ( a6 )
ENDC
.cont
DEBUGMEM
POPM
rts
IFGE DEBUG_DETAIL - 10
.errorbottom
PUTMSG 10 , < "!!! Could not pop bottom memory stack (TOP: %d vs %d)" > , fw_CurrMemBottomLevel - 2 ( a6 ), fw_CurrMemTopLevel - 2 ( a6 )
move.w # ERROR_MEMORYWRONGPOP , d0
bra fw_Error
.errortop
PUTMSG 10 , < "!!! Could not pop top memory stack (TOP: %d vs %d)" > , fw_CurrMemBottomLevel - 2 ( a6 ), fw_CurrMemTopLevel - 2 ( a6 )
move.w # ERROR_MEMORYWRONGPOP , d0
bra fw_Error
ENDC
IF FW_TOP_BOTTOM_MEM_SECTIONS
.toptobottom
IFGE DEBUG_DETAIL - 10
PUTMSG 10 , < "DOWN: ------ Popping mem state ------" >
bsr fw_DropCurrentMemoryAllocations
sub.w # cf_SIZEOF , fw_CurrMemTopLevel ( a6 )
bmi .errortop
ELSE
sub.w # cf_SIZEOF , fw_CurrMemTopLevel ( a6 )
ENDC
bra .cont
ENDC
;--------------------------------------------------------------------
; Allocates the given amount of fastmem in the current direction of
; memory allocation (bottom->top or top->bottom).
;
; If theres not enough fast-mem, it falls back and returns chip-mem
; instead.
;
; Contents of memory are not cleared!
;
; In : d0: Size in bytes
; Out: a0: Start of memory allocation
; d0: Rounded size of allocation
; d1/a1: Trashed.
;
fw_AllocFast:
2024-09-15 17:43:33 +02:00
PUTMSG 10 , < "%d: AllocFast(%ld)" > , fw_FrameCounter - 2 ( a6 ), d0
2023-05-22 16:17:35 +02:00
addq.l # 3 , d0
and.w # - 4 , d0
lea fw_MemBottomStack ( a6 ), a0
adda.w fw_CurrMemBottomLevel ( a6 ), a0
lea fw_MemTopStack ( a6 ), a1
adda.w fw_CurrMemTopLevel ( a6 ), a1
move.l cf_FastMemLevel + mtb_CurrLevelPtr ( a1 ), d1
sub.l cf_FastMemLevel + mtb_CurrLevelPtr ( a0 ), d1
cmp.l d0 , d1
blo.s fw_AllocChip
moveq.l # cf_FastMemLevel , d1
bsr fw_DoAllocation
PUTMSG 30 , < "Fast allocated at %p" > , a0
IFGE DEBUG_DETAIL - 12
bsr.s fw_FillWithGarbage
ENDC
DEBUGMEM
rts
;--------------------------------------------------------------------
; Allocates the given amount of chipmem in the current direction of
; memory allocation (bottom->top or top->bottom).
;
; Contents of memory are not cleared!
;
; In : d0: Size in bytes
; Out: a0: Start of memory allocation
; d0: Rounded size of allocation
; d1/a1: Trashed.
;
fw_AllocChip:
2024-09-15 17:43:33 +02:00
PUTMSG 10 , < "%d: AllocChip(%ld)" > , fw_FrameCounter - 2 ( a6 ), d0
2023-05-22 16:17:35 +02:00
addq.l # 7 , d0
and.w # - 8 , d0
lea fw_MemBottomStack ( a6 ), a0
adda.w fw_CurrMemBottomLevel ( a6 ), a0
lea fw_MemTopStack ( a6 ), a1
adda.w fw_CurrMemTopLevel ( a6 ), a1
move.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 ), d1
sub.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a0 ), d1
cmp.l d0 , d1
blo.s .error
moveq.l # cf_ChipMemLevel , d1
bsr fw_DoAllocation
PUTMSG 30 , < "Chip allocated at %p" > , a0
IFGE DEBUG_DETAIL - 12
bsr fw_FillWithGarbage
ENDC
DEBUGMEM
rts
.error
PUTMSG 10 , < "Out of memory: %ld smaller than %ld" > , d1 , d0
DEBUGMEM
move.w # ERROR_OUTOFMEMORY , d0
bra fw_Error
;--------------------------------------------------------------------
; Allocates the given amount of chipmem within a 64 KB page in the
; current direction of memory allocation.
;
; Memory area returned is guaranteed not to cross a 64 KB page
; boundary for the given size. Depending on the current memory
; situation and size requirements, may waste up to 64 KB of memory
; in the worst case. If you need multiple allocations these
; requirements, make sure to cluster them in a good way.
;
; Contents of memory are not cleared!
;
; In : d0: Size in bytes (less or equal to 64 KB!)
; Out: a0: Start of memory allocation
; d0: Rounded size of allocation
; d1/a1: Trashed.
;
IF FW_64KB_PAGE_MEMORY_SUPPORT
fw_AllocChip64KB:
2024-09-15 17:43:33 +02:00
PUTMSG 10 , < "%d: AllocChip64KB(%ld)" > , fw_FrameCounter - 2 ( a6 ), d0
2023-05-22 16:17:35 +02:00
addq.l # 7 , d0
and.w # - 8 , d0
lea fw_MemBottomStack ( a6 ), a0
adda.w fw_CurrMemBottomLevel ( a6 ), a0
lea fw_MemTopStack ( a6 ), a1
adda.w fw_CurrMemTopLevel ( a6 ), a1
.retry
move.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 ), d1
sub.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a0 ), d1
cmp.l d0 , d1
blo .error
IF FW_TOP_BOTTOM_MEM_SECTIONS
bsr fw_DetectAllocationDirection
bne.s .toptobottom
ENDC
move.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a0 ), d1
add.l d0 , d1
subq.l # 1 , d1
swap d1
cmp.w cf_ChipMemLevel + mtb_CurrLevelPtr ( a0 ), d1
beq .doallocation
addq.w # 1 , cf_ChipMemLevel + mtb_CurrLevelPtr ( a0 )
IFGE DEBUG_DETAIL - 10
moveq.l # 0 , d1
move.w cf_ChipMemLevel + mtb_CurrLevelPtr + 2 ( a0 ), d1
neg.w d1
PUTMSG 10 , < "Skipping %ld bytes of memory DOWN (sorry)" > , d1
ENDC
clr.w cf_ChipMemLevel + mtb_CurrLevelPtr + 2 ( a0 )
bra.s .retry
IF FW_TOP_BOTTOM_MEM_SECTIONS
.toptobottom
moveq.l # 0 , d1
move.w cf_ChipMemLevel + mtb_CurrLevelPtr + 2 ( a1 ), d1
beq.s .doallocation
cmp.l d0 , d1
bge.s .doallocation
PUTMSG 10 , < "Skipping %d bytes of memory UP (sorry)" > , cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 )
clr.w cf_ChipMemLevel + mtb_CurrLevelPtr + 2 ( a1 )
bra .retry
ENDC
.doallocation
moveq.l # cf_ChipMemLevel , d1
bsr fw_DoAllocation
PUTMSG 30 , < "Chip within 64 KB page allocated at %p" > , a0
IFGE DEBUG_DETAIL - 20
bsr fw_FillWithGarbage
ENDC
DEBUGMEM
rts
.error
PUTMSG 10 , < "Out of memory: %ld smaller than %ld" > , d1 , d0
DEBUGMEM
move.w # ERROR_OUTOFMEMORY , d0
bra fw_Error
ENDC
;--------------------------------------------------------------------
; Changes the direction of memory allocation (bottom to top vs top
; to bottom). Also works from subtasks (be a bit careful there).
;
; Out: All registers unchanged.
;
IF FW_TOP_BOTTOM_MEM_SECTIONS
fw_FlipAllocationDirection:
IF FW_MULTITASKING_SUPPORT
tst.l fw_BackgroundTask ( a6 )
beq.s .flipmain
PUSHM a0
move.l fw_BackgroundTask ( a6 ), a0
eor.w # 1 , ft_MemDirection ( a0 )
PUTMSG 10 , < "Flipping allocation direction of task %p (%s) to %d" > , a0 , LN_NAME ( a0 ), ft_MemDirection - 2 ( a0 )
POPM
rts
ENDC
.flipmain
eor.w # 1 , fw_MainMemDirection ( a6 )
PUTMSG 10 , < "Flipping main allocation direction to %d" > , fw_MainMemDirection - 2 ( a6 )
rts
;--------------------------------------------------------------------
fw_DetectAllocationDirection:
IF FW_MULTITASKING_SUPPORT
tst.l fw_BackgroundTask ( a6 )
beq.s .flipmain
PUSHM a0 / d0 ; avoid optimizing the movem to move so that the CCs remain intact
move.l fw_BackgroundTask ( a6 ), a0
tst.w ft_MemDirection ( a0 )
POPM
rts
ENDC
.flipmain
tst.w fw_MainMemDirection ( a6 )
rts
ENDC
;--------------------------------------------------------------------
fw_DoAllocation:
PUSHM a1 / d0 / d1
IF FW_TOP_BOTTOM_MEM_SECTIONS
bsr fw_DetectAllocationDirection
bne.s .toptobottom
ENDC
; allocate from bottom
lea fw_MemBottomStack ( a6 ), a1
adda.w fw_CurrMemBottomLevel ( a6 ), a1
move.l mtb_CurrLevelPtr ( a1 , d1.w ), a0
PUTMSG 10 , < "UP: Allocating %ld bytes from bottom at %p" > , d0 , a0
add.l a0 , d0
move.l d0 , mtb_CurrLevelPtr ( a1 , d1.w )
.cont
POPM
rts
IF FW_TOP_BOTTOM_MEM_SECTIONS
.toptobottom
; allocate from top
lea fw_MemTopStack ( a6 ), a1
adda.w fw_CurrMemTopLevel ( a6 ), a1
move.l mtb_CurrLevelPtr ( a1 , d1.w ), a0
sub.l d0 , a0
PUTMSG 10 , < "DOWN: Allocating %ld bytes from top at %p" > , d0 , a0
move.l a0 , mtb_CurrLevelPtr ( a1 , d1.w )
bra.s .cont
ENDC
;--------------------------------------------------------------------
IFGE DEBUG_DETAIL - 12
fw_FillWithGarbage:
PUTMSG 10 , < "Filling with garbage %p (%ld)" > , a0 , d0
PUSHM a0 / d0 / d1
lsr.l # 2 , d0
beq.s .skipfill
subq.w # 1 , d0
move.l # $ DEADBE00 , d1
.fillloop
move.l d1 ,( a0 ) +
addq.l # 1 , d1
db ra d0 , .fillloop
swap d0
subq.w # 1 , d0
bcs.s .skipfill
swap d0
bra.s .fillloop
.skipfill
POPM
rts
ENDC
;--------------------------------------------------------------------
IFGE DEBUG_DETAIL - 10
fw_DebugMemoryManagement:
PUSHM d0 - d7 / a0 / a1
lea fw_MemBottomStack ( a6 ), a0
adda.w fw_CurrMemBottomLevel ( a6 ), a0
lea fw_MemTopStack ( a6 ), a1
adda.w fw_CurrMemTopLevel ( a6 ), a1
move.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 ), d0 ; current free chip: chip top - bottom
sub.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a0 ), d0
lsr.l # 8 , d0
lsr.w # 2 , d0
move.l fw_MemTopStack + cf_ChipMemLevel + mtb_MinLevelPtr ( a6 ), d1 ; max free chip within this frame
sub.l cf_ChipMemLevel + mtb_MinLevelPtr ( a0 ), d1
lsr.l # 8 , d1
lsr.w # 2 , d1
move.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a0 ), d2 ; bottom chip allocated in stack
sub.l cf_ChipMemLevel + mtb_MinLevelPtr ( a0 ), d2
lsr.l # 8 , d2
lsr.w # 2 , d2
move.l cf_ChipMemLevel + mtb_MinLevelPtr ( a1 ), d3 ; top chip allocated in stack
sub.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 ), d3
lsr.l # 8 , d3
lsr.w # 2 , d3
move.l cf_FastMemLevel + mtb_CurrLevelPtr ( a1 ), d4 ; current free fast: fast top - bottom
sub.l cf_FastMemLevel + mtb_CurrLevelPtr ( a0 ), d4
lsr.l # 8 , d4
lsr.w # 2 , d4
move.l cf_FastMemLevel + mtb_MinLevelPtr ( a1 ), d5 ; max free fast within this frame
sub.l fw_MemBottomStack + cf_FastMemLevel + mtb_MinLevelPtr ( a6 ), d5
lsr.l # 8 , d5
lsr.w # 2 , d5
move.l cf_FastMemLevel + mtb_CurrLevelPtr ( a0 ), d6 ; bottom fast allocated in stack
sub.l cf_FastMemLevel + mtb_MinLevelPtr ( a0 ), d6
lsr.l # 8 , d6
lsr.w # 2 , d6
move.l cf_FastMemLevel + mtb_MinLevelPtr ( a1 ), d7 ; top fast allocated in stack
sub.l cf_FastMemLevel + mtb_CurrLevelPtr ( a1 ), d7
lsr.l # 8 , d7
lsr.w # 2 , d7
PUTMSG 10 , < "Mem Free: Chip: %ld of %ld KB (%ld/%ld KB) | Fast: %ld of %ld KB (%ld/%ld KB)" > , d0 , d1 , d2 , d3 , d4 , d5 , d6 , d7
move.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a0 ), d0 ; bottom chip allocated total
sub.l fw_MemBottomStack + cf_ChipMemLevel + mtb_MinLevelPtr ( a6 ), d0
add.l fw_MemTopStack + cf_ChipMemLevel + mtb_MinLevelPtr ( a6 ), d0 ; top chip allocated total
sub.l cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 ), d0
lsr.l # 8 , d0
lsr.w # 2 , d0
cmp.l fw_MaxChipUsed ( a6 ), d0
blt.s .lesschip
move.l d0 , fw_MaxChipUsed ( a6 )
.lesschip
move.l fw_MemTopStack + cf_ChipMemLevel + mtb_MinLevelPtr ( a6 ), d1 ; max free chip total
sub.l fw_MemBottomStack + cf_ChipMemLevel + mtb_MinLevelPtr ( a6 ), d1
lsr.l # 8 , d1
lsr.w # 2 , d1
move.l cf_FastMemLevel + mtb_CurrLevelPtr ( a0 ), d2 ; bottom fast allocated total
sub.l fw_MemBottomStack + cf_FastMemLevel + mtb_MinLevelPtr ( a6 ), d2
add.l fw_MemTopStack + cf_FastMemLevel + mtb_MinLevelPtr ( a6 ), d2 ; top fast allocated total
sub.l cf_FastMemLevel + mtb_CurrLevelPtr ( a1 ), d2
lsr.l # 8 , d2
lsr.w # 2 , d2
cmp.l fw_MaxFastUsed ( a6 ), d2
blt.s .lessfast
move.l d2 , fw_MaxFastUsed ( a6 )
.lessfast
move.l fw_MemTopStack + cf_FastMemLevel + mtb_MinLevelPtr ( a6 ), d3 ; max free fast total
sub.l fw_MemBottomStack + cf_FastMemLevel + mtb_MinLevelPtr ( a6 ), d3
lsr.l # 8 , d3
lsr.w # 2 , d3
PUTMSG 10 , < "Mem Used: Chip: %ld of %ld KB (max. %ld KB) | Fast: %ld of %ld KB (max. %ld KB)" > , d0 , d1 , fw_MaxChipUsed ( a6 ), d2 , d3 , fw_MaxFastUsed ( a6 )
PUTMSG 20 , < "Chip Bottom: %p, Chip Top %p, Fast Bottom: %p, Fast Top: %p" > , cf_ChipMemLevel + mtb_CurrLevelPtr ( a0 ), cf_ChipMemLevel + mtb_CurrLevelPtr ( a1 ), cf_FastMemLevel + mtb_CurrLevelPtr ( a0 ), cf_FastMemLevel + mtb_CurrLevelPtr ( a1 )
POPM
rts
ENDC