Mercurial > hg > index.cgi
view src/memory.s @ 135:3a4cb89a419c
Add a memory insertion routine to swap the end block into middle of a block
author | William Astle <lost@l-w.ca> |
---|---|
date | Tue, 09 Jul 2024 22:18:30 -0600 |
parents | |
children | e49bd0493baf |
line wrap: on
line source
*pragmapush list *pragma list ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Insert the sequence of bytes at U, of length D, at X. The memory from X to (U+D-1) is assumed to be a continguous ; block and that D bytes of free memory are not available at U+D. That is, this is an in-place insertion of D bytes at ; the end of a memory block into said memory block. ; ; This works in two stages. As long as there are more than D bytes between X and U, a full copy that swaps the data ; at U with the data at X is done and then X is advanced by D bytes. Once there are less than D bytes between X and U, ; a byte by byte insertion process is run. ; ; Without the first phase, U-X bytes must by copied D times making the process O((U-X)*D). However, the first phase ; will run FLOOR((U-X)/D) times, each time swapping exactly D bytes, but at basically twice the cost per byte and then ; only the remainder needs to be copied on the byte by byte sequence meaning each byte sequence will have to shift ; (U-X)%D bytes. This will show the biggest gain for larger insertion sizes inserted a fairly large number of bytes ; before the end of the memory block. ; ; Entry: ; X Insertion point ; U Source data ; D Length of source data (must not be zero) ; ; Exit: ; ; DO NOT ENTER WITH D SET TO 0 mem_insert pshs d,u ; save the length and insertion point mem_insert0 leay d,x ; point to the end of this copy iteration cmpy 2,s ; is there room for a full iteration? bhi mem_insert2 ; brif not tfr d,y ; get copy length somewhere usfule mem_insert1 ldb ,x ; swap a byte lda ,u sta ,x+ stb ,u+ leay -1,y ; done this iteration? bne mem_insert1 ; brif not ldd ,s ; get back length ldu 2,s ; get back source pointer cmpx 2,s ; did we actually finish? bne mem_insert0 ; brif not puls d,x,pc ; we're done - clean up stack and return mem_insert2 ldy ,s ; get number bytes to insert one by one mem_insert3 pshs x,u ; save the pointers lda ,u ; get byte at top of move range mem_insert4 ldb ,-u stb 1,u cmpu ,s bne mem_insert4 puls x,u ; get back original pointers sta ,x+ ; save new byte in insert location leau 1,u ; move to next source byte leay -1,y ; done all source bytes? bne mem_insert3 ; brif not puls d,x,pc ; clean up stack and return *pragmapop list