changeset 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 3ab4b62665c3
children e49bd0493baf
files src/lwbasic.s src/memory.s
diffstat 2 files changed, 56 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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
--- /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