Mercurial > hg > index.cgi
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