# HG changeset patch # User William Astle # Date 1720585110 21600 # Node ID 3a4cb89a419cf8a31e921d45cb2aafe40e81b889 # Parent 3ab4b62665c36f529ce91860d15792eb30fd1093 Add a memory insertion routine to swap the end block into middle of a block diff -r 3ab4b62665c3 -r 3a4cb89a419c src/lwbasic.s --- a/src/lwbasic.s Mon Jun 24 23:49:10 2024 -0600 +++ b/src/lwbasic.s Tue Jul 09 22:18:30 2024 -0600 @@ -42,6 +42,7 @@ include irq.s include consscr.s include genio.s + include memory.s include interp.s include progctrl.s include stack.s diff -r 3ab4b62665c3 -r 3a4cb89a419c src/memory.s --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/memory.s Tue Jul 09 22:18:30 2024 -0600 @@ -0,0 +1,55 @@ + *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