view src/memory.s @ 136:e49bd0493baf

Checkpoint updates to immediate mode program editing and some memory handling
author William Astle <lost@l-w.ca>
date Fri, 12 Jul 2024 23:29:45 -0600
parents 3a4cb89a419c
children
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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Block copy routines. There are two routines here. One for moving a block upward in memory and one for moving the block
; downward in memory. Which one is used doesn't matter if the source and destination do not overlap. However, if the
; source and destination do overlap, the direction that needs to be used depends on whether the source is after or
; before the destination. There are three entry points below. One is a general block copy, one is for moving upward
; and one is for moving downward. All entry points have the same input conditions.
;
; Entry:
; X: Destination pointer
; U: Source pointer
; Y: Length of the block to copy
;
; General copy. This just dispatches either mem_copyup or mem_copydn based on whether the source is before or after
; the destination.
mem_copy        pshs u                          ; save source address for compare
                cmpx ,s++                       ; is the destination below or above?
                blo mem_copydn                  ; brif destination is below the source - we're copying downward
                ; fall through                  ; we're copying upward here
; Copy Y bytes from (U) to (X), working from the top down
mem_copyup      tfr y,d                         ; need to move pointers to the end of the block
                leax d,x
                leau d,u
mem_copyup0     lda ,-u                         ; copy a byte upward
                sta ,-x
                leay -1,y                       ; done yet?
                bne mem_copyup0
                rts
; Copy Y bytes from (U) to (X), working from bottom up
mem_copydn      lda ,u+                         ; copy a byte downward
                sta ,x+
                leay -1,y                       ; done yet?
                bne mem_copydn                  ; brif not
mem_checkptr0   rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Check for D bytes of free memory
mem_checkd      addd freestart                  ; add to current start of free memory
                ; fall through to test the resulting pointer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Check if the address in D is within the free memory area allowing for a buffer for the system stack.
mem_checkptr    addd #stackheadroom             ; add in the stack buffer space to the pointer
                sts ,--s                        ; get the current stack pointer somewhere
                cmpd ,s++                       ; did the pointer run into the stack pointer?
                blo mem_checkptr0               ; brif not - no error
OMERROR         ldb #err_om                     ; raise an OM error
                jmp ERROR
                *pragmapop list