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