//----------------------------------------------------------- // // 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