//----------------------------------------------------------- // // memory library ( Malloc, Free ) for 65CM // //----------------------------------------------------------- // 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 //ORGIN $1000 GOTO lib_skip_memlib //general defs. WORD NULL = 0 WORD lib_memstart = $3000 WORD lib_memend = $9fff WORD lib_alloctable_end //----------------------------------------------------------- // Init: sets upp things for the lib in mem before start //----------------------------------------------------------- LABEL lib_memlib_init //set allocation table end start value LET lib_alloctable_end GET lib_memend INCREMENT lib_alloctable_end SUBEND //----------------------------------------------------------- // Malloc: alloc memory of size lib_malloc_size // Address to allocated space is returned in lib_malloc_return //----------------------------------------------------------- WORD lib_malloc_size WORD lib_malloc_return LABEL lib_malloc WORD lib_malloc_maxsize //max possible size now in heap WORD lib_malloc_newspaceb WORD lib_malloc_newspacee WORD lib_malloc_newtableend DECREMENT lib_malloc_size // 1 = e.g. $2001-$2001 ( $2001 - $2001 = 0 ) LET lib_malloc_newtableend GET lib_alloctable_end SUBTRACT 4 FROM lib_malloc_newtableend GIVING lib_malloc_newtableend IF lib_alloctable_end > lib_memend THEN // only when first item! SUBTRACT lib_memstart FROM lib_malloc_newtableend GIVING lib_malloc_maxsize IF lib_malloc_maxsize < lib_malloc_size THEN //error handling: return NULL pointer! LET lib_malloc_return GET NULL GOTO lib_malloc_exit ENDIF LET lib_malloc_newspaceb GET lib_memstart ADD lib_malloc_newspaceb TO lib_malloc_size GIVING lib_malloc_newspacee //insert first record and recalc lib_alloctable_end DECREMENT lib_alloctable_end DECREMENT lib_alloctable_end PUTASWORD@ lib_alloctable_end VALUE lib_malloc_newspaceb DECREMENT lib_alloctable_end DECREMENT lib_alloctable_end PUTASWORD@ lib_alloctable_end VALUE lib_malloc_newspacee LET lib_malloc_return GET lib_malloc_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 SUBTRACT 3 FROM lib_malloc_ptr GIVING lib_malloc_ptr GETASWORD@ lib_malloc_ptr GIVING lib_malloc_spaceend LET lib_malloc_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? INCREMENT lib_malloc_spaceend SUBTRACT lib_malloc_spaceend FROM lib_malloc_newtableend GIVING lib_malloc_maxsize IF lib_malloc_maxsize > lib_malloc_size THEN LET lib_malloc_newspaceb GET lib_malloc_spaceend ADD lib_malloc_size TO lib_malloc_newspaceb GIVING lib_malloc_newspacee ENDIF GOTO lib_malloc_break ENDIF DECREMENT lib_malloc_ptr DECREMENT lib_malloc_ptr GETASWORD@ lib_malloc_ptr GIVING lib_malloc_spacestart SUBTRACT lib_malloc_spaceend FROM lib_malloc_spacestart GIVING lib_malloc_maxsize DECREMENT lib_malloc_maxsize //if we found a space big enough for the allocation IF lib_malloc_maxsize > lib_malloc_size THEN //Save the pointer to the new space end the pointer in the alloctable LET lib_malloc_newspaceb GET lib_malloc_spaceend INCREMENT lib_malloc_newspaceb // must start @ the next byte ADD lib_malloc_size TO lib_malloc_newspaceb GIVING lib_malloc_newspacee INCREMENT lib_malloc_ptr // set it to start of record! ( for move ) // INCREMENT lib_malloc_ptr GOTO lib_malloc_break ENDIF DECREMENT lib_malloc_ptr DECREMENT lib_malloc_ptr GETASWORD@ lib_malloc_ptr GIVING lib_malloc_spaceend WEND LABEL lib_malloc_break IF lib_malloc_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 DECREMENT lib_alloctable_end DECREMENT lib_alloctable_end PUTASWORD@ lib_alloctable_end VALUE lib_malloc_newspaceb DECREMENT lib_alloctable_end DECREMENT lib_alloctable_end PUTASWORD@ lib_alloctable_end VALUE lib_malloc_newspacee //return new pointer LET lib_malloc_return GET lib_malloc_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 lib_malloc_newtableend WHILE 1 PEEK lib_malloc_from GIVING lib_malloc_byte POKE lib_malloc_to WITH lib_malloc_byte IF lib_malloc_from = lib_malloc_ptr THEN GOTO lib_malloc_break2 ENDIF INCREMENT lib_malloc_from INCREMENT lib_malloc_to WEND LABEL lib_malloc_break2 //insert record and recalc lib_alloctable_end DECREMENT lib_malloc_ptr PUTASWORD@ lib_malloc_ptr VALUE lib_malloc_newspaceb DECREMENT lib_malloc_ptr DECREMENT lib_malloc_ptr PUTASWORD@ lib_malloc_ptr VALUE lib_malloc_newspacee LET lib_alloctable_end GET lib_malloc_newtableend //return new pointer LET lib_malloc_return GET lib_malloc_newspaceb ENDIF IF lib_malloc_newspaceb = NULL THEN // return null pointer LET lib_malloc_return GET NULL GOTO lib_malloc_exit ENDIF LABEL lib_malloc_exit INCREMENT lib_malloc_size SUBEND //----------------------------------------------------------- // Free: free alloced memory at lib_free_pointer //----------------------------------------------------------- WORD lib_free_pointer LABEL lib_free WORD lib_free_ptr WORD lib_free_startaddr WORD lib_free_lastrecfirst IF lib_alloctable_end > lib_memend THEN // no entries GOTO lib_free_exit ENDIF LET lib_free_ptr GET lib_memend DECREMENT lib_free_ptr ADD 2 TO lib_alloctable_end GIVING lib_free_lastrecfirst WHILE 1 GETASWORD@ lib_free_ptr GIVING lib_free_startaddr IF lib_free_startaddr = lib_free_pointer THEN //found allocation! //remove it! IF lib_free_ptr = lib_free_lastrecfirst THEN ADD 4 TO lib_alloctable_end GIVING lib_alloctable_end GOTO lib_free_break ENDIF WORD lib_free_from WORD lib_free_to BYTE lib_free_byte LET lib_free_to GET lib_free_ptr INCREMENT lib_free_to SUBTRACT 4 FROM lib_free_to GIVING lib_free_from WHILE 1 PEEK lib_free_from GIVING lib_free_byte POKE lib_free_to WITH lib_free_byte IF lib_free_from = lib_alloctable_end THEN GOTO lib_free_break2 ENDIF DECREMENT lib_free_from DECREMENT lib_free_to WEND LABEL lib_free_break2 ADD 4 TO lib_alloctable_end GIVING lib_alloctable_end GOTO lib_free_break ENDIF DECREMENT lib_free_ptr DECREMENT lib_free_ptr IF lib_free_ptr = lib_alloctable_end THEN GOTO lib_free_break ENDIF DECREMENT lib_free_ptr DECREMENT lib_free_ptr WEND LABEL lib_free_break LABEL lib_free_exit SUBEND LABEL lib_skip_memlib