Mercurial > hg > index.cgi
comparison 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 |
comparison
equal
deleted
inserted
replaced
134:3ab4b62665c3 | 135:3a4cb89a419c |
---|---|
1 *pragmapush list | |
2 *pragma list | |
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
4 ; 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 | |
5 ; 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 | |
6 ; the end of a memory block into said memory block. | |
7 ; | |
8 ; 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 | |
9 ; 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, | |
10 ; a byte by byte insertion process is run. | |
11 ; | |
12 ; Without the first phase, U-X bytes must by copied D times making the process O((U-X)*D). However, the first phase | |
13 ; will run FLOOR((U-X)/D) times, each time swapping exactly D bytes, but at basically twice the cost per byte and then | |
14 ; only the remainder needs to be copied on the byte by byte sequence meaning each byte sequence will have to shift | |
15 ; (U-X)%D bytes. This will show the biggest gain for larger insertion sizes inserted a fairly large number of bytes | |
16 ; before the end of the memory block. | |
17 ; | |
18 ; Entry: | |
19 ; X Insertion point | |
20 ; U Source data | |
21 ; D Length of source data (must not be zero) | |
22 ; | |
23 ; Exit: | |
24 ; | |
25 ; DO NOT ENTER WITH D SET TO 0 | |
26 mem_insert pshs d,u ; save the length and insertion point | |
27 mem_insert0 leay d,x ; point to the end of this copy iteration | |
28 cmpy 2,s ; is there room for a full iteration? | |
29 bhi mem_insert2 ; brif not | |
30 tfr d,y ; get copy length somewhere usfule | |
31 mem_insert1 ldb ,x ; swap a byte | |
32 lda ,u | |
33 sta ,x+ | |
34 stb ,u+ | |
35 leay -1,y ; done this iteration? | |
36 bne mem_insert1 ; brif not | |
37 ldd ,s ; get back length | |
38 ldu 2,s ; get back source pointer | |
39 cmpx 2,s ; did we actually finish? | |
40 bne mem_insert0 ; brif not | |
41 puls d,x,pc ; we're done - clean up stack and return | |
42 mem_insert2 ldy ,s ; get number bytes to insert one by one | |
43 mem_insert3 pshs x,u ; save the pointers | |
44 lda ,u ; get byte at top of move range | |
45 mem_insert4 ldb ,-u | |
46 stb 1,u | |
47 cmpu ,s | |
48 bne mem_insert4 | |
49 puls x,u ; get back original pointers | |
50 sta ,x+ ; save new byte in insert location | |
51 leau 1,u ; move to next source byte | |
52 leay -1,y ; done all source bytes? | |
53 bne mem_insert3 ; brif not | |
54 puls d,x,pc ; clean up stack and return | |
55 *pragmapop list |