309 lines
6.8 KiB
Text
309 lines
6.8 KiB
Text
//-----------------------------------------------------------
|
|
//
|
|
// Memory library ( Malloc, Free )
|
|
//
|
|
//
|
|
// Author: Mattias Hansson
|
|
// Copyright (c) : 2000-2005 Mattias Hansson
|
|
// License: GNU LGPL 2
|
|
// Language: 65CM v0.4+
|
|
// Dependencies:
|
|
// Target: generic 6502
|
|
//
|
|
// Purpose: Provide some functions the help to create, update and access
|
|
// a linked list of strings.
|
|
//-----------------------------------------------------------
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
// Internals:
|
|
//
|
|
// Makes heap-handling in a defined part of the memory.
|
|
//
|
|
// Requested memory is placed "from bottom upwards".
|
|
// Allocation entries are written from the top downwards.
|
|
//
|
|
// layout:
|
|
//
|
|
// Bottom ( e.g. $2000-$2fff )
|
|
// --------------
|
|
// $2000
|
|
// .
|
|
// . area 1 allocated by application
|
|
// .
|
|
// $2020
|
|
// $2021
|
|
// .
|
|
// . area 2 allocated by application
|
|
// .
|
|
// $2025
|
|
//
|
|
// .
|
|
// .
|
|
// .
|
|
//
|
|
// $2ff8 + $2ff9 = $2025 end of area 2
|
|
// $2ffa + $2ffb = $2021 start of area 2
|
|
// $2ffc + $2ffd = $2020 end of area 1
|
|
// $2ffe + $2fff = $2000 start of area 1
|
|
|
|
#IFNDEF __LIB_MEM
|
|
#DEFINE __LIB_MEM = 1
|
|
|
|
#PRAGMA _P_USE_LONG_JUMP 1
|
|
|
|
#IFNDEF __LIB_MEM_START
|
|
#DEFINE __LIB_MEM_START = $5000
|
|
#IFEND
|
|
|
|
#IFNDEF __LIB_MEM_END
|
|
#DEFINE __LIB_MEM_END = $9fff
|
|
#IFEND
|
|
|
|
#IFNDEF NULL
|
|
#DEFINE NULL = 0
|
|
#IFEND
|
|
|
|
GOTO lib_memlib_skip
|
|
|
|
WORD CONST lib_memstart = __LIB_MEM_START
|
|
WORD CONST lib_memend = __LIB_MEM_END
|
|
|
|
WORD lib_alloctable_end
|
|
|
|
//-----------------------------------------------------------
|
|
// Init: sets upp things for the lib in mem before start
|
|
//-----------------------------------------------------------
|
|
FUNC lib_mem_init
|
|
|
|
//set allocation table end start value
|
|
LET lib_alloctable_end GET lib_memend
|
|
INC lib_alloctable_end
|
|
|
|
FEND
|
|
|
|
//-----------------------------------------------------------
|
|
// Malloc: alloc memory of size size_t
|
|
// Address to allocated space is returned in result
|
|
//-----------------------------------------------------------
|
|
|
|
FUNC lib_mem_malloc ( {WORD size_t} out:{WORD result} )
|
|
WORD maxsize //max possible size now in heap
|
|
WORD newspaceb
|
|
WORD newspacee
|
|
WORD newtableend
|
|
|
|
DEC size_t // 1 = e.g. $2001-$2001 ( $2001 - $2001 = 0 )
|
|
|
|
LET newtableend GET lib_alloctable_end
|
|
SUBT newtableend - 4 -> newtableend
|
|
|
|
IF lib_alloctable_end > lib_memend THEN // only when first item!
|
|
|
|
SUBT newtableend - lib_memstart -> maxsize
|
|
IF maxsize < size_t THEN
|
|
//error handling: return NULL pointer!
|
|
LET result GET NULL
|
|
GOTO lib_malloc_exit
|
|
ENDIF
|
|
|
|
LET newspaceb GET lib_memstart
|
|
ADD newspaceb + size_t -> newspacee
|
|
|
|
//insert first record and recalc lib_alloctable_end
|
|
DEC lib_alloctable_end
|
|
DEC lib_alloctable_end
|
|
POKEW lib_alloctable_end , newspaceb
|
|
DEC lib_alloctable_end
|
|
DEC lib_alloctable_end
|
|
POKEW lib_alloctable_end , newspacee
|
|
|
|
LET result GET newspaceb
|
|
|
|
GOTO lib_malloc_exit;
|
|
|
|
ENDIF
|
|
//else if this is not the first item then:
|
|
|
|
WORD lib_malloc_ptr
|
|
WORD lib_malloc_spaceend
|
|
WORD lib_malloc_spacestart
|
|
|
|
//LET lib_malloc_ptr GET lib_memend
|
|
//SUBT lib_malloc_ptr - 3 -> lib_malloc_ptr
|
|
LET lib_malloc_ptr GET lib_alloctable_end
|
|
|
|
lib_malloc_spaceend = PEEKW lib_malloc_ptr
|
|
|
|
LET newspaceb GET NULL //if not found afterwards
|
|
|
|
WHILE 1
|
|
|
|
//if we reached the last record in the alloc-table
|
|
IF lib_malloc_ptr = lib_alloctable_end THEN
|
|
//is there sufficient space left @ top of heap?
|
|
INC lib_malloc_spaceend
|
|
SUBT newtableend - lib_malloc_spaceend -> maxsize
|
|
|
|
IF maxsize > size_t THEN
|
|
LET newspaceb GET lib_malloc_spaceend
|
|
ADD size_t + newspaceb -> newspacee
|
|
ENDIF
|
|
|
|
BREAK
|
|
ENDIF
|
|
|
|
DEC lib_malloc_ptr
|
|
DEC lib_malloc_ptr
|
|
lib_malloc_spacestart = PEEKW lib_malloc_ptr
|
|
SUBT lib_malloc_spacestart - lib_malloc_spaceend -> maxsize
|
|
DEC maxsize
|
|
//if we found a space big enough for the allocation
|
|
IF maxsize > size_t THEN
|
|
//Save the pointer to the new space end the pointer in the alloctable
|
|
LET newspaceb GET lib_malloc_spaceend
|
|
INC newspaceb // must start @ the next byte
|
|
ADD size_t + newspaceb -> newspacee
|
|
|
|
INC lib_malloc_ptr // set it to start of record! ( for move )
|
|
// INC lib_malloc_ptr
|
|
|
|
BREAK
|
|
ENDIF
|
|
|
|
DEC lib_malloc_ptr
|
|
DEC lib_malloc_ptr
|
|
lib_malloc_spaceend = PEEKW lib_malloc_ptr
|
|
|
|
WEND
|
|
|
|
IF newspaceb <> NULL THEN // allocate @ found space
|
|
IF lib_malloc_ptr = lib_alloctable_end THEN //allocate @ end of table
|
|
|
|
//insert record and recalc lib_alloctable_end
|
|
DEC lib_alloctable_end
|
|
DEC lib_alloctable_end
|
|
POKEW lib_alloctable_end , newspaceb
|
|
DEC lib_alloctable_end
|
|
DEC lib_alloctable_end
|
|
POKEW lib_alloctable_end , newspacee
|
|
|
|
//return new pointer
|
|
LET result GET newspaceb
|
|
|
|
GOTO lib_malloc_exit
|
|
ENDIF
|
|
//else = insert into alloctable
|
|
WORD lib_malloc_from
|
|
WORD lib_malloc_to
|
|
BYTE lib_malloc_byte
|
|
|
|
// move the rest of the stack
|
|
LET lib_malloc_from GET lib_alloctable_end
|
|
LET lib_malloc_to GET newtableend
|
|
|
|
WHILE 1
|
|
PEEK lib_malloc_from -> lib_malloc_byte
|
|
POKE lib_malloc_to WITH lib_malloc_byte
|
|
IF lib_malloc_from = lib_malloc_ptr THEN
|
|
BREAK
|
|
ENDIF
|
|
INC lib_malloc_from
|
|
INC lib_malloc_to
|
|
WEND
|
|
|
|
//insert record and recalc lib_alloctable_end
|
|
DEC lib_malloc_ptr
|
|
POKEW lib_malloc_ptr , newspaceb
|
|
DEC lib_malloc_ptr
|
|
DEC lib_malloc_ptr
|
|
POKEW lib_malloc_ptr , newspacee
|
|
LET lib_alloctable_end GET newtableend
|
|
|
|
//return new pointer
|
|
LET result GET newspaceb
|
|
|
|
ENDIF
|
|
|
|
IF newspaceb = NULL THEN // return null pointer
|
|
LET result GET NULL
|
|
GOTO lib_malloc_exit
|
|
ENDIF
|
|
|
|
LABEL lib_malloc_exit
|
|
|
|
INC size_t
|
|
|
|
FEND
|
|
|
|
//-----------------------------------------------------------
|
|
// Free: free alloced memory at m_ptr
|
|
//-----------------------------------------------------------
|
|
|
|
FUNC lib_mem_free ( {WORD m_ptr} )
|
|
WORD ptr
|
|
WORD startaddr
|
|
WORD lastrecfirst
|
|
WORD from
|
|
WORD to
|
|
BYTE tempb
|
|
|
|
IF lib_alloctable_end > lib_memend THEN // no entries
|
|
GOTO lib_free_exit
|
|
ENDIF
|
|
|
|
LET ptr GET lib_memend
|
|
DEC ptr
|
|
|
|
ADD 2 + lib_alloctable_end -> lastrecfirst
|
|
|
|
WHILE 1
|
|
startaddr = PEEKW ptr
|
|
|
|
IF startaddr = m_ptr THEN //found allocation!
|
|
//remove it!
|
|
IF ptr = lastrecfirst THEN
|
|
ADD 4 + lib_alloctable_end -> lib_alloctable_end
|
|
BREAK
|
|
ENDIF
|
|
|
|
LET to GET ptr
|
|
INC to
|
|
SUBT to - 4 -> from
|
|
|
|
WHILE 1
|
|
PEEK from -> tempb
|
|
POKE to WITH tempb
|
|
IF from = lib_alloctable_end THEN
|
|
BREAK
|
|
ENDIF
|
|
DEC from
|
|
DEC to
|
|
WEND
|
|
|
|
ADD 4 + lib_alloctable_end -> lib_alloctable_end
|
|
|
|
BREAK
|
|
ENDIF
|
|
|
|
DEC ptr
|
|
DEC ptr
|
|
|
|
IF ptr = lib_alloctable_end THEN
|
|
BREAK
|
|
ENDIF
|
|
|
|
DEC ptr
|
|
DEC ptr
|
|
|
|
WEND
|
|
|
|
LABEL lib_free_exit
|
|
|
|
FEND
|
|
|
|
LABEL lib_memlib_skip
|
|
|
|
#PRAGMA _P_USE_LONG_JUMP 0
|
|
|
|
#IFEND
|